org.commonjava.cartographer.graph.RelationshipGraph.java Source code

Java tutorial

Introduction

Here is the source code for org.commonjava.cartographer.graph.RelationshipGraph.java

Source

/**
 * Copyright (C) 2012 Red Hat, Inc. (jdcasey@commonjava.org)
 *
 * 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.
 */
package org.commonjava.cartographer.graph;

import org.commonjava.cartographer.graph.filter.ProjectRelationshipFilter;
import org.commonjava.maven.atlas.graph.model.EProjectCycle;
import org.commonjava.maven.atlas.graph.model.EProjectDirectRelationships;
import org.commonjava.cartographer.graph.model.GraphPath;
import org.commonjava.cartographer.graph.model.GraphPathInfo;
import org.commonjava.cartographer.graph.mutate.GraphMutator;
import org.commonjava.maven.atlas.graph.rel.ProjectRelationship;
import org.commonjava.maven.atlas.graph.rel.RelationshipType;
import org.commonjava.cartographer.graph.spi.RelationshipGraphConnection;
import org.commonjava.cartographer.graph.spi.RelationshipGraphConnectionException;
import org.commonjava.cartographer.graph.traverse.RelationshipGraphTraversal;
import org.commonjava.cartographer.graph.traverse.TraversalType;
import org.commonjava.maven.atlas.ident.ref.ProjectRef;
import org.commonjava.maven.atlas.ident.ref.ProjectVersionRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.IOException;
import java.net.URI;
import java.util.*;

import static org.apache.commons.lang.StringUtils.join;

public final class RelationshipGraph implements Closeable {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private static final String GROUP_ID = "groupId";

    private static final String ARTIFACT_ID = "artifactId";

    private static final String VERSION = "version";

    private List<RelationshipGraphListener> listeners;

    private final ViewParams params;

    private RelationshipGraphConnection connection;

    // if we didn't have a user, we wouldn't have constructed this thing!
    private int userCount = 1;

    RelationshipGraph(final ViewParams params, final RelationshipGraphConnection driver) {
        this.params = params;
        this.connection = driver;

        getConnectionInternal().registerView(params);
    }

    public ViewParams getParams() {
        return params;
    }

    public void storeProjectError(final ProjectVersionRef ref, final Throwable error)
            throws RelationshipGraphException {
        getConnectionInternal().addProjectError(ref,
                String.format("%s\n%s", error.getMessage(), join(error.getStackTrace(), "\n  ")));

        for (final RelationshipGraphListener listener : listeners) {
            listener.projectError(this, ref, error);
        }
    }

    public String getProjectError(final ProjectVersionRef ref) {
        return getConnectionInternal().getProjectError(ref);
    }

    public boolean hasProjectError(final ProjectVersionRef ref) {
        return getConnectionInternal().hasProjectError(ref);
    }

    public void clearProjectError(final ProjectVersionRef ref) throws RelationshipGraphException {
        getConnectionInternal().clearProjectError(ref);
    }

    public Set<ProjectRelationship<?, ?>> storeRelationships(final ProjectRelationship<?, ?>... relationships)
            throws RelationshipGraphException {
        final List<ProjectRelationship<?, ?>> rels = Arrays.asList(relationships);

        for (final RelationshipGraphListener listener : listeners) {
            listener.storing(this, rels);
        }

        final Set<ProjectRelationship<?, ?>> rejected = getConnectionInternal().addRelationships(relationships);

        for (final RelationshipGraphListener listener : listeners) {
            listener.stored(this, rels, rejected);
        }

        return rejected;
    }

    public Set<ProjectRelationship<?, ?>> storeRelationships(
            final Collection<? extends ProjectRelationship<?, ?>> relationships) throws RelationshipGraphException {
        for (final RelationshipGraphListener listener : listeners) {
            listener.storing(this, relationships);
        }

        final Set<ProjectRelationship<?, ?>> rejected = getConnectionInternal()
                .addRelationships(relationships.toArray(new ProjectRelationship<?, ?>[relationships.size()]));

        for (final RelationshipGraphListener listener : listeners) {
            listener.stored(this, relationships, rejected);
        }

        return rejected;
    }

