anchor.diff:  open System.IO.Compression
   open System.Linq
   
  -// Generic helpers
  +// ---------------------------------------------
  +// Generic Helpers
  +// ---------------------------------------------
   let (<!!>) (path1 : string) (path2 : string) = Path.Combine([| path1; path2 |])
   let loopDir (dir : string) = Directory.EnumerateDirectories(dir)
   let loopFiles (dir : string) = Directory.EnumerateFiles(dir)
   let createDir (dir : string) = Directory.CreateDirectory(dir) |> ignore
  -let (!>) (content : string) = printfn "%s" content |> ignore
  +let (!>) (content : string) = printfn "[INFO] %s" content |> ignore
   let (!>>) (content : string) = printfn "\t%s" content |> ignore
  -let OK() = printfn "[SUCCESS]"
  -let FAIL() = printfn "[FAILED]"
  +let brk() = !>"------------------------------------------------------------------------"
  +// ---------------------------------------------
  +// Build script configuration section
  +// Modify these to update the versioning information
  +// ---------------------------------------------
  +let IkvmVersion = "8.0.5449.1"
  +let LuceneVersion = "5.0.0"
  +let LuceneFullVersion = "5.0.0.0"
  +let FileVersion = "5.0.0.0"
  +
  +brk()
  +!>"Starting FlexLucene Build"
  +brk()
  +!>"Global Variable Information"
  +!>>(sprintf "IKVM Version: %s" IkvmVersion)
  +!>>(sprintf "Lucene Version: %s" LuceneVersion)
  +!>>(sprintf "Lucene full Version: %s" LuceneFullVersion)
  +!>>(sprintf "File Version: %s" FileVersion)
  +
  +let JAVA_HOME = Environment.GetEnvironmentVariable("JAVA_HOME")
  +
  +!>>(sprintf "JAVA_HOME: %s" JAVA_HOME)
  +brk()
   
   [<AutoOpenAttribute>]
   module Helpers = 
  
