Package org.neo4j.collections.graphdb.impl

Source Code of org.neo4j.collections.graphdb.impl.VertexImpl$TraversalIterator

/**
* Copyright (c) 2002-2013 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j 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.
*
* This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.collections.graphdb.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;

import org.neo4j.collections.graphdb.BijectiveConnectionMode;
import org.neo4j.collections.graphdb.BinaryEdge;
import org.neo4j.collections.graphdb.Connection;
import org.neo4j.collections.graphdb.Connector;
import org.neo4j.collections.graphdb.ConnectorType;
import org.neo4j.collections.graphdb.DatabaseService;
import org.neo4j.collections.graphdb.Edge;
import org.neo4j.collections.graphdb.EdgeType;
import org.neo4j.collections.graphdb.Property;
import org.neo4j.collections.graphdb.PropertyType;
import org.neo4j.collections.graphdb.RightRestrictedConnectionMode;
import org.neo4j.collections.graphdb.SortableBinaryEdge;
import org.neo4j.collections.graphdb.SortableBinaryEdgeType;
import org.neo4j.collections.graphdb.Traversal;
import org.neo4j.collections.graphdb.TraversalDescription;
import org.neo4j.collections.graphdb.TraversalPath;
import org.neo4j.collections.graphdb.Vertex;
import org.neo4j.collections.graphdb.VertexType;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;

public class VertexImpl implements Vertex {

  static class EdgeIterator implements Iterator<Edge> {

    private final Vertex vertex;
    private final Iterator<Relationship> connectorRels;

    public EdgeIterator(
        EdgeType edgeType,
        ConnectorType<?> connectorType,
        Vertex vertex) {
      this.vertex = vertex;
      this.connectorRels = vertex
          .getNode()
          .getRelationships(
              DynamicRelationshipType.withName(edgeType.getName()
                  + EDGEROLE_SEPARATOR
                  + connectorType.getName()),
              Direction.INCOMING).iterator();
    }

    @Override
    public boolean hasNext() {
      return connectorRels.hasNext();
    }

    @Override
    public Edge next() {
      if (connectorRels.hasNext()) {
        return new EdgeImpl(vertex.getDb(), connectorRels.next().getStartNode().getId());
      } else {
        throw new NoSuchElementException();
      }
    }

    @Override
    public void remove() {
    }
  }

  static class ConnectorTypeIterable implements Iterable<Edge> {

    final Iterable<ConnectorType<?>> connectorTypes;
    final EdgeType edgeType;

    private final Vertex vertex;

    public ConnectorTypeIterable(
        EdgeType edgeType,
        Iterable<ConnectorType<?>> connectorTypes,
        Vertex vertex) {
      this.edgeType = edgeType;
      this.connectorTypes = connectorTypes;
      this.vertex = vertex;
    }

    @Override
    public Iterator<Edge> iterator() {
      return new ConnectorTypeIterator(edgeType, connectorTypes.iterator(), vertex);
    }

  }

  static class ConnectorTypeIterator implements Iterator<Edge> {

    private final Iterator<ConnectorType<?>> connectorTypes;

    private final Vertex vertex;
    private final EdgeType edgeType;
    private EdgeIterator currentEdgeIterator = null;
    private Boolean hasNext = null;

    public ConnectorTypeIterator(
        EdgeType edgeType,
        Iterator<ConnectorType<?>> connectorTypes,
        Vertex vertex) {
      this.edgeType = edgeType;
      this.connectorTypes = connectorTypes;
      this.vertex = vertex;
    }

    @Override
    public boolean hasNext() {
      if (hasNext == null) {
        if (currentEdgeIterator == null) {
          if (connectorTypes.hasNext()) {
            currentEdgeIterator = new EdgeIterator(edgeType,
                connectorTypes.next(), vertex);
            return hasNext();
          } else {
            hasNext = false;
            return false;
          }
        } else {
          if (currentEdgeIterator.hasNext()) {
            hasNext = true;
            return true;
          } else {
            currentEdgeIterator = null;
            return hasNext();
          }
        }
      } else {
        return hasNext;
      }
    }

    @Override
    public Edge next() {
      if (hasNext()) {
        hasNext = null;
        return currentEdgeIterator.next();
      } else {
        throw new NoSuchElementException();
      }
    }

    @Override
    public void remove() {
    }

  }

  static class EdgeTypeIterable implements Iterable<Edge> {

    EdgeType[] edgeTypes;

    private final Vertex vertex;

    EdgeTypeIterable(Vertex vertex, EdgeType... edgeTypes) {
      this.edgeTypes = edgeTypes;
      this.vertex = vertex;
    }

    @Override
    public Iterator<Edge> iterator() {
      ArrayList<EdgeType> ets = new ArrayList<EdgeType>();
      for (EdgeType edgeType : edgeTypes) {
        ets.add(edgeType);
      }
      return new EdgeTypeIterator(ets.iterator(), vertex);
    }

  }

  static class EdgeTypeIterator implements Iterator<Edge> {

    Iterator<EdgeType> edgeTypes;
    ConnectorTypeIterator currentConnectorTypeIterator = null;
    Boolean hasNext = null;
    private final Vertex vertex;

    EdgeTypeIterator(Iterator<EdgeType> edgeTypes, Vertex vertex) {
      this.edgeTypes = edgeTypes;
      this.vertex = vertex;
    }

    @Override
    public boolean hasNext() {
      if (hasNext == null) {
        if (currentConnectorTypeIterator == null) {
          if (edgeTypes.hasNext()) {
            EdgeType edgeType = edgeTypes.next();
            currentConnectorTypeIterator = new ConnectorTypeIterator(edgeType, edgeType.getConnectorTypes().iterator(), vertex);
            return hasNext();
          } else {
            hasNext = false;
            return false;
          }
        } else {
          if (currentConnectorTypeIterator.hasNext()) {
            hasNext = true;
            return true;
          } else {
            currentConnectorTypeIterator = null;
            return hasNext();
          }
        }
      } else {
        return hasNext;
      }
    }

    @Override
    public Edge next() {
      if (hasNext()) {
        hasNext = null;
        return currentConnectorTypeIterator.next();
      } else {
        throw new NoSuchElementException();
      }
    }

    @Override
    public void remove() {
    }

  }

  class TraversalIterator implements Iterator<Traversal> {

    @Override
    public boolean hasNext() {
      return false;
    }

    @Override
    public Traversal next() {
      throw new NoSuchElementException();
    }

    @Override
    public void remove() {
    }

  }

  class PropertyTypeIterable implements Iterable<PropertyType<?>> {

    final Node node;

    public PropertyTypeIterable(Node node) {
      this.node = node;
    }

    @Override
    public Iterator<PropertyType<?>> iterator() {
      return new PropertyTypeIterator(node);
    }

  }

  class PropertyTypeIterator implements Iterator<PropertyType<?>> {

    final Iterator<String> keys;

    PropertyTypeIterator(Node n) {
      keys = n.getPropertyKeys().iterator();
    }

    @Override
    public boolean hasNext() {
      return keys.hasNext();
    }

    @Override
    public PropertyType<?> next() {
      return PropertyType.getPropertyTypeByName(db, keys.next());
    }

    @Override
    public void remove() {
    }

  }

  private class VertexTypeIterable implements Iterable<VertexType> {

    @Override
    public Iterator<VertexType> iterator() {
      return new VertexTypeIterator();
    }

  }

  private class VertexTypeIterator implements Iterator<VertexType> {

    private final Iterator<Node> nodes;
    boolean foundSpecial = false;
    VertexType special = getSpecialVertexType();

    public VertexTypeIterator() {
      ArrayList<Node> nodes = new ArrayList<Node>();
      Long[] nodeIds = (Long[]) getNode().getProperty(TYPE_IDS);
      for (Long id : nodeIds) {
        nodes.add(db.getNodeById(id));
      }
      this.nodes = nodes.iterator();
    }

    @Override
    public boolean hasNext() {
      if (nodes.hasNext()) {
        return true;
      } else if (foundSpecial) {
        return false;
      } else if (special == null) {
        return false;
      } else {
        return true;
      }
    }

    @Override
    public VertexType next() {
      if (hasNext()) {
        if (nodes.hasNext()) {
          VertexType vertexType = (VertexType) db.getVertex(
              nodes.next());
          if (special.getName().equals(vertexType.getName())) {
            foundSpecial = true;
          }
          return vertexType;
        } else {
          return special;
        }
      } else {
        throw new NoSuchElementException();
      }
    }

    @Override
    public void remove() {
    }

  }

  public static final String EDGEROLE_SEPARATOR = "/#/";

  public static final String TYPE_IDS = "org.neo4j.collections.graphdb.type_ids";

  final protected long id;
  final protected DatabaseService db;

  public VertexImpl(DatabaseService db, Long id) {
    this.id = id;
    this.db = db;
  }

  @Override
  public Vertex addEdge(Vertex vertex, RelationshipType type) {
    createEdgeTo(vertex, type);
    return this;
  }

  @Override
  public Vertex addEdge(Vertex vertex, SortableBinaryEdgeType<?> type) {
    createEdgeTo(vertex, type);
    return this;
  }

  @Override
  public Vertex addType(VertexType vertexType) {
    Long[] nodeIds = (Long[]) getNode().getProperty(TYPE_IDS);
    boolean exists = false;
    for (Long id : nodeIds) {
      if (id == vertexType.getNode().getId()) {
        exists = true;
      }
    }
    if (!exists) {
      Long[] ids = new Long[nodeIds.length + 1];
      for (int i = 0; i < nodeIds.length; i++) {
        ids[i] = nodeIds[i];
      }
      ids[nodeIds.length] = vertexType.getNode().getId();
    }
    return this;
  }

  @Override
  public BinaryEdge createEdgeTo(Vertex vertex, RelationshipType type) {
    return db.getBinaryEdgeType(type).createEdge(this, vertex);
  }

  @Override
  public <T> SortableBinaryEdge<T> createEdgeTo(Vertex vertex,
      SortableBinaryEdgeType<T> type) {
    return type.createEdge(this, vertex);
  }

  /**
   * We don't dispatch here to Binary Edges because we can't iterate over
   * relationship types.
   */
  @Override
  public Iterable<BinaryEdge> getBinaryEdges() {
    return new RelationshipIterable(getNode().getRelationships());
  }

  /**
   * We don't dispatch here to Binary Edges because we can't iterate over
   * relationship types.
   */
  @Override
  public Iterable<BinaryEdge> getBinaryEdges(Direction dir) {
    return new RelationshipIterable(getNode().getRelationships(dir));
  }

  /**
   * We don't dispatch here to Binary Edges because then we would have to read
   * all relationships for each type. As soon as relationships are partitioned
   * per relationship type, per role/direction, the implementation of this
   * method can dispatch to Binary Edge
   */
  @Override
  public Iterable<BinaryEdge> getBinaryEdges(Direction dir,
      RelationshipType... relTypes) {
    return new RelationshipIterable(getNode().getRelationships(dir,
        relTypes));
  }

  /**
   * We don't dispatch here to Binary Edges because then we would have to read
   * all relationships for each type. As soon as relationships are partitioned
   * per relationship type, per role/direction, the implementation of this
   * method can dispatch to Binary Edge
   */
  @Override
  public Iterable<BinaryEdge> getBinaryEdges(RelationshipType... relTypes) {
    return new RelationshipIterable(getNode().getRelationships(relTypes));
  }

  /**
   * We can dispatch here to Binary Edge because we have a single
   * RelationshipType
   */
  @Override
  public Iterable<BinaryEdge> getBinaryEdges(RelationshipType relType,
      Direction dir) {
    return db.getBinaryEdgeType(relType).getEdges(this, dir);
  }

  @Override
  public DatabaseService getDb() {
    return db;
  }

  /**
   * We don't dispatch here to Binary Edges because then we would have to read
   * all relationships for each type. As soon as relationships are partitioned
   * per relationship type, per role/direction, the implementation of this
   * method can dispatch to Binary Edge
   */
  @Override
  public Iterable<Edge> getEdges(EdgeType... edgeTypes) {
    return new EdgeTypeIterable(this, edgeTypes);
  }

  @Override
  public Iterable<Edge> getEdges(EdgeType type,
      ConnectorType<?>... connectors) {
    return type.getEdges(this, connectors);
  }

  @Override
  public Node getNode() {
    return db.getNodeById(id);
  }

  @Override
  public <T> Property<T> getProperty(PropertyType<T> pt) {
    return pt.getProperty(this);
  }

  @Override
  public PropertyContainer getPropertyContainer() {
    return getNode();
  }

  @Override
  public Iterable<PropertyType<?>> getPropertyTypes() {
    return new PropertyTypeIterable(getNode());
  }

  @Override
  public <T> T getPropertyValue(PropertyType<T> pt) {
    return pt.getPropertyValue(this);
  }

  @Override
  public BinaryEdge getSingleBinaryEdge(RelationshipType type, Direction dir) {
    return db.getBinaryEdgeType(type).getSingleBinaryEdge(this, dir);
  }

  protected VertexType getSpecialVertexType() {
    return null;
  }

  @Override
  public Iterable<VertexType> getTypes() {
    return new VertexTypeIterable();
  }

  @Override
  public boolean hasBinaryEdge() {
    return getNode().hasRelationship();
  }

  @Override
  public boolean hasBinaryEdge(Direction dir) {
    return getNode().hasRelationship(dir);
  }

  @Override
  public boolean hasBinaryEdge(Direction dir, RelationshipType... relTypes) {
    return getNode().hasRelationship(dir, relTypes);
  }

  @Override
  public boolean hasBinaryEdge(RelationshipType... relType) {
    return getNode().hasRelationship(relType);
  }

  @Override
  public boolean hasBinaryEdge(RelationshipType relType, Direction dir) {
    return db.getBinaryEdgeType(relType).hasEdge(this, dir);
  }

  @Override
  public boolean hasEdge(EdgeType edgeType, ConnectorType<?>... connectors) {
    return edgeType.hasEdge(this, connectors);
  }

  @Override
  public <T> boolean hasProperty(PropertyType<T> pt) {
    return pt.hasProperty(this);
  }

  @Override
  public Iterator<Traversal> iterator() {
    return new TraversalIterator();
  }

  @Override
  public Vertex removeProperty(PropertyType<?> pt) {
    pt.removeProperty(this);
    return this;
  }

  @Override
  public Vertex removeType(VertexType vertexType) {
    Long[] nodeIds = (Long[]) getNode().getProperty(TYPE_IDS);
    boolean exists = false;
    for (Long id : nodeIds) {
      if (id == vertexType.getNode().getId()) {
        exists = true;
      }
    }
    if (!exists) {
      Long[] ids = new Long[nodeIds.length - 1];
      boolean skipped = false;
      for (int i = 0; i < nodeIds.length; i++) {
        if (skipped) {
          ids[i - 1] = nodeIds[i];
        } else {
          if (ids[i] == nodeIds[i]) {
            skipped = true;
          } else {
            ids[i] = nodeIds[i];
          }
        }
      }
      ids[nodeIds.length] = vertexType.getNode().getId();
    }
    return this;
  }

  @Override
  public <T> Vertex setProperty(PropertyType<T> pt, T value) {
    pt.setProperty(this, value);
    return this;
  }

  @Override
  public TraversalPath getPath() {
    return new TraversalPath() {

      @Override
      public Iterator<Connection<?>> iterator() {
        return new Iterator<Connection<?>>() {

          boolean hasNext = true;

          @Override
          public boolean hasNext() {
            return hasNext;
          }

          @Override
          public Connection<?> next() {
            if (hasNext) {
              hasNext = false;
              return getSelfConnection();
            } else {
              throw new NoSuchElementException();
            }
          }

          @Override
          public void remove() {
          }
        };
      }

      @Override
      public Connection<?> getFirstElement() {
        return getSelfConnection();
      }

      @Override
      public Connection<?> getLastElement() {
        return getSelfConnection();
      }

      @Override
      public int length() {
        return 0;
      }

    };

  }

  @SuppressWarnings("unchecked")
  @Override
  public Connection<BijectiveConnectionMode> getSelfConnection() {
    Edge edge = new NullaryEdgeImpl(db, getNode().getId());
    return new Connection<BijectiveConnectionMode>((Connector<BijectiveConnectionMode>) Connector.getInstance(edge.getType().getConnectorType(NullaryEdgeTypeImpl.NULLARYCONNECTORNAME), edge), this);
  }

  @Override
  public Traversal traverse(TraversalDescription descr) {
    return descr.traverse(this);
  }

  @Override
  public Iterable<TraversalPath> getContainedPaths() {
    ArrayList<TraversalPath> paths = new ArrayList<TraversalPath>();
    return paths;
  }

  @Override
  public Edge getEdge(EdgeType edgeType,
      ConnectorType<RightRestrictedConnectionMode> connectorType) {
    Relationship rel = getNode().getSingleRelationship(DynamicRelationshipType.withName(edgeType.getName()+EDGEROLE_SEPARATOR+connectorType.getName()), Direction.INCOMING);
    if(rel == null){
      return null;
    }else{
      return new EdgeImpl(db, rel.getStartNode().getId());
    }
    
  }

}
TOP

Related Classes of org.neo4j.collections.graphdb.impl.VertexImpl$TraversalIterator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.