travis.model.project.structure.StructComponent.java Source code

Java tutorial

Introduction

Here is the source code for travis.model.project.structure.StructComponent.java

Source

/*
 * StructComponent.java
 *
 * Copyright (C) 2011-2012, Artur Jonkisz, <travis.source@gmail.com>
 *
 * This file is part of TraVis.
 * See https://github.com/ajonkisz/TraVis for more info.
 *
 * TraVis is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * TraVis is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with TraVis.  If not, see <http://www.gnu.org/licenses/>.
 */

package travis.model.project.structure;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;

import org.objectweb.asm.Opcodes;
import travis.model.project.StructStub;
import travis.model.project.structure.StructUtil.Visibility;

public abstract class StructComponent implements Comparable<StructComponent>, Serializable {

    private static final long serialVersionUID = -7522901348550035402L;

    // This is used for lazy loading. Once calculated data is stored to avoid
    // future calculations.
    protected enum State {
        YES, NO, UNKNOWN
    }

    protected State isPartOfClassPath;
    private String classPath;

    private final Visibility visibility;
    private final String name;
    private final int access;
    private final TreeSet<StructComponent> children;
    private final StructComponent parent;

    protected StructComponent(StructComponent parent, StructStub stub) {
        this(stub.getName(), stub.getAccessFlag(), parent);
    }

    protected StructComponent(String name, StructComponent parent) {
        this(name, 0, parent);
    }

    protected StructComponent(String name, int access, StructComponent parent) {
        this(name, access, parent, State.UNKNOWN);
    }

    protected StructComponent(String name, int access, StructComponent parent, State hasAnyClasses) {
        this.name = name;
        this.visibility = StructUtil.getVisibility(access);
        this.access = access;
        this.children = new TreeSet<StructComponent>();
        this.parent = parent;
        this.classPath = "";
        this.isPartOfClassPath = State.UNKNOWN;
    }

    public String getTooltipFriendlyName() {
        return toString();
    }

    public Map<StructMethod, Integer> getMethods() {
        Map<StructMethod, Integer> map = new HashMap<StructMethod, Integer>();
        getMethods(map, new AtomicInteger());
        return map;
    }

    private void getMethods(Map<StructMethod, Integer> methods, AtomicInteger i) {
        for (StructComponent child : children) {
            if (child instanceof StructMethod) {
                methods.put((StructMethod) child, i.getAndIncrement());
            } else {
                child.getMethods(methods, i);
            }
        }
    }

    public boolean containsAnyClasses() {
        for (Iterator<StructComponent> iterator = children.descendingIterator(); iterator.hasNext();) {
            StructComponent child = iterator.next();
            if (child instanceof StructClass) {
                return true;
            } else if (child instanceof StructPackage) {
                // This takes advantage of the fact that the tree is sorted and
                // classes are stored always after packages
                return false;
            }
        }
        return false;
    }

    public boolean isPartOfClassPath() {
        switch (isPartOfClassPath) {
        case YES:
            return true;
        case NO:
            return false;
        case UNKNOWN:
            if (parent != null && parent.isPartOfClassPath == State.YES) {
                isPartOfClassPath = State.YES;
                return true;
            }

            for (StructComponent child : children) {
                if (child.isPartOfClassPath()) {
                    String childClassPath = child.getClassPath();
                    if (!childClassPath.equals("") && name.endsWith(childClassPath)) {
                        setClassPath(removeLastDotWord(childClassPath));
                        isPartOfClassPath = State.YES;
                        return true;
                    }
                }
            }
            isPartOfClassPath = State.NO;
            return false;
        }
        return false;
    }

    protected String getClassPath() {
        return classPath;
    }

    protected void setClassPath(String classPath) {
        this.classPath = classPath;
    }

    public Set<String> getMainMethodComponents() {
        Set<String> mainClasses = new TreeSet<String>();
        addMainMethodComponents(mainClasses);
        return mainClasses;
    }

    private void addMainMethodComponents(Set<String> mainClasses) {
        if (this.isMainMethod()) {
            mainClasses.add(getParentName());
        } else {
            for (StructComponent comp : children) {
                comp.addMainMethodComponents(mainClasses);
            }
        }
    }

    public boolean isMainMethod() {
        return false;
    }