    public void addListener(final RelationshipGraphListener listener) {
        if (listeners == null) {
            listeners = new ArrayList<RelationshipGraphListener>();
        }

        listeners.add(listener);
    }

    public void removeListener(final RelationshipGraphListener listener) {
        if (listeners != null) {
            listeners.remove(listener);
        }
    }

    synchronized void incrementGraphOwnership() {
        userCount++;
        logger.info("User count incremented to: {} for: {}", userCount, params);
    }

    public synchronized void forceClose() throws RelationshipGraphException {
        logger.info("Closing: {}", params);

        if (listeners != null) {
            for (final RelationshipGraphListener listener : listeners) {
                listener.closing(this);
            }
        }

        connection = null;

        if (listeners != null) {
            for (final RelationshipGraphListener listener : listeners) {
                listener.closed(this);
            }
        }
    }

    @Override
    public synchronized void close() throws IOException {
        userCount--;
        logger.info("User count decremented to: {} for: {}", userCount, params);

        if (userCount < 1) {
            try {
                forceClose();
            } catch (final RelationshipGraphException e) {
                throw new IOException("Failed to close graph.", e);
            }
        } else {
            logger.info("NOT closing; there are other users registered!");
        }
    }

    // +++ IMPORTED FROM EProjectWeb...

    public Set<ProjectRelationship<?, ?>> getAllRelationships() {
        return new HashSet<ProjectRelationship<?, ?>>(getConnectionInternal().getAllRelationships(params));
    }

    public boolean isComplete() {
        return !getConnectionInternal().hasMissingProjects(params);
    }

    public boolean isConcrete() {
        return !getConnectionInternal().hasVariableProjects(params);
    }

    public Set<ProjectVersionRef> getIncompleteSubgraphs() {
        return Collections.unmodifiableSet(getConnectionInternal().getMissingProjects(params));
    }

    public Set<ProjectVersionRef> getVariableSubgraphs() {
        return Collections.unmodifiableSet(getConnectionInternal().getVariableProjects(params));
    }

    public Set<ProjectRelationship<?, ?>> add(final EProjectDirectRelationships rels)
            throws RelationshipGraphException {
        return addAll(rels.getAllRelationships());
    }

    public boolean add(final ProjectRelationship<?, ?> rel) throws RelationshipGraphException {
        if (rel == null) {
            return false;
        }

        return getConnectionInternal().addRelationships(rel).isEmpty();
    }

    public <T extends ProjectRelationship<?, ?>> Set<T> addAll(final Collection<T> rels)
            throws RelationshipGraphException {
        if (rels == null) {
            return null;
        }

        final Set<T> result = new HashSet<T>(rels);

        final Set<ProjectRelationship<?, ?>> rejected = getConnectionInternal()
                .addRelationships(rels.toArray(new ProjectRelationship<?, ?>[rels.size()]));
        result.removeAll(rejected);

        if (!result.isEmpty()) {
            getConnectionInternal().recomputeIncompleteSubgraphs();
        }

        return result;
    }

    public <T extends ProjectRelationship<?, ?>> Set<T> addAll(final T... rels) throws RelationshipGraphException {
        if (rels == null) {
            return null;
        }

        final Set<T> result = new HashSet<T>();
        for (final T rel : rels) {
            if (add(rel)) {
                result.add(rel);
            }
        }

        getConnectionInternal().recomputeIncompleteSubgraphs();

        return result;
    }

    public void traverse(final ProjectVersionRef start, final RelationshipGraphTraversal traversal,
            final TraversalType type) throws RelationshipGraphException {
        getConnectionInternal().traverse(traversal, start, this, type);
    }

    public void traverse(final ProjectVersionRef start, final RelationshipGraphTraversal traversal)
            throws RelationshipGraphException {
        traverse(start, traversal, TraversalType.breadth_first);
    }

    public void traverse(final RelationshipGraphTraversal traversal, final TraversalType type)
            throws RelationshipGraphException {
        for (final ProjectVersionRef root : params.getRoots()) {
            getConnectionInternal().traverse(traversal, root, this, type);
        }
    }

    public void traverse(final RelationshipGraphTraversal traversal) throws RelationshipGraphException {
        traverse(traversal, TraversalType.breadth_first);
    }

    public Set<ProjectRelationship<?, ?>> getUserRelationships(final ProjectVersionRef ref) {
        if (!getConnectionInternal().containsProject(params, ref)) {
            return Collections.emptySet();
        }

        return new HashSet<ProjectRelationship<?, ?>>(
                getConnectionInternal().getRelationshipsTargeting(params, ref));
    }

    public Set<ProjectRelationship<?, ?>> getDirectRelationships(final ProjectVersionRef ref) {
        if (!getConnectionInternal().containsProject(params, ref)) {
            return Collections.emptySet();
        }

        return new HashSet<ProjectRelationship<?, ?>>(
                getConnectionInternal().getRelationshipsDeclaredBy(params, ref));
    }

    public Set<ProjectVersionRef> getRoots() {
        return params.getRoots();
    }

    public Set<ProjectRelationship<?, ?>> getExactAllRelationships() {
        return getAllRelationships();
    }

    public boolean isCycleParticipant(final ProjectVersionRef ref) {
        return getConnectionInternal().isCycleParticipant(params, ref);
    }

    public boolean isCycleParticipant(final ProjectRelationship<?, ?> rel) {
        return getConnectionInternal().isCycleParticipant(params, rel);
    }

    public void addCycle(final EProjectCycle cycle) throws RelationshipGraphException {
        getConnectionInternal().addCycle(cycle);
    }

    public Set<EProjectCycle> getCycles() {
        return getConnectionInternal().getCycles(params);
    }

    public Set<ProjectRelationship<?, ?>> getRelationshipsTargeting(final ProjectVersionRef ref) {
        final Collection<? extends ProjectRelationship<?, ?>> rels = getConnectionInternal()
                .getRelationshipsTargeting(params, ref.asProjectVersionRef());
        if (rels == null) {
            return Collections.emptySet();
        }

        return new HashSet<ProjectRelationship<?, ?>>(rels);
    }

    public RelationshipGraphConnection getDatabase() {
        return connection;
    }

    public Set<ProjectVersionRef> getAllProjects() {
        return getConnectionInternal().getAllProjects(params);
    }

    public void addMetadata(final ProjectVersionRef ref, final String name, final String value)
            throws RelationshipGraphException {
        getConnectionInternal().addMetadata(ref, name, value);
    }

    public void addMetadata(final ProjectVersionRef ref, final Map<String, String> metadata)
            throws RelationshipGraphException {
        getConnectionInternal().setMetadata(ref, metadata);
    }

    public Set<ProjectVersionRef> getProjectsWithMetadata(final String key) {
        return getConnectionInternal().getProjectsWithMetadata(params, key);
    }

    public void reindex() throws RelationshipGraphException {
        getConnectionInternal().reindex();
    }

    public void reindex(final ProjectVersionRef ref) throws RelationshipGraphConnectionException {
        getConnectionInternal().reindex(ref);
    }

    public Set<List<ProjectRelationship<?, ?>>> getPathsTo(final ProjectVersionRef... projectVersionRefs) {
        return getConnectionInternal().getAllPathsTo(params, projectVersionRefs);
    }

    public boolean introducesCycle(final ProjectRelationship<?, ?> rel) {
        return getConnectionInternal().introducesCycle(params, rel);
    }

    public void addDisconnectedProject(final ProjectVersionRef ref) throws RelationshipGraphException {
        getConnectionInternal().addDisconnectedProject(ref);
    }

    public boolean isMissing(final ProjectVersionRef ref) {
        return getConnectionInternal().isMissing(params, ref);
    }

    public Set<URI> getSources() {
        return params.getActiveSources();
        //        final Set<ProjectRelationship<?>> rels = getAllRelationships();
        //        final Set<URI> sources = new HashSet<URI>();
        //        for ( final ProjectRelationship<?> rel : rels )
        //        {
        //            sources.addAll( rel.getSources() );
        //        }
        //
        //        return sources;
    }

    public GraphMutator getMutator() {
        return params.getMutator();
    }

    public ProjectRelationshipFilter getFilter() {
        return params.getFilter();
    }

    public ViewParams addActivePomLocation(final URI location) {
        return params.addActivePomLocation(location);
    }

    public ViewParams addActivePomLocations(final Collection<URI> locations) {
        return params.addActivePomLocations(locations);
    }

    public ViewParams addActivePomLocations(final URI... locations) {
        return params.addActivePomLocations(locations);
    }

    public ViewParams addActiveSources(final Collection<URI> sources) {
        return params.addActiveSources(sources);
    }

    public ViewParams addActiveSources(final URI... sources) {
        return params.addActiveSources(sources);
    }

    public ViewParams addActiveSource(final URI source) {
        return params.addActiveSource(source);
    }

    public long getLastAccess() {
        return params.getLastAccess();
    }

    public String setProperty(final String key, final String value) {
        return params.setProperty(key, value);
    }

    public String getProperty(final String key) {
        return params.getProperty(key);
    }

    public String getProperty(final String key, final String def) {
        return params.getProperty(key, def);
    }

    public final String getWorkspaceId() {
        return params.getWorkspaceId();
    }

    public final Set<URI> getActivePomLocations() {
        return params.getActivePomLocations();
    }

    public final Set<URI> getActiveSources() {
        return params.getActiveSources();
    }

    public final ProjectVersionRef getSelection(final ProjectRef ref) {
        return params.getSelection(ref);
    }

    // --- IMPORTED FROM EProjectWeb

    // +++ IMPORTED FROM EGraphManager
    public boolean containsGraph(final ProjectVersionRef ref) {
        return getConnectionInternal().containsProject(params, ref);
    }

    public Set<ProjectRelationship<?, ?>> findDirectRelationshipsTo(final ProjectVersionRef to,
            final boolean includeManagedInfo, final RelationshipType... types) {
        return getConnectionInternal().getDirectRelationshipsTo(params, to, includeManagedInfo, true, types);
    }

    public Set<ProjectRelationship<?, ?>> findDirectRelationshipsTo(final ProjectVersionRef to,
            final boolean includeManagedInfo, final boolean includeConcreteInfo, final RelationshipType... types) {
        return getConnectionInternal().getDirectRelationshipsTo(params, to, includeManagedInfo, includeConcreteInfo,
                types);
    }

    public Set<ProjectRelationship<?, ?>> findDirectRelationshipsFrom(final ProjectVersionRef source,
            final boolean managed, final RelationshipType... types) {
        return getConnectionInternal().getDirectRelationshipsFrom(params, source, managed, true, types);
    }

    public Set<ProjectRelationship<?, ?>> findDirectRelationshipsFrom(final ProjectVersionRef source,
            final boolean managed, final boolean concrete, final RelationshipType... types) {
        return getConnectionInternal().getDirectRelationshipsFrom(params, source, managed, concrete, types);
    }

    public Set<ProjectVersionRef> getAllIncompleteSubgraphs() {
        return getConnectionInternal().getMissingProjects(params);
    }

    public Set<ProjectVersionRef> getAllVariableSubgraphs() {
        return getConnectionInternal().getVariableProjects(params);
    }

    public Map<String, String> getMetadata(final ProjectVersionRef ref) {
        final Map<String, String> result = new HashMap<String, String>();
        final Map<String, String> metadata = getConnectionInternal().getMetadata(ref);
        if (metadata != null) {
            result.putAll(metadata);
        }

        result.put(GROUP_ID, ref.getGroupId());
        result.put(ARTIFACT_ID, ref.getArtifactId());
        result.put(VERSION, ref.getVersionString());

        return result;
    }

