// Path: jar-analyzer/src/main/java/mb/jar_analyzer/jar/JarUtils.java
// public class JarUtils {
// 
//     public static final void processJarClasses(Iterable<File> files, ClassProcessor processor) throws IOException {
//         for(File file : files) {
//             try(JarFile jar = new JarFile(file)) {
//                 final Enumeration<JarEntry> entries = jar.entries();
//                 while(entries.hasMoreElements()) {
//                     final JarEntry entry = entries.nextElement();
//                     if(entry.getName().endsWith(".class")) {
//                         final ClassReader classReader = new ClassReader(jar.getInputStream(entry));
//                         processor.accept(classReader);
//                     }
//                 }
//             }
//         }
//     }
// 
//     public static final Map<String, ClassNode> readJarClasses(Iterable<File> files) throws IOException {
//         final Map<String, ClassNode> classes = new HashMap<>();
//         processJarClasses(files, cr -> {
//             final ClassNode classNode = new ClassNode();
//             cr.accept(classNode, ClassReader.SKIP_CODE & ClassReader.SKIP_DEBUG & ClassReader.SKIP_FRAMES);
//             if(classes.put(classNode.name, classNode) != null) {
//                 throw new IllegalArgumentException("Duplicate class " + classNode.name);
//             }
//         });
//         return classes;
//     }
// 
//     public static boolean isJavaClass(String name) {
//         // @formatter:off
//         return name.startsWith("java/")
// //                || name.startsWith("javax/")
//                 ;
//         // @formatter:on
//     }
// 
//     public static boolean isJDKClass(String name) {
//         // @formatter:off
//         return name.startsWith("java/")
//                 || name.startsWith("javax/")
//                 || name.startsWith("sun/")
//                 || name.startsWith("jdk/")
//                 || name.startsWith("com/sun/")
//                 || name.startsWith("com/apple/")
//                 || name.startsWith("com/oracle/")
//                 || name.startsWith("org/w3c/")
//                 || name.startsWith("org/xml/")
//                 || name.startsWith("org/omg/")
//                 || name.startsWith("org/ietf/")
//                 || name.startsWith("org/jcp/")
//                 || name.startsWith("apple/")
//                 ;
//         // @formatter:on
//     }
// 
// }


import static mb.nabl2.terms.build.TermBuild.B;
import java.io.File;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.metaborg.util.Ref;
import org.metaborg.util.functions.Action2;
import org.metaborg.util.functions.Predicate1;
import org.metaborg.util.tuple.Tuple2;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InnerClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.spoofax.interpreter.terms.IStrategoTerm;
import org.spoofax.terms.TermFactory;
import org.spoofax.terms.io.SimpleTextTermWriter;
import org.spoofax.terms.io.TermWriter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Streams;
import mb.jar_analyzer.jar.JarUtils;
import mb.nabl2.terms.ITerm;
import mb.nabl2.terms.stratego.StrategoTerms;
import mb.scopegraph.oopsla20.IScopeGraph;
import mb.scopegraph.oopsla20.reference.ScopeGraph;
import mb.statix.concurrent.IStatixLibrary;
import mb.statix.concurrent.StatixLibrary;
import mb.statix.scopegraph.Scope;
    private static final String VARARGS = "VARARGS";

    private static final String INIT = "<init>";

    // @formatter:off
    private static final Map<String, ITerm> boxedTypes = ImmutableMap.<String, ITerm>builder()
        .put("java/lang/Boolean",   B.newAppl("BOOLEAN"))
        .put("java/lang/Character", B.newAppl("CHAR"))
        .put("java/lang/Byte",      B.newAppl("BYTE"))
        .put("java/lang/Short",     B.newAppl("SHORT"))
        .put("java/lang/Integer",   B.newAppl("INT"))
        .put("java/lang/Long",      B.newAppl("LONG"))
        .put("java/lang/Float",     B.newAppl("FLOAT"))
        .put("java/lang/Double",    B.newAppl("DOUBLE"))
        .build();
    // @formatter:on

    // @formatter:off
    private static final Set<String> jreTypes = ImmutableSet.<String>builder()
        .add("java/lang/String")
        .add("java/lang/Throwable")
        .add("java/lang/Enum")
        .add("java/lang/Iterable")
        .build();
    // @formatter:on

    ////////////////////////////////////////////////////////////////////////////

    private final List<File> files = new ArrayList<>();
    private File output = null;
