You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by re...@apache.org on 2022/02/10 14:37:21 UTC

[uima-uimaj] 14/15: [UIMA-6373] Format UIMA Core Java SDK codebase

This is an automated email from the ASF dual-hosted git repository.

rec pushed a commit to branch refactoring/UIMA-6373-Format-UIMA-Core-Java-SDK-codebase
in repository https://gitbox.apache.org/repos/asf/uima-uimaj.git

commit ce516fb1c612727d092901e0bb7c65acaed3b305
Author: Richard Eckart de Castilho <re...@apache.org>
AuthorDate: Thu Feb 10 15:28:14 2022 +0100

    [UIMA-6373] Format UIMA Core Java SDK codebase
    
    - Auto-format
---
 .../apache/uima/migratev3/jcas/MigrateJCas.java    | 3404 +++++++++++---------
 1 file changed, 1808 insertions(+), 1596 deletions(-)

diff --git a/uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/MigrateJCas.java b/uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/MigrateJCas.java
index ba3561e..99d5ae4 100644
--- a/uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/MigrateJCas.java
+++ b/uimaj-v3migration-jcas/src/main/java/org/apache/uima/migratev3/jcas/MigrateJCas.java
@@ -120,34 +120,47 @@ import com.github.javaparser.printer.PrettyPrinter;
 import com.github.javaparser.printer.PrettyPrinterConfiguration;
 
 /**
- * <p>A driver that scans given roots for source and/or class Java files that contain JCas classes
+ * <p>
+ * A driver that scans given roots for source and/or class Java files that contain JCas classes
  * 
- * <ul><li>identifies which ones appear to be JCas classes (heuristic)
- *   <ul><li>of these, identifies which ones appear to be v2
- *     <ul><li>converts these to v3</li></ul></li></ul>
+ * <ul>
+ * <li>identifies which ones appear to be JCas classes (heuristic)
+ * <ul>
+ * <li>of these, identifies which ones appear to be v2
+ * <ul>
+ * <li>converts these to v3</li>
+ * </ul>
+ * </li>
+ * </ul>
  * 
- *   <li>also can receive a list of individual class names</li>
- *   <li>also can do a single source file</li>
+ * <li>also can receive a list of individual class names</li>
+ * <li>also can do a single source file</li>
  * </ul>
- *   
- * <p>Creates summary and detailed reports of its actions.
  * 
- * <p>Files representing JCas classes to convert are discovered by walking file system 
- * directories from various roots, specified as input.  The tool operates in 1 of two exclusive
- * "modes":  migrating from sources (e.g., .java files) and migrating using compiled classes.
+ * <p>
+ * Creates summary and detailed reports of its actions.
+ * 
+ * <p>
+ * Files representing JCas classes to convert are discovered by walking file system directories from
+ * various roots, specified as input. The tool operates in 1 of two exclusive "modes": migrating
+ * from sources (e.g., .java files) and migrating using compiled classes.
+ * 
+ * <p>
+ * Compiled classes are decompiled and then migrated. This decompilation step usually requires a
+ * java classpath, which is supplied using the -migrateClasspath parameter. Exception: migrating
+ * PEAR files, which contain their own specification for a classpath.
  * 
- * <p>Compiled classes are decompiled and then migrated.  This decompilation step usually
- * requires a java classpath, which is supplied using the -migrateClasspath parameter.
- * Exception: migrating PEAR files, which contain their own specification for a classpath. 
+ * <p>
+ * The same JCas class may be encountered multiple times while walking the directory tree from the
+ * roots, with the same or different definition. All of these definitions are migrated.
  * 
- * <p>The same JCas class may be encountered multiple
- * times while walking the directory tree from the roots, 
- * with the same or different definition.  All of these definitions are migrated.
+ * <p>
+ * Copies of the original and the converted files are put into the output file tree.
+ * 
+ * <p>
+ * Directory structure, starting at -outputDirectory (which if not specified, is a new temp
+ * directory). The "a0", "a1" represent non-identical alternative definitions for the same class.
  * 
- * <p>Copies of the original and the converted files are put into the output file tree.
- *   
- * <p>Directory structure, starting at -outputDirectory (which if not specified, is a new temp directory).
- * The "a0", "a1" represent non-identical alternative definitions for the same class.
  * <pre>
  *     converted/      
  *       v2/    these are the decompiled or "found" source files
@@ -194,8 +207,10 @@ import com.github.javaparser.printer.PrettyPrinterConfiguration;
  *       jarFileUpdates.txt
  *       ...
  * </pre>
- *     
- * <p>Operates in one of two modes:
+ * 
+ * <p>
+ * Operates in one of two modes:
+ * 
  * <pre>
  *   Mode 1: Given classes-roots and/or individual class names, and a migrateClasspath, 
  *     scans the classes-routes looking for classes candidates
@@ -212,14 +227,39 @@ import com.github.javaparser.printer.PrettyPrinterConfiguration;
  *       - migrates that decompiled source.
  * </pre>
  * 
- * <p>Note: Each run clears the output directory before starting the migration.
+ * <p>
+ * Note: Each run clears the output directory before starting the migration.
  * 
- * <p>Note: classpath may be specified using -migrateClassPath or as the class path used to run this tool. 
+ * <p>
+ * Note: classpath may be specified using -migrateClassPath or as the class path used to run this
+ * tool.
  */
 public class MigrateJCas extends VoidVisitorAdapter<Object> {
-  
-  /* *****************************************************
-   * Internals
+
+  // @formatter:off
+  /*
+   * ***************************************************** Internals
+   * 
+   * Unique IDs of v2 and v3 artifacts: RootId + classname
+   * 
+   * RootIdContainers (Set<RootId>) hold all discovered rootIds, at each Jar/Pear nesting level
+   * including outer level (no Jar/Pear). These are kept in a push-down stack
+   * 
+   * 
+   * Processing roots collection: done for source or class - iterate, for all roots --
+   * processCollection for candidates rooted at that root --- candidate is .java or .class, with
+   * path, with pearClasspath string ---- migrate called on each candidate ----- check to see if
+   * already done, and if so, skip. ------ means: same byte or source code associated with same fqcn
+   * 
+   * Root-ids: created for each unique pathpart in front of fully-qualified class name created for
+   * each unique path to Jar or PEAR
+   * 
+   * Caching to speed up duplicate processing: - decompiling: if the byte[] is already done, use
+   * other value (if augmented migrateClasspath is the same) - source-migrating: if the source
+   * strings are the same.
+   * 
+   * Multiple sources for single class: classname2multiSources: TreeMap from fqcn to CommonConverted
+   * (string or bytes) CommonConverted: supports multiple paths having identical string/bytes.
    * 
    *   Unique IDs of v2 and v3 artifacts:
    *     RootId + classname
@@ -254,75 +294,83 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    *      - set when visiting top-level compilation unit non-built-in type
    *     
    */
-  
+    // @formatter:on
   /** manange the indention of printing routines */
   private static final int[] indent = new int[1];
-  
-  private static StringBuilder si(StringBuilder sb) { return Misc.indent(sb, indent); }
-  
+
+  private static StringBuilder si(StringBuilder sb) {
+    return Misc.indent(sb, indent);
+  }
+
   private static StringBuilder flush(StringBuilder sb) {
     System.out.print(sb);
     sb.setLength(0);
     return sb;
   }
-  
+
   private static final Integer INTEGER0 = 0;
-  
+
   private static int nextContainerId = 0;
+
+  // @formatter:off
   /******************************************************************
    * Container - exists in tree structure, has super, sub containers
    *              -- subcontainers: has path to it
    *           - holds set of rootIds in that container
    *           - topmost one has null parent, and null pathToJarOrPear
    ******************************************************************/
+  // @formatter:on
   private static class Container implements Comparable<Container> {
     final int id = nextContainerId++;
-    final Container parent;      // null if at top level
+    final Container parent; // null if at top level
+    // @formatter:off
     /**  root to scan from.  
      *     Pears: is the loc in temp space of installed pear
      *     Jars: is the file system mounted on the Jar
      *             -- for inner Jars, the Jar is copied out into temp space. */
-    Path root;  
+    // @formatter:on
+    Path root;
     final Path rootOrig; // for Jars and Pears, the original path ending in jar or pear
-    final Set<Container> subContainers = new TreeSet<>();  // tree set for better ordering
+    final Set<Container> subContainers = new TreeSet<>(); // tree set for better ordering
     final List<Path> candidates = new ArrayList<>();
     final List<CommonConverted> convertedItems = new ArrayList<>();
     final List<V3CompiledPathAndContainerItemPath> v3CompiledPathAndContainerItemPath = new ArrayList<>();
-    final boolean isPear; 
+    final boolean isPear;
     final boolean isJar;
     final boolean isSingleJavaSource;
     /** can't use Path as the type, because the equals for Path is object == */
     final Set<String> _Types = new HashSet<>(); // has the non_Type path only if the _Type is found
     boolean haveDifferentCapitalizedNamesCollidingOnWindows = false;
 
-    String pearClasspath;  // not final - set by subroutine after defaulting
-    
-    /** Cache of already done compiled classes, to avoid redoing them 
-     *  Kept by container, because the classpath could change the decompile */
+    String pearClasspath; // not final - set by subroutine after defaulting
+
+    /**
+     * Cache of already done compiled classes, to avoid redoing them Kept by container, because the
+     * classpath could change the decompile
+     */
     private Map<byte[], CommonConverted> origBytesToCommonConverted = new HashMap<>();
- 
+
     Container(Container parent, Path root) {
       this.parent = parent;
       if (parent != null) {
         parent.subContainers.add(this);
-        this.pearClasspath = parent.pearClasspath;  // default, when expanding Jars.
+        this.pearClasspath = parent.pearClasspath; // default, when expanding Jars.
       }
       this.rootOrig = root;
       String s = root.toString().toLowerCase();
       isJar = s.endsWith(".jar");
       isPear = s.endsWith(".pear");
       isSingleJavaSource = s.endsWith(".java");
-      this.root = (isPear || isJar) 
-                   ? installJarOrPear()
-                   : root;
-//      // debug
-//      if (!isPear && isJar) {
-//        System.out.println("debug prepare jar: " + this);
-//      }
-    }
-      
+      this.root = (isPear || isJar) ? installJarOrPear() : root;
+      // // debug
+      // if (!isPear && isJar) {
+      // System.out.println("debug prepare jar: " + this);
+      // }
+    }
+
     /**
      * Called when a new container is created
+     * 
      * @param container
      * @param path
      * @return install directory
@@ -331,22 +379,24 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       try {
         Path theJarOrPear = rootOrig;
         if (!theJarOrPear.getFileSystem().equals(FileSystems.getDefault())) {
-          // pear is embedded in another pear or jar, so copy the Jar (intact) to a temp spot so it's no longer embedded
+          // pear is embedded in another pear or jar, so copy the Jar (intact) to a temp spot so
+          // it's no longer embedded
           theJarOrPear = getTempOutputPathForJarOrPear(theJarOrPear);
           Files.copy(rootOrig, theJarOrPear, StandardCopyOption.REPLACE_EXISTING);
         }
-        
+
         if (isPear) {
-          // extract the pear just to get the classpath 
+          // extract the pear just to get the classpath
           File pearInstallDir = Files.createTempDirectory(getTempDir(), "installedPear").toFile();
-          PackageBrowser ip = PackageInstaller.installPackage(pearInstallDir, rootOrig.toFile(), false);
+          PackageBrowser ip = PackageInstaller.installPackage(pearInstallDir, rootOrig.toFile(),
+                  false);
           String newClasspath = ip.buildComponentClassPath();
           String parentClasspath = parent.pearClasspath;
-          this.pearClasspath = (null == parentClasspath || 0 == parentClasspath.length()) 
-                    ? newClasspath
-                    : newClasspath + File.pathSeparator + parentClasspath;
-        }        
-        
+          this.pearClasspath = (null == parentClasspath || 0 == parentClasspath.length())
+                  ? newClasspath
+                  : newClasspath + File.pathSeparator + parentClasspath;
+        }
+
         FileSystem pfs = FileSystems.newFileSystem(theJarOrPear, (ClassLoader) null);
         return pfs.getPath("/");
       } catch (IOException e) {
@@ -354,7 +404,9 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       }
     }
 
-    /* (non-Javadoc)
+    /*
+     * (non-Javadoc)
+     * 
      * @see java.lang.Object#toString()
      */
     @Override
@@ -362,31 +414,36 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       StringBuilder sb = toString1();
       indent[0] += 2;
       try {
-      si(sb);  // new line + indent
-      sb.append("subContainers=");
-      Misc.addElementsToStringBuilder(indent, sb, Misc.setAsList(subContainers), -1, (sbx, i) -> sbx.append(i.id)).append(',');
-      si(sb).append("paths migrated=");  // new line + indent
-      Misc.addElementsToStringBuilder(indent, sb, candidates, -1, StringBuilder::append).append(',');
-//      si(sb).append("v3CompilePath=");  // new line + indent
-//      Misc.addElementsToStringBuilder(indent,  sb, v3CompiledPathAndContainerItemPath, 100, StringBuilder::append);
+        si(sb); // new line + indent
+        sb.append("subContainers=");
+        Misc.addElementsToStringBuilder(indent, sb, Misc.setAsList(subContainers), -1,
+                (sbx, i) -> sbx.append(i.id)).append(',');
+        si(sb).append("paths migrated="); // new line + indent
+        Misc.addElementsToStringBuilder(indent, sb, candidates, -1, StringBuilder::append)
+                .append(',');
+        // si(sb).append("v3CompilePath="); // new line + indent
+        // Misc.addElementsToStringBuilder(indent, sb, v3CompiledPathAndContainerItemPath, 100,
+        // StringBuilder::append);
       } finally {
-        indent[0] -=2;
+        indent[0] -= 2;
         si(sb).append(']');
       }
       return sb.toString();
     }
-    
+
     public StringBuilder toString1() {
       StringBuilder sb = new StringBuilder();
       si(sb); // initial nl and indentation
       sb.append(isJar ? "Jar " : isPear ? "PEAR " : "");
-      sb.append("container [id=").append(id)
-          .append(", parent.id=").append((null == parent) ? "null" : parent.id)
-          .append(", root or pathToJarOrPear=").append(rootOrig).append(',');
+      sb.append("container [id=").append(id).append(", parent.id=")
+              .append((null == parent) ? "null" : parent.id).append(", root or pathToJarOrPear=")
+              .append(rootOrig).append(',');
       return sb;
     }
 
-    /* (non-Javadoc)
+    /*
+     * (non-Javadoc)
+     * 
      * @see java.lang.Object#hashCode()
      */
     @Override
@@ -394,7 +451,9 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       return 31 * id;
     }
 
-    /* (non-Javadoc)
+    /*
+     * (non-Javadoc)
+     * 
      * @see java.lang.Object#equals(java.lang.Object)
      */
     @Override
@@ -411,27 +470,28 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       return true;
     }
 
-
     @Override
     public int compareTo(Container o) {
-      return Integer.compare(id,  o.id);
-    }    
+      return Integer.compare(id, o.id);
+    }
   }
-  
+
   /**
-   * A path to a .java or .class file in some container, for the v2 version
-   * For Jars and Pears, the path is relative to the zip "/" dir
+   * A path to a .java or .class file in some container, for the v2 version For Jars and Pears, the
+   * path is relative to the zip "/" dir
    */
   private static class ContainerAndPath implements Comparable<ContainerAndPath> {
     final Path path;
     final Container container;
-    
+
     ContainerAndPath(Path path, Container container) {
       this.path = path;
-      this.container = container;          
+      this.container = container;
     }
-    
-    /* (non-Javadoc)
+
+    /*
+     * (non-Javadoc)
+     * 
      * @see java.lang.Comparable#compareTo(java.lang.Object)
      */
     @Override
@@ -443,19 +503,21 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       return Integer.compare(container.id, o.container.id);
     }
 
-
-
-    /* (non-Javadoc)
+    /*
+     * (non-Javadoc)
+     * 
      * @see java.lang.Object#toString()
      */
     @Override
     public String toString() {
       StringBuilder sb = new StringBuilder();
-      sb.append("ContainerAndPath [path=").append(path).append(", container=").append(container.id).append("]");
+      sb.append("ContainerAndPath [path=").append(path).append(", container=").append(container.id)
+              .append("]");
       return sb.toString();
     }
   }
-  
+
+  // @formatter:off
   /**
    * This class holds information used to replace compiled items in Jars and Pears.
    * 
@@ -465,16 +527,19 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    *   - Note: if a Jar has the same compiled class at multiple nesting levels, each one will have 
    *     an instance of this class 
    */
+  // @formatter:on
   private static class V3CompiledPathAndContainerItemPath {
     final Path v3CompiledPath;
-    final String pathInContainer; 
-    
+    final String pathInContainer;
+
     public V3CompiledPathAndContainerItemPath(Path v3CompiledPath, String pathInContainer) {
       this.v3CompiledPath = v3CompiledPath;
       this.pathInContainer = pathInContainer;
     }
 
-    /* (non-Javadoc)
+    /*
+     * (non-Javadoc)
+     * 
      * @see java.lang.Object#toString()
      */
     @Override
@@ -491,12 +556,11 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       }
       return sb.toString();
     }
-    
-    
+
   }
-  
+
   private static final JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
-  
+
   /****************************************************************
    * Command line parameters
    ****************************************************************/
@@ -505,52 +569,54 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
   private static final String CLASS_FILE_ROOTS = "-classesRoots";
 
   private static final String OUTPUT_DIRECTORY = "-outputDirectory";
-  
-//  private static final String SKIP_TYPE_CHECK = "-skipTypeCheck";
-  
-  private static final String MIGRATE_CLASSPATH = "-migrateClasspath"; 
-  
-//  private static final String CLASSES = "-classes"; // individual classes to migrate, get from supplied classpath
-  
+
+  // private static final String SKIP_TYPE_CHECK = "-skipTypeCheck";
+
+  private static final String MIGRATE_CLASSPATH = "-migrateClasspath";
+
+  // private static final String CLASSES = "-classes"; // individual classes to migrate, get from
+  // supplied classpath
 
   private static final Type intType = PrimitiveType.intType();
-  
+
   private static final Type callSiteType = JavaParser.parseType("CallSite");
-  
+
   private static final Type methodHandleType = JavaParser.parseType("MethodHandle");
-  
+
   private static final Type stringType = JavaParser.parseType("String");
-  
-  private static final EnumSet<Modifier> public_static_final = 
-      EnumSet.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL);
-  private static final EnumSet<Modifier> private_static_final = 
-      EnumSet.of(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL);
-  
-  private static final PrettyPrinterConfiguration printWithoutComments = 
-      new PrettyPrinterConfiguration();
-  static { printWithoutComments.setPrintComments(false); }
-
-  private static final PrettyPrinterConfiguration printCu = 
-      new PrettyPrinterConfiguration();
-  static { printCu.setIndent("  "); }
-  
+
+  private static final EnumSet<Modifier> public_static_final = EnumSet.of(Modifier.PUBLIC,
+          Modifier.STATIC, Modifier.FINAL);
+  private static final EnumSet<Modifier> private_static_final = EnumSet.of(Modifier.PRIVATE,
+          Modifier.STATIC, Modifier.FINAL);
+
+  private static final PrettyPrinterConfiguration printWithoutComments = new PrettyPrinterConfiguration();
+  static {
+    printWithoutComments.setPrintComments(false);
+  }
+
+  private static final PrettyPrinterConfiguration printCu = new PrettyPrinterConfiguration();
+  static {
+    printCu.setIndent("  ");
+  }
+
   private static final String ERROR_DECOMPILING = "!!! ERROR:";
-  
+
   static private boolean isSource = false;
 
   static private Path tempDir = null;
 
-/***************************************************************************************************/
-  
-  private String packageName;  // with dots?
-  private String className;  // (omitting package)
-  private String packageAndClassNameSlash;  
-  
+  /***************************************************************************************************/
+
+  private String packageName; // with dots?
+  private String className; // (omitting package)
+  private String packageAndClassNameSlash;
+
   // next 3 set at start of migrate for item being migrated
-  private CommonConverted current_cc;  
+  private CommonConverted current_cc;
   private Path current_path;
   private Container current_container;
-  
+
   /** includes trailing / */
   private String outputDirectory;
   /** includes trailing / */
@@ -559,24 +625,25 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
   private String outDirSkipped;
   /** includes trailing / */
   private String outDirLog;
-   
+
   private Container[] sourcesRoots = null; // only one of these has 1 or more Container instances
   private Container[] classesRoots = null;
-  
+
   private CompilationUnit cu;
-  
+
   // save this value in the class instance to avoid recomputing it
   private ClassLoader cachedMigrateClassLoader = null;
-  
+
   private String migrateClasspath = null;
-  
-//  private String individualClasses = null;  // to decompile
+
+  // private String individualClasses = null; // to decompile
 
   /**
-   * CommonConverted next id, by fqcn
-   * key: fqcn_slashes value: next id
+   * CommonConverted next id, by fqcn key: fqcn_slashes value: next id
    */
-  private Map<String, Integer> nextCcId = new HashMap<>();  
+  private Map<String, Integer> nextCcId = new HashMap<>();
+
+  // @formatter:off
   /**
    * Common info about a particular source-code instance of a class
    *   Used to avoid duplicate work for the same JCas definition
@@ -590,27 +657,30 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    *     use map: origBytesToCommonConverted  key = byte[], kept by container in container
    *     if found, use previous converted results
    */
