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

com.oracle.objectfile.BuildDependency Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.oracle.objectfile;

/**
 * A build dependency is a pair of LayoutDecisions (a, b), such that a depends on b.
 */
public final class BuildDependency implements Comparable {

    private static class DuplicateDependencyException extends Exception {

        static final long serialVersionUID = 42;

        BuildDependency existing;

        DuplicateDependencyException(BuildDependency existing) {
            this.existing = existing;
        }
    }

    public static BuildDependency createOrGet(LayoutDecision depending, LayoutDecision dependedOn) {
        try {
            return new BuildDependency(depending, dependedOn);
        } catch (DuplicateDependencyException ex) {
            return ex.existing;
        }
    }

    public final LayoutDecision depending;
    public final LayoutDecision dependedOn;

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof BuildDependency)) {
            return false;
        }
        BuildDependency arg = (BuildDependency) obj;
        // we'd better have an identityHashCode with sensible semantics
        assert (!(arg.depending == this.depending && arg.dependedOn == this.dependedOn)) ||
                        (System.identityHashCode(arg.depending) == System.identityHashCode(this.depending) && System.identityHashCode(arg.dependedOn) == System.identityHashCode(this.dependedOn));

        return arg.depending == this.depending && arg.dependedOn == this.dependedOn;
    }

    @Override
    public int hashCode() {
        return depending.hashCode() ^ dependedOn.hashCode();
    }

    @Override
    public int compareTo(Object arg0) {
        if (arg0 == null) {
            throw new NullPointerException();
        }
        // all non-BuildDependency objects are less than us
        if (!(arg0 instanceof BuildDependency)) {
            return -1;
        } else {
            BuildDependency arg = (BuildDependency) arg0;
            int our0 = System.identityHashCode(depending);
            int our1 = System.identityHashCode(dependedOn);
            int their0 = System.identityHashCode(arg.depending);
            int their1 = System.identityHashCode(arg.dependedOn);
            // lexicographic comparison
            if (our0 < their0 || (our0 == their0 && our1 < their1)) {
                return -1;
            } else if (our0 > their0 || (our0 == their0 && our1 > their1)) {
                return 1;
            } else {
                assert our0 == their0 && our1 == their1;
                return 0;
            }
        }
    }

    private BuildDependency(LayoutDecision depending, LayoutDecision dependedOn) throws DuplicateDependencyException {
        assert depending != null;
        assert dependedOn != null;
        assert depending != dependedOn; // 1-cycle is bad (all cycles are bad)
        // must be same file
        assert depending.getElement().getOwner() == dependedOn.getElement().getOwner();
        ObjectFile of = depending.getElement().getOwner();

        this.depending = depending;
        this.dependedOn = dependedOn;

        // avoid adding duplicate entries
        if (depending.dependsOn().contains(dependedOn)) {
            assert dependedOn.dependedOnBy().contains(depending);
            BuildDependency existing = of.getExistingDependency(this);
            assert existing != null;
            throw new DuplicateDependencyException(existing);
        }
        depending.dependsOn().add(dependedOn);
        dependedOn.dependedOnBy().add(depending);
        of.putDependency(this);
    }
}