/**
* Copyright (c) 2002-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.util;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.kernel.impl.transaction.IllegalResourceException;
public abstract class AbstractLink<T> implements Link<T>
{
private final Node node;
private final RelationshipType type;
private final Direction direction;
public AbstractLink( Node node, RelationshipType type,
Direction direction )
{
this.node = node;
this.type = type;
this.direction = direction;
}
public AbstractLink( Node node, RelationshipType type )
{
this( node, type, Direction.OUTGOING );
}
protected Node node()
{
return this.node;
}
protected Direction direction()
{
return this.direction;
}
protected RelationshipType type()
{
return this.type;
}
protected abstract T newObject( Node node );
private T newObject( Relationship relationship )
{
return newObject( relationship.getOtherNode( this.node ) );
}
protected abstract Node getNodeFromItem( T item );
protected Relationship getLinkRelationshipOrNull()
{
return this.node.getSingleRelationship( this.type(),
this.direction() );
}
public T get()
{
Relationship relationship = getLinkRelationshipOrNull();
return relationship == null ? null : newObject( relationship );
}
public boolean has()
{
return getLinkRelationshipOrNull() != null;
}
public T remove()
{
Relationship relationship = getLinkRelationshipOrNull();
T result = null;
if ( relationship != null )
{
result = newObject( relationship );
entityRemoved( result, relationship );
relationship.delete();
}
return result;
}
public T set( T object )
{
GraphDatabaseUtil.acquireWriteLock( node );
try
{
Relationship existingRelationship = getLinkRelationshipOrNull();
T existingObject = null;
if ( existingRelationship != null )
{
existingObject = newObject( existingRelationship );
entityRemoved( existingObject, existingRelationship );
existingRelationship.delete();
}
Node entityNode = getNodeFromItem( object );
Node startNode = this.direction() == Direction.OUTGOING ?
this.node() : entityNode;
Node endNode = this.direction() == Direction.OUTGOING ?
entityNode : this.node();
Relationship createdRelationship =
startNode.createRelationshipTo( endNode, this.type() );
entitySet( object, createdRelationship );
return existingObject;
}
catch ( IllegalResourceException e )
{
throw new RuntimeException( e );
}
}
protected void entitySet( T entity, Relationship createdRelationship )
{
}
protected void entityRemoved( T entity, Relationship removedRelationship )
{
}
}