+  // @formatter:on
   private class CommonConverted {
     /**
-     * starts at 0, incr for each new instance for a particular fqcn_slash
-     * can't be assigned until fqcn known
+     * starts at 0, incr for each new instance for a particular fqcn_slash can't be assigned until
+     * fqcn known
+     */
+    int id = -1; // temp value
+    final String v2Source; // remembered original source
+    final byte[] v2ByteCode; // remembered original bytes
+
+    /**
+     * all paths + their containers having the same converted result Need container because might
+     * change classpath for compiling - path is to v2 source or compiled class
      */
-    int id = -1;            // temp value
-    final String v2Source;  // remembered original source
-    final byte[] v2ByteCode;   // remembered original bytes
-    
-    /** all paths + their containers having the same converted result 
-     *  Need container because might change classpath for compiling 
-     *    - path is to v2 source or compiled class*/
-    final Set<ContainerAndPath> containersAndV2Paths = new HashSet<>(); 
- 
-    String v3Source;           // if converted, the result
+    final Set<ContainerAndPath> containersAndV2Paths = new HashSet<>();
+
+    String v3Source; // if converted, the result
     /** converted/v3/id-of-cc/pkg/name/classname.java */
-    Path v3SourcePath;       // path to converted source or null
-    
-    String fqcn_slash;           // full name of the class e.g. java/util/Foo.  unknown for sources at first
-    
-    CommonConverted(String origSource, byte[] v2ByteCode, Path path, Container container, String fqcn_slash) {
+    Path v3SourcePath; // path to converted source or null
+
+    String fqcn_slash; // full name of the class e.g. java/util/Foo. unknown for sources at first
+
+    CommonConverted(String origSource, byte[] v2ByteCode, Path path, Container container,
+            String fqcn_slash) {
       this.v2Source = origSource;
       this.v2ByteCode = v2ByteCode;
       containersAndV2Paths.add(new ContainerAndPath(path, container));
@@ -619,9 +689,10 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
 
     /**
      * 
-     * @param container having this commonConverted instance
-     * @return the path to .java or .class file.  
-     *         If the container is a Jar or PEAR, it is the path within that Jar or Pear FileSystem
+     * @param container
+     *          having this commonConverted instance
+     * @return the path to .java or .class file. If the container is a Jar or PEAR, it is the path
+     *         within that Jar or Pear FileSystem
      */
     Path getV2SourcePath(Container container) {
       for (ContainerAndPath cp : containersAndV2Paths) {
@@ -631,7 +702,7 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       }
       throw new RuntimeException("internalError");
     }
-    
+
     int getId() {
       if (id < 0) {
         Integer nextId = nextCcId.computeIfAbsent(fqcn_slash, s -> INTEGER0);
@@ -640,8 +711,10 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       }
       return id;
     }
-    
-    /* (non-Javadoc)
+
+    /*
+     * (non-Javadoc)
+     * 
      * @see java.lang.Object#hashCode()
      */
     @Override
@@ -649,16 +722,18 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       return v2Source == null ? 0 : v2Source.hashCode();
     }
 
-    /* equal if the v2source is equal
+    /*
+     * equal if the v2source is equal
      */
     @Override
     public boolean equals(Object obj) {
-      return obj instanceof CommonConverted &&
-             v2Source != null &&
-             v2Source.equals(((CommonConverted)obj).v2Source);
+      return obj instanceof CommonConverted && v2Source != null
+              && v2Source.equals(((CommonConverted) obj).v2Source);
     }
 
-    /* (non-Javadoc)
+    /*
+     * (non-Javadoc)
+     * 
      * @see java.lang.Object#toString()
      */
     @Override
@@ -668,78 +743,87 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       si(sb).append("CommonConverted [v2Source=").append(Misc.elide(v2Source, 100));
       indent[0] += 2;
       try {
-      si(sb).append("v2ByteCode=");
-      sb.append(v2ByteCode != null
-                  ? Arrays.toString(Arrays.copyOf(v2ByteCode, Math.min(v2ByteCode.length, maxLen))) : 
-                  "null").append(',');
-      si(sb).append("containersAndPaths=")
-            .append(containersAndV2Paths != null 
-                      ? Misc.ppList(indent, Misc.setAsList(containersAndV2Paths), -1, StringBuilder::append)
-                      : "null").append(',');
-      si(sb).append("v3SourcePath=").append(v3SourcePath).append(',');
-      si(sb).append("fqcn_slash=").append(fqcn_slash).append("]").append('\n');
+        si(sb).append("v2ByteCode=");
+        sb.append(v2ByteCode != null
+                ? Arrays.toString(Arrays.copyOf(v2ByteCode, Math.min(v2ByteCode.length, maxLen)))
+                : "null").append(',');
+        si(sb).append("containersAndPaths=")
+                .append(containersAndV2Paths != null ? Misc.ppList(indent,
+                        Misc.setAsList(containersAndV2Paths), -1, StringBuilder::append) : "null")
+                .append(',');
+        si(sb).append("v3SourcePath=").append(v3SourcePath).append(',');
+        si(sb).append("fqcn_slash=").append(fqcn_slash).append("]").append('\n');
       } finally {
         indent[0] -= 2;
       }
       return sb.toString();
     }
-  }      
+  }
+
+  // @formatter:off
   /** Cache of already converted source classes, to avoid redoing them; 
    *    - key is the actual source
    *    - value is CommonConverted 
    *  This cache is over all containers 
-   *  */
+   */
+  // @formatter:on
   private Map<String, CommonConverted> sourceToCommonConverted = new HashMap<>();
-  
+
   /**
-   * A map from fqcn_slash to a list of converted sources
-   *   one per non-duplicated source
+   * A map from fqcn_slash to a list of converted sources one per non-duplicated source
    */
   private Map<String, List<CommonConverted>> classname2multiSources = new TreeMap<>();
-      
+
   /************************************
    * Reporting
    ************************************/
-//  private final List<Path> v2JCasFiles = new ArrayList<>();  // unused
-//  private final List<Path> v3JCasFiles = new ArrayList<>();  // unused
-  
-  private final List<PathContainerAndReason> nonJCasFiles = new ArrayList<>();  // path, reason
+  // private final List<Path> v2JCasFiles = new ArrayList<>(); // unused
+  // private final List<Path> v3JCasFiles = new ArrayList<>(); // unused
+
+  private final List<PathContainerAndReason> nonJCasFiles = new ArrayList<>(); // path, reason
   private final List<PathContainerAndReason> failedMigration = new ArrayList<>(); // path, reason
-  private final List<PathContainerAndReason> skippedBuiltins = new ArrayList<>();  // path, "built-in"
-  private final List<PathContainerAndReason> deletedCheckModified = new ArrayList<>();  // path, deleted check string
+  private final List<PathContainerAndReason> skippedBuiltins = new ArrayList<>(); // path,
+                                                                                  // "built-in"
+  private final List<PathContainerAndReason> deletedCheckModified = new ArrayList<>(); // path,
+                                                                                       // deleted
+                                                                                       // check
+                                                                                       // string
   private final List<String1AndString2> pathWorkaround = new ArrayList<>(); // original, workaround
   private final List<String1AndString2> pearClassReplace = new ArrayList<>(); // pear, classname
-  private final List<String1AndString2> jarClassReplace  = new ArrayList<>(); // jar, classname
-  
+  private final List<String1AndString2> jarClassReplace = new ArrayList<>(); // jar, classname
+
   private final List<PathContainerAndReason> manualInspection = new ArrayList<>(); // path, reason
-//  private final List<PathAndPath> embeddedJars = new ArrayList<>(); // source, temp   
-  
-  private boolean isV2JCas;  // false at start of migrate, set to true if a v2 class candidate is discovered
-  private boolean isConvert2v3;  // true at start of migrate, set to false if conversion fails, left true if already a v3
-  private boolean isBuiltinJCas; // false at start of migrate, set to true if a built-in class is discovered
-        
-  /************************************ 
-   * Context for visits    
+  // private final List<PathAndPath> embeddedJars = new ArrayList<>(); // source, temp
+
+  private boolean isV2JCas; // false at start of migrate, set to true if a v2 class candidate is
+                            // discovered
+  private boolean isConvert2v3; // true at start of migrate, set to false if conversion fails, left
+                                // true if already a v3
+  private boolean isBuiltinJCas; // false at start of migrate, set to true if a built-in class is
+                                 // discovered
+
+  /************************************
+   * Context for visits
    ************************************/
 
   /**
    * if non-null, we're inside the ast for a likely JCas getter or setter method
    */
-  private MethodDeclaration get_set_method; 
+  private MethodDeclaration get_set_method;
   private String featName;
   private boolean isGetter;
-  private boolean isArraySetter; 
+  private boolean isArraySetter;
 
   /**
    * the range name part for _getXXXValue.. calls
    */
   private Object rangeNamePart;
-  
+
   /**
    * the range name part for _getXXXValue.. calls without converting Ref to Feature
    */
   private String rangeNameV2Part;
-  
+
   /**
    * temp place to insert static final int feature declarations
    */
@@ -759,9 +843,8 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    * set if getAndProcessCasndidatesInContainer encounters a class where it cannot do the compile
    */
   private boolean unableToCompile;
-  
-  final private StringBuilder psb = new StringBuilder();
 
+  final private StringBuilder psb = new StringBuilder();
 
   public MigrateJCas() {
   }
@@ -769,16 +852,18 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
   public static void main(String[] args) {
     (new MigrateJCas()).run(args);
   }
-  
+
   /***********************************
    * Main
-   * @param args -
+   * 
+   * @param args
+   *          -
    ***********************************/
   void run(String[] args) {
     CommandLineParser clp = parseCommandArgs(args);
-    
+
     System.out.format("Output top directory: %s%n", outputDirectory);
-    
+
     // clear output dir
     FileUtils.deleteRecursive(new File(outputDirectory));
 
@@ -789,111 +874,107 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     } else {
       if (javaCompiler == null) {
         System.out.println("The migration tool cannot compile the migrated files, \n"
-            + "  because no Java compiler is available.\n"
-            + "  To make one available, run this tool using a Java JDK, not JRE");
-      } 
+                + "  because no Java compiler is available.\n"
+                + "  To make one available, run this tool using a Java JDK, not JRE");
+      }
       isOk = processRootsCollection("classes", classesRoots, clp);
     }
-    
-//    if (individualClasses != null) {
-//      processCollection("individual classes: ", new Iterator<String>() {
-//        Iterator<String> it = Arrays.asList(individualClasses.split(File.pathSeparator)).iterator();
-//        public boolean hasNext() {return it.hasNext();}
-//        public String next() {
-//          return prepareIndividual(it.next());}
-//      });
-//    }
-
-    if (error_decompiling) { 
+
+    // if (individualClasses != null) {
+    // processCollection("individual classes: ", new Iterator<String>() {
+    // Iterator<String> it = Arrays.asList(individualClasses.split(File.pathSeparator)).iterator();
+    // public boolean hasNext() {return it.hasNext();}
+    // public String next() {
+    // return prepareIndividual(it.next());}
+    // });
+    // }
+
+    if (error_decompiling) {
       isOk = false;
     }
-    
+
     isOk = report() && isOk;
-    
-    System.out.println("Migration finished " + 
-       (isOk 
-           ? "with no unusual conditions." 
-           : "with 1 or more unusual conditions that need manual checking."));
-  }
-  
-  
+
+    System.out.println("Migration finished " + (isOk ? "with no unusual conditions."
+            : "with 1 or more unusual conditions that need manual checking."));
+  }
+
   /**
-   * called for compiled input when a compiler is available and don't have name collision
-   *        if the container is a PEAR or a Jar
-   * Updates a copy of the Pear or Jar
+   * called for compiled input when a compiler is available and don't have name collision if the
+   * container is a PEAR or a Jar Updates a copy of the Pear or Jar
+   * 
    * @param container
    */
   private void postProcessPearOrJar(Container container) {
-    Path outDir = Paths.get(outputDirectory, 
-                            container.isJar ? "jars" : "pears",
-                            Integer.toString(container.id));
+    Path outDir = Paths.get(outputDirectory, container.isJar ? "jars" : "pears",
+            Integer.toString(container.id));
     withIOX(() -> Files.createDirectories(outDir));
     si(psb).append("Replacing .class files in copy of ").append(container.rootOrig);
     flush(psb);
     try {
       // copy the pear or jar so we don't change the original
       Path lastPartOfPath = container.rootOrig.getFileName();
-      if (null == lastPartOfPath) throw new RuntimeException("Internal Error");
-      Path pearOrJarCopy = Paths.get(outputDirectory,
-                                     container.isJar ? "jars" : "pears",
-                                     Integer.toString(container.id), 
-                                     lastPartOfPath.toString());
-     
-      Files.copy(container.rootOrig, pearOrJarCopy);    
+      if (null == lastPartOfPath)
+        throw new RuntimeException("Internal Error");
+      Path pearOrJarCopy = Paths.get(outputDirectory, container.isJar ? "jars" : "pears",
+              Integer.toString(container.id), lastPartOfPath.toString());
+
+      Files.copy(container.rootOrig, pearOrJarCopy);
 
       // put up a file system on the pear or jar
       FileSystem pfs = FileSystems.newFileSystem(pearOrJarCopy, (ClassLoader) null);
-    
+
       // replace the .class files in this PEAR or Jar with corresponding v3 ones
       indent[0] += 2;
-      String[] previousSkip = {""};
+      String[] previousSkip = { "" };
       container.v3CompiledPathAndContainerItemPath.forEach(c_p -> {
-            if (Files.exists(c_p.v3CompiledPath)) {
-              withIOX(() -> Files.copy(c_p.v3CompiledPath, pfs.getPath(c_p.pathInContainer), StandardCopyOption.REPLACE_EXISTING));
-              reportPearOrJarClassReplace(pearOrJarCopy.toString(), c_p.v3CompiledPath.toString(), container);
-            } else {
-              String pstr = c_p.v3CompiledPath.toString();
-              String pstr2 = pstr;
-              if (previousSkip[0] != "") {
-                int cmn = findFirstCharDifferent(previousSkip[0], pstr);
-                pstr2 = cmn > 5 
-                          ? ("..." + pstr.substring(cmn))
-                          : pstr;    
-              } 
-              previousSkip[0] = pstr;
-              si(psb).append("Skipping replacing ").append(pstr2)
-                     .append(" because it could not be found, perhaps due to compile errors.");
-              flush(psb);
-            }
-          });
+        if (Files.exists(c_p.v3CompiledPath)) {
+          withIOX(() -> Files.copy(c_p.v3CompiledPath, pfs.getPath(c_p.pathInContainer),
+                  StandardCopyOption.REPLACE_EXISTING));
+          reportPearOrJarClassReplace(pearOrJarCopy.toString(), c_p.v3CompiledPath.toString(),
+                  container);
+        } else {
+          String pstr = c_p.v3CompiledPath.toString();
+          String pstr2 = pstr;
+          if (previousSkip[0] != "") {
+            int cmn = findFirstCharDifferent(previousSkip[0], pstr);
+            pstr2 = cmn > 5 ? ("..." + pstr.substring(cmn)) : pstr;
+          }
+          previousSkip[0] = pstr;
+          si(psb).append("Skipping replacing ").append(pstr2)
+                  .append(" because it could not be found, perhaps due to compile errors.");
+          flush(psb);
+        }
+      });
       indent[0] -= 2;
-//      for (CommonConverted cc : container.convertedItems) {
-//        Map<Container, Path> v3ccs = cc.v3CompiledResultPaths;
-//        v3ccs.forEach((v3ccc, v3cc_path) ->
-//          {
-//            if (v3ccc == container) {
-//              String path_in_v3_classes = cc.v3CompiledResultPaths.get(container).toString();
-//              
-//              withIOX(() -> Files.copy(v3cc_path,  pfs.getPath(path_in_v3_classes)));
-//              reportPearOrJarClassReplace(pearOrJarCopy.toString(), path_in_v3_classes, container);
-//            }
-//          });
-//      }
-      
-      pfs.close();     
-      
+      // for (CommonConverted cc : container.convertedItems) {
+      // Map<Container, Path> v3ccs = cc.v3CompiledResultPaths;
+      // v3ccs.forEach((v3ccc, v3cc_path) ->
+      // {
+      // if (v3ccc == container) {
+      // String path_in_v3_classes = cc.v3CompiledResultPaths.get(container).toString();
+      //
+      // withIOX(() -> Files.copy(v3cc_path, pfs.getPath(path_in_v3_classes)));
+      // reportPearOrJarClassReplace(pearOrJarCopy.toString(), path_in_v3_classes, container);
+      // }
+      // });
+      // }
+
+      pfs.close();
+
     } catch (IOException e) {
       throw new RuntimeException(e);
     }
   }
-  
+
+  // @formatter:off
   /**
-   * Compile all the migrated JCas classes in this container, adjusting the classpath
-   * if the container is a Jar or Pear to include the Jar or PEAR.
+   * Compile all the migrated JCas classes in this container, adjusting the classpath if the
+   * container is a Jar or Pear to include the Jar or PEAR.
+   * 
+   * As a side effect, it saves in the container, a list of all the compiled things together with
+   * the path in container part, for use by a subsequent step to update copies of the jars/pears.
    * 
-   * As a side effect, it saves in the container, a list of all the compiled things together 
-   *   with the path in container part, for use by a subsequent step to update copies of the jars/pears.
-   *   
    * The items in the container are broken into batches of multiple classes to be compiled together.
    *   - The grouping is to group by alternative number.  This insures that multiple 
    *     definitions of the same class are done separately (otherwise the compiler complains 
@@ -905,26 +986,27 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    * @param container -
    * @return true if compiled 1 or more sources, false if nothing was compiled
    */
+  // @formatter:on
   private boolean compileV3SourcesCommon2(Container container) {
-    
+
     String classesBaseDir = outDirConverted + "v3-classes/" + container.id;
-    
-    // specify the classpath.  For PEARs use a class loader that loads first.
+
+    // specify the classpath. For PEARs use a class loader that loads first.
     String classpath = getCompileClassPath(container);
-    
-//    // debug
-//    String[] cpa = classpath.split(File.pathSeparator);
-//    System.out.println("debug - compilation classpath");
-//    int j = 0;
-//    for (String s : cpa) System.out.println("debug classpath: " + (++j) + " " + s);
-    
+
+    // // debug
+    // String[] cpa = classpath.split(File.pathSeparator);
+    // System.out.println("debug - compilation classpath");
+    // int j = 0;
+    // for (String s : cpa) System.out.println("debug classpath: " + (++j) + " " + s);
+
     // get a list of compilation unit path strings to the converted/v3/nnn/path
     /**
-     * containerRoot is
-     * rootOrig or for Jars/Pears the Path to "/" in the zip file system 
+     * containerRoot is rootOrig or for Jars/Pears the Path to "/" in the zip file system
      */
     Path containerRoot = null;
-         
+
+    // @formatter:off
     /**
      * The Cu Path Strings for one container might have multiple instances of the class.
      * These might be for identical or different sources. 
@@ -938,94 +1020,102 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
      *   different paths saying "duplicate class definition".  
      *   - Fix:  do compilation in batches, one for each different commonConverted id.   
      */
-    
-    Map<Integer, ArrayList<String>>  cu_path_strings_by_ccId = new TreeMap<>();  // tree map to have nice order of keys
-    
+    // @formatter:on
+    Map<Integer, ArrayList<String>> cu_path_strings_by_ccId = new TreeMap<>(); // tree map to have
+                                                                               // nice order of keys
+
     indent[0] += 2;
     boolean isEmpty = true;
     for (CommonConverted cc : container.convertedItems) {
-      if (cc.v3SourcePath == null) continue;  // skip items that failed migration
+      if (cc.v3SourcePath == null)
+        continue; // skip items that failed migration
       isEmpty = false;
-      // relativePathInContainer = the whole path with the first part (up to the end of the container root) stripped off
+      // relativePathInContainer = the whole path with the first part (up to the end of the
+      // container root) stripped off
       /**
-       * itemPath is the original path in the container to where the source or class file is
-       * For Jars and PEARs, it is relative to the Jar or PEAR
+       * itemPath is the original path in the container to where the source or class file is For
+       * Jars and PEARs, it is relative to the Jar or PEAR
        */
       Path itemPath = cc.getV2SourcePath(container);
       if (null == containerRoot) {
         // lazy setup on first call
         // for Pears, must use the == filesystem, otherwise get
-        //   ProviderMismatchException
-        containerRoot = (container.isJar || container.isPear) 
-            ? itemPath.getFileSystem().getPath("/")
-            : container.rootOrig;
+        // ProviderMismatchException
+        containerRoot = (container.isJar || container.isPear)
+                ? itemPath.getFileSystem().getPath("/")
+                : container.rootOrig;
       }
       /**
-       * relativePathInContainer might be x/y/z/a/b/c/name.class
-       * (ends in .class because we only get here when the input is class files)
+       * relativePathInContainer might be x/y/z/a/b/c/name.class (ends in .class because we only get
+       * here when the input is class files)
        */
       String relativePathInContainer = containerRoot.relativize(itemPath).toString();
-      
-      container.v3CompiledPathAndContainerItemPath.add(
-          new V3CompiledPathAndContainerItemPath(
-              Paths.get(classesBaseDir, "a" + cc.id, cc.fqcn_slash + ".class"  /*relativePathInContainer*/),
+
+      container.v3CompiledPathAndContainerItemPath.add(new V3CompiledPathAndContainerItemPath(
+              Paths.get(classesBaseDir, "a" + cc.id,
+                      cc.fqcn_slash + ".class" /* relativePathInContainer */),
               relativePathInContainer));
-      ArrayList<String> items = cu_path_strings_by_ccId.computeIfAbsent(cc.id, x -> new ArrayList<>());
+      ArrayList<String> items = cu_path_strings_by_ccId.computeIfAbsent(cc.id,
+              x -> new ArrayList<>());
       items.add(cc.v3SourcePath.toString());
     }
-    
+
     if (isEmpty) {
-      si(psb).append("Skipping compiling for container ").append(container.id).append(" ").append(container.rootOrig);
+      si(psb).append("Skipping compiling for container ").append(container.id).append(" ")
+              .append(container.rootOrig);
       si(psb).append("  because non of the v2 classes were migrated (might have been built-ins)");
       flush(psb);
       return false;
-    }
-    else { 
-      si(psb).append("Compiling for container ").append(container.id).append(" ").append(container.rootOrig);
+    } else {
+      si(psb).append("Compiling for container ").append(container.id).append(" ")
+              .append(container.rootOrig);
       flush(psb);
     }
-    
-//    List<String> cu_path_strings = container.convertedItems.stream()
-//        .filter(cc -> cc.v3SourcePath != null)
-//        .peek(cc -> container.v3CompiledPathAndContainerItemPath.add(
-//            new V3CompiledPathAndContainerItemPath(
-//                Paths.get(classesBaseDir, cc.v3SourcePath.toString()),
-//                getPathInContainer(container, cc).toString())))
-//        .map(cc -> cc.v3SourcePath.toString())
-//        .collect(Collectors.toList());
-    
+
+    // List<String> cu_path_strings = container.convertedItems.stream()
+    // .filter(cc -> cc.v3SourcePath != null)
+    // .peek(cc -> container.v3CompiledPathAndContainerItemPath.add(
+    // new V3CompiledPathAndContainerItemPath(
+    // Paths.get(classesBaseDir, cc.v3SourcePath.toString()),
+    // getPathInContainer(container, cc).toString())))
+    // .map(cc -> cc.v3SourcePath.toString())
+    // .collect(Collectors.toList());
+
     boolean resultOk = true;
-    
-    for (int ccId = 0;; ccId++) {  // do each version of classes separately
+
+    for (int ccId = 0;; ccId++) { // do each version of classes separately
       List<String> cups = cu_path_strings_by_ccId.get(ccId);
       if (cups == null) {
         break;
       }
-      
-      StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null, Charset.forName("UTF-8"));
-
-      Iterable<? extends JavaFileObject> compilationUnits = 
-          fileManager.getJavaFileObjectsFromStrings(cups);
-      
-//      //debug
-//      System.out.println("Debug: list of compilation unit strings for iteration " + i);
-//      int[] k = new int[] {0};
-//      cups.forEach(s -> System.out.println(Integer.toString(++(k[0])) + " " + s));
-//      System.out.println("debug end");  
-    
+
+      StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null,
+              Charset.forName("UTF-8"));
+
+      Iterable<? extends JavaFileObject> compilationUnits = fileManager
+              .getJavaFileObjectsFromStrings(cups);
+
+      // //debug
+      // System.out.println("Debug: list of compilation unit strings for iteration " + i);
+      // int[] k = new int[] {0};
+      // cups.forEach(s -> System.out.println(Integer.toString(++(k[0])) + " " + s));
+      // System.out.println("debug end");
+
       String classesBaseDirN = classesBaseDir + "/a" + ccId;
       withIOX(() -> Files.createDirectories(Paths.get(classesBaseDirN)));
       Iterable<String> options = Arrays.asList("-d", classesBaseDirN, "-classpath", classpath);
-  
-      si(psb).append("Compiling for commonConverted version ").append(ccId)
-             .append(", ").append(cups.size()).append(" classes");
+
+      si(psb).append("Compiling for commonConverted version ").append(ccId).append(", ")
+              .append(cups.size()).append(" classes");
       flush(psb);
       DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
 
-      /***********  Compile ***********/
-      resultOk = javaCompiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits).call() && resultOk;
+      /*********** Compile ***********/
+      resultOk = javaCompiler
+              .getTask(null, fileManager, diagnostics, options, null, compilationUnits).call()
+              && resultOk;
       /********************************/
-      
+
       indent[0] += 2;
       for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
         JavaFileObject s = diagnostic.getSource();
@@ -1044,19 +1134,18 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
         si(psb).append("  ").append(diagnostic.getMessage(null));
         flush(psb);
       }
-      withIOX( () -> fileManager.close());
+      withIOX(() -> fileManager.close());
       indent[0] -= 2;
-      si(psb).append("Compilation finished").append(
-          resultOk ? " with no errors." : "with some errors.");
+      si(psb).append("Compilation finished")
+              .append(resultOk ? " with no errors." : "with some errors.");
       flush(psb);
     }
     indent[0] -= 2;
     unableToCompile = !resultOk;
     return true;
   }
