public static void main(String[] args) throws ParseException, IOException {
    Options options = createOptions();
    CommandLineParser parser = new GnuParser();
    CommandLine cmd = parser.parse(options, args);
    if (cmd.hasOption("?")) {
      new HelpFormatter().printHelp("java " + ShowMoves.class.getName(), options);
      System.exit(1);
    }
    File rootFile = new File(cmd.getOptionValue("root"));
    File movesFile = new File(cmd.getOptionValue("moves"));
    Predicate<ClassName> packageFilter = new PackagePredicate(cmd.getOptionValue("package", ""));
    String groupPrefix = cmd.getOptionValue("group", "");
    File refsFile = cmd.hasOption("refs") ? new File(cmd.getOptionValue("refs")) : null;

    // scan all the pom.xml files
    Modules modules = new Modules();
    modules.scan(rootFile, groupPrefix);

    // load the moves and refs files
    ClassLocations moves = ClassLocations.parseFile(movesFile, groupPrefix);
    ClassLocations refs =
        (refsFile != null) ? ClassLocations.parseFile(refsFile, groupPrefix) : null;

    // scan the compiled classes of all the maven targets
    ClassScanner classScanner = new ClassScanner(packageFilter);
    classScanner.scan(modules.getAllModules());
    ClassLocations locations = classScanner.getLocations();
    ClassDependencies dependencies = classScanner.getDependencies();

    // apply the moves file
    locations.moveAll(moves);

    // apply the refs file, if one was specified
    if (refs != null) {
      for (ModuleName moduleName : refs.getAllModules()) {
        ClassName refsName = new ClassName(moduleName + ":" + refsFile);
        locations.add(refsName, moduleName);
        dependencies.add(refsName, refs.getClasses(moduleName));
      }
    }

    // find modules that reference classes they don't have access to
    Map<ModuleName, ListMultimap<ClassName, ClassName>> brokenMap = Maps.newHashMap();
    for (Map.Entry<ClassName, ModuleName> entry : locations.getLocations()) {
      ClassName className = entry.getKey();
      ModuleName moduleName = entry.getValue();
      Set<ClassName> referencedClasses = dependencies.getReferencedClasses(className);

      ListMultimap<ClassName, ClassName> moduleBrokenMap = null;
      for (ClassName referencedClass : referencedClasses) {
        ModuleName referencedModule = locations.getModule(referencedClass);
        if (referencedModule != null && !modules.isDependentOf(moduleName, referencedModule)) {
          if (moduleBrokenMap == null) {
            moduleBrokenMap = brokenMap.get(moduleName);
            if (moduleBrokenMap == null) {
              brokenMap.put(moduleName, moduleBrokenMap = ArrayListMultimap.create());
            }
          }
          moduleBrokenMap.put(className, referencedClass);
        }
      }
    }

    // report broken dependencies
    System.out.println();
    for (ModuleName moduleName : Utils.sorted(brokenMap.keySet())) {
      ListMultimap<ClassName, ClassName> missingMap = brokenMap.get(moduleName);

      System.out.println();
      System.out.println(moduleName.toString(groupPrefix));

      for (ClassName className : Utils.sorted(missingMap.keySet())) {
        System.out.println("  " + className);
        for (ClassName referencedClass : Utils.sorted(missingMap.get(className))) {
          ModuleName referencedModule = locations.getModule(referencedClass);
          System.out.println(
              "    " + referencedClass + " (" + referencedModule.toString(groupPrefix) + ")");
        }
      }
    }
  }