positive.code:     sb.Append(sprintf " -target:library -out:%s/%s.dll -version:%s -fileversion:%s" OutputDirectory "FlexLucene" 
                    LuceneFullVersion FileVersion).ToString()
  
  !>"Execute IKVM"
  Exec(IkvmPath, GetIkvmBuildString())
  !>"Append build information"
  
  let finalDllPath = OutputDirectory <!!> "FlexLucene.dll"
  let patchExec (args : string) = Exec(VersionPatchPath, args)
  
  patchExec (sprintf """%s %s /pv %s /va""" finalDllPath LuceneFullVersion FileVersion)
  patchExec (sprintf """%s /s FileDescription "Built using IKVM version %s" """ finalDllPath IkvmVersion)
  patchExec (sprintf """%s /s product "FlexSearch Search Engine" """ finalDllPath)
  patchExec (sprintf """%s /s copyright "(c) 2010-2015 FlexSearch" """ finalDllPath)
  
  // ---------------------------------------------
  // Mono Cecil based rewrite section
  // ---------------------------------------------
  let md = Mono.Cecil.ModuleDefinition.ReadModule(OutputDirectory <!!> "FlexLucene.dll")
  let editorBrowsableCtor = md.Import(typeof<EditorBrowsableAttribute>.GetConstructor(Type.EmptyTypes))
  let obsoleteCtor = md.Import(typeof<ObsoleteAttribute>.GetConstructor(Type.EmptyTypes))
  let editorStateRef = md.Import(typeof<EditorBrowsableState>)
  
  // Custom attribute to stop method from showing in intellisense
  let GetEditorBrowsableAttr() = 
      let attr = new CustomAttribute(editorBrowsableCtor)
      attr.Properties.Add
          (new CustomAttributeNamedArgument("EditorBrowsableState", new CustomAttributeArgument(editorStateRef, 1)))
      attr
  
  // Obsolete Attribute
  let GetObsAttr() = new CustomAttribute(obsoleteCtor)
  
  let mutable renameFileMethod : MethodBody = Unchecked.defaultof<_>
  
  let copyMethodBody (m : MethodDefinition) =
      if m.FullName.Contains("FlexFSDirectory") && m.FullName.Contains("renameFile")
      then
          renameFileMethod <- m.Body
          m.Body
      else
          if m.FullName.Contains("FSDirectory") && m.FullName.Contains("renameFile")
          then m.Body <- renameFileMethod
          m.Body
  
  let ProcessMethods(typ : TypeDefinition) = 
      let newMethods = new ResizeArray<MethodDefinition>()
      for meth in typ.Methods do
          if meth.Name <> null && not meth.IsRuntimeSpecialName && not meth.IsSpecialName && not meth.IsConstructor 
             && not meth.IsNative && not meth.IsAssembly && not meth.IsPInvokeImpl && not meth.IsUnmanaged 
             && meth.IsPublic then 
              if meth.IsAbstract 
                  || meth.Name = ConvertNamingConvention(meth.Name) then ()
              else 
                  let newMeth = new MethodDefinition(ConvertNamingConvention(meth.Name), meth.Attributes, meth.ReturnType)
                  meth.Parameters |> Seq.iter (fun x -> newMeth.Parameters.Add(x))
                  // Adding it to make sure that the newly generated method are similar to Ikvm
                  meth.NoInlining <- true
                  newMeth.Body <- copyMethodBody meth
                  newMethods.Add(newMeth)
                  meth.CustomAttributes.Add(GetEditorBrowsableAttr())
                  meth.CustomAttributes.Add(GetObsAttr())
      newMethods |> Seq.iter (fun x -> typ.Methods.Add(x))
  
  let regenerateImplementsAtt (_type : TypeDefinition) = 
      if _type.HasCustomAttributes then 
          let implAtts = _type.CustomAttributes |> Seq.filter (fun a -> a.AttributeType.Name = "ImplementsAttribute")
          if implAtts
             |> Seq.length
             > 0 then 
              let implAtt = implAtts |> Seq.head
              let arg = implAtt.ConstructorArguments |> Seq.head
              if arg.Type.Name <> "String[]" then 
                  failwithf "Expected type of argument to be String[], but found %s" arg.Type.Name
              let javaTypes = arg.Value :?> CustomAttributeArgument []
              
              let newJavaTypes = 
                  javaTypes
                  |> Seq.map (fun jt -> 
                         if not <| (jt.Value :?> System.String).StartsWith("java.") then 
                             ConvertNamingConvention(jt.Value :?> System.String)
                         else (jt.Value :?> System.String))
                  |> Seq.map (fun strJt -> new CustomAttributeArgument((javaTypes |> Seq.head).Type, strJt))
              // Replace the Attribute arguments with the new ones
              implAtt.ConstructorArguments.Clear()
              implAtt.ConstructorArguments.Add(new CustomAttributeArgument(arg.Type, newJavaTypes.ToArray()))
  
  let rec ProcessType(typ : TypeDefinition) = 
      if not (typ.Name = "WindowsDirectory") && not (typ.Name = "NativePosixUtil")
      then 
          let classCondition (t : TypeDefinition) = 
              not t.IsRuntimeSpecialName && t.Name <> "<Module>" 
              && t.Name <> "Resources" && t.IsPublic
          let nestedClassCondition (t : TypeDefinition) = not t.IsRuntimeSpecialName && t.IsNestedPublic
          // Replace the Class's namespace and 'Implements' attribute with the FlexLucene version
          typ.Namespace <- ConvertNamingConvention(typ.Namespace)
          typ |> regenerateImplementsAtt
          // Change the Method and Field names to FlexLucene convention
          if classCondition typ || nestedClassCondition typ then 
              if (not typ.IsInterface || not typ.IsAbstract) && typ.IsPublic then 
                  // Change field names
                  typ.Fields
                  |> Seq.filter (fun x -> x.IsPublic)
                  |> Seq.iter (fun x -> x.Name <- ConvertNamingConvention(x.Name))
                  // Change method names
                  ProcessMethods(typ)
          // Process all nested types (public, internal, etc)
          typ.NestedTypes |> Seq.iter ProcessType
  
  let RegenerateMethodNames() = 
      md.Types |> Seq.iter ProcessType
      md.Write(OutputDirectory <!!> "FlexLucene.dll")
  
  !>"Regenerate Method names"
  RegenerateMethodNames()
  
