/*
* Copyright (c) 2008-2010 "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 Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.graphmatching;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
/**
* Represents a pattern for matching a {@link Relationship}.
*/
public class PatternRelationship extends AbstractPatternObject<Relationship>
{
private final RelationshipType type;
private final boolean directed;
private final boolean optional;
private final boolean anyType;
private final PatternNode firstNode;
private final PatternNode secondNode;
private boolean isMarked = false;
PatternRelationship( PatternNode firstNode,
PatternNode secondNode, boolean optional, boolean directed )
{
this.directed = directed;
this.anyType = true;
this.firstNode = firstNode;
this.secondNode = secondNode;
this.optional = optional;
this.type = null;
}
PatternRelationship( RelationshipType type, PatternNode firstNode,
PatternNode secondNode, boolean optional, boolean directed )
{
this.directed = directed;
this.anyType = false;
this.type = type;
this.firstNode = firstNode;
this.secondNode = secondNode;
this.optional = optional;
}
boolean anyRelType()
{
return anyType;
}
/**
* Get the {@link PatternNode} that this pattern relationship relates, that
* is not the specified node.
*
* @param node one of the {@link PatternNode}s this pattern relationship
* relates.
* @return the other pattern node.
*/
public PatternNode getOtherNode( PatternNode node )
{
if ( node == firstNode )
{
return secondNode;
}
if ( node == secondNode )
{
return firstNode;
}
throw new RuntimeException( "Node[" + node +
"] not in this relationship" );
}
/**
* Get the first pattern node that this pattern relationship relates.
*
* @return the first pattern node.
*/
public PatternNode getFirstNode()
{
return firstNode;
}
/**
* Get the second pattern node that this pattern relationship relates.
*
* @return the second pattern node.
*/
public PatternNode getSecondNode()
{
return secondNode;
}
/**
* Does this pattern relationship represent a relationship that has to exist
* in the subgraph to consider the subgraph a match of the pattern, or is it
* an optional relationship.
*
* @return <code>true</code> if this pattern relationship represents an
* optional relationship, <code>false</code> if it represents a
* required relationship.
*/
public boolean isOptional()
{
return optional;
}
void mark()
{
isMarked = true;
}
void unMark()
{
isMarked = false;
}
boolean isMarked()
{
return isMarked;
}
/**
* Get the {@link RelationshipType} a relationship must have in order to
* match this pattern relationship. Will return <code>null</code> if a
* relationship with any {@link RelationshipType} will match.
*
* @return the {@link RelationshipType} of this relationship pattern.
*/
public RelationshipType getType()
{
return type;
}
/**
* Get the direction in which relationships are discovered using this
* relationship pattern from the specified node. May be
* {@link Direction#OUTGOING outgoing}, {@link Direction#INCOMING incoming},
* or {@link Direction#BOTH both}.
*
* @param fromNode the pattern node to find the direction of this pattern
* relationship from.
* @return the direction to discover relationships matching this pattern in.
*/
public Direction getDirectionFrom( PatternNode fromNode )
{
if ( !directed )
{
return Direction.BOTH;
}
if ( fromNode.equals( firstNode ) )
{
return Direction.OUTGOING;
}
if ( fromNode.equals( secondNode ) )
{
return Direction.INCOMING;
}
throw new RuntimeException( fromNode + " not in " + this );
}
@Override
public String toString()
{
return type + ":" + optional;
}
}