-  
-  
-  
+
+  // @formatter:off
   /**
    * The classpath used to compile is (in precedence order)
    *   - the classpath for this migration app  (first in order to pick up v3 support, overriding others)
@@ -1065,23 +1154,24 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    *   - passed in migrate classpath
    * @return the classpath to use in compiling the jcasgen'd sources
    */
+  // @formatter:on
   private String getCompileClassPath(Container container) {
- 
+
     // start with this (the v3migration tool) app's classpath to a cp string
     URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
     URL[] urls = systemClassLoader.getURLs();
     StringBuilder cp = new StringBuilder();
-    
+
     boolean firstTime = true;
     for (URL url : urls) {
-      if (! firstTime) {
+      if (!firstTime) {
         cp.append(File.pathSeparatorChar);
       } else {
         firstTime = false;
       }
       cp.append(url.getPath());
     }
-    
+
     // pears up the classpath, closest first
     Container c = container;
     while (c != null) {
@@ -1090,13 +1180,13 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       }
       c = c.parent;
     }
-    
+
     // add the migrateClasspath, expanded
-    
+
     if (null != migrateClasspath) {
       cp.append(File.pathSeparator).append(Misc.expandClasspath(migrateClasspath));
     }
- 
+
     // add the Jars, closest last
     c = container;
     List<String> ss = new ArrayList<>();
@@ -1108,45 +1198,44 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     }
     Collections.reverse(ss);
     ss.forEach(s -> cp.append(File.pathSeparator).append(s));
-        
-//    System.out.println("debug: compile classpath = " + cp.toString());
+
+    // System.out.println("debug: compile classpath = " + cp.toString());
     return cp.toString();
   }
-      
-  /** 
-   * iterate to process collections from all roots
-   * Called once, to process either sources or classes
+
+  /**
+   * iterate to process collections from all roots Called once, to process either sources or classes
+   * 
    * @return false if unable to compile, true otherwise
    */
   private boolean processRootsCollection(String kind, Container[] roots, CommandLineParser clp) {
     unableToCompile = false; // preinit
-    
+
     psb.setLength(0);
     indent[0] = 0;
     itemCount = 1;
 
-    
-    for (Container rootContainer : roots) { 
-      showWorkStart(rootContainer);      
-      
+    for (Container rootContainer : roots) {
+      showWorkStart(rootContainer);
+
       // adds candidates to root containers, and adds sub containers for Jars and Pears
       getAndProcessCandidatesInContainer(rootContainer);
-      
-//      for (Path path : rootContainer.candidates) {
-//        
-//        CommonConverted cc = getSource(path, rootContainer);
-//        migrate(cc, rootContainer, path);
-//        
-//        if ((i % 50) == 0) System.out.format("%4d%n    ", Integer.valueOf(i));
-//        i++;
-//      }
+
+      // for (Path path : rootContainer.candidates) {
+      //
+      // CommonConverted cc = getSource(path, rootContainer);
+      // migrate(cc, rootContainer, path);
+      //
+      // if ((i % 50) == 0) System.out.format("%4d%n ", Integer.valueOf(i));
+      // i++;
+      // }
     }
     si(psb).append("Total number of candidates processed: ").append(itemCount - 1);
     flush(psb);
     indent[0] = 0;
     return !unableToCompile;
   }
-  
+
   private void showWorkStart(Container rootContainer) {
     si(psb).append("Migrating " + rootContainer.rootOrig.toString());
     indent[0] += 2;
@@ -1158,10 +1247,12 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     si(psb).append("  nnn at the end of the line is the number of classes migrated\n");
     flush(psb);
   }
-    
+
   /**
    * parse command line args
-   * @param args - 
+   * 
+   * @param args
+   *          -
    * @return the CommandLineParser instance
    */
   private CommandLineParser parseCommandArgs(String[] args) {
@@ -1175,18 +1266,18 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       printUsage();
       System.exit(2);
     }
-    
+
     if (clp.isInArgsList(CLASS_FILE_ROOTS)) {
       classesRoots = getRoots(clp, CLASS_FILE_ROOTS);
     }
-    
+
     if (clp.isInArgsList(SOURCE_FILE_ROOTS)) {
       sourcesRoots = getRoots(clp, SOURCE_FILE_ROOTS);
     }
-    
+
     return clp;
   }
-    
+
   private Container[] getRoots(CommandLineParser clp, String kind) {
     String[] paths = clp.getParamArgument(kind).split("\\" + File.pathSeparator);
     Container[] cs = new Container[paths.length];
@@ -1196,23 +1287,25 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     }
     return cs;
   }