    public boolean isDefaultPackage() {
        return false;
    }

    public Visibility getVisibility() {
        return visibility;
    }

    public String getName() {
        return name;
    }

    public int getAccessFlag() {
        return access;
    }

    public boolean isStatic() {
        return StructUtil.isFlagSet(access, Opcodes.ACC_STATIC);
    }

    public boolean isFinal() {
        return StructUtil.isFlagSet(access, Opcodes.ACC_FINAL);
    }

    public boolean isOrdinaryClass() {
        return false;
    }

    public boolean isAbstract() {
        return StructUtil.isFlagSet(access, Opcodes.ACC_ABSTRACT);
    }

    public boolean isEnum() {
        return StructUtil.isFlagSet(access, Opcodes.ACC_ENUM);
    }

    public boolean isInterface() {
        return StructUtil.isFlagSet(access, Opcodes.ACC_INTERFACE);
    }

    public String getDescriptor() {
        return "";
    }

    public StructComponent getParent() {
        return parent;
    }

    public String getParentName() {
        return parent == null ? "" : parent.name;
    }

    public String getReturnType() {
        return "";
    }

    public String getParameters(boolean fullClassNames) {
        return "";
    }

    public boolean isConstructor() {
        return false;
    }

    public boolean isEmpty() {
        return children.isEmpty();
    }

    public Collection<StructComponent> getChildren() {
        return children;
    }

    public boolean addStructComponent(StructComponent sComponent) {
        return children.add(sComponent);
    }

    public void addStructComponents(Collection<StructComponent> sComponents) {
        for (StructComponent comp : sComponents) {
            if (children.contains(comp)) {
                StructComponent child = getChild(comp);
                child.addStructComponents(comp.getChildren());
            } else {
                addStructComponent(comp);
            }
        }
    }

    /**
     * Searches only children in depth 1.
     *
     * @param structComponent child to be searched for
     * @return found child or null if child was not found in depth
     */
    public StructComponent getChild(StructComponent structComponent) {
        for (StructComponent child : children) {
            if (child.compareTo(structComponent) == 0)
                return child;
        }
        return null;
    }

    /**
     * Perform breadth first search.
     *
     * @param structComponent child to be searched for
     * @return found child or null if one was not found
     */
    public StructComponent findChild(StructComponent structComponent) {
        Queue<StructComponent> q = new LinkedList<StructComponent>();
        q.addAll(children);
        StructComponent foundChild = null;
        while (!q.isEmpty()) {
            StructComponent child = q.poll();
            if (child.compareTo(structComponent) == 0) {
                foundChild = child;
                break;
            } else {
                q.addAll(child.children);
            }
        }
        return foundChild;
    }

    public boolean removeStructComponent(StructComponent sComponent) {
        return children.remove(sComponent);
    }

    public static String removeLastDotWord(String string) {
        int i = string.lastIndexOf('.');
        return i == -1 ? "" : string.substring(0, i);
    }

    @Override
    public String toString() {
        return name;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof StructComponent) {
            int result = this.compareTo((StructComponent) obj);
            return result == 0;
        }
        return false;
    }

    @Override
    public int hashCode() {
        int code = name.hashCode();
        if (parent != null)
            code += parent.hashCode();
        return code;
    }

    @Override
    public int compareTo(StructComponent o) {
        if (this instanceof StructPackage && !(o instanceof StructPackage))
            return -1;
        else if (o instanceof StructPackage && !(this instanceof StructPackage))
            return 1;
        else if (this instanceof StructClass && !(o instanceof StructClass))
            return -1;
        else if (o instanceof StructClass && !(this instanceof StructClass))
            return 1;
        else if (this instanceof StructMethod && o instanceof StructMethod) {
            StructMethod m1 = (StructMethod) this;
            StructMethod m2 = (StructMethod) o;
            if (m1.isConstructor() && !m2.isConstructor())
                return -1;
            else if (m2.isConstructor() && !m1.isConstructor())
                return 1;
            String m1Name = m1.toString() + ' ' + m1.getParentName();
            String m2Name = m2.toString() + ' ' + m2.getParentName();
            return m1Name.compareTo(m2Name);
        }
        return this.name.compareTo(o.name);
    }

}