// Path: jar-analyzer/src/main/java/mb/jar_analyzer/jar/JarUtils.java
// public class JarUtils {
// 
//     public static final void processJarClasses(Iterable<File> files, ClassProcessor processor) throws IOException {
//         for(File file : files) {
//             try(JarFile jar = new JarFile(file)) {
//                 final Enumeration<JarEntry> entries = jar.entries();
//                 while(entries.hasMoreElements()) {
//                     final JarEntry entry = entries.nextElement();
//                     if(entry.getName().endsWith(".class")) {
//                         final ClassReader classReader = new ClassReader(jar.getInputStream(entry));
//                         processor.accept(classReader);
//                     }
//                 }
//             }
//         }
//     }
// 
//     public static final Map<String, ClassNode> readJarClasses(Iterable<File> files) throws IOException {
//         final Map<String, ClassNode> classes = new HashMap<>();
//         processJarClasses(files, cr -> {
//             final ClassNode classNode = new ClassNode();
//             cr.accept(classNode, ClassReader.SKIP_CODE & ClassReader.SKIP_DEBUG & ClassReader.SKIP_FRAMES);
//             if(classes.put(classNode.name, classNode) != null) {
//                 throw new IllegalArgumentException("Duplicate class " + classNode.name);
//             }
//         });
//         return classes;
//     }
// 
//     public static boolean isJavaClass(String name) {
//         // @formatter:off
//         return name.startsWith("java/")
// //                || name.startsWith("javax/")
//                 ;
//         // @formatter:on
//     }
// 
//     public static boolean isJDKClass(String name) {
//         // @formatter:off
//         return name.startsWith("java/")
//                 || name.startsWith("javax/")
//                 || name.startsWith("sun/")
//                 || name.startsWith("jdk/")
//                 || name.startsWith("com/sun/")
//                 || name.startsWith("com/apple/")
//                 || name.startsWith("com/oracle/")
//                 || name.startsWith("org/w3c/")
//                 || name.startsWith("org/xml/")
//                 || name.startsWith("org/omg/")
//                 || name.startsWith("org/ietf/")
//                 || name.startsWith("org/jcp/")
//                 || name.startsWith("apple/")
//                 ;
//         // @formatter:on
//     }
// 
// }


// Path: jar-analyzer/src/main/java/mb/jar_analyzer/stxlib/StxLibCommand.java
import static mb.nabl2.terms.build.TermBuild.B;
import java.io.File;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.metaborg.util.Ref;
import org.metaborg.util.functions.Action2;
import org.metaborg.util.functions.Predicate1;
import org.metaborg.util.tuple.Tuple2;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InnerClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.spoofax.interpreter.terms.IStrategoTerm;
import org.spoofax.terms.TermFactory;
import org.spoofax.terms.io.SimpleTextTermWriter;
import org.spoofax.terms.io.TermWriter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Streams;
import mb.jar_analyzer.jar.JarUtils;
import mb.nabl2.terms.ITerm;
import mb.nabl2.terms.stratego.StrategoTerms;
import mb.scopegraph.oopsla20.IScopeGraph;
import mb.scopegraph.oopsla20.reference.ScopeGraph;
import mb.statix.concurrent.IStatixLibrary;
import mb.statix.concurrent.StatixLibrary;
import mb.statix.scopegraph.Scope;

    private static final String VARARGS = "VARARGS";

    private static final String INIT = "<init>";

    // @formatter:off
    private static final Map<String, ITerm> boxedTypes = ImmutableMap.<String, ITerm>builder()
        .put("java/lang/Boolean",   B.newAppl("BOOLEAN"))
        .put("java/lang/Character", B.newAppl("CHAR"))
        .put("java/lang/Byte",      B.newAppl("BYTE"))
        .put("java/lang/Short",     B.newAppl("SHORT"))
        .put("java/lang/Integer",   B.newAppl("INT"))
        .put("java/lang/Long",      B.newAppl("LONG"))
        .put("java/lang/Float",     B.newAppl("FLOAT"))
        .put("java/lang/Double",    B.newAppl("DOUBLE"))
        .build();
    // @formatter:on

    // @formatter:off
    private static final Set<String> jreTypes = ImmutableSet.<String>builder()
        .add("java/lang/String")
        .add("java/lang/Throwable")
        .add("java/lang/Enum")
        .add("java/lang/Iterable")
        .build();
    // @formatter:on

    ////////////////////////////////////////////////////////////////////////////

    private final List<File> files = new ArrayList<>();
    private File output = null;
    private Predicate1<String> include = className -> JarUtils.isJavaClass(className);