-  
+
   /**
-   * @param p the path to the compiled or non-compiled source
-   * @param container the container
-   * @return the instance of the CommonConverted object, 
-   *         and update the container's convertedItems list if needed to include it
-   */ 
+   * @param p
+   *          the path to the compiled or non-compiled source
+   * @param container
+   *          the container
+   * @return the instance of the CommonConverted object, and update the container's convertedItems
+   *         list if needed to include it
+   */
   private CommonConverted getSource(Path p, Container container) {
     try {
       byte[] localV2ByteCode = null;
-      
+
       CommonConverted cc;
       String v2Source;
-      
+
       if (!isSource) {
         localV2ByteCode = Files.readAllBytes(p);
-        
+
         // only use prev decompiled if same container
         cc = container.origBytesToCommonConverted.get(localV2ByteCode);
         if (null != cc) {
@@ -1230,37 +1323,40 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
           System.err.println("Candidate with bad Class Name is: " + p.toString());
           return null;
         }
-        final byte[] finalbc = localV2ByteCode;  
-        cc = sourceToCommonConverted.computeIfAbsent(v2Source, 
+        final byte[] finalbc = localV2ByteCode;
+        cc = sourceToCommonConverted.computeIfAbsent(v2Source,
                 src -> new CommonConverted(src, finalbc, p, container, packageAndClassNameSlash));
-//        cc = new CommonConverted(v2Source, localV2ByteCode, p, container, packageAndClassNameSlash);
+        // cc = new CommonConverted(v2Source, localV2ByteCode, p, container,
+        // packageAndClassNameSlash);
         container.origBytesToCommonConverted.put(localV2ByteCode, cc);
       } else {
-        
+
         v2Source = FileUtils.reader2String(Files.newBufferedReader(p));
         cc = sourceToCommonConverted.get(v2Source);
         if (null == cc) {
           cc = new CommonConverted(v2Source, null, p, container, "unknown");
-          sourceToCommonConverted.put(v2Source,  cc);
+          sourceToCommonConverted.put(v2Source, cc);
         } else {
-          // add this new path + container to set of pathsAndContainers kept by this CommonConverted object
-          cc.containersAndV2Paths.add(new ContainerAndPath(p, container));  
+          // add this new path + container to set of pathsAndContainers kept by this CommonConverted
+          // object
+          cc.containersAndV2Paths.add(new ContainerAndPath(p, container));
         }
       }
 
-      //Containers have list of CommonConverted, which, in turn 
-      //             have Set of ContainerAndPath elements.
-      //               (the same JCas class might appear in two different paths in a container)
+      // Containers have list of CommonConverted, which, in turn
+      // have Set of ContainerAndPath elements.
+      // (the same JCas class might appear in two different paths in a container)
       if (!container.convertedItems.contains(cc)) {
         container.convertedItems.add(cc);
       }
-      
-      return cc;      
+
+      return cc;
     } catch (IOException e) {
       throw new RuntimeException(e);
     }
   }
-  
+
+  // @formatter:off
   /**
    * Migrate one JCas definition, writes to Sysem.out 1 char to indicate progress.
    * 
@@ -1291,16 +1387,17 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    *   
    * @param source - the source, either directly from a .java file, or a decompiled .class file
    */
+  // @formatter:on
   private void migrate(CommonConverted cc, Container container, Path path) {
-    
+
     if (null == cc) {
       System.err.println("Skipping this component due to decompile failure: " + path.toString());
       System.err.println("  in container: " + container);
-      isConvert2v3 = false;  
-      error_decompiling  = true;
+      isConvert2v3 = false;
+      error_decompiling = true;
       return;
     }
-    
+
     if (cc.v3Source != null) {
       // next updates classname2multiSources for tracking non-identical defs
       boolean identical = collectInfoForReports(cc);
@@ -1310,38 +1407,42 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       cc.containersAndV2Paths.add(new ContainerAndPath(path, container));
       return;
     }
-     
+
     assert cc.v2Source != null;
 
     packageName = null;
     className = null;
     packageAndClassNameSlash = null;
     cu = null;
-    
+
     String source = cc.v2Source;
-    isConvert2v3 = true;  // preinit, set false if convert fails
-    isV2JCas = false;     // preinit, set true by reportV2Class, called by visit to ClassOrInterfaceDeclaration,
-                          //   when it has v2 constructors, and the right type and type_index_id field declares
+    isConvert2v3 = true; // preinit, set false if convert fails
+    isV2JCas = false; // preinit, set true by reportV2Class, called by visit to
+                      // ClassOrInterfaceDeclaration,
+                      // when it has v2 constructors, and the right type and type_index_id field
+                      // declares
     isBuiltinJCas = false;
     featNames.clear();
     fi_fields.clear();
-    
-    try {  // to reset the next 3 items
+
+    try { // to reset the next 3 items
       current_cc = cc;
       current_container = container;
       current_path = path;
-        
-    //    System.out.println("Migrating source before migration:\n");
-    //    System.out.println(source);
-    //    System.out.println("\n\n\n");
+
+      // System.out.println("Migrating source before migration:\n");
+      // System.out.println(source);
+      // System.out.println("\n\n\n");
       if (source.startsWith(ERROR_DECOMPILING)) {
-        System.err.println("Decompiling failed for class: " + cc.toString() + "\n got: " + Misc.elide(source, 300, false));
+        System.err.println("Decompiling failed for class: " + cc.toString() + "\n got: "
+                + Misc.elide(source, 300, false));
         System.err.println("Please check the migrateClasspath");
         if (null == migrateClasspath) {
           System.err.println("classpath of this app is");
           System.err.println(System.getProperty("java.class.path"));
         } else {
-          System.err.println(" first part of migrateClasspath argument was: " + Misc.elide(migrateClasspath, 300, false));
+          System.err.println(" first part of migrateClasspath argument was: "
+                  + Misc.elide(migrateClasspath, 300, false));
           System.err.println("  Value used was:");
           URL[] urls = Misc.classpath2urls(migrateClasspath);
           for (URL url : urls) {
@@ -1349,28 +1450,29 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
           }
         }
         System.err.println("Skipping this component");
-        isConvert2v3 = false;  
-        error_decompiling  = true;
+        isConvert2v3 = false;
+        error_decompiling = true;
         return;
       }
-        
+
       StringReader sr = new StringReader(source);
       try {
-        cu = JavaParser.parse(sr); 
-              
+        cu = JavaParser.parse(sr);
+
         addImport("java.lang.invoke.CallSite");
         addImport("java.lang.invoke.MethodHandle");
         addImport("org.apache.uima.cas.impl.CASImpl");
         addImport("org.apache.uima.cas.impl.TypeImpl");
         addImport("org.apache.uima.cas.impl.TypeSystemImpl");
-        
-        this.visit(cu, null);    // side effect: sets the className, packageAndClassNameSlash, packageName  
-        
+
+        this.visit(cu, null); // side effect: sets the className, packageAndClassNameSlash,
+                              // packageName
+
         new removeEmptyStmts().visit(cu, null);
         if (isConvert2v3) {
           removeImport("org.apache.uima.jcas.cas.TOP_Type");
         }
-        
+
         if (isConvert2v3 && fi_fields.size() > 0) {
           NodeList<BodyDeclaration<?>> classMembers = cu.getTypes().get(0).getMembers();
           int positionOfFirstConstructor = findConstructor(classMembers);
@@ -1379,15 +1481,13 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
           }
           classMembers.addAll(positionOfFirstConstructor, fi_fields);
         }
-        
+
         ImportDeclaration firstImport = cu.getImports().get(0);
-        String transformedMessage = String.format(" Migrated by uimaj-v3-migration-jcas, %s%n" +
-                                  " Container: %s%n" + 
-                                  " Path in container: %s%n",
-                                  new Date(),
-                                  container.toString1(),
-                                  path.toString()).replace('\\','/'); 
-        
+        String transformedMessage = String.format(
+                " Migrated by uimaj-v3-migration-jcas, %s%n" + " Container: %s%n"
+                        + " Path in container: %s%n",
+                new Date(), container.toString1(), path.toString()).replace('\\', '/');
+
         Optional<Comment> existingComment = firstImport.getComment();
         if (existingComment.isPresent()) {
           Comment comment = existingComment.get();
@@ -1395,27 +1495,26 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
         } else {
           firstImport.setBlockComment(transformedMessage);
         }
-                
+
         if (isSource) {
           sourceToCommonConverted.put(source, cc);
-        } 
-  
+        }
+
         boolean identicalFound = collectInfoForReports(cc);
-        assert ! identicalFound;
-  
-        if (isV2JCas) { 
+        assert !identicalFound;
+
+        if (isV2JCas) {
           writeV2Orig(cc, isConvert2v3);
         }
         if (isConvert2v3) {
           cc.v3Source = new PrettyPrinter(printCu).print(cu);
-          writeV3(cc);  
+          writeV3(cc);
         }
-        
-        psb.append(isBuiltinJCas 
-                     ? "b" 
-                     : (classname2multiSources.get(cc.fqcn_slash).size() == 1)
-                         ? "."
-                         : "d");  // means non-identical duplicate
+
+        psb.append(isBuiltinJCas ? "b"
+                : (classname2multiSources.get(cc.fqcn_slash).size() == 1) ? "." : "d"); // means
+                                                                                        // non-identical
+                                                                                        // duplicate
         flush(psb);
       } catch (IOException e) {
         e.printStackTrace();
@@ -1432,60 +1531,61 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
   }
 
   /**
-   * Called when have already converted this exact source or
-   *   when we just finished converting this source.
-   * Add this instance to the tracking information for multiple versions (identical or not) of a class
+   * Called when have already converted this exact source or when we just finished converting this
+   * source. Add this instance to the tracking information for multiple versions (identical or not)
+   * of a class
+   * 
    * @return true if this is an identical duplicate of one already done
    */
-  
+
   private boolean collectInfoForReports(CommonConverted cc) {
     String fqcn_slash = cc.fqcn_slash;
-    
+
     // track, by fqcn, all duplicates (identical or not)
-    
-//    // for a given fully qualified class name (slashified), 
-//    //   find the list of CommonConverteds - one per each different version
-//    //     create it if null
-    List<CommonConverted> commonConverteds = classname2multiSources
-        .computeIfAbsent(fqcn_slash, k -> new ArrayList<>());
+
+    // // for a given fully qualified class name (slashified),
+    // // find the list of CommonConverteds - one per each different version
+    // // create it if null
+    List<CommonConverted> commonConverteds = classname2multiSources.computeIfAbsent(fqcn_slash,
+            k -> new ArrayList<>());
 
     // search to see if this instance already in the set
-    //   if so, add the path to the set of identicals
+    // if so, add the path to the set of identicals
     // For class sources case, we compare the decompiled version
     boolean found = commonConverteds.contains(cc);
     if (!found) {
       commonConverteds.add(cc);
-    }  
-    
+    }
+
     return found;
   }
-    
+
   /******************
-   *  Visitors
+   * Visitors
    ******************/
   /**
-   * Capture the type name from all top-level types
-   *   AnnotationDeclaration, Empty, and Enum
+   * Capture the type name from all top-level types AnnotationDeclaration, Empty, and Enum
    */
-  
+
   @Override
   public void visit(AnnotationDeclaration n, Object ignore) {
     updateClassName(n);
-    super.visit(n,  ignore);
+    super.visit(n, ignore);
   }
 
-//  @Override
-//  public void visit(EmptyTypeDeclaration n, Object ignore) {
-//    updateClassName(n);
-//    super.visit(n,  ignore);
-//  }
+  // @Override
+  // public void visit(EmptyTypeDeclaration n, Object ignore) {
+  // updateClassName(n);
+  // super.visit(n, ignore);
+  // }
 
   @Override
   public void visit(EnumDeclaration n, Object ignore) {
     updateClassName(n);
-    super.visit(n,  ignore);
+    super.visit(n, ignore);
   }
 
+  // @formatter:off
   /**
    * Check if the top level class looks like a JCas class, and report if not:
    *   has 0, 1, and 2 element constructors
@@ -1499,10 +1599,11 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    * @param n -
    * @param ignore -
    */
+  // @formatter:on
   @Override
   public void visit(ClassOrInterfaceDeclaration n, Object ignore) {
     // do checks to see if this is a JCas class; if not report skipped
-   
+
     Optional<Node> maybeParent = n.getParentNode();
     if (maybeParent.isPresent()) {
       Node parent = maybeParent.get();
@@ -1517,14 +1618,14 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
         if (supers == null || supers.size() == 0) {
           reportNotJCasClass("class doesn't extend a superclass");
           super.visit(n, ignore);
-          return; 
+          return;
         }
-        
+
         NodeList<BodyDeclaration<?>> members = n.getMembers();
         setHasJCasConstructors(members);
         if (hasV2Constructors && hasTypeFields(members)) {
           reportV2Class();
-          super.visit(n,  ignore);
+          super.visit(n, ignore);
           return;
         }
         if (hasV2Constructors) {
@@ -1536,63 +1637,68 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
           return;
         }
         reportNotJCasClass("missing v2 constructors");
-        return;        
+        return;
       }
     }
-    
-    super.visit(n,  ignore);
+
+    super.visit(n, ignore);
     return;
-    
+
   }
-  
+
   @Override
   public void visit(PackageDeclaration n, Object ignored) {
     packageName = n.getNameAsString();
     super.visit(n, ignored);
   }
-    
+
   /***************
-   * Constructors
-   *   - modify the 2 arg constructor - changing the args and the body
-   * @param n - the constructor node
-   * @param ignored -
+   * Constructors - modify the 2 arg constructor - changing the args and the body
+   * 
+   * @param n
+   *          - the constructor node
+   * @param ignored
+   *          -
    */
   @Override
   public void visit(ConstructorDeclaration n, Object ignored) {
-    super.visit(n, ignored);  // processes the params 
-    if (!isConvert2v3) {  // for enums, annotations
+    super.visit(n, ignored); // processes the params
+    if (!isConvert2v3) { // for enums, annotations
       return;
     }
     List<Parameter> ps = n.getParameters();
-    
-    if (ps.size() == 2 && 
-        getParmTypeName(ps, 0).equals("int") &&
-        getParmTypeName(ps, 1).equals("TOP_Type")) {
-        
-      /** public Foo(TypeImpl type, CASImpl casImpl) {
-       *   super(type, casImpl);
-       *   readObject();
+
+    if (ps.size() == 2 && getParmTypeName(ps, 0).equals("int")
+            && getParmTypeName(ps, 1).equals("TOP_Type")) {
+
+      /**
+       * public Foo(TypeImpl type, CASImpl casImpl) { super(type, casImpl); readObject();
        */
       setParameter(ps, 0, "TypeImpl", "type");
       setParameter(ps, 1, "CASImpl", "casImpl");
-      
+
       // Body: change the 1st statement (must be super)
       NodeList<Statement> stmts = n.getBody().getStatements();
       if (!(stmts.get(0) instanceof ExplicitConstructorInvocationStmt)) {
         recordBadConstructor("missing super call");
         return;
       }
-      NodeList<Expression> args = ((ExplicitConstructorInvocationStmt)(stmts.get(0))).getArguments();
+      NodeList<Expression> args = ((ExplicitConstructorInvocationStmt) (stmts.get(0)))
+              .getArguments();
       args.set(0, new NameExpr("type"));
-      args.set(1,  new NameExpr("casImpl"));
-     
+      args.set(1, new NameExpr("casImpl"));
+
       // leave the rest unchanged.
-    }      
+    }
   }
 
-  private final static Pattern refGetter = Pattern.compile("(ll_getRef(Array)?Value)|"
-      +                                                    "(ll_getFSForRef)");
-  private final static Pattern word1 = Pattern.compile("\\A(\\w*)");  // word chars starting at beginning \\A means beginning
+  private final static Pattern refGetter = Pattern
+          .compile("(ll_getRef(Array)?Value)|" + "(ll_getFSForRef)");
+  private final static Pattern word1 = Pattern.compile("\\A(\\w*)"); // word chars starting at
+                                                                     // beginning \\A means
+                                                                     // beginning
+
+  // @formatter:off
   /*****************************
    * Method Declaration Visitor
    *   Heuristic to determine if a feature getter or setter:
@@ -1606,45 +1712,53 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    *   Workaround for decompiler - getters which return FSs might be missing the cast to the return value type
    *     
    *****************************/
+  // @formatter:on
   @Override
   public void visit(MethodDeclaration n, Object ignore) {
     String name = n.getNameAsString();
     isGetter = isArraySetter = false;
-    do {  // to provide break exit
-      
-      if (name.length() >= 4 && 
-          ((isGetter = name.startsWith("get")) || name.startsWith("set")) &&
-          Character.isUpperCase(name.charAt(3)) &&
-          !name.equals("getTypeIndexID")) {
+    do { // to provide break exit
+
+      if (name.length() >= 4 && ((isGetter = name.startsWith("get")) || name.startsWith("set"))
+              && Character.isUpperCase(name.charAt(3)) && !name.equals("getTypeIndexID")) {
         List<Parameter> ps = n.getParameters();
         if (isGetter) {
-          if (ps.size() > 1) break;
+          if (ps.size() > 1)
+            break;
         } else { // is setter
-          if (ps.size() > 2 || 
-              ps.size() == 0) break;
+          if (ps.size() > 2 || ps.size() == 0)
+            break;
           if (ps.size() == 2) {
-            if (!getParmTypeName(ps, 0).equals("int")) break;
+            if (!getParmTypeName(ps, 0).equals("int"))
+              break;
             isArraySetter = true;
-          } 
+          }
         }
-        
+
         // get the range-part-name and convert to v3 range ("Ref" changes to "Feature")
         String bodyString = n.getBody().get().toString(printWithoutComments);
         int i = bodyString.indexOf("jcasType.ll_cas.ll_");
-        if (i < 0) break; 
-        String s = bodyString.substring(i + "jcasType.ll_cas.ll_get".length()); // also for ...ll_set - same length!
+        if (i < 0)
+          break;
+        String s = bodyString.substring(i + "jcasType.ll_cas.ll_get".length()); // also for
+                                                                                // ...ll_set - same
+                                                                                // length!
         if (s.startsWith("FSForRef(")) { // then it's the wrapper and the wrong instance.
           i = s.indexOf("jcasType.ll_cas.ll_");
           if (i < 0) {
-            reportUnrecognizedV2Code("Found \"jcasType.ll_cas.ll_[set or get]...FSForRef(\" but didn't find following \"jcasType.ll_cas_ll_\"\n" + n.toString());
+            reportUnrecognizedV2Code(
+                    "Found \"jcasType.ll_cas.ll_[set or get]...FSForRef(\" but didn't find following \"jcasType.ll_cas_ll_\"\n"
+                            + n.toString());
             break;
           }
           s = s.substring(i + "jcasType.ll_cas.ll_get".length());
         }
         i = s.indexOf("Value");
         if (i < 0) {
-          reportUnrecognizedV2Code("Found \"jcasType.ll_cas.ll_[set or get]\" but didn't find following \"Value\"\n" + n.toString());
-          break;  // give up
+          reportUnrecognizedV2Code(
+                  "Found \"jcasType.ll_cas.ll_[set or get]\" but didn't find following \"Value\"\n"
+                          + n.toString());
+          break; // give up
         }
         s = Character.toUpperCase(s.charAt(0)) + s.substring(1, i);
         rangeNameV2Part = s;
@@ -1656,69 +1770,78 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
           reportUnrecognizedV2Code("Didn't find \"...jcasType).casFeatCode_\"\n" + n.toString());
           break;
         }
-        Matcher m = word1.matcher(bodyString.substring(i + "jcasType).casFeatCode_".length() ));
+        Matcher m = word1.matcher(bodyString.substring(i + "jcasType).casFeatCode_".length()));
         if (!m.find()) {
-          reportUnrecognizedV2Code("Found \"...jcasType).casFeatCode_\" but didn't find subsequent word\n" + n.toString());
+          reportUnrecognizedV2Code(
+                  "Found \"...jcasType).casFeatCode_\" but didn't find subsequent word\n"
+                          + n.toString());
           break;
         }
         featName = m.group(1);
         String fromMethod = Character.toLowerCase(name.charAt(3)) + name.substring(4);
         if (!featName.equals(fromMethod)) {
           // don't report if the only difference is the first letter captialization
-          if (!(Character.toLowerCase(featName.charAt(0)) + featName.substring(1)).equals(fromMethod)) {
+          if (!(Character.toLowerCase(featName.charAt(0)) + featName.substring(1))
+                  .equals(fromMethod)) {
             reportMismatchedFeatureName(String.format("%-25s %s", featName, name));
           }
         }
         // add _FI_xxx = TypeSystemImpl.getAdjustedFeatureOffset("xxx");
         // replaced Sept 2017
-//        NodeList<Expression> args = new NodeList<>();
-//        args.add(new StringLiteralExpr(featName));
-//        VariableDeclarator vd = new VariableDeclarator(
-//            intType, 
-//            "_FI_" + featName, 
-//            new MethodCallExpr(new NameExpr("TypeSystemImpl"), new SimpleName("getAdjustedFeatureOffset"), args));
-//        if (featNames.add(featName)) {  // returns true if it was added, false if already in the set of featNames
-//          fi_fields.add(new FieldDeclaration(public_static_final, vd));
-//        }
-        
+        // NodeList<Expression> args = new NodeList<>();
+        // args.add(new StringLiteralExpr(featName));
+        // VariableDeclarator vd = new VariableDeclarator(
+        // intType,
+        // "_FI_" + featName,
+        // new MethodCallExpr(new NameExpr("TypeSystemImpl"), new
+        // SimpleName("getAdjustedFeatureOffset"), args));
+        // if (featNames.add(featName)) { // returns true if it was added, false if already in the
+        // set of featNames
+        // fi_fields.add(new FieldDeclaration(public_static_final, vd));
+        // }
+
         // add _FC_xxx = TypeSystemImpl.createCallSite(ccc.class, "xxx");
         // add _FH_xxx = _FC_xxx.dynamicInvoker();
-        // add _FeatName_xxx = "xxx"  //  https://issues.apache.org/jira/browse/UIMA-5575
-        
-        if (featNames.add(featName)) {  // returns true if it was added, false if already in the set of featNames
+        // add _FeatName_xxx = "xxx" // https://issues.apache.org/jira/browse/UIMA-5575
+
+        if (featNames.add(featName)) { // returns true if it was added, false if already in the set
+                                       // of featNames
           // _FC_xxx = TypeSystemImpl.createCallSite(ccc.class, "xxx");
-          MethodCallExpr initCallSite = new MethodCallExpr(new NameExpr("TypeSystemImpl"), "createCallSite");
+          MethodCallExpr initCallSite = new MethodCallExpr(new NameExpr("TypeSystemImpl"),
+                  "createCallSite");
           initCallSite.addArgument(new FieldAccessExpr(new NameExpr(className), "class"));
           initCallSite.addArgument(new StringLiteralExpr(featName));
-          VariableDeclarator vd_FC = new VariableDeclarator(callSiteType, "_FC_" + featName, initCallSite);
+          VariableDeclarator vd_FC = new VariableDeclarator(callSiteType, "_FC_" + featName,
+                  initCallSite);
           fi_fields.add(new FieldDeclaration(private_static_final, vd_FC));
-          
+
           // _FH_xxx = _FC_xxx.dynamicInvoker();
-          MethodCallExpr initInvoker = new MethodCallExpr(new NameExpr(vd_FC.getName()), "dynamicInvoker");
-          VariableDeclarator vd_FH = new VariableDeclarator(methodHandleType, "_FH_" + featName, initInvoker);
+          MethodCallExpr initInvoker = new MethodCallExpr(new NameExpr(vd_FC.getName()),
+                  "dynamicInvoker");
+          VariableDeclarator vd_FH = new VariableDeclarator(methodHandleType, "_FH_" + featName,
+                  initInvoker);
           fi_fields.add(new FieldDeclaration(private_static_final, vd_FH));
-          
-          // _FeatName_xxx = "xxx"  //  https://issues.apache.org/jira/browse/UIMA-5575
-          VariableDeclarator vd_fn = new VariableDeclarator(stringType, "_FeatName_" + featName, new StringLiteralExpr(featName));
+
+          // _FeatName_xxx = "xxx" // https://issues.apache.org/jira/browse/UIMA-5575
+          VariableDeclarator vd_fn = new VariableDeclarator(stringType, "_FeatName_" + featName,
+                  new StringLiteralExpr(featName));
           fi_fields.add(new FieldDeclaration(public_static_final, vd_fn));
-           
+
         }
-        
+
         /**
-         * add missing cast stmt for
-         * return stmts where the value being returned:
-         *   - doesn't have a cast already
-         *   - has the expression be a methodCallExpr with a name which looks like:
-         *       ll_getRefValue or 
-         *       ll_getRefArrayValue  
+         * add missing cast stmt for return stmts where the value being returned: - doesn't have a
+         * cast already - has the expression be a methodCallExpr with a name which looks like:
+         * ll_getRefValue or ll_getRefArrayValue
          */
         if (isGetter && "Feature".equals(rangeNamePart)) {
           for (Statement stmt : n.getBody().get().getStatements()) {
             if (stmt instanceof ReturnStmt) {
-              Expression e = getUnenclosedExpr(((ReturnStmt)stmt).getExpression().get());
+              Expression e = getUnenclosedExpr(((ReturnStmt) stmt).getExpression().get());
               if ((e instanceof MethodCallExpr)) {
-                String methodName = ((MethodCallExpr)e).getNameAsString();
-                if (refGetter.matcher(methodName).matches()) { // ll_getRefValue or ll_getRefArrayValue
+                String methodName = ((MethodCallExpr) e).getNameAsString();
+                if (refGetter.matcher(methodName).matches()) { // ll_getRefValue or
+                                                               // ll_getRefArrayValue
                   addCastExpr(stmt, n.getType());
                 }
               }
@@ -1726,176 +1849,183 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
           }
         }
 
-        get_set_method = n; // used as a flag during inner "visits" to signal  
+        get_set_method = n; // used as a flag during inner "visits" to signal
                             // we're inside a likely feature setter/getter
 
       } // end of test for getter or setter method
-    } while (false);  // do once, provide break exit
-    
+    } while (false); // do once, provide break exit
+
     super.visit(n, ignore);
     get_set_method = null; // after visiting, reset the get_set_method to null
   }
-    
+
   /**
-   * Visitor for if stmts
-   *   - removes feature missing test
+   * Visitor for if stmts - removes feature missing test
    */
   @Override
   public void visit(IfStmt n, Object ignore) {
     do {
-      // if (get_set_method == null) break;  // sometimes, these occur outside of recogn. getters/setters
-      
+      // if (get_set_method == null) break; // sometimes, these occur outside of recogn.
+      // getters/setters
+
       Expression c = n.getCondition(), e;
-      BinaryExpr be, be2; 
+      BinaryExpr be, be2;
       List<Statement> stmts;
-      if ((c instanceof BinaryExpr) &&
-          ((be = (BinaryExpr)c).getLeft() instanceof FieldAccessExpr) &&
-          ((FieldAccessExpr)be.getLeft()).getNameAsString().equals("featOkTst")) {
+      if ((c instanceof BinaryExpr) && ((be = (BinaryExpr) c).getLeft() instanceof FieldAccessExpr)
+              && ((FieldAccessExpr) be.getLeft()).getNameAsString().equals("featOkTst")) {
         // remove the feature missing if statement
-        
-        // verify the remaining form 
-        if (! (be.getRight() instanceof BinaryExpr) 
-         || ! ((be2 = (BinaryExpr)be.getRight()).getRight() instanceof NullLiteralExpr) 
-         || ! (be2.getLeft() instanceof FieldAccessExpr)
-
-         || ! ((e = getExpressionFromStmt(n.getThenStmt())) instanceof MethodCallExpr)
-         || ! (((MethodCallExpr)e).getNameAsString()).equals("throwFeatMissing")) {
+
+        // verify the remaining form
+        if (!(be.getRight() instanceof BinaryExpr)
+                || !((be2 = (BinaryExpr) be.getRight()).getRight() instanceof NullLiteralExpr)
+                || !(be2.getLeft() instanceof FieldAccessExpr)
+
+                || !((e = getExpressionFromStmt(n.getThenStmt())) instanceof MethodCallExpr)
+                || !(((MethodCallExpr) e).getNameAsString()).equals("throwFeatMissing")) {
           reportDeletedCheckModified("The featOkTst was modified:\n" + n.toString() + '\n');
         }
-              
+
         BlockStmt parent = (BlockStmt) n.getParentNode().get();
         stmts = parent.getStatements();
-        stmts.set(stmts.indexOf(n), new EmptyStmt()); //dont remove
-                                            // otherwise iterators fail
-//        parent.getStmts().remove(n);
+        stmts.set(stmts.indexOf(n), new EmptyStmt()); // dont remove
+        // otherwise iterators fail
+        // parent.getStmts().remove(n);
         return;
       }
     } while (false);
-    
-    super.visit(n,  ignore);
+
+    super.visit(n, ignore);
   }
-  /** 
+
+  /**
    * visitor for method calls
    */
   @Override
   public void visit(MethodCallExpr n, Object ignore) {
-    Optional<Node> p1, p2, p3 = null; 
+    Optional<Node> p1, p2, p3 = null;
     Node updatedNode = null;
     NodeList<Expression> args;
-    
+
     do {
-      if (get_set_method == null) break;
-     
+      if (get_set_method == null)
+        break;
+
       /** remove checkArraybounds statement **/
-      if (n.getNameAsString().equals("checkArrayBounds") &&
-          ((p1 = n.getParentNode()).isPresent() && p1.get() instanceof ExpressionStmt) &&
-          ((p2 = p1.get().getParentNode()).isPresent() && p2.get() instanceof BlockStmt) &&
-          ((p3 = p2.get().getParentNode()).isPresent() && p3.get() == get_set_method)) {
-        NodeList<Statement> stmts = ((BlockStmt)p2.get()).getStatements();
+      if (n.getNameAsString().equals("checkArrayBounds")
+              && ((p1 = n.getParentNode()).isPresent() && p1.get() instanceof ExpressionStmt)
+              && ((p2 = p1.get().getParentNode()).isPresent() && p2.get() instanceof BlockStmt)
+              && ((p3 = p2.get().getParentNode()).isPresent() && p3.get() == get_set_method)) {
+        NodeList<Statement> stmts = ((BlockStmt) p2.get()).getStatements();
         stmts.set(stmts.indexOf(p1.get()), new EmptyStmt());
         return;
       }
-           
+
       // convert simpleCore expression ll_get/setRangeValue
       boolean useGetter = isGetter || isArraySetter;
-      if (n.getNameAsString().startsWith("ll_" + (useGetter ? "get" : "set") + rangeNameV2Part + "Value")) {
+      if (n.getNameAsString()
+              .startsWith("ll_" + (useGetter ? "get" : "set") + rangeNameV2Part + "Value")) {
         args = n.getArguments();
-        if (args.size() != (useGetter ? 2 : 3)) break;
+        if (args.size() != (useGetter ? 2 : 3))
+          break;
         String suffix = useGetter ? "Nc" : rangeNamePart.equals("Feature") ? "NcWj" : "Nfc";
-        String methodName = "_" + (useGetter ? "get" : "set") + rangeNamePart + "Value" + suffix; 
-        args.remove(0);    // remove the old addr arg
-        // arg 0 converted when visiting args FieldAccessExpr 
+        String methodName = "_" + (useGetter ? "get" : "set") + rangeNamePart + "Value" + suffix;
+        args.remove(0); // remove the old addr arg
+        // arg 0 converted when visiting args FieldAccessExpr
         n.setScope(null);
         n.setName(methodName);
       }
-      
+
       // convert array sets/gets
       String z = "ll_" + (isGetter ? "get" : "set");
       String nname = n.getNameAsString();
-      if (nname.startsWith(z) &&
-          nname.endsWith("ArrayValue")) {
-        
+      if (nname.startsWith(z) && nname.endsWith("ArrayValue")) {
+
         String s = nname.substring(z.length());
-        s = s.substring(0,  s.length() - "Value".length()); // s = "ShortArray",  etc.
-        if (s.equals("RefArray")) s = "FSArray";
-        if (s.equals("IntArray")) s = "IntegerArray";
+        s = s.substring(0, s.length() - "Value".length()); // s = "ShortArray", etc.
+        if (s.equals("RefArray"))
+          s = "FSArray";
+        if (s.equals("IntArray"))
+          s = "IntegerArray";
         EnclosedExpr ee = new EnclosedExpr(
-            new CastExpr(new ClassOrInterfaceType(s), n.getArguments().get(0)));
-        
-        n.setScope(ee);    // the getter for the array fs
+                new CastExpr(new ClassOrInterfaceType(s), n.getArguments().get(0)));
+
+        n.setScope(ee); // the getter for the array fs
         n.setName(isGetter ? "get" : "set");
         n.getArguments().remove(0);
       }
-      
+
       /** remove ll_getFSForRef **/
       /** remove ll_getFSRef **/
-      if (n.getNameAsString().equals("ll_getFSForRef") ||
-          n.getNameAsString().equals("ll_getFSRef")) {
-        updatedNode = replaceInParent(n, n.getArguments().get(0));        
+      if (n.getNameAsString().equals("ll_getFSForRef")
+              || n.getNameAsString().equals("ll_getFSRef")) {
+        updatedNode = replaceInParent(n, n.getArguments().get(0));
       }
-      
-      
-      
+
     } while (false);
-        
+
     if (updatedNode != null) {
-      updatedNode.accept(this,  null);
+      updatedNode.accept(this, null);
     } else {
       super.visit(n, null);
     }
   }
 
   /**
-   * visitor for field access expressions
-   *   - convert ((...type_Type)jcasType).casFeatCode_XXXX to _FI_xxx
-   * @param n -
-   * @param ignore -
+   * visitor for field access expressions - convert ((...type_Type)jcasType).casFeatCode_XXXX to
+   * _FI_xxx
+   * 
+   * @param n
+   *          -
+   * @param ignore
+   *          -
    */
   @Override
   public void visit(FieldAccessExpr n, Object ignore) {
     Expression e;
     Optional<Expression> oe;
     String nname = n.getNameAsString();
-    
-    if (get_set_method != null) {  
-      if (nname.startsWith("casFeatCode_") &&
-          ((oe = n.getScope()).isPresent()) &&
-          ((e = getUnenclosedExpr(oe.get())) instanceof CastExpr) &&
-          ("jcasType".equals(getName(((CastExpr)e).getExpression())))) {
+
+    if (get_set_method != null) {
+      if (nname.startsWith("casFeatCode_") && ((oe = n.getScope()).isPresent())
+              && ((e = getUnenclosedExpr(oe.get())) instanceof CastExpr)
+              && ("jcasType".equals(getName(((CastExpr) e).getExpression())))) {
         String featureName = nname.substring("casFeatCode_".length());
-//        replaceInParent(n, new NameExpr("_FI_" + featureName)); // repl last in List<Expression> (args)
-        
+        // replaceInParent(n, new NameExpr("_FI_" + featureName)); // repl last in List<Expression>
+        // (args)
+
         MethodCallExpr getint = new MethodCallExpr(null, "wrapGetIntCatchException");
         getint.addArgument(new NameExpr("_FH_" + featureName));
         replaceInParent(n, getint);
-        
+
         return;
       } else if (nname.startsWith("casFeatCode_")) {
-        reportMigrateFailed("Found field casFeatCode_ ... without a previous cast expr using jcasType");
+        reportMigrateFailed(
+                "Found field casFeatCode_ ... without a previous cast expr using jcasType");
       }
     }
-    super.visit(n,  ignore);      
+    super.visit(n, ignore);
   }
-  
+
   private class removeEmptyStmts extends VoidVisitorAdapter<Object> {
     @Override
     public void visit(BlockStmt n, Object ignore) {
       n.getStatements().removeIf(statement -> statement instanceof EmptyStmt);
-      super.visit(n,  ignore);
-    }
-    
-//    @Override
-//    public void visit(MethodDeclaration n, Object ignore) {
-//      if (n.getNameAsString().equals("getModifiablePrimitiveNodes")) {
-//        System.out.println("debug");
-//      }
-//      super.visit(n,  ignore);
-//      if (n.getNameAsString().equals("getModifiablePrimitiveNodes")) {
-//        System.out.println("debug");
-//      }
-//    }
-  }
-    
+      super.visit(n, ignore);
+    }
+
+    // @Override
+    // public void visit(MethodDeclaration n, Object ignore) {
+    // if (n.getNameAsString().equals("getModifiablePrimitiveNodes")) {
+    // System.out.println("debug");
+    // }
+    // super.visit(n, ignore);
+    // if (n.getNameAsString().equals("getModifiablePrimitiveNodes")) {
+    // System.out.println("debug");
+    // }
+    // }
+  }
+
+  // @formatter:off
   /**
    * converted files: 
    *    java name, path  (sorted by java name, v3 name only)
@@ -1905,6 +2035,7 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    *    java name, path  (sorted by java name)
    * @return true if it's likely everything converted OK.
    */
+  // @formatter:on
   private boolean report() {
     System.out.println("\n\nMigration Summary");
     System.out.format("Output top directory: %s%n", outputDirectory);
@@ -1916,22 +2047,28 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     try {
       // these reports, if non-empty items, imply something needs manual checking, so reset isOk2
       isOk2 = reportPaths("Workaround Directories", "workaroundDir.txt", pathWorkaround) && isOk2;
-      isOk2 = reportPaths("Reports of converted files where a deleted check was customized", "deletedCheckModified.txt", deletedCheckModified) && isOk2;
-      isOk2 = reportPaths("Reports of converted files needing manual inspection", "manualInspection.txt", manualInspection) && isOk2;
-      isOk2 = reportPaths("Reports of files which failed migration", "failed.txt", failedMigration) && isOk2;
+      isOk2 = reportPaths("Reports of converted files where a deleted check was customized",
+              "deletedCheckModified.txt", deletedCheckModified) && isOk2;
+      isOk2 = reportPaths("Reports of converted files needing manual inspection",
+              "manualInspection.txt", manualInspection) && isOk2;
+      isOk2 = reportPaths("Reports of files which failed migration", "failed.txt", failedMigration)
+              && isOk2;
       isOk2 = reportPaths("Reports of non-JCas files", "NonJCasFiles.txt", nonJCasFiles) && isOk2;
-      isOk2 = reportPaths("Builtin JCas classes - skipped - need manual checking to see if they are modified",
-          "skippedBuiltins.txt", skippedBuiltins) && isOk2;
+      isOk2 = reportPaths(
+              "Builtin JCas classes - skipped - need manual checking to see if they are modified",
+              "skippedBuiltins.txt", skippedBuiltins) && isOk2;
 
       // these reports, if non-empty, do not imply OK issues
       reportPaths("Reports of updated Jars", "jarFileUpdates.txt", jarClassReplace);
       reportPaths("Reports of updated PEARs", "pearFileUpdates.txt", pearClassReplace);
-         
-//      computeDuplicates();
-//      reportPaths("Report of duplicates - not identical", "nonIdenticalDuplicates.txt", nonIdenticalDuplicates);
-//      reportPaths("Report of duplicates - identical", "identicalDuplicates.txt", identicalDuplicates);
-//      isOk2 = reportDuplicates() && isOk2;  // false if non-identical duplicates
-           
+
+      // computeDuplicates();
+      // reportPaths("Report of duplicates - not identical", "nonIdenticalDuplicates.txt",
+      // nonIdenticalDuplicates);
+      // reportPaths("Report of duplicates - identical", "identicalDuplicates.txt",
+      // identicalDuplicates);
+      // isOk2 = reportDuplicates() && isOk2; // false if non-identical duplicates
+
       return isOk2;
     } catch (IOException e) {
       throw new RuntimeException(e);
@@ -1941,14 +2078,15 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
   private void pprintRoots(String kind, Container[] roots) {
     if (roots != null && roots.length > 0) {
       try {
-        try (BufferedWriter bw = Files.newBufferedWriter(makePath(outDirLog + "ItemsProcessed"), StandardOpenOption.CREATE)) {
+        try (BufferedWriter bw = Files.newBufferedWriter(makePath(outDirLog + "ItemsProcessed"),
+                StandardOpenOption.CREATE)) {
           logPrintNl(kind + " Roots:", bw);
           indent[0] += 2;
           try {
-          for (Container container : roots) {
-            pprintContainer(container, bw);
-          }
-          logPrintNl("", bw);
+            for (Container container : roots) {
+              pprintContainer(container, bw);
+            }
+            logPrintNl("", bw);
           } finally {
             indent[0] -= 2;
           }
@@ -1958,7 +2096,7 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       }
     }
   }
-  
+
   private void pprintContainer(Container container, BufferedWriter bw) throws IOException {
     logPrintNl(container.toString(), bw);
     if (container.subContainers.size() > 1) {
@@ -1968,66 +2106,65 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
         pprintContainer(subc, bw);
       }
     }
-    
-    
-  }
-  
-//  private void computeDuplicates() {
-//    List<ClassnameAndPath> toCheck = new ArrayList<>(c2ps);
-//    toCheck.addAll(extendableBuiltins);
-//    sortReport2(toCheck);
-//    ClassnameAndPath prevP = new ClassnameAndPath(null, null);
-//    List<ClassnameAndPath> sameList = new ArrayList<>();
-//    boolean areAllEqual = true;
-//    
-//    for (ClassnameAndPath p : toCheck) {
-//      if (!p.getFirst().equals(prevP.getFirst())) {
-//        
-//        addToIdenticals(sameList, areAllEqual);
-//        sameList.clear();
-//        areAllEqual = true;
-//        
-//        prevP = p;
-//        continue;
-//      }
-//      
-//      // have 2nd or subsequent same class
-//      if (sameList.size() == 0) {
-//        sameList.add(prevP);
-//      }
-//      sameList.add(p);
-//      if (areAllEqual) {
-//        if (isFilesMiscompare(p.path, prevP.path)) {
-//          areAllEqual = false;
-//        }
-//      }      
-//    }
-//    
-//    addToIdenticals(sameList, areAllEqual);    
-//  }
-  
-//  /**
-//   * Compare two java source or class files
-//   * @param p1
-//   * @param p2
-//   * @return
-//   */
-//  private boolean isFilesMiscompare(Path p1, Path p2) {
-//      String s1 = (p1);
-//      String s2 = (p2);
-//      return !s1.equals(s2);
-//  }
-  
-//  private void addToIdenticals(List<ClassnameAndPath> sameList, boolean areAllEqual) {
-//    if (sameList.size() > 0) {
-//      if (areAllEqual) {
-//        identicalDuplicates.addAll(sameList);
-//      } else {
-//        nonIdenticalDuplicates.addAll(sameList);
-//      }
-//    }
-//  }
- 
+
+  }
+
+  // private void computeDuplicates() {
+  // List<ClassnameAndPath> toCheck = new ArrayList<>(c2ps);
+  // toCheck.addAll(extendableBuiltins);
+  // sortReport2(toCheck);
+  // ClassnameAndPath prevP = new ClassnameAndPath(null, null);
+  // List<ClassnameAndPath> sameList = new ArrayList<>();
+  // boolean areAllEqual = true;
+  //
+  // for (ClassnameAndPath p : toCheck) {
+  // if (!p.getFirst().equals(prevP.getFirst())) {
+  //
+  // addToIdenticals(sameList, areAllEqual);
+  // sameList.clear();
+  // areAllEqual = true;
+  //
+  // prevP = p;
+  // continue;
+  // }
+  //
+  // // have 2nd or subsequent same class
+  // if (sameList.size() == 0) {
+  // sameList.add(prevP);
+  // }
+  // sameList.add(p);
+  // if (areAllEqual) {
+  // if (isFilesMiscompare(p.path, prevP.path)) {
+  // areAllEqual = false;
+  // }
+  // }
+  // }
+  //
+  // addToIdenticals(sameList, areAllEqual);
+  // }
+
+  // /**
+  // * Compare two java source or class files
+  // * @param p1
+  // * @param p2
+  // * @return
+  // */
+  // private boolean isFilesMiscompare(Path p1, Path p2) {
+  // String s1 = (p1);
+  // String s2 = (p2);
+  // return !s1.equals(s2);
+  // }
+
+  // private void addToIdenticals(List<ClassnameAndPath> sameList, boolean areAllEqual) {
+  // if (sameList.size() > 0) {
+  // if (areAllEqual) {
+  // identicalDuplicates.addAll(sameList);
+  // } else {
+  // nonIdenticalDuplicates.addAll(sameList);
+  // }
+  // }
+  // }
+
   /**
    * 
    * @param name
@@ -2036,7 +2173,7 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    */
   private Path makePath(String name) throws IOException {
     Path p = Paths.get(name);
-    Path parent = p.getParent();  // all the parts of the path up to the final segment
+    Path parent = p.getParent(); // all the parts of the path up to the final segment
     if (parent == null) {
       return p;
     }
@@ -2044,8 +2181,8 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       Files.createDirectories(parent);
     } catch (FileAlreadyExistsException e) { // parent already exists but is not a directory!
       // caused by running on Windows system which ignores "case"
-      // there's a file at /x/y/  named "z", but the path wants to be /x/y/Z/
-      //   Workaround: change "z" to "z_c"  c for capitalization issue
+      // there's a file at /x/y/ named "z", but the path wants to be /x/y/Z/
+      // Workaround: change "z" to "z_c" c for capitalization issue
       current_container.haveDifferentCapitalizedNamesCollidingOnWindows = true;
       Path fn = parent.getFileName();
       if (fn == null) {
@@ -2053,58 +2190,65 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       }
       String newDir = fn.toString() + "_c";
       Path parent2 = parent.getParent();
-      
+
       Path p2 = parent2 == null ? Paths.get(newDir) : Paths.get(parent2.toString(), newDir);
       try {
         Files.createDirectories(p2);
       } catch (FileAlreadyExistsException e2) { // parent already exists but is not a directory!
         throw new RuntimeException(e2);
       }
-      
+
       reportPathWorkaround(parent.toString(), p2.toString());
       Path lastPartOfPath = p.getFileName();
-      if (null == lastPartOfPath) throw new RuntimeException();
+      if (null == lastPartOfPath)
+        throw new RuntimeException();
       return Paths.get(p2.toString(), lastPartOfPath.toString());
     }
     return p;
   }
-  
-  
+
   private void logPrint(String msg, Writer bw) throws IOException {
     System.out.print(msg);
     bw.write(msg);
   }
-  
+
   private void logPrintNl(String msg, Writer bw) throws IOException {
     logPrint(msg, bw);
     logPrint("\n", bw);
   }
-  
+
   /**
-   * prints "There were no xxx" if there are no items.
-   * prints a title, followed by a ================== underneath it
+   * prints "There were no xxx" if there are no items. prints a title, followed by a
+   * ================== underneath it
    * 
    * prints a sorted report of two fields.
    * 
-   * @param title title of report
-   * @param fileName file name to save the report in (as well as print to sysout
-   * @param items the set of items to report on-
+   * @param title
+   *          title of report
+   * @param fileName
+   *          file name to save the report in (as well as print to sysout
+   * @param items
+   *          the set of items to report on-
    * @return true if items were empty
-   * @throws IOException -
+   * @throws IOException
+   *           -
    */
-  private <T, U> boolean reportPaths(String title, String fileName, List<? extends Report2<T, U>> items) throws IOException {
+  private <T, U> boolean reportPaths(String title, String fileName,
+          List<? extends Report2<T, U>> items) throws IOException {
     if (items.size() == 0) {
       System.out.println("There were no " + title);
       return true;
     }
     System.out.println("\n" + title);
-    for (int i = 0; i < title.length(); i++) System.out.print('=');
+    for (int i = 0; i < title.length(); i++)
+      System.out.print('=');
     System.out.println("");
-    
-    try (BufferedWriter bw = Files.newBufferedWriter(makePath(outDirLog + fileName), StandardOpenOption.CREATE)) {
+
+    try (BufferedWriter bw = Files.newBufferedWriter(makePath(outDirLog + fileName),
+            StandardOpenOption.CREATE)) {
       List<Report2<T, U>> sorted = new ArrayList<>(items);
 
-      sortReport2(sorted);  
+      sortReport2(sorted);
       int max = 0;
       int nbrFirsts = 0;
       Object prevFirst = null;
@@ -2113,28 +2257,27 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
         Comparable<T> first = p.getFirst();
         if (first != prevFirst) {
           prevFirst = first;
-          nbrFirsts ++;
+          nbrFirsts++;
         }
       }
-      
-      /** 
-       * Two styles.
-       *   Style 1: where nbrFirst &lt;= 25% nbr: first on separate line, seconds indented
-       *   Style 2: firsts and seconds on same line.
+
+      /**
+       * Two styles. Style 1: where nbrFirst &lt;= 25% nbr: first on separate line, seconds indented
+       * Style 2: firsts and seconds on same line.
        */
       int i = 1;
       boolean style1 = nbrFirsts <= sorted.size() / 4;
       prevFirst = null;
       for (Report2<T, U> p : sorted) {
         if (style1) {
-          
+
           if (prevFirst != p.getFirst()) {
             prevFirst = p.getFirst();
             logPrintNl(String.format("\n  For: %s", p.getFirst()), bw);
-          } 
+          }
           logPrintNl(String.format("    %5d   %s", i, p.getSecond()), bw);
         } else {
-          logPrintNl(String.format("%5d %-" +max+ "s %s", i, p.getFirst(), p.getSecond()), bw);
+          logPrintNl(String.format("%5d %-" + max + "s %s", i, p.getFirst(), p.getSecond()), bw);
         }
         i++;
       }
@@ -2142,14 +2285,15 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     } // end of try-with-resources
     return false;
   }
-    
+
   private boolean isZipFs(Object o) {
     // Surprise! sometimes the o is not an instance of FileSystem but is the zipfs anyways
-    return o.getClass().getName().contains("zipfs");  // java 8 and 9
+    return o.getClass().getName().contains("zipfs"); // java 8 and 9
   }
-  
+
   /**
    * Sort the items on first, then second
+   * 
    * @param items
    */
   private <T, U> void sortReport2(List<? extends Report2<T, U>> items) {
@@ -2161,17 +2305,19 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       return r;
     });
   }
-        
+
   /**
-   * protect against comparing zip fs with non-zip fs - these are not comparable to each other in IBM Java 8
+   * protect against comparing zip fs with non-zip fs - these are not comparable to each other in
+   * IBM Java 8
+   * 
    * @return -
    */
   private <T> int protectedCompare(Comparable<T> comparable, Comparable<T> comparable2) {
-    //debug
+    // debug
     try {
       if (isZipFs(comparable)) {
         if (isZipFs(comparable2)) {
-          return comparable.compareTo((T) comparable2);  // both zip
+          return comparable.compareTo((T) comparable2); // both zip
         } else {
           return 1;
         }
@@ -2179,16 +2325,19 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
         if (isZipFs(comparable2)) {
           return -1;
         } else {
-          return comparable.compareTo((T) comparable2);  // both not zip
+          return comparable.compareTo((T) comparable2); // both not zip
         }
       }
     } catch (ClassCastException e) {
-      //debug
-      System.out.format("Internal error: c1: %b  c2: %b%n c1: %s%n c2: %s%n", isZipFs(comparable), isZipFs(comparable2), comparable.getClass().getName(), comparable2.getClass().getName());
+      // debug
+      System.out.format("Internal error: c1: %b  c2: %b%n c1: %s%n c2: %s%n", isZipFs(comparable),
+              isZipFs(comparable2), comparable.getClass().getName(),
+              comparable2.getClass().getName());
       throw e;
     }
   }
 
+  // @formatter:off
   /**
    * Called only for top level roots.  Sub containers recurse getCandidates_processFile2.
    * 
@@ -2205,16 +2354,21 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    * @param root
    * @throws IOException
    */
+  // @formatter:on
   private void getAndProcessCandidatesInContainer(Container container) {
-    
-//    current_paths2RootIds = top_paths2RootIds;  // don't do lower, that's called within Jars etc.
+
+    // current_paths2RootIds = top_paths2RootIds; // don't do lower, that's called within Jars etc.
     if (container.isSingleJavaSource) {
       getCandidates_processFile2(container.root, container);
     } else {
-      try (Stream<Path> stream = Files.walk(container.root, FileVisitOption.FOLLOW_LINKS)) {  // needed to release file handles
-          stream.forEachOrdered(
-              // only puts into the RootIds possible Fqcn (ending in either .class or .java)
-            p -> getCandidates_processFile2(p, container));
+      try (Stream<Path> stream = Files.walk(container.root, FileVisitOption.FOLLOW_LINKS)) { // needed
+                                                                                             // to
+                                                                                             // release
+                                                                                             // file
+                                                                                             // handles
+        stream.forEachOrdered(
+                // only puts into the RootIds possible Fqcn (ending in either .class or .java)
+                p -> getCandidates_processFile2(p, container));
       } catch (IOException e) {
         throw new RuntimeException(e);
       }
@@ -2224,38 +2378,35 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     // prunes empty rootIds and subContainer nodes
     removeNonJCas(container);
 
-    if (container.candidates.size() == 0 && 
-        container.subContainers.size() == 0) { // above call might remove all candidates
+    if (container.candidates.size() == 0 && container.subContainers.size() == 0) { // above call
+                                                                                   // might remove
+                                                                                   // all candidates
       Container parent = container.parent;
       if (parent != null) {
-//        System.out.println("No Candidates found, removing container: " + container.toString() );
-//        // debug
-//        System.out.println("debug: " + container.rootOrig.toString());
+        // System.out.println("No Candidates found, removing container: " + container.toString() );
+        // // debug
+        // System.out.println("debug: " + container.rootOrig.toString());
         parent.subContainers.remove(container);
       }
       return;
     }
-    
+
     si(psb).append("Migrating JCas files ");
-    psb.append( container.isJar
-                  ? "in Jar: "
-                  : container.isPear 
-                     ? "in Pear: "
-                     : "from root: ");
+    psb.append(container.isJar ? "in Jar: " : container.isPear ? "in Pear: " : "from root: ");
     psb.append(container.rootOrig);
-    
+
     indent[0] += 2;
     si(psb);
     flush(psb);
     try {
       for (Path path : container.candidates) {
-        
+
         CommonConverted cc = getSource(path, container);
         // migrate checks to see if already done, outputs a "." or some other char for the candidate
         migrate(cc, container, path);
-        
-        //defer any compilation to container level
-  
+
+        // defer any compilation to container level
+
         if ((itemCount % 50) == 0) {
           psb.append(" ").append(itemCount);
           si(psb);
@@ -2263,18 +2414,16 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
         }
         itemCount++;
       }
-      
+
       psb.append(" ").append(itemCount - 1);
       flush(psb);
-  
-      
+
       if (isSource) {
-        return;  // done
+        return; // done
       }
-      
-      if (!isSource &&
-          !container.haveDifferentCapitalizedNamesCollidingOnWindows && 
-          javaCompiler != null) {
+
+      if (!isSource && !container.haveDifferentCapitalizedNamesCollidingOnWindows
+              && javaCompiler != null) {
         boolean somethingCompiled = compileV3SourcesCommon2(container);
         if (container.isPear || container.isJar) {
           if (somethingCompiled) {
@@ -2283,9 +2432,9 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
         }
         return;
       }
-      
+
       unableToCompile = true;
-      return;  // unable to do post processing or compiling
+      return; // unable to do post processing or compiling
     } finally {
       indent[0] -= 2;
     }
@@ -2297,31 +2446,33 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     while (it.hasNext()) {
       String candidate = it.next().toString();
       // remove non JCas classes
-//      //debug
-//      System.out.println("debug, testing to remove: " + candidate);
-//      if (candidate.indexOf("Corrected") >= 0) {
-//        if (!container._Types.contains(candidate)) {
-//          System.out.println("debug dumping _Types map keys to see why ... Corrected.class not there");
-//          System.out.println("debug key is=" + candidate);
-//          System.out.println("keys are:");
-//          int i = 0;
-//          for (String k : container._Types) {
-//            if (i == 4) {
-//              i = 0;
-//              System.out.println("");
-//            }
-//            System.out.print(k + ", ");
-//          }
-//        } else {
-//          System.out.println("debug container._Types did contain " + candidate);
-//        }
-//      }
+      // //debug
+      // System.out.println("debug, testing to remove: " + candidate);
+      // if (candidate.indexOf("Corrected") >= 0) {
+      // if (!container._Types.contains(candidate)) {
+      // System.out.println("debug dumping _Types map keys to see why ... Corrected.class not
+      // there");
+      // System.out.println("debug key is=" + candidate);
+      // System.out.println("keys are:");
+      // int i = 0;
+      // for (String k : container._Types) {
+      // if (i == 4) {
+      // i = 0;
+      // System.out.println("");
+      // }
+      // System.out.print(k + ", ");
+      // }
+      // } else {
+      // System.out.println("debug container._Types did contain " + candidate);
+      // }
+      // }
       if (!container.isSingleJavaSource && !container._Types.contains(candidate)) {
-          it.remove();
+        it.remove();
       }
-    }    
+    }
   }
-  
+
+  // @formatter:off
   /**
    * Called from Stream walker starting at a root or starting at an imbedded Jar or Pear.
    * 
@@ -2346,24 +2497,26 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    *                    - rootIds (which have the JCas candidates) and
    *                    - subContainers for imbedded Pears and Jars
    */
+  // @formatter:on
   private void getCandidates_processFile2(Path path, Container container) {
-      
+
     String pathString = path.toString();
     final boolean isPear = pathString.endsWith(".pear"); // path.endsWith does not mean this !!
     final boolean isJar = pathString.endsWith(".jar");
-    
+
     if (isPear || isJar) {
-      Container subc = new Container(container, path); 
+      Container subc = new Container(container, path);
       getAndProcessCandidatesInContainer(subc);
       return;
     }
-    
+
     if (pathString.endsWith(isSource ? ".java" : ".class")) {
       // Skip candidates except .java or .class
       addToCandidates(path, container);
-    }     
+    }
   }
-  
+
+  // @formatter:off
   /**
    * if _Type kind, add artifactId to set kept in current rootIdContainer 
    * If currently scanning within a PEAR, 
@@ -2379,70 +2532,74 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    * @param path
    * @param pearClassPath
    */
+  // @formatter:on
   private void addToCandidates(Path path, Container container) {
     String ps = path.toString();
-    
+
     if (ps.endsWith(isSource ? "_Type.java" : "_Type.class")) {
-      container._Types.add(isSource 
-                            ? (ps.substring(0, ps.length() - 10) + ".java")
-                            : (ps.substring(0, ps.length() - 11) + ".class"));
-//      if (container.isJar) {
-//        System.out.println("debug add container._Types " + Paths.get(ps.substring(0, ps.length() - 11)).toString() + ".class".toString() + " for Jar " + container.rootOrig.getFileName().toString());
-//      }
+      container._Types.add(isSource ? (ps.substring(0, ps.length() - 10) + ".java")
+              : (ps.substring(0, ps.length() - 11) + ".class"));
+      // if (container.isJar) {
+      // System.out.println("debug add container._Types " + Paths.get(ps.substring(0, ps.length() -
+      // 11)).toString() + ".class".toString() + " for Jar " +
+      // container.rootOrig.getFileName().toString());
+      // }
 
       return;
     }
-    
+
     if (ps.contains("$")) {
       return; // don't add these kinds of things, they're not JCas classes
     }
-    
-    //debug
-//    if (container.isJar) {
-//      System.out.println("debug add candidate " + path.toString() + " for Jar " + container.rootOrig.getFileName().toString());
-//    }
+
+    // debug
+    // if (container.isJar) {
+    // System.out.println("debug add candidate " + path.toString() + " for Jar " +
+    // container.rootOrig.getFileName().toString());
+    // }
     container.candidates.add(path);
   }
-  
-  
+
   /**
-   * For Jars inside other Jars, we copy the Jar to a temp spot in the default file system
-   * Extracted Jar is marked delete-on-exit
+   * For Jars inside other Jars, we copy the Jar to a temp spot in the default file system Extracted
+   * Jar is marked delete-on-exit
    * 
-   * @param path embedded Jar to copy (only the last name is used, in constructing the temp dir)
+   * @param path
+   *          embedded Jar to copy (only the last name is used, in constructing the temp dir)
    * @return a temporary file in the local temp directory that is a copy of the Jar
-   * @throws IOException -
+   * @throws IOException
+   *           -
    */
   private static Path getTempOutputPathForJarOrPear(Path path) throws IOException {
     Path localTempDir = getTempDir();
-    if (path == null ) {
+    if (path == null) {
       throw new IllegalArgumentException();
     }
     Path fn = path.getFileName();
     if (fn == null) {
       throw new IllegalArgumentException();
     }
-    Path tempPath = Files.createTempFile(localTempDir, fn.toString(),  "");
+    Path tempPath = Files.createTempFile(localTempDir, fn.toString(), "");
     tempPath.toFile().deleteOnExit();
     return tempPath;
   }
-  
+
   private static Path getTempDir() throws IOException {
     if (tempDir == null) {
       tempDir = Files.createTempDirectory("migrateJCas");
       tempDir.toFile().deleteOnExit();
     }
     return tempDir;
-  }   
-  
+  }
+
   private static final CommandLineParser createCmdLineParser() {
     CommandLineParser parser = new CommandLineParser();
     parser.addParameter(SOURCE_FILE_ROOTS, true);
     parser.addParameter(CLASS_FILE_ROOTS, true);
     parser.addParameter(OUTPUT_DIRECTORY, true);
-//    parser.addParameter(SKIP_TYPE_CHECK, false);
+    // parser.addParameter(SKIP_TYPE_CHECK, false);
     parser.addParameter(MIGRATE_CLASSPATH, true);
-//    parser.addParameter(CLASSES, true);
+    // parser.addParameter(CLASSES, true);
     return parser;
   }
 
@@ -2457,17 +2614,19 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       System.err.println();
       return false;
     }
-    
+
     if (!clp.isInArgsList(SOURCE_FILE_ROOTS) && !clp.isInArgsList(CLASS_FILE_ROOTS)) {
-      System.err.println("Neither sources file roots nor classes file roots parameters specified; please specify just one.");
+      System.err.println(
+              "Neither sources file roots nor classes file roots parameters specified; please specify just one.");
       return false;
     }
-    
+
     if (clp.isInArgsList(SOURCE_FILE_ROOTS) && clp.isInArgsList(CLASS_FILE_ROOTS)) {
-      System.err.println("both sources file roots and classes file roots parameters specified; please specify just one.");
+      System.err.println(
+              "both sources file roots and classes file roots parameters specified; please specify just one.");
       return false;
     }
-    
+
     if (clp.isInArgsList(OUTPUT_DIRECTORY)) {
       outputDirectory = Paths.get(clp.getParamArgument(OUTPUT_DIRECTORY)).toString();
       if (!outputDirectory.endsWith("/")) {
@@ -2485,33 +2644,34 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     outDirSkipped = outputDirectory + "not-converted/";
     outDirLog = outputDirectory + "logs/";
 
-    
     if (clp.isInArgsList(MIGRATE_CLASSPATH)) {
       migrateClasspath = clp.getParamArgument(MIGRATE_CLASSPATH);
     } else {
       if (clp.isInArgsList(CLASS_FILE_ROOTS)) {
         System.err.println("WARNING: classes file roots is specified, but the\n"
-                         + "       migrateClasspath parameter is missing\n");
+                + "       migrateClasspath parameter is missing\n");
       }
     }
-    
-//    if (clp.isInArgsList(CLASSES)) {
-//      individualClasses = clp.getParamArgument(CLASSES);
-//    }
+
+    // if (clp.isInArgsList(CLASSES)) {
+    // individualClasses = clp.getParamArgument(CLASSES);
+    // }
     return true;
   }
-  
+
   // called to decompile a string of bytes.
-  //   - first get the class name (fully qualified) 
-  //     and skip decompiling if already decompiled this class
-  //     for this pearClasspath
-  //     - this handles multiple class definitions, insuring
-  //       only one decompile happens per pearClasspath (including null)
+  // - first get the class name (fully qualified)
+  // and skip decompiling if already decompiled this class
+  // for this pearClasspath
+  // - this handles multiple class definitions, insuring
+  // only one decompile happens per pearClasspath (including null)
   /**
    * Caller does any caching to avoid this method.
    * 
-   * @param b bytecode to decompile
-   * @param pearClasspath to prepend to the classpath
+   * @param b
+   *          bytecode to decompile
+   * @param pearClasspath
+   *          to prepend to the classpath
    * @return
    */
   private String decompile(byte[] b, String pearClasspath) {
@@ -2519,112 +2679,116 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     String classNameWithSlashes = Misc.classNameFromByteCode(b);
     packageAndClassNameSlash = classNameWithSlashes;
     ClassLoader cl = getClassLoader(pearClasspath);
-    
+
     UimaDecompiler ud = new UimaDecompiler(cl, null);
 
     if (classNameWithSlashes == null || classNameWithSlashes.length() < 2) {
-      System.err.println("Failed to extract class name from binary code, "
-          + "name found was \"" + ((classNameWithSlashes == null) ? "null" : classNameWithSlashes) 
-          + "\"\n  byte array was:");
+      System.err.println("Failed to extract class name from binary code, " + "name found was \""
+              + ((classNameWithSlashes == null) ? "null" : classNameWithSlashes)
+              + "\"\n  byte array was:");
       System.err.println(Misc.dumpByteArray(b, 2000));
       badClassName = true;
     }
 
     return ud.decompileToString(classNameWithSlashes, b);
   }
-    
+
   /**
-   * The classloader to use in decompiling, if it is provided, is one that delegates first
-   * to the parent.  This may need fixing for PEARs
+   * The classloader to use in decompiling, if it is provided, is one that delegates first to the
+   * parent. This may need fixing for PEARs
+   * 
    * @return classloader to use for migrate decompiling
    */
   private ClassLoader getClassLoader(String pearClasspath) {
     if (null == pearClasspath) {
       if (null == cachedMigrateClassLoader) {
-        cachedMigrateClassLoader = (null == migrateClasspath)
-                        ? this.getClass().getClassLoader()
-                        : new UIMAClassLoader(Misc.classpath2urls(migrateClasspath));
+        cachedMigrateClassLoader = (null == migrateClasspath) ? this.getClass().getClassLoader()
+                : new UIMAClassLoader(Misc.classpath2urls(migrateClasspath));
       }
       return cachedMigrateClassLoader;
     } else {
       try {
-        return new UIMAClassLoader((null == migrateClasspath) 
-                                     ? pearClasspath
-                                     : (pearClasspath + File.pathSeparator + migrateClasspath));
+        return new UIMAClassLoader((null == migrateClasspath) ? pearClasspath
+                : (pearClasspath + File.pathSeparator + migrateClasspath));
       } catch (MalformedURLException e) {
         throw new UIMARuntimeException(e);
       }
     }
   }
-  
+
   private void addImport(String s) {
     cu.getImports().add(new ImportDeclaration(new Name(s), false, false));
   }
-  
+
   private void removeImport(String s) {
     Iterator<ImportDeclaration> it = cu.getImports().iterator();
-    while (it.hasNext()) { 
+    while (it.hasNext()) {
       ImportDeclaration impDcl = it.next();
       if (impDcl.getNameAsString().equals(s)) {
         it.remove();
         break;
       }
-    } 
+    }
   }
 
   /******************
    * AST Utilities
    ******************/
-  
+
   private Node replaceInParent(Node n, Expression v) {
     Optional<Node> maybeParent = n.getParentNode();
     if (maybeParent.isPresent()) {
       Node parent = n.getParentNode().get();
       if (parent instanceof EnclosedExpr) {
-        ((EnclosedExpr)parent).setInner(v);
+        ((EnclosedExpr) parent).setInner(v);
       } else if (parent instanceof MethodCallExpr) { // args in the arg list
-        List<Expression> args = ((MethodCallExpr)parent).getArguments();
+        List<Expression> args = ((MethodCallExpr) parent).getArguments();
         args.set(args.indexOf(n), v);
         v.setParentNode(parent);
-      } else if (parent instanceof ExpressionStmt) { 
-        ((ExpressionStmt)parent).setExpression(v);
-      } else if (parent instanceof CastExpr) { 
-        ((CastExpr)parent).setExpression(v);
-      } else if (parent instanceof ReturnStmt) { 
-        ((ReturnStmt)parent).setExpression(v);
+      } else if (parent instanceof ExpressionStmt) {
+        ((ExpressionStmt) parent).setExpression(v);
+      } else if (parent instanceof CastExpr) {
+        ((CastExpr) parent).setExpression(v);
+      } else if (parent instanceof ReturnStmt) {
+        ((ReturnStmt) parent).setExpression(v);
       } else if (parent instanceof AssignExpr) {
-        ((AssignExpr)parent).setValue(v);
+        ((AssignExpr) parent).setValue(v);
       } else if (parent instanceof VariableDeclarator) {
-        ((VariableDeclarator)parent).setInitializer(v);      
+        ((VariableDeclarator) parent).setInitializer(v);
       } else if (parent instanceof ObjectCreationExpr) {
-        List<Expression> args = ((ObjectCreationExpr)parent).getArguments();
+        List<Expression> args = ((ObjectCreationExpr) parent).getArguments();
         int i = args.indexOf(n);
-        if (i < 0) throw new RuntimeException();
-        args.set(i, v);      
+        if (i < 0)
+          throw new RuntimeException();
+        args.set(i, v);
       } else {
         System.out.println(parent.getClass().getName());
         throw new RuntimeException();
       }
       return v;
     }
-    System.out.println("internal error replacing in parent: no parent for node: " + n.getClass().getName());
+    System.out.println(
+            "internal error replacing in parent: no parent for node: " + n.getClass().getName());
     System.out.println("   node: " + n.toString());
     System.out.println("   expression replacing: " + v.toString());
     throw new RuntimeException();
   }
-    
+
   /**
    * 
-   * @param p the parameter to modify
-   * @param t the name of class or interface
-   * @param name the name of the variable
+   * @param p
+   *          the parameter to modify
+   * @param t
+   *          the name of class or interface
+   * @param name
+   *          the name of the variable
    */
   private void setParameter(List<Parameter> ps, int i, String t, String name) {
     Parameter p = ps.get(i);
     p.setType(new ClassOrInterfaceType(t));
     p.setName(new SimpleName(name));
   }
-  
+
   private int findConstructor(NodeList<BodyDeclaration<?>> classMembers) {
     int i = 0;
     for (BodyDeclaration<?> bd : classMembers) {
@@ -2635,26 +2799,26 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     }
     return -1;
   }
-  
+
   private boolean hasTypeFields(NodeList<BodyDeclaration<?>> members) {
     boolean hasType = false;
     boolean hasTypeId = false;
     for (BodyDeclaration<?> bd : members) {
       if (bd instanceof FieldDeclaration) {
-        FieldDeclaration f = (FieldDeclaration)bd;
+        FieldDeclaration f = (FieldDeclaration) bd;
         EnumSet<Modifier> m = f.getModifiers();
-        if (m.contains(Modifier.PUBLIC) &&
-            m.contains(Modifier.STATIC) &&
-            m.contains(Modifier.FINAL) 
-//            &&
-//            getTypeName(f.getType()).equals("int")
-            ) {
+        if (m.contains(Modifier.PUBLIC) && m.contains(Modifier.STATIC) && m.contains(Modifier.FINAL)
+        // &&
+        // getTypeName(f.getType()).equals("int")
+        ) {
           List<VariableDeclarator> vds = f.getVariables();
           for (VariableDeclarator vd : vds) {
             if (vd.getType().equals(intType)) {
               String n = vd.getNameAsString();
-              if (n.equals("type")) hasType = true;
-              if (n.equals("typeIndexID")) hasTypeId = true;
+              if (n.equals("type"))
+                hasType = true;
+              if (n.equals("typeIndexID"))
+                hasTypeId = true;
               if (hasTypeId && hasType) {
                 return true;
               }
@@ -2665,7 +2829,8 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     } // end of for
     return false;
   }
-  
+
+  // @formatter:off
   /**
    * Heuristic:
    *   JCas classes have 0, 1, and 2 arg constructors with particular arg types
@@ -2676,110 +2841,117 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
    * Additional 1 and 2 arg constructors are permitted.
    * 
    * Sets fields hasV2Constructors, hasV3Constructors
+   * 
    * @param members
    */
+  // @formatter:on
   private void setHasJCasConstructors(NodeList<BodyDeclaration<?>> members) {
     boolean has0ArgConstructor = false;
     boolean has1ArgJCasConstructor = false;
     boolean has2ArgJCasConstructorV2 = false;
     boolean has2ArgJCasConstructorV3 = false;
-    
+
     for (BodyDeclaration<?> bd : members) {
       if (bd instanceof ConstructorDeclaration) {
-        List<Parameter> ps = ((ConstructorDeclaration)bd).getParameters();
-        if (ps.size() == 0) has0ArgConstructor = true;
+        List<Parameter> ps = ((ConstructorDeclaration) bd).getParameters();
+        if (ps.size() == 0)
+          has0ArgConstructor = true;
         if (ps.size() == 1 && getParmTypeName(ps, 0).equals("JCas")) {
           has1ArgJCasConstructor = true;
         }
         if (ps.size() == 2) {
-          if (getParmTypeName(ps, 0).equals("int") &&
-              getParmTypeName(ps, 1).equals("TOP_Type")) {
+          if (getParmTypeName(ps, 0).equals("int") && getParmTypeName(ps, 1).equals("TOP_Type")) {
             has2ArgJCasConstructorV2 = true;
-          } else if (getParmTypeName(ps, 0).equals("TypeImpl") &&
-                     getParmTypeName(ps, 1).equals("CASImpl")) {
+          } else if (getParmTypeName(ps, 0).equals("TypeImpl")
+                  && getParmTypeName(ps, 1).equals("CASImpl")) {
             has2ArgJCasConstructorV3 = true;
           }
         } // end of 2 arg constructor
       } // end of is-constructor
     } // end of for loop
-    
+
     hasV2Constructors = has0ArgConstructor && has1ArgJCasConstructor && has2ArgJCasConstructorV2;
     hasV3Constructors = has0ArgConstructor && has1ArgJCasConstructor && has2ArgJCasConstructorV3;
   }
-  
+
   private String getParmTypeName(List<Parameter> p, int i) {
     return getTypeName(p.get(i).getType());
   }
-  
+
   private String getTypeName(Type t) {
-//    if (t instanceof ReferenceType) {
-//      t = ((ReferenceType<?>)t).getType();
-//    }
-    
+    // if (t instanceof ReferenceType) {
+    // t = ((ReferenceType<?>)t).getType();
+    // }
+
     if (t instanceof PrimitiveType) {
-      return ((PrimitiveType)t).toString(); 
+      return ((PrimitiveType) t).toString();
     }
     if (t instanceof ClassOrInterfaceType) {
-      return ((ClassOrInterfaceType)t).getNameAsString();
+      return ((ClassOrInterfaceType) t).getNameAsString();
     }
-    Misc.internalError(); return null;
+    Misc.internalError();
+    return null;
   }
-  
+
   /**
    * Get the name of a field
-   * @param e -
+   * 
+   * @param e
+   *          -
    * @return the field name or null
    */
   private String getName(Expression e) {
     e = getUnenclosedExpr(e);
     if (e instanceof NameExpr) {
-      return ((NameExpr)e).getNameAsString();
+      return ((NameExpr) e).getNameAsString();
     }
     if (e instanceof FieldAccessExpr) {
-      return ((FieldAccessExpr)e).getNameAsString();
+      return ((FieldAccessExpr) e).getNameAsString();
     }
     return null;
   }
-  
+
   /**
-   * Called on Annotation Decl, Class/intfc decl, empty type decl, enum decl
-   * Does nothing unless at top level of compilation unit
+   * Called on Annotation Decl, Class/intfc decl, empty type decl, enum decl Does nothing unless at
+   * top level of compilation unit
    * 
    * Otherwise, adds an entry to c2ps for the classname and package, plus full path
    * 
-   * @param n type being declared
+   * @param n
+   *          type being declared
    */
   private void updateClassName(TypeDeclaration<?> n) {
     Optional<Node> pnode = n.getParentNode();
     Node node;
-    if (pnode.isPresent() && 
-        (node = pnode.get()) instanceof CompilationUnit) {
+    if (pnode.isPresent() && (node = pnode.get()) instanceof CompilationUnit) {
       CompilationUnit cu2 = (CompilationUnit) node;
       className = cu2.getType(0).getNameAsString();
-      String packageAndClassName = 
-          (className.contains(".")) 
-            ? className 
-            : packageName + '.' + className;
+      String packageAndClassName = (className.contains(".")) ? className
+              : packageName + '.' + className;
       packageAndClassNameSlash = packageAndClassName.replace('.', '/');
-//      assert current_cc.fqcn_slash == null;  // for decompiling, already set
-      assert (current_cc.fqcn_slash != null) ? current_cc.fqcn_slash.equals(packageAndClassNameSlash) : true;
+      // assert current_cc.fqcn_slash == null; // for decompiling, already set
+      assert (current_cc.fqcn_slash != null)
+              ? current_cc.fqcn_slash.equals(packageAndClassNameSlash)
+              : true;
       current_cc.fqcn_slash = packageAndClassNameSlash;
-      
-      TypeImpl ti = TypeSystemImpl.staticTsi.getType(Misc.javaClassName2UimaTypeName(packageAndClassName));
+
+      TypeImpl ti = TypeSystemImpl.staticTsi
+              .getType(Misc.javaClassName2UimaTypeName(packageAndClassName));
       if (null != ti) {
         // is a built-in type
-//        ContainerAndPath p = new ContainerAndPath(
-//            current_path,
-//            current_container,packageAndClassNameSlash, 
-//            current_cc., 
-//            current_cc.pearClasspath);
-        skippedBuiltins.add(new PathContainerAndReason(current_path, current_container, "built-in"));
+        // ContainerAndPath p = new ContainerAndPath(
+        // current_path,
+        // current_container,packageAndClassNameSlash,
+        // current_cc.,
+        // current_cc.pearClasspath);
+        skippedBuiltins
+                .add(new PathContainerAndReason(current_path, current_container, "built-in"));
         isBuiltinJCas = true;
         isConvert2v3 = false;
-        return;  
+        return;
       } else {
-        VariableDeclarator vd_typename = new VariableDeclarator(
-            stringType, "_TypeName", new StringLiteralExpr(packageAndClassName));
+        VariableDeclarator vd_typename = new VariableDeclarator(stringType, "_TypeName",
+                new StringLiteralExpr(packageAndClassName));
         fi_fields.add(new FieldDeclaration(public_static_final, vd_typename));
       }
 
@@ -2791,21 +2963,23 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
   private Expression getExpressionFromStmt(Statement stmt) {
     stmt = getStmtFromStmt(stmt);
     if (stmt instanceof ExpressionStmt) {
-      return getUnenclosedExpr(((ExpressionStmt)stmt).getExpression());
+      return getUnenclosedExpr(((ExpressionStmt) stmt).getExpression());
     }
     return null;
   }
-  
+
   private Expression getUnenclosedExpr(Expression e) {
     while (e instanceof EnclosedExpr) {
-      e = ((EnclosedExpr)e).getInner().get();
+      e = ((EnclosedExpr) e).getInner().get();
     }
     return e;
   }
-  
+
   /**
    * Unwrap (possibly nested) 1 statement blocks
-   * @param stmt -
+   * 
+   * @param stmt
+   *          -
    * @return unwrapped (non- block) statement
    */
   private Statement getStmtFromStmt(Statement stmt) {
@@ -2819,18 +2993,18 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     }
     return stmt;
   }
-  
+
   private void addCastExpr(Statement stmt, Type castType) {
     ReturnStmt rstmt = (ReturnStmt) stmt;
-    Optional<Expression> o_expr = rstmt.getExpression(); 
+    Optional<Expression> o_expr = rstmt.getExpression();
     Expression expr = o_expr.isPresent() ? o_expr.get() : null;
     CastExpr ce = new CastExpr(castType, expr);
-    rstmt.setExpression(ce);  // removes the parent link from expr
+    rstmt.setExpression(ce); // removes the parent link from expr
     if (expr != null) {
       expr.setParentNode(ce); // restore it
     }
   }
-  
+
   /********************
    * Recording results
    ********************/
@@ -2838,73 +3012,79 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
   private void recordBadConstructor(String msg) {
     reportMigrateFailed("Constructor is incorrect, " + msg);
   }
-      
-//  private void reportParseException() {
-//    reportMigrateFailed("Unparsable Java");
-//  }
-  
+
+  // private void reportParseException() {
+  // reportMigrateFailed("Unparsable Java");
+  // }
+
   private void migrationFailed(String reason) {
     failedMigration.add(new PathContainerAndReason(current_path, current_container, reason));
-    isConvert2v3 = false;    
+    isConvert2v3 = false;
   }
-  
+
   private void reportMigrateFailed(String m) {
     System.out.format("Skipping this file due to error: %s, path: %s%n", m, current_path);
     migrationFailed(m);
   }
-  
+
   private void reportV2Class() {
-//    v2JCasFiles.add(current_path);
+    // v2JCasFiles.add(current_path);
     isV2JCas = true;
   }
-  
+
   private void reportV3Class() {
-//    v3JCasFiles.add(current_path);
+    // v3JCasFiles.add(current_path);
     isConvert2v3 = true;
   }
-  
+
   private void reportNotJCasClass(String reason) {
     nonJCasFiles.add(new PathContainerAndReason(current_path, current_container, reason));
     isConvert2v3 = false;
   }
-  
+
   private void reportNotJCasClassMissingTypeFields() {
     reportNotJCasClass("missing required type and/or typeIndexID static fields");
   }
-  
+
   private void reportDeletedCheckModified(String m) {
     deletedCheckModified.add(new PathContainerAndReason(current_path, current_container, m));
   }
-  
+
   private void reportMismatchedFeatureName(String m) {
-    manualInspection.add(new PathContainerAndReason(current_path, current_container, 
-        "This getter/setter name doesn't match internal feature name: " + m));
+    manualInspection.add(new PathContainerAndReason(current_path, current_container,
+            "This getter/setter name doesn't match internal feature name: " + m));
   }
-  
+
   private void reportUnrecognizedV2Code(String m) {
     migrationFailed("V2 code not recognized:\n" + m);
   }
-  
+
   private void reportPathWorkaround(String orig, String modified) {
     pathWorkaround.add(new String1AndString2(orig, modified));
   }
-  
-  private void reportPearOrJarClassReplace(String pearOrJar, String classname, Container kind) { // pears or jars
+
+  private void reportPearOrJarClassReplace(String pearOrJar, String classname, Container kind) { // pears
+                                                                                                 // or
+                                                                                                 // jars
     if (kind.isPear) {
       pearClassReplace.add(new String1AndString2(pearOrJar, classname));
     } else {
       jarClassReplace.add(new String1AndString2(pearOrJar, classname));
     }
-  }  
-  
+  }
+
   /***********************************************/
   /**
-   * Output directory for source and migrated files
-   * Consisting of converted/skipped, v2/v3, a+cc.id, slashified classname      
-   * @param cc -
-   * @param isV2 -
-   * @param wasConverted -
-   * @return converted/skipped, v2/v3, a+cc.id, slashified classname      
+   * Output directory for source and migrated files Consisting of converted/skipped, v2/v3, a+cc.id,
+   * slashified classname
+   * 
+   * @param cc
+   *          -
+   * @param isV2
+   *          -
+   * @param wasConverted
+   *          -
+   * @return converted/skipped, v2/v3, a+cc.id, slashified classname
    */
   private String getBaseOutputPath(CommonConverted cc, boolean isV2, boolean wasConverted) {
     StringBuilder sb = new StringBuilder();
@@ -2913,85 +3093,106 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
     sb.append("a").append(cc.getId()).append('/');
     sb.append(cc.fqcn_slash).append(".java");
     return sb.toString();
-  }  
-  
+  }
+
   private void writeV2Orig(CommonConverted cc, boolean wasConverted) throws IOException {
-    String base = getBaseOutputPath(cc, true, wasConverted);  // adds numeric suffix if dupls
+    String base = getBaseOutputPath(cc, true, wasConverted); // adds numeric suffix if dupls
     FileUtils.writeToFile(makePath(base), cc.v2Source);
   }
-  
+
   private void writeV3(CommonConverted cc) throws IOException {
-    String base = getBaseOutputPath(cc, false, true); 
+    String base = getBaseOutputPath(cc, false, true);
     cc.v3SourcePath = makePath(base);
     String data = fixImplementsBug(cc.v3Source);
     FileUtils.writeToFile(cc.v3SourcePath, data);
   }
-  
+
   private void printUsage() {
-    System.out.println(
-        "Usage: java org.apache.uima.migratev3.jcas.MigrateJCas \n"
-        + "  [-sourcesRoots <One-or-more-directories-or-jars-separated-by-Path-separator, or a path to a single JCas source class>]\n"
-        + "  [-classesRoots <One-or-more-directories-or-jars-or-pears-separated-by-Path-separator>]\n"
-        + "  [-outputDirectory a-writable-directory-path (optional)\n"
-        + "     if omitted, a temporary directory is used\n"
-        + "     if not omitted, the directory contents WILL BE ERASED at the start.\n"
-        + "  [-migrateClasspath a-class-path to use in decompiling, when -classesRoots is specified\n"
-        + "                     also used when compiling the migrated classes.\n"
-        + "  NOTE: either -sourcesRoots or -classesRoots is required, but only one may be specified.\n"
-        + "  NOTE: classesRoots are scanned for JCas classes, which are then decompiled, and the results processed like sourcesRoots\n"
-       );
+    System.out.println("Usage: java org.apache.uima.migratev3.jcas.MigrateJCas \n"
+            + "  [-sourcesRoots <One-or-more-directories-or-jars-separated-by-Path-separator, or a path to a single JCas source class>]\n"
+            + "  [-classesRoots <One-or-more-directories-or-jars-or-pears-separated-by-Path-separator>]\n"
+            + "  [-outputDirectory a-writable-directory-path (optional)\n"
+            + "     if omitted, a temporary directory is used\n"
+            + "     if not omitted, the directory contents WILL BE ERASED at the start.\n"
+            + "  [-migrateClasspath a-class-path to use in decompiling, when -classesRoots is specified\n"
+            + "                     also used when compiling the migrated classes.\n"
+            + "  NOTE: either -sourcesRoots or -classesRoots is required, but only one may be specified.\n"
+            + "  NOTE: classesRoots are scanned for JCas classes, which are then decompiled, and the results processed like sourcesRoots\n");
   }
 
   private static final Pattern implementsEmpty = Pattern.compile("implements  \\{");
+
   private String fixImplementsBug(String data) {
     return implementsEmpty.matcher(data).replaceAll("{");
   }
-       
+
   /*********************************************************************
    * Reporting classes
    *********************************************************************/
-  
+
   private static abstract class Report2<T, U> {
-    public abstract Comparable<T> getFirst(); // Eclipse on linux complained if not public, was OK on windows
-    public abstract Comparable<U> getSecond();  
+    public abstract Comparable<T> getFirst(); // Eclipse on linux complained if not public, was OK
+                                              // on windows
+
+    public abstract Comparable<U> getSecond();
+
     abstract int getFirstLength();
   }
- 
+
   private static class PathContainerAndReason extends Report2<ContainerAndPath, String> {
     final ContainerAndPath cap;
     final String reason;
+
     PathContainerAndReason(ContainerAndPath cap, String reason) {
       this.cap = cap;
       this.reason = reason;
     }
-    
+
     PathContainerAndReason(Path path, Container container, String reason) {
       this(new ContainerAndPath(path, container), reason);
     }
-    
+
     @Override
-    public Comparable<ContainerAndPath> getFirst() { return cap; }
+    public Comparable<ContainerAndPath> getFirst() {
+      return cap;
+    }
+
     @Override
-    public Comparable<String> getSecond() { return reason; }
+    public Comparable<String> getSecond() {
+      return reason;
+    }
+
     @Override
-    int getFirstLength() { return cap.toString().length(); }
+    int getFirstLength() {
+      return cap.toString().length();
+    }
   }
-    
+
   private static class String1AndString2 extends Report2<String, String> {
     String s1;
     String s2;
+
     String1AndString2(String s1, String s2) {
       this.s1 = s1;
       this.s2 = s2;
     }
+
     @Override
-    public Comparable<String> getFirst() { return s1; }
+    public Comparable<String> getFirst() {
+      return s1;
+    }
+
     @Override
-    public Comparable<String> getSecond() { return s2; }
+    public Comparable<String> getSecond() {
+      return s2;
+    }
+
     @Override
-    int getFirstLength() { return s1.toString().length(); }
+    int getFirstLength() {
+      return s1.toString().length();
+    }
   }
-  
+
   private static void withIOX(Runnable_withException r) {
     try {
       r.run();
@@ -2999,11 +3200,11 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       throw new UIMARuntimeException(e);
     }
   }
-  
+
   private int findFirstCharDifferent(String s1, String s2) {
     int s1l = s1.length();
     int s2l = s2.length();
-    for (int i = 0;;i++) {
+    for (int i = 0;; i++) {
       if (i == s1l || i == s2l) {
         return i;
       }
@@ -3012,549 +3213,560 @@ public class MigrateJCas extends VoidVisitorAdapter<Object> {
       }
     }
   }
-//  private String drop_Type(String s) {
-//    return s.substring(0, isSource ? "_Type.java".length() 
-//                                     : "_Type.class".length()) + 
-//          (isSource ? ".java" : ".class");  
-//  }
-
-///*****************
-//* Root-id
-//*****************/
-//private static int nextRootId = 1;
-//
-///***********************************************************************
-//* Root-id - this is the path part up to the start of the package name.
-//*   - it is relative to container
-//*   - has the collection of artifacts that might be candidates, having this rootId
-//*   - has the collection of _Type things having this rootId
-//*   - "null" path is OK - means package name starts immediately
-//* There is no Root-id for path ending in Jar or PEAR - these created containers instead
-//***********************************************************************/
-//private static class RootId {
-// final int id = nextRootId++;   
-// /**
-//  * The path relative to the the container (if any) (= Jar or Pear)
-//  *   - for Pears, the path is as if it was not installed, but within the PEAR file
-//  */
-// final Path path;
-// 
-// /** The container holding this RootId */
-// final Container container;
-// /**
-//  * For this rootId, all of the fully qualified classnames that are migration eligible.
-//  *   - not all might be migrated, if upon further inspection they are not JCas class files.
-//  */
-// final Set<Fqcn> fqcns = new HashSet<>();
-// final Set<String> fqcns_ignore_case = new HashSet<>();
-// boolean haveDifferentCapitalizedNamesCollidingOnWindows = false;
-//    
-// RootId(Path path, Container container) {
-//   this.path = path;
-//   this.container = container;
-// }
-//
-// /* (non-Javadoc)
-//  * @see java.lang.Object#toString()
-//  */
-// @Override
-// public String toString() {
-//   return "RootId [id=" 
-//       + id 
-//       + ", path=" 
-//       + path 
-//       + ", container=" 
-//       + container.id 
-//       + ", fqcns="
-//       + Misc.ppList(Misc.setAsList(fqcns)) 
-//       + ", fqcns_Type="
-//       + Misc.ppList(Misc.setAsList(fqcns_Type)) 
-//       + "]";
-// }
-// 
-// void add(Fqcn fqcn) {
-//   boolean wasNotPresent = fqcns.add(fqcn);
-//   boolean lc = fqcns_ignore_case.add(fqcn.fqcn_dots.toLowerCase());
-//   if (!lc && wasNotPresent) {
-//     haveDifferentCapitalizedNamesCollidingOnWindows = true;
-//   }
-// }
-// 
-// boolean hasMatching_Type(Fqcn fqcn) {
-//   
-// }
-//}
-///**
-//* Called from Stream walker starting at a root or starting at an imbedded Jar or Pear.
-//* 
-//* adds all the .java or .class files to the candidates, including _Type if not skipping the _Type check
-//* Handling embedded jar files
-//*   - single level Jar (at the top level of the default file system)
-//*     -- handle using an overlayed file system
-//*   - embedded Jars within Jars: 
-//*     - not supported by Zip File System Provider (it only supports one level)
-//*     - handle by extracting to a temp dir, and then using the Zip File System Provider
-//* @param path the path to a .java or .class or .jar or .pear
-//* @param pearClasspath - a string representing a path to the pear's classpath if there is one, or null
-//*/
-//private void getCandidates_processFile(Path path, String pearClasspath) {
-//// if (path.toString().contains("commons-httpclient-3.1.jar"))
-////   System.out.println("Debug: " + path.toString());
-//// System.out.println("debug processing " + path);
-// try {
-////   URI pathUri = path.toUri();
-//   String pathString = path.toString();
-//   final boolean isPear = pathString.endsWith(".pear"); // path.endsWith does not mean this !!
-//   final boolean isJar = pathString.endsWith(".jar");
-//         
-//   if (isJar || isPear) {  
-//     if (!path.getFileSystem().equals(FileSystems.getDefault())) {        
-//       // embedded Pear or Jar: extract to temp
-//       Path out = getTempOutputPathForJar(path);
-//       Files.copy(path, out, StandardCopyOption.REPLACE_EXISTING);
-////       embeddedJars.add(new PathAndPath(path, out));
-//       path = out;   // path points to pear or jar
-//     }
-//     
-//     Path start;
-//     final String localPearClasspath; 
-//     if (isPear) {
-//       if (pearClasspath != null) {
-//         throw new UIMARuntimeException("Nested PEAR files not supported");
-//       }
-//       
-////       pear_current = new PearOrJar(path);
-////       pears.add(pear_current);
-//       // add pear classpath info
-//       File pearInstallDir = Files.createTempDirectory(getTempDir(), "installedPear").toFile();
-//       PackageBrowser ip = PackageInstaller.installPackage(pearInstallDir, path.toFile(), false);
-//       localPearClasspath = ip.buildComponentClassPath();
-//       String[] children = pearInstallDir.list();
-//       if (children == null || children.length != 1) {
-//         Misc.internalError();
-//       }
-//       pearResolveStart = Paths.get(pearInstallDir.getAbsolutePath(), children[0]);
-//       
-//       start = pearInstallDir.toPath();
-//     } else {
-//       if (isJar) {
-//         PearOrJar jarInfo = new PearOrJar(path);
-//         pear_or_jar_current_stack.push(jarInfo);
-//         jars.add(jarInfo);
-//       }
-//       
-//       localPearClasspath = pearClasspath;
-//       FileSystem jfs = FileSystems.newFileSystem(Paths.get(path.toUri()), null);
-//       start = jfs.getPath("/");
-//     }
-//     
-//     try (Stream<Path> stream = Files.walk(start)) {  // needed to release file handles
-//       stream.forEachOrdered(
-//         p -> getCandidates_processFile(p, localPearClasspath));
-//     }
-//     if (isJar) {
-//       pear_or_jar_current_stack.pop();
-//     }
-//     if (isPear) {
-//       pear_current = null;
-//     }
-//   } else {
-//     // is not a .jar or .pear file.  add .java or .class files to initial candidate set
-//     //    will be filtered additionally later
-////     System.out.println("debug path ends with java or class " + pathString.endsWith(isSource ? ".java" : ".class") + " " + pathString);
-//     if (pathString.endsWith(isSource ? ".java" : ".class")) {
-//       candidates.add(new Candidate(path, pearClasspath));
-//       if (!isSource && null != pear_current) {
-//         // inside a pear, which has been unzipped into pearInstallDir;
-//         path2InsidePearOrJarPath.put(path.toString(), pearResolveStart.relativize(path).toString());                
-//         pear_current.pathsToCandidateFiles.add(path.toString());           
-//       }
-//       
-//       if (!isSource && pear_or_jar_current_stack.size() > 0) {
-//         // inside a jar, not contained in a pear                
-//         pear_or_jar_current_stack.getFirst().pathsToCandidateFiles.add(path.toString());    
-//       }
-//     }
-//   }
-// } catch (IOException e) {
-//   throw new RuntimeException(e);
-// }
-//}
-//private void postProcessPearsOrJars(String kind, List<PearOrJar> pearsOrJars, List<String1AndString2> classReplace) {  // pears or jars
-//try {
-//  Path outDir = Paths.get(outputDirectory, kind);
-//  FileUtils.deleteRecursive(outDir.toFile());
-//  Files.createDirectories(outDir);
-//} catch (IOException e) {
-//  throw new RuntimeException(e);
-//}
-//
-//// pearsOrJars may have entries with 0 candidate paths.  This happens when we scan them
-//// but find nothing to convert.  
-//// eliminate these.
-//
-//Iterator<PearOrJar> it = pearsOrJars.iterator();
-//while (it.hasNext()) {
-//  PearOrJar poj = it.next();
-//  if (poj.pathsToCandidateFiles.size() == 0) {
-//    it.remove();
-//  } else {
-////    //debug
-////    if (poj.pathToPearOrJar.toString().contains("commons-httpclient-3.1")) {
-////      System.err.println("debug found converted things inside commons-httpclient");;
-////      for (String x : poj.pathsToCandidateFiles) {
-////        System.err.println(x);
-////      }
-////      System.err.println("");
-////    }
-//  }
-//}
-//
-//it = pearsOrJars.iterator();
-//while (it.hasNext()) {
-//  PearOrJar poj = it.next();
-//  if (poj.pathsToCandidateFiles.size() == 0) {
-//    System.err.print("debug failed to remove unconverted Jar");
-//  }
-//}
-//
-//if (pearsOrJars.size() == 0) {
-//  System.out.format("No .class files were replaced in %s.%n", kind);
-//} else {
-//  System.out.format("replacing .class files in %,d %s%n", pearsOrJars.size(), kind);
-//  for (PearOrJar p : pearsOrJars) {
-//    pearOrJarPostProcessing(p, kind);
-//  }
-//  try {
-//    reportPaths("Reports of updated " + kind, kind + "FileUpdates.txt", classReplace);
-//   
-//  } catch (IOException e) {
-//    throw new RuntimeException(e);
-//  }
-//}
-//
-//}
-///**
-//* When running the compiler to compile v3 sources, we need a classpath that at a minimum
-//* includes uimaj-core.  The strategy is to use the invoker of this tool's classpath as
-//* specified from the application class loader
-//* @return true if no errors
-//*/
-//private boolean compileV3SourcesCommon(List<ClassnameAndPath> items, String msg, String pearClasspath) {
-// 
-// if (items.size() == 0) {
-//   return true;
-// }
-// System.out.format("Compiling %,d classes %s -- This may take a while!%n", c2ps.size(), msg);
-// StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null, Charset.forName("UTF-8"));
-// 
-// List<String> cus = items.stream()
-//                         .map(c -> outDirConverted + "v3/" + c.classname + ".java")
-//                         .collect(Collectors.toList());
-// 
-// Iterable<String> compilationUnitStrings = cus;
-//
-// Iterable<? extends JavaFileObject> compilationUnits = 
-//     fileManager.getJavaFileObjectsFromStrings(compilationUnitStrings);
-// 
-// // specify where the output classes go
-// String classesBaseDir = outDirConverted + "v3-classes";
-// try {
-//   Files.createDirectories(Paths.get(classesBaseDir));
-// } catch (IOException e) {
-//   throw new UIMARuntimeException(e);
-// }
-// // specify the classpath
-// String classpath = getCompileClassPath(pearClasspath);
-// Iterable<String> options = Arrays.asList("-d", classesBaseDir,
-//                                          "-classpath", classpath);
-// return javaCompiler.getTask(null, fileManager, null, options, null, compilationUnits).call();    
-//}
-///**
-//* Called after class is migrated
-//* Given a path to a class (source or class file), 
-//* return the URL to the class as found in the classpath.
-//*   This returns the "first" one found in the classpath, in the case of duplicates.
-//* @param path
-//* @return the location of the class in the class path
-//*/
-//private URL getPathForClass(Path path) {
-// return (null == packageAndClassNameSlash) 
-//          ? null 
-//          : migrateClassLoader.getResource(packageAndClassNameSlash + ".class");
-//}
-//private void getBaseOutputPath() {
-//String s = packageAndClassNameSlash;
-//int i = 0;
-//while (!usedPackageAndClassNames.add(s)) {
-//  i = i + 1;
-//  s = packageAndClassNameSlash + "_dupid_" + i;
-//}
-//packageAndClassNameSlash_i = i;
-//}
-//private String prepareIndividual(String classname) {
-//candidate = new Candidate(Paths.get(classname)); // a pseudo path
-//packageName = null;
-//className = null;
-//packageAndClassNameSlash = null;
-//cu = null;
-//return decompile(classname); // always look up in classpath
-//                             // to decompile individual source - put in sourcesRoots
-//}
-//if (!isSource)  {  // skip this recording if source
-//if (null != pear_current) {
-//  // inside a pear, which has been unzipped into a temporary pearInstallDir;
-//  // we don't want that temporary dir to be part of the path.
-//  path2InsidePearOrJarPath.put(path.toString(), pearResolveStart.relativize(path).toString());                
-//  pear_current.pathsToCandidateFiles.add(path.toString());           
-//}
-//
-//if (!isSource && pear_or_jar_current_stack.size() > 0) {
-//  // inside a jar, not contained in a pear                
-//  pear_or_jar_current_stack.getFirst().pathsToCandidateFiles.add(path.toString());    
-//}
-//}
-//}
-///**
-//* For a given candidate, use its path:
-//*   switch the ...java to ..._Type.java, or ...class to ..._Type.class
-//*   look thru all the candidates
-//* @param cand
-//* @param start
-//* @return
-//*/
-//private boolean has_Type(Candidate cand, int start) {
-// if (start >= candidates.size()) {
-//   return false;
-// }
-//
-// String sc = cand.p.toString();
-// String sc_minus_suffix = sc.substring(0,  sc.length() - ( isSource ? ".java".length() : ".class".length())); 
-// String sc_Type = sc_minus_suffix + ( isSource ? "_Type.java" : "_Type.class");
-// // a string which sorts beyond the candidate + a suffix of "_"
-// String s_end = sc_minus_suffix + (char) (((int)'_') + 1);
-// for (Candidate c : candidates.subList(start,  candidates.size())) {
-//   String s = c.p.toString();
-//   if (s_end.compareTo(s) < 0) {
-//     return false;  // not found, we're already beyond where it would be found
-//   }
-//   if (s.equals(sc_Type)) {
-//     return true;
-//   }
-// }
-// return false;
-//}
-//private final static Comparator<Candidate> pathComparator = new Comparator<Candidate>() {
-//@Override
-//public int compare(Candidate o1, Candidate o2) {
-//  return o1.p.toString().compareTo(o2.p.toString());
-//}
-//};
-
-//// there may be several same-name roots not quite right
-////   xxx_Type$1.class
-//
-//private void addIfPreviousIsSameName(List<Path> c, int i) {
-//if (i == 0) return;
-//String _Type = candidates.get(i).toString();
-////String prev = r.get(i-1).getPath();
-//String prefix = _Type.substring(0, _Type.length() - ("_Type." + (isSource ? "java" : "class")).length());
-//i--;
-//while (i >= 0) {
-//  String s = candidates.get(i).toString();
-//  if ( ! s.startsWith(prefix)) {
-//    break;
-//  }
-//  if (s.substring(prefix.length()).equals((isSource ? ".java" : ".class"))) {
-//    c.add(candidates.get(i));
-//    break;
-//  }
-//  i--;
-//}
-//}
-
-  
-//
-//for (int i = 0; i < pearOrJar.pathsToCandidateFiles.size(); i++) {
-//  String candidatePath = pearOrJar.pathsToCandidateFiles.get(i);
-//  String path_in_v3_classes = isPear
-//                                ? getPath_in_v3_classes(candidatePath)
-//                                : candidatePath;
-//
-//  Path src = Paths.get(outputDirectory, "converted/v3-classes", path_in_v3_classes 
-//      + (isPear ? ".class" : ""));
-//  Path tgt = pfs.getPath(
-//      "/", 
-//      isPear 
-//        ? path2InsidePearOrJarPath.get(candidatePath) // needs to be bin/org/... etc
-//        : candidatePath);  // needs to be org/... etc
-//  if (Files.exists(src)) {
-//    Files.copy(src, tgt, StandardCopyOption.REPLACE_EXISTING);
-//    reportPearOrJarClassReplace(pearOrJarCopy.toString(), path_in_v3_classes, kind);
-//  }
-//}
-
-///** for compiled mode, do recompiling and reassembly of Jars and Pears */
-//
-//private boolean compileAndReassemble(CommonConverted cc, Container container, Path path) {
-//  boolean noErrors = true;
-//  if (javaCompiler != null) {
-//    if (container.haveDifferentCapitalizedNamesCollidingOnWindows) {
-//      System.out.println("Skipping compiling / reassembly because class " + container.toString() + " has multiple names differing only in capitalization, please resolve first.");
-//    } else {
-//      
-//      
-//      noErrors = compileV3PearSources(container, path);
-//      noErrors = noErrors && compileV3NonPearSources(container, path);
-//      
-//      postProcessPearsOrJars("jars" , jars ,  jarClassReplace);
-//      postProcessPearsOrJars("pears", pears, pearClassReplace);
-//    
-////  
-////    try {
-////      Path pearOutDir = Paths.get(outputDirectory, "pears");
-////      FileUtils.deleteRecursive(pearOutDir.toFile());
-////      Files.createDirectories(pearOutDir);
-////    } catch (IOException e) {
-////      throw new RuntimeException(e);
-////    }
-////      
-////    System.out.format("replacing .class files in %,d PEARs%n", pears.size());
-////    for (PearOrJar p : pears) {
-////      pearOrJarPostProcessing(p);
-////    }
-////    try {
-////      reportPaths("Reports of updated Pears", "pearFileUpdates.txt", pearClassReplace);
-////    } catch (IOException e) {
-////      throw new RuntimeException(e);
-////    }
-//    }
-//  }
-//  
-//  return noErrors;
-//}
-
-///**
-//* @return true if no errors
-//*/
-//private boolean compileV3PearSources() {
-// boolean noError = true;
-// Map<String, List<ClassnameAndPath>> p2c = c2ps.stream()
-//   .filter(c -> c.pearClasspath != null)
-//   .collect(Collectors.groupingBy(c -> c.pearClasspath));
-// 
-// List<Entry<String, List<ClassnameAndPath>>> ea = p2c.entrySet().stream()
-//         .sorted(Comparator.comparing(Entry::getKey)) //(e1, e2) -> e1.getKey().compareTo(e2.getKey())
-//         .collect(Collectors.toList());
-//
-// for (Entry<String, List<ClassnameAndPath>> e : ea) {
-//   noError = noError && compileV3SourcesCommon(e.getValue(), "for Pear " + e.getKey(), e.getKey() );
-// }
-// return noError;
-//}
-//
-///**
-//* @return true if no errors
-//*/
-//private boolean compileV3NonPearSources() {
-// 
-// List<ClassnameAndPath> cnps = c2ps.stream()
-//                                   .filter(c -> c.pearClasspath == null)
-//                                   .collect(Collectors.toList());
-// 
-// return compileV3SourcesCommon(cnps, "(non PEAR)", null);
-//}
-
-///**
-//* @param pathInPear a complete path to a class inside an (installed) pear
-//* @return the part starting after the top node of the install dir
-//*/
-//private String getPath_in_v3_classes(String pathInPear) { 
-// return path2classname.get(pathInPear);  
-//}
-  
-//private boolean reportDuplicates() throws IOException {
-//List<List<CommonConverted>> nonIdenticals = new ArrayList<>();
-//List<CommonConverted> onlyIdenticals = new ArrayList<>();
-//
-//classname2multiSources.forEach(
-//      (classname, ccs) -> {
-//        if (ccs.size() > 1) {
-//          nonIdenticals.add(ccs);
-//        } else {
-//          CommonConverted cc = ccs.get(0);
-//          if (cc.containersAndV2Paths.size() > 1) 
-//            onlyIdenticals.add(cc);  // the same item in multiple containers and/or paths
-//        }
-//      }
-//    );
-//
-//if (nonIdenticals.size() == 0) {
-//  if (onlyIdenticals.size() == 0) {
-//    System.out.println("There were no duplicates found.");
-//  } else {
-//    // report identical duplicates
-//    try (BufferedWriter bw = Files.newBufferedWriter(makePath(outDirLog + "identical_duplicates.txt"), StandardOpenOption.CREATE)) {
-//      logPrintNl("Report of Identical duplicates:", bw);
-//      for (CommonConverted cc : onlyIdenticals) {
-//        int i = 0;
-//        logPrintNl("Class: " + cc.fqcn_slash, bw);
-//        for (ContainerAndPath cp : cc.containersAndV2Paths) {
-//          logPrintNl("  " + (++i) + " " + cp, bw);
-//        }
-//        logPrintNl("", bw);
-//      }
-//    }
-//  }
-//  return true;
-//} 
-//
-//// non-identicals, print out all of them
-//try (BufferedWriter bw = Files.newBufferedWriter(makePath(outDirLog + "nonIdentical_duplicates.txt"), StandardOpenOption.CREATE)) {
-//  logPrintNl("Report of non-identical duplicates", bw);
-//  for (List<CommonConverted> nonIdentical : nonIdenticals) {
-//    String fqcn = nonIdentical.get(0).fqcn_slash;
-//    logPrintNl("  classname: " + fqcn, bw);
-//    int i = 1;
-//    // for each cc, and within each cc, for each containerAndPath
-//    for (CommonConverted cc : nonIdentical) {
-////      logPrintNl("    version " + i, bw);
-//      assert fqcn.equals(cc.fqcn_slash);
-//      int j = 1;
-//      boolean isSame = cc.containersAndV2Paths.size() > 1;
-//      boolean isFirstTime = true;
-//      for (ContainerAndPath cp : cc.containersAndV2Paths) {
-//        String first = isSame && isFirstTime 
-//                        ? "      same: "
-//                        : isSame 
-//                           ? "            "
-//                           : "      ";
-//        isFirstTime = false;
-//        logPrintNl(first + i + "." + (j++) + " " + cp, bw);
-//      }
-//      indent[0] -= 6;
-////      logPrintNl("", bw);
-//      i++;
-//    }
-////    logPrintNl("", bw);
-//  }
-//}
-//return false;
-//}
-  
-//private static class PathAndReason extends Report2<Path, String> {
-//Path path;
-//String reason;
-//PathAndReason(Path path, String reason) {
-//  this.path = path;
-//  this.reason = reason;
-//}
-//@Override
-//public Comparable<Path> getFirst() { return path; }
-//@Override
-//public Comparable<String> getSecond() { return reason; }
-//@Override
-//int getFirstLength() { return path.toString().length(); }
-//}
+  // private String drop_Type(String s) {
+  // return s.substring(0, isSource ? "_Type.java".length()
+  // : "_Type.class".length()) +
+  // (isSource ? ".java" : ".class");
+  // }
+
+  /// *****************
+  // * Root-id
+  // *****************/
+  // private static int nextRootId = 1;
+  //
+  /// ***********************************************************************
+  // * Root-id - this is the path part up to the start of the package name.
+  // * - it is relative to container
+  // * - has the collection of artifacts that might be candidates, having this rootId
+  // * - has the collection of _Type things having this rootId
+  // * - "null" path is OK - means package name starts immediately
+  // * There is no Root-id for path ending in Jar or PEAR - these created containers instead
+  // ***********************************************************************/
+  // private static class RootId {
+  // final int id = nextRootId++;
+  // /**
+  // * The path relative to the the container (if any) (= Jar or Pear)
+  // * - for Pears, the path is as if it was not installed, but within the PEAR file
+  // */
+  // final Path path;
+  //
+  // /** The container holding this RootId */
+  // final Container container;
+  // /**
+  // * For this rootId, all of the fully qualified classnames that are migration eligible.
+  // * - not all might be migrated, if upon further inspection they are not JCas class files.
+  // */
+  // final Set<Fqcn> fqcns = new HashSet<>();
+  // final Set<String> fqcns_ignore_case = new HashSet<>();
+  // boolean haveDifferentCapitalizedNamesCollidingOnWindows = false;
+  //
+  // RootId(Path path, Container container) {
+  // this.path = path;
+  // this.container = container;
+  // }
+  //
+  // /* (non-Javadoc)
+  // * @see java.lang.Object#toString()
+  // */
+  // @Override
+  // public String toString() {
+  // return "RootId [id="
+  // + id
+  // + ", path="
+  // + path
+  // + ", container="
+  // + container.id
+  // + ", fqcns="
+  // + Misc.ppList(Misc.setAsList(fqcns))
+  // + ", fqcns_Type="
+  // + Misc.ppList(Misc.setAsList(fqcns_Type))
+  // + "]";
+  // }
+  //
+  // void add(Fqcn fqcn) {
+  // boolean wasNotPresent = fqcns.add(fqcn);
+  // boolean lc = fqcns_ignore_case.add(fqcn.fqcn_dots.toLowerCase());
+  // if (!lc && wasNotPresent) {
+  // haveDifferentCapitalizedNamesCollidingOnWindows = true;
+  // }
+  // }
+  //
+  // boolean hasMatching_Type(Fqcn fqcn) {
+  //
+  // }
+  // }
+  /// **
+  // * Called from Stream walker starting at a root or starting at an imbedded Jar or Pear.
+  // *
+  // * adds all the .java or .class files to the candidates, including _Type if not skipping the
+  /// _Type check
+  // * Handling embedded jar files
+  // * - single level Jar (at the top level of the default file system)
+  // * -- handle using an overlayed file system
+  // * - embedded Jars within Jars:
+  // * - not supported by Zip File System Provider (it only supports one level)
+  // * - handle by extracting to a temp dir, and then using the Zip File System Provider
+  // * @param path the path to a .java or .class or .jar or .pear
+  // * @param pearClasspath - a string representing a path to the pear's classpath if there is one,
+  /// or null
+  // */
+  // private void getCandidates_processFile(Path path, String pearClasspath) {
+  //// if (path.toString().contains("commons-httpclient-3.1.jar"))
+  //// System.out.println("Debug: " + path.toString());
+  //// System.out.println("debug processing " + path);
+  // try {
+  //// URI pathUri = path.toUri();
+  // String pathString = path.toString();
+  // final boolean isPear = pathString.endsWith(".pear"); // path.endsWith does not mean this !!
+  // final boolean isJar = pathString.endsWith(".jar");
+  //
+  // if (isJar || isPear) {
+  // if (!path.getFileSystem().equals(FileSystems.getDefault())) {
+  // // embedded Pear or Jar: extract to temp
+  // Path out = getTempOutputPathForJar(path);
+  // Files.copy(path, out, StandardCopyOption.REPLACE_EXISTING);
+  //// embeddedJars.add(new PathAndPath(path, out));
+  // path = out; // path points to pear or jar
+  // }
+  //
+  // Path start;
+  // final String localPearClasspath;
+  // if (isPear) {
+  // if (pearClasspath != null) {
+  // throw new UIMARuntimeException("Nested PEAR files not supported");
+  // }
+  //
+  //// pear_current = new PearOrJar(path);
+  //// pears.add(pear_current);
+  // // add pear classpath info
+  // File pearInstallDir = Files.createTempDirectory(getTempDir(), "installedPear").toFile();
+  // PackageBrowser ip = PackageInstaller.installPackage(pearInstallDir, path.toFile(), false);
+  // localPearClasspath = ip.buildComponentClassPath();
+  // String[] children = pearInstallDir.list();
+  // if (children == null || children.length != 1) {
+  // Misc.internalError();
+  // }
+  // pearResolveStart = Paths.get(pearInstallDir.getAbsolutePath(), children[0]);
+  //
+  // start = pearInstallDir.toPath();
+  // } else {
+  // if (isJar) {
+  // PearOrJar jarInfo = new PearOrJar(path);
+  // pear_or_jar_current_stack.push(jarInfo);
+  // jars.add(jarInfo);
+  // }
+  //
+  // localPearClasspath = pearClasspath;
+  // FileSystem jfs = FileSystems.newFileSystem(Paths.get(path.toUri()), null);
+  // start = jfs.getPath("/");
+  // }
+  //
+  // try (Stream<Path> stream = Files.walk(start)) { // needed to release file handles
+  // stream.forEachOrdered(
+  // p -> getCandidates_processFile(p, localPearClasspath));
+  // }
+  // if (isJar) {
+  // pear_or_jar_current_stack.pop();
+  // }
+  // if (isPear) {
+  // pear_current = null;
+  // }
+  // } else {
+  // // is not a .jar or .pear file. add .java or .class files to initial candidate set
+  // // will be filtered additionally later
+  //// System.out.println("debug path ends with java or class " + pathString.endsWith(isSource ?
+  /// ".java" : ".class") + " " + pathString);
+  // if (pathString.endsWith(isSource ? ".java" : ".class")) {
+  // candidates.add(new Candidate(path, pearClasspath));
+  // if (!isSource && null != pear_current) {
+  // // inside a pear, which has been unzipped into pearInstallDir;
+  // path2InsidePearOrJarPath.put(path.toString(), pearResolveStart.relativize(path).toString());
+  // pear_current.pathsToCandidateFiles.add(path.toString());
+  // }
+  //
+  // if (!isSource && pear_or_jar_current_stack.size() > 0) {
+  // // inside a jar, not contained in a pear
+  // pear_or_jar_current_stack.getFirst().pathsToCandidateFiles.add(path.toString());
+  // }
+  // }
+  // }
+  // } catch (IOException e) {
+  // throw new RuntimeException(e);
+  // }
+  // }
+  // private void postProcessPearsOrJars(String kind, List<PearOrJar> pearsOrJars,
+  /// List<String1AndString2> classReplace) { // pears or jars
+  // try {
+  // Path outDir = Paths.get(outputDirectory, kind);
+  // FileUtils.deleteRecursive(outDir.toFile());
+  // Files.createDirectories(outDir);
+  // } catch (IOException e) {
+  // throw new RuntimeException(e);
+  // }
+  //
+  //// pearsOrJars may have entries with 0 candidate paths. This happens when we scan them
+  //// but find nothing to convert.
+  //// eliminate these.
+  //
+  // Iterator<PearOrJar> it = pearsOrJars.iterator();
+  // while (it.hasNext()) {
+  // PearOrJar poj = it.next();
+  // if (poj.pathsToCandidateFiles.size() == 0) {
+  // it.remove();
+  // } else {
+  //// //debug
+  //// if (poj.pathToPearOrJar.toString().contains("commons-httpclient-3.1")) {
+  //// System.err.println("debug found converted things inside commons-httpclient");;
+  //// for (String x : poj.pathsToCandidateFiles) {
+  //// System.err.println(x);
+  //// }
+  //// System.err.println("");
+  //// }
+  // }
+  // }
+  //
+  // it = pearsOrJars.iterator();
+  // while (it.hasNext()) {
+  // PearOrJar poj = it.next();
+  // if (poj.pathsToCandidateFiles.size() == 0) {
+  // System.err.print("debug failed to remove unconverted Jar");
+  // }
+  // }
+  //
+  // if (pearsOrJars.size() == 0) {
+  // System.out.format("No .class files were replaced in %s.%n", kind);
+  // } else {
+  // System.out.format("replacing .class files in %,d %s%n", pearsOrJars.size(), kind);
+  // for (PearOrJar p : pearsOrJars) {
+  // pearOrJarPostProcessing(p, kind);
+  // }
+  // try {
+  // reportPaths("Reports of updated " + kind, kind + "FileUpdates.txt", classReplace);
+  //
+  // } catch (IOException e) {
+  // throw new RuntimeException(e);
+  // }
+  // }
+  //
+  // }
+  /// **
+  // * When running the compiler to compile v3 sources, we need a classpath that at a minimum
+  // * includes uimaj-core. The strategy is to use the invoker of this tool's classpath as
+  // * specified from the application class loader
+  // * @return true if no errors
+  // */
+  // private boolean compileV3SourcesCommon(List<ClassnameAndPath> items, String msg, String
+  /// pearClasspath) {
+  //
+  // if (items.size() == 0) {
+  // return true;
+  // }
+  // System.out.format("Compiling %,d classes %s -- This may take a while!%n", c2ps.size(), msg);
+  // StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null,
+  /// Charset.forName("UTF-8"));
+  //
+  // List<String> cus = items.stream()
+  // .map(c -> outDirConverted + "v3/" + c.classname + ".java")
+  // .collect(Collectors.toList());
+  //
+  // Iterable<String> compilationUnitStrings = cus;
+  //
+  // Iterable<? extends JavaFileObject> compilationUnits =
+  // fileManager.getJavaFileObjectsFromStrings(compilationUnitStrings);
+  //
+  // // specify where the output classes go
+  // String classesBaseDir = outDirConverted + "v3-classes";
+  // try {
+  // Files.createDirectories(Paths.get(classesBaseDir));
+  // } catch (IOException e) {
+  // throw new UIMARuntimeException(e);
+  // }
+  // // specify the classpath
+  // String classpath = getCompileClassPath(pearClasspath);
+  // Iterable<String> options = Arrays.asList("-d", classesBaseDir,
+  // "-classpath", classpath);
+  // return javaCompiler.getTask(null, fileManager, null, options, null, compilationUnits).call();
+  // }
+  /// **
+  // * Called after class is migrated
+  // * Given a path to a class (source or class file),
+  // * return the URL to the class as found in the classpath.
+  // * This returns the "first" one found in the classpath, in the case of duplicates.
+  // * @param path
+  // * @return the location of the class in the class path
+  // */
+  // private URL getPathForClass(Path path) {
+  // return (null == packageAndClassNameSlash)
+  // ? null
+  // : migrateClassLoader.getResource(packageAndClassNameSlash + ".class");
+  // }
+  // private void getBaseOutputPath() {
+  // String s = packageAndClassNameSlash;
+  // int i = 0;
+  // while (!usedPackageAndClassNames.add(s)) {
+  // i = i + 1;
+  // s = packageAndClassNameSlash + "_dupid_" + i;
+  // }
+  // packageAndClassNameSlash_i = i;
+  // }
+  // private String prepareIndividual(String classname) {
+  // candidate = new Candidate(Paths.get(classname)); // a pseudo path
+  // packageName = null;
+  // className = null;
+  // packageAndClassNameSlash = null;
+  // cu = null;
+  // return decompile(classname); // always look up in classpath
+  // // to decompile individual source - put in sourcesRoots
+  // }
+  // if (!isSource) { // skip this recording if source
+  // if (null != pear_current) {
+  // // inside a pear, which has been unzipped into a temporary pearInstallDir;
+  // // we don't want that temporary dir to be part of the path.
+  // path2InsidePearOrJarPath.put(path.toString(), pearResolveStart.relativize(path).toString());
+  // pear_current.pathsToCandidateFiles.add(path.toString());
+  // }
+  //
+  // if (!isSource && pear_or_jar_current_stack.size() > 0) {
+  // // inside a jar, not contained in a pear
+  // pear_or_jar_current_stack.getFirst().pathsToCandidateFiles.add(path.toString());
+  // }
+  // }
+  // }
+  /// **
+  // * For a given candidate, use its path:
+  // * switch the ...java to ..._Type.java, or ...class to ..._Type.class
+  // * look thru all the candidates
+  // * @param cand
+  // * @param start
+  // * @return
+  // */
+  // private boolean has_Type(Candidate cand, int start) {
+  // if (start >= candidates.size()) {
+  // return false;
+  // }
+  //
+  // String sc = cand.p.toString();
+  // String sc_minus_suffix = sc.substring(0, sc.length() - ( isSource ? ".java".length() :
+  /// ".class".length()));
+  // String sc_Type = sc_minus_suffix + ( isSource ? "_Type.java" : "_Type.class");
+  // // a string which sorts beyond the candidate + a suffix of "_"
+  // String s_end = sc_minus_suffix + (char) (((int)'_') + 1);
+  // for (Candidate c : candidates.subList(start, candidates.size())) {
+  // String s = c.p.toString();
+  // if (s_end.compareTo(s) < 0) {
+  // return false; // not found, we're already beyond where it would be found
+  // }
+  // if (s.equals(sc_Type)) {
+  // return true;
+  // }
+  // }
+  // return false;
+  // }
+  // private final static Comparator<Candidate> pathComparator = new Comparator<Candidate>() {
+  // @Override
+  // public int compare(Candidate o1, Candidate o2) {
+  // return o1.p.toString().compareTo(o2.p.toString());
+  // }
+  // };
+
+  //// there may be several same-name roots not quite right
+  //// xxx_Type$1.class
+  //
+  // private void addIfPreviousIsSameName(List<Path> c, int i) {
+  // if (i == 0) return;
+  // String _Type = candidates.get(i).toString();
+  //// String prev = r.get(i-1).getPath();
+  // String prefix = _Type.substring(0, _Type.length() - ("_Type." + (isSource ? "java" :
+  //// "class")).length());
+  // i--;
+  // while (i >= 0) {
+  // String s = candidates.get(i).toString();
+  // if ( ! s.startsWith(prefix)) {
+  // break;
+  // }
+  // if (s.substring(prefix.length()).equals((isSource ? ".java" : ".class"))) {
+  // c.add(candidates.get(i));
+  // break;
+  // }
+  // i--;
+  // }
+  // }
+
+  //
+  // for (int i = 0; i < pearOrJar.pathsToCandidateFiles.size(); i++) {
+  // String candidatePath = pearOrJar.pathsToCandidateFiles.get(i);
+  // String path_in_v3_classes = isPear
+  // ? getPath_in_v3_classes(candidatePath)
+  // : candidatePath;
+  //
+  // Path src = Paths.get(outputDirectory, "converted/v3-classes", path_in_v3_classes
+  // + (isPear ? ".class" : ""));
+  // Path tgt = pfs.getPath(
+  // "/",
+  // isPear
+  // ? path2InsidePearOrJarPath.get(candidatePath) // needs to be bin/org/... etc
+  // : candidatePath); // needs to be org/... etc
+  // if (Files.exists(src)) {
+  // Files.copy(src, tgt, StandardCopyOption.REPLACE_EXISTING);
+  // reportPearOrJarClassReplace(pearOrJarCopy.toString(), path_in_v3_classes, kind);
+  // }
+  // }
+
+  /// ** for compiled mode, do recompiling and reassembly of Jars and Pears */
+  //
+  // private boolean compileAndReassemble(CommonConverted cc, Container container, Path path) {
+  // boolean noErrors = true;
+  // if (javaCompiler != null) {
+  // if (container.haveDifferentCapitalizedNamesCollidingOnWindows) {
+  // System.out.println("Skipping compiling / reassembly because class " + container.toString() + "
+  /// has multiple names differing only in capitalization, please resolve first.");
+  // } else {
+  //
+  //
+  // noErrors = compileV3PearSources(container, path);
+  // noErrors = noErrors && compileV3NonPearSources(container, path);
+  //
+  // postProcessPearsOrJars("jars" , jars , jarClassReplace);
+  // postProcessPearsOrJars("pears", pears, pearClassReplace);
+  //
+  ////
+  //// try {
+  //// Path pearOutDir = Paths.get(outputDirectory, "pears");
+  //// FileUtils.deleteRecursive(pearOutDir.toFile());
+  //// Files.createDirectories(pearOutDir);
+  //// } catch (IOException e) {
+  //// throw new RuntimeException(e);
+  //// }
+  ////
+  //// System.out.format("replacing .class files in %,d PEARs%n", pears.size());
+  //// for (PearOrJar p : pears) {
+  //// pearOrJarPostProcessing(p);
+  //// }
+  //// try {
+  //// reportPaths("Reports of updated Pears", "pearFileUpdates.txt", pearClassReplace);
+  //// } catch (IOException e) {
+  //// throw new RuntimeException(e);
+  //// }
+  // }
+  // }
+  //
+  // return noErrors;
+  // }
+
+  /// **
+  // * @return true if no errors
+  // */
+  // private boolean compileV3PearSources() {
+  // boolean noError = true;
+  // Map<String, List<ClassnameAndPath>> p2c = c2ps.stream()
+  // .filter(c -> c.pearClasspath != null)
+  // .collect(Collectors.groupingBy(c -> c.pearClasspath));
+  //
+  // List<Entry<String, List<ClassnameAndPath>>> ea = p2c.entrySet().stream()
+  // .sorted(Comparator.comparing(Entry::getKey)) //(e1, e2) -> e1.getKey().compareTo(e2.getKey())
+  // .collect(Collectors.toList());
+  //
+  // for (Entry<String, List<ClassnameAndPath>> e : ea) {
+  // noError = noError && compileV3SourcesCommon(e.getValue(), "for Pear " + e.getKey(), e.getKey()
+  /// );
+  // }
+  // return noError;
+  // }
+  //
+  /// **
+  // * @return true if no errors
+  // */
+  // private boolean compileV3NonPearSources() {
+  //
+  // List<ClassnameAndPath> cnps = c2ps.stream()
+  // .filter(c -> c.pearClasspath == null)
+  // .collect(Collectors.toList());
+  //
+  // return compileV3SourcesCommon(cnps, "(non PEAR)", null);
+  // }
+
+  /// **
+  // * @param pathInPear a complete path to a class inside an (installed) pear
+  // * @return the part starting after the top node of the install dir
+  // */
+  // private String getPath_in_v3_classes(String pathInPear) {
+  // return path2classname.get(pathInPear);
+  // }
+
+  // private boolean reportDuplicates() throws IOException {
+  // List<List<CommonConverted>> nonIdenticals = new ArrayList<>();
+  // List<CommonConverted> onlyIdenticals = new ArrayList<>();
+  //
+  // classname2multiSources.forEach(
+  // (classname, ccs) -> {
+  // if (ccs.size() > 1) {
+  // nonIdenticals.add(ccs);
+  // } else {
+  // CommonConverted cc = ccs.get(0);
+  // if (cc.containersAndV2Paths.size() > 1)
+  // onlyIdenticals.add(cc); // the same item in multiple containers and/or paths
+  // }
+  // }
+  // );
+  //
+  // if (nonIdenticals.size() == 0) {
+  // if (onlyIdenticals.size() == 0) {
+  // System.out.println("There were no duplicates found.");
+  // } else {
+  // // report identical duplicates
+  // try (BufferedWriter bw = Files.newBufferedWriter(makePath(outDirLog +
+  // "identical_duplicates.txt"), StandardOpenOption.CREATE)) {
+  // logPrintNl("Report of Identical duplicates:", bw);
+  // for (CommonConverted cc : onlyIdenticals) {
+  // int i = 0;
+  // logPrintNl("Class: " + cc.fqcn_slash, bw);
+  // for (ContainerAndPath cp : cc.containersAndV2Paths) {
+  // logPrintNl(" " + (++i) + " " + cp, bw);
+  // }
+  // logPrintNl("", bw);
+  // }
+  // }
+  // }
+  // return true;
+  // }
+  //
+  //// non-identicals, print out all of them
+  // try (BufferedWriter bw = Files.newBufferedWriter(makePath(outDirLog +
+  // "nonIdentical_duplicates.txt"), StandardOpenOption.CREATE)) {
+  // logPrintNl("Report of non-identical duplicates", bw);
+  // for (List<CommonConverted> nonIdentical : nonIdenticals) {
+  // String fqcn = nonIdentical.get(0).fqcn_slash;
+  // logPrintNl(" classname: " + fqcn, bw);
+  // int i = 1;
+  // // for each cc, and within each cc, for each containerAndPath
+  // for (CommonConverted cc : nonIdentical) {
+  //// logPrintNl(" version " + i, bw);
+  // assert fqcn.equals(cc.fqcn_slash);
+  // int j = 1;
+  // boolean isSame = cc.containersAndV2Paths.size() > 1;
+  // boolean isFirstTime = true;
+  // for (ContainerAndPath cp : cc.containersAndV2Paths) {
+  // String first = isSame && isFirstTime
+  // ? " same: "
+  // : isSame
+  // ? " "
+  // : " ";
+  // isFirstTime = false;
+  // logPrintNl(first + i + "." + (j++) + " " + cp, bw);
+  // }
+  // indent[0] -= 6;
+  //// logPrintNl("", bw);
+  // i++;
+  // }
+  //// logPrintNl("", bw);
+  // }
+  // }
+  // return false;
+  // }
+
+  // private static class PathAndReason extends Report2<Path, String> {
+  // Path path;
+  // String reason;
+  // PathAndReason(Path path, String reason) {
+  // this.path = path;
+  // this.reason = reason;
+  // }
+  // @Override
+  // public Comparable<Path> getFirst() { return path; }
+  // @Override
+  // public Comparable<String> getSecond() { return reason; }
+  // @Override
+  // int getFirstLength() { return path.toString().length(); }
+  // }
 
 }