All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.spricom.dessert.resolve.ClassPackage Maven / Gradle / Ivy

The newest version!
package de.spricom.dessert.resolve;

/*-
 * #%L
 * Dessert Dependency Assertion Library for Java
 * %%
 * Copyright (C) 2017 - 2023 Hans Jörg Heßmann
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import de.spricom.dessert.matching.ShortNameMatcher;

import java.io.File;
import java.util.*;
import java.util.logging.Logger;

/**
 * A ClassEntry represents a single package within one classes directory or .jar file.
 * It's either linked to the parent {@link ClassPackage} it belongs to or it is a
 * {@link ClassRoot} itself. It maintains a probably empty list of all its subpackages
 * and classes it contains directly.
 * If there is another package with the same name in some other classes directory or
 * .jar file within the {@link ClassResolver} scope it has a reference to a list of all
 * such packages.
 */
public class ClassPackage {
    private static final Logger log = Logger.getLogger(ClassPackage.class.getName());

    private final String packageName;
    private final ClassPackage parent;
    private final Map subPackages = new TreeMap();
    private final Map classes = new TreeMap();
    private List alternatives;

    protected ClassPackage() {
        packageName = "";
        parent = null;
    }

    public ClassPackage(ClassPackage parent, String packageName) {
        this.parent = parent;
        this.packageName = packageName;
        if (parent.subPackages.put(packageName, this) != null) {
            log.warning(packageName + " appears twice.");
        }
    }

    public ClassPackage getParent() {
        return parent;
    }

    public final String getPackageName() {
        return packageName;
    }

    public final String getClassName(String simpleName) {
        return packageName.isEmpty() ? simpleName : packageName + "." + simpleName;
    }

    /**
     * @return the package name without parent package prefix
     */
    public String getShortName() {
        if (parent == null) {
            return "";
        }
        String parentPackageName = getParent().getPackageName();
        if (parentPackageName.isEmpty()) {
            return this.packageName;
        }
        return this.packageName.substring(parentPackageName.length() + 1);
    }

    public ClassRoot getRoot() {
        return parent.getRoot();
    }

    @Deprecated
    public File getRootFile() {
        return getRoot().getRootFile();
    }

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

    /**
     * @return the probably empty list of all direct nested packages of this package
     */
    public List getSubPackages() {
        return new ArrayList(subPackages.values());
    }

    public ClassPackage getSubPackage(String packageName) {
        return subPackages.get(packageName);
    }

    /**
     * @return the list of all classes directly contained in this package
     */
    public List getClasses() {
        return new ArrayList(classes.values());
    }

    public void addClass(ClassEntry ce) {
        ClassEntry previous = classes.get(ce.getClassname());
        if (previous == null || (previous.getVersion() != null && ce.getVersion() == null)) {
            classes.put(ce.getClassname(), ce);
        } else if (previous.getVersion() == null && ce.getVersion() == null) {
            log.warning(ce.getURI() + " appears twice, using first one.");
        }
    }

    public ClassEntry getClass(String classname) {
        return classes.get(classname);
    }

    /**
     * Returns a list of all other packages with the same fully qualified name.
     * For the root package "" this method returns all roots ({@link ClassRoot})
     * within the {@link ClassResolver}.
     *
     * @return the other packages or null if there are none
     */
    public List getAlternatives() {
        return alternatives;
    }

    void addAlternative(ClassPackage alt) {
        assert alt.alternatives == null : "alt.alternatives != null";
        if (alternatives == null) {
            alternatives = new LinkedList();
            alternatives.add(this);
        }
        assert !alternatives.contains(alt) : "alternatives.contains(alt)";
        alternatives.add(alt);
        alt.alternatives = alternatives;
    }

    protected final void traverse(ShortNameMatcher matcher, ClassVisitor visitor) {
        if (!matcher.isMatchPossible()) {
            return;
        }
        if (matcher.isLast()) {
            traverseClasses(matcher, visitor);
        } else {
            traverseSubPackages(matcher, visitor);
            if (matcher.isWildcard()) {
                traverse(matcher.next(), visitor);
            }
        }
    }

    private void traverseClasses(ShortNameMatcher matcher, ClassVisitor visitor) {
        for (ClassEntry clazz : classes.values()) {
            if (matcher.match(clazz.getShortName()).matches()) {
                visitor.visit(clazz);
                for (ClassEntry versionedAlternative : clazz.getAlternativesWithinSamePackage()) {
                    visitor.visit(versionedAlternative);
                }
            }
        }
    }

    private void traverseSubPackages(ShortNameMatcher matcher, ClassVisitor visitor) {
        for (ClassPackage subPackage : subPackages.values()) {
            subPackage.traverse(matcher.match(subPackage.getShortName()), visitor);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy