org.commonjava.cartographer.graph.spi.neo4j.model.Neo4jGraphPath.java Source code

Java tutorial

Introduction

Here is the source code for org.commonjava.cartographer.graph.spi.neo4j.model.Neo4jGraphPath.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.spi.neo4j.model;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.codec.digest.DigestUtils;
import org.commonjava.cartographer.graph.model.GraphPath;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.Relationship;

public class Neo4jGraphPath implements GraphPath<Long> {

    private final long[] relationships;

    private final long startNode;

    private final long endNode;

    public Neo4jGraphPath(final Neo4jGraphPath parent, final Relationship... relationships) {
        if (parent == null) {
            throw new NullPointerException("Parent path cannot be null");
        }

        this.startNode = parent.startNode;
        if (relationships.length > 0) {
            this.endNode = relationships[relationships.length - 1].getEndNode().getId();
        } else {
            this.endNode = parent.endNode;
        }

        final int parentLen = parent.relationships.length;

        this.relationships = new long[parentLen + relationships.length];

        if (parentLen > 0) {
            System.arraycopy(parent.relationships, 0, this.relationships, 0, parent.relationships.length);
        }

        if (this.relationships.length > 0) {
            for (int i = parentLen; i < this.relationships.length; i++) {
                this.relationships[i] = relationships[i - parentLen].getId();
            }
        }
    }

    public Neo4jGraphPath(final Path path) {
        this.startNode = path.startNode().getId();
        this.endNode = path.endNode().getId();

        final List<Long> ids = new ArrayList<Long>();
        for (final Relationship r : path.relationships()) {
            ids.add(r.getId());
        }

        this.relationships = new long[ids.size()];
        for (int i = 0; i < ids.size(); i++) {
            this.relationships[i] = ids.get(i);
        }
    }

    public Neo4jGraphPath(final Node start, final Node end, final long[] rids) {
        this.startNode = start.getId();
        this.endNode = end.getId();
        this.relationships = rids;
    }

    public Neo4jGraphPath(final Relationship[] relationships) {
        if (relationships.length > 0) {
            this.startNode = relationships[0].getStartNode().getId();

            this.endNode = relationships[relationships.length - 1].getEndNode().getId();
        } else {
            throw new IllegalArgumentException(
                    "Cannot initialize path with zero relationships and no explicit start node!");
        }

        this.relationships = new long[relationships.length];

        final int i = 0;
        for (final Relationship relationship : relationships) {
            this.relationships[i] = relationship.getId();
        }
    }

    private Neo4jGraphPath(final Neo4jGraphPath parent, final long endNode, final long[] newRelationships) {
        this.startNode = parent.startNode;
        this.endNode = endNode;

        final int parentLen = parent.relationships.length;

        this.relationships = new long[parentLen + newRelationships.length];

        System.arraycopy(parent.relationships, 0, this.relationships, 0, parentLen);
        System.arraycopy(newRelationships, 0, this.relationships, parentLen, newRelationships.length);
    }

    public Neo4jGraphPath append(final Neo4jGraphPath childPath) {
        if (length() > 0 && getLastRelationshipId() != childPath.getFirstRelationshipId()) {
            throw new IllegalArgumentException("Cannot splice " + childPath + " onto " + this
                    + ". They don't overlap on last/first relationshipId!");
        }

        if (childPath.length() < 2) {
            return this;
        }

        final long[] ids = new long[childPath.length() - 1];
        System.arraycopy(childPath.getRelationshipIds(), 1, ids, 0, ids.length);

        return new Neo4jGraphPath(this, childPath.endNode, ids);
    }

    public long getStartNodeId() {
        return startNode;
    }

    public long getEndNodeId() {
        return endNode;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + Long.valueOf(startNode).hashCode();
        result = prime * result + Long.valueOf(endNode).hashCode();
        result = prime * result + Arrays.hashCode(relationships);
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Neo4jGraphPath other = (Neo4jGraphPath) obj;
        if (startNode != other.startNode) {
            return false;
        }
        if (endNode != other.endNode) {
            return false;
        }
        return Arrays.equals(relationships, other.relationships);
    }

    @Override
    public Iterator<Long> iterator() {
        return new Iterator<Long>() {
            private int next = 0;

            @Override
            public boolean hasNext() {
                return relationships.length > next;
            }

            @Override
            public Long next() {
                return relationships[next++];
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException(
                        "Immutable array of relationship ID's. Remove not supported.");
            }
        };
    }

    @Override
    public String toString() {
        return String.format("%s [relationships=%s, from=%s, to=%s]", getClass().getSimpleName(),
                Arrays.toString(relationships), startNode, endNode);
    }

    @Override
    public String getKey() {
        final StringBuilder sb = new StringBuilder();
        for (final long id : relationships) {
            if (sb.length() > 0) {
                sb.append(',');
            }
            sb.append(id);
        }

        return DigestUtils.shaHex(sb.toString());
    }

    public long getLastRelationshipId() {
        if (relationships.length < 1) {
            return -1;
        }

        return relationships[relationships.length - 1];
    }

    public long getFirstRelationshipId() {
        if (relationships.length < 1) {
            return -1;
        }

        return relationships[0];
    }

    public long[] getRelationshipIds() {
        return relationships;
    }

    public int length() {
        return relationships.length;
    }

    public boolean contains(final long id) {
        for (final long rid : relationships) {
            if (rid == id) {
                return true;
            }
        }
        return false;
    }

}