    public Map<String, String> getMetadata(final ProjectVersionRef ref, final Set<String> keys) {
        final Map<String, String> result = new HashMap<String, String>();
        final Map<String, String> metadata = getConnectionInternal().getMetadata(ref, keys);
        if (metadata != null) {
            result.putAll(metadata);
        }

        if (keys.contains(GROUP_ID)) {
            result.put(GROUP_ID, ref.getGroupId());
        }

        if (keys.contains(ARTIFACT_ID)) {
            result.put(ARTIFACT_ID, ref.getArtifactId());
        }

        if (keys.contains(VERSION)) {
            result.put(VERSION, ref.getVersionString());
        }

        return result;
    }

    public Map<Map<String, String>, Set<ProjectVersionRef>> collateByMetadata(final Set<ProjectVersionRef> refs,
            final Set<String> keys) {
        final Map<Map<String, String>, Set<ProjectVersionRef>> result = new HashMap<Map<String, String>, Set<ProjectVersionRef>>();
        for (final ProjectVersionRef ref : refs) {
            final Map<String, String> metadata = getMetadata(ref, keys);
            Set<ProjectVersionRef> collated = result.get(metadata);
            if (collated == null) {
                collated = new HashSet<ProjectVersionRef>();
                result.put(metadata, collated);
            }

            collated.add(ref);
        }

        return result;
    }

    public void setMetadata(final ProjectVersionRef project, final Map<String, String> metadata)
            throws RelationshipGraphException {
        getConnectionInternal().setMetadata(project, metadata);
    }

    public void deleteRelationshipsDeclaredBy(final ProjectVersionRef ref) throws RelationshipGraphException {
        getConnectionInternal().deleteRelationshipsDeclaredBy(ref);
    }

    public Set<ProjectVersionRef> getProjectsMatching(final ProjectRef projectRef) {
        return getConnectionInternal().getProjectsMatching(params, projectRef);
    }

    public Map<GraphPath<?>, GraphPathInfo> getPathMapTargeting(final Set<ProjectVersionRef> refs) {
        return getConnectionInternal().getPathMapTargeting(params, refs);
    }

    public ProjectVersionRef getPathTargetRef(final GraphPath<?> path) {
        return getConnectionInternal().getPathTargetRef(path);
    }

    public GraphPath<?> createPath(final GraphPath<?> parentPath, final ProjectRelationship<?, ?> relationship) {
        return getConnectionInternal().createPath(parentPath, relationship);
    }

    public GraphPath<?> createPath(final ProjectRelationship<?, ?>... relationships) {
        return getConnectionInternal().createPath(relationships);
    }

    public List<ProjectVersionRef> getPathRefs(final GraphPath<?> path) {
        return getConnectionInternal().getPathRefs(params, path);
    }

    public List<ProjectRelationship<?, ?>> getRelationships(final GraphPath<?> path) {
        return getConnectionInternal().getRelationships(params, path);
    }

    RelationshipGraphConnection getConnection() {
        return connection;
    }

    // --- IMPORTED FROM EGraphManager

    @Override
    public String toString() {
        return "RelationshipGraph [params=" + params + "]";
    }

    public void printStats() {
        getConnectionInternal().printStats();
    }

    public Map<ProjectVersionRef, String> getAllProjectErrors() {
        final Map<ProjectVersionRef, String> errors = new HashMap<ProjectVersionRef, String>();
        final Set<ProjectVersionRef> projects = getConnectionInternal().getAllProjects(params);
        for (final ProjectVersionRef ref : projects) {
            final String error = getConnectionInternal().getProjectError(ref);
            if (error != null) {
                errors.put(ref, error);
            }
        }

        return errors;
    }

    public synchronized boolean isOpen() {
        return connection != null;
    }

    private synchronized RelationshipGraphConnection getConnectionInternal() {
        if (connection == null) {
            throw new IllegalStateException("Relationship graph has been closed!");
        }

        return connection;
    }

    public Collection<? extends ProjectRelationship<?, ?>> getRelationshipsDeclaring(final ProjectVersionRef root) {
        return getConnectionInternal().getRelationshipsDeclaredBy(params, root);
    }

}