package ch.usi.inf.sp.callgraph;

import ch.usi.inf.sp.framework.ClassAnalyzer;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;


/**
 * Build a class hierarchy (including methods).
 *
 * @author maggicl@usi.ch
 * @author Matthias.Hauswirth@usi.ch
 */
public final class ClassHierarchyBuilder implements ClassAnalyzer {

    private final ClassHierarchy classHierarchy;

    public ClassHierarchyBuilder() {
        this.classHierarchy = new ClassHierarchy();
    }

    public ClassHierarchy getClassHierarchy() {
        return classHierarchy;
    }

    public void analyze(final String location, final ClassNode clazz) {
        try {
            final ClassType classType = classHierarchy.getOrCreateClass(clazz.name);
            if (classType.isResolved()) {
                System.err.println("WARNING: Class " + classType.getInternalName() + " defined multiple times");
                return;
            }
            classType.setLocation(location);

            // extract modifiers
            classType.setModifiers(clazz.access);

            // extract superclass
            classType.setSuperClass(classHierarchy.getOrCreateClass(clazz.superName));

            // extract interfaces
            for (final String i : clazz.interfaces) {
                classType.addInterface(classHierarchy.getOrCreateClass(i));
            }

            // extract methods
            for (final MethodNode m : clazz.methods) {
                classType.addMethod(new Method(clazz.name, m.name, m.desc, m.access));
            }

            classType.setResolved();
        } catch (final TypeInconsistencyException ex) {
            ex.printStackTrace(System.err);
        }
    }

}