negative.code:        sprintf "lucene-spatial-%s" LuceneVersion
         sprintf "lucene-sandbox-%s" LuceneVersion |]
  
  let JarFiles = Directory.GetFiles(RootDirectory, "*.jar", System.IO.SearchOption.AllDirectories)
  let javaExec (args : string) = Exec(JAVA_HOME <!!> @"bin\java.exe", args)
  
  /// <summary>
  /// Compiles FlexSearch related custom Java code to a jar file using Maven
  /// </summary>
  let codecsCompilation() = 
      !>>"Compiling using MAVEN."
      Exec(FlexSearchJar <!!> "compile.bat", "")
      !>>"Copy FlexSearch.Codec-0.0.0.jar to Lucene Files directory"
      assert File.Exists(FlexSearchJar <!!> @"target\FlexSearch.Codec-0.0.0.jar")
      File.Copy(FlexSearchJar <!!> @"target\FlexSearch.Codec-0.0.0.jar", LuceneDirectory <!!> @"FlexSearch.Codec.jar")
  
  /// <summary>
  /// Copies all the required Lucene jar files to the target directory
  /// </summary>
  let copyLuceneFilesToTarget() = 
      LuceneJars |> Array.iter (fun jar -> 
                        match JarFiles.FirstOrDefault(fun x -> x.Contains(jar)) with
                        | null -> failwithf "Jar not found: %s" jar
                        | filePath -> 
                            !>>(sprintf "Copying: %s" filePath)
                            File.Copy(filePath, LuceneDirectory <!!> (Path.GetFileName(filePath))))
  
  /// <summary>
  /// Extracts meta data information from Lucene jars
  /// </summary>
  let extractMetaInformation() = 
      loopFiles LuceneDirectory |> Seq.iter (fun file -> 
                                       use archive = ZipFile.Open(file, ZipArchiveMode.Update)
                                       
                                       let toBeDeleted = 
                                           Seq.fold (fun (acc : string list) (entry : ZipArchiveEntry) -> 
                                               if entry.FullName.StartsWith(@"META-INF/services/") then 
                                                   let info = Directory.CreateDirectory(TempDirectory <!!> entry.Name)
                                                   entry.ExtractToFile(info.FullName <!!> (Guid.NewGuid().ToString()))
                                                   entry.FullName :: acc
                                               else if entry.FullName.StartsWith("META-INF") then entry.FullName :: acc
                                               else acc) [] archive.Entries
                                       toBeDeleted |> Seq.iter (fun res -> archive.GetEntry(res).Delete()))
  
  /// <summary>
  /// Builds FlexLucene compatible meta data information
  /// </summary>
  let generateMetaInformation() = 
      loopDir TempDirectory |> Seq.iter (fun dir -> 
                                   loopFiles dir |> Seq.iter (fun file -> 
                                                        let dirInfo = new DirectoryInfo(Path.GetDirectoryName(file))
                                                        let targetFileName = ConvertNamingConvention(dirInfo.Name)
                                                        let targetPath = ServicesDirectory <!!> targetFileName
                                                        File.AppendAllLines(targetPath, CreateServiceFile(file))))
      !>"Create meta data jar"
      ZipFile.CreateFromDirectory(MetaDirectory, LuceneDirectory <!!> "Metadata.jar")
  
  /// <summary>
  /// Copies related libraries which are needed for compilation
  /// </summary>
  let copyLibraries() = 
      loopFiles LibSrcDirectory |> Seq.iter (fun f -> File.Copy(f, LibTargetDirectory <!!> (Path.GetFileName(f))))
  
  /// <summary>
  /// Executes Proguard which create a fat FlexLucene jar file
  /// </summary>
  let executeProguard() = 
      !>>"Move proguard.cfg to work directory"
      File.Copy(RootDirectory <!!> "proguard.cfg", WorkDirectory <!!> "proguard.cfg")
      javaExec """-jar ProGuard.jar @work\proguard.cfg"""
  
  /// <summary>
  ///Generated IKVM build string
  /// </summary>
  let GetIkvmBuildString() = 
      let sb = new System.Text.StringBuilder()
      loopFiles LibTargetDirectory |> Seq.iter (fun f -> sb.Append(f).Append(" ") |> ignore)
  