package org.neo4j.meta.model;
import java.util.Collection;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.ReturnableEvaluator;
import org.neo4j.graphdb.StopEvaluator;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.Traverser;
// TODO ContainerMempership:
// http://www.w3.org/TR/rdf-schema/#ch_containermembershipproperty?
//
// rdfs:seeAlso
// rdfs:idDefinedBy
/**
* The super class of {@link MetaModelClass} and
* {@link MetaModelProperty}. It contains hierarchial functionality.
*/
public abstract class MetaModelThing extends MetaModelObject
{
MetaModelThing( MetaModel model, Node node )
{
super( model, node );
}
/**
* @return a modifiable {@link Collection} of directly connected
* (non-recursive) sub "things" (class or property).
*/
public abstract Collection<? extends MetaModelThing> getDirectSubs();
/**
* @return a modifiable {@link Collection} of directly connected
* (non-recursive) super "things" (class or property).
*/
public abstract Collection<? extends MetaModelThing> getDirectSupers();
protected abstract RelationshipType subRelationshipType();
/**
* @param <T> the type of {@link MetaModelThing}, should match
* the type of this instance.
* @param thing the {@link MetaModelThing} to check against.
* @return {@code true} if this thing is a sub (class or property) of
* {@code thing}.
*/
public <T extends MetaModelThing> boolean isSubOf( T thing )
{
Transaction tx = graphDb().beginTx();
try
{
boolean found = false;
Node target = thing.node();
for ( Node node : node().traverse( Traverser.Order.BREADTH_FIRST,
StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL,
subRelationshipType(), Direction.OUTGOING ) )
{
if ( node.equals( target ) )
{
found = true;
break;
}
}
tx.success();
return found;
}
finally
{
tx.finish();
}
}
private String additionalPropertyKey( String key )
{
return "additional." + key;
}
/**
* Sets an additional property for this thing, f.ex. a label or a comment.
* @param key the property key.
* @param value the property value.
*/
public void setAdditionalProperty( String key, Object value )
{
node().setProperty( additionalPropertyKey( key ), value );
}
/**
* Removes an additional property from this thing, f.ex. a label or
* a comment.
* @param key the property key.
*/
public void removeAdditionalProperty( String key )
{
node().removeProperty( additionalPropertyKey( key ) );
}
/**
* Returns an additional property from this thing, f.ex. a label or
* a comment.
* @param key the property key.
* @return the property value for property {@code key} or
* {@code null} if no value exists for {@code key}.
*/
public Object getAdditionalProperty( String key )
{
return ( String ) node().getProperty(
additionalPropertyKey( key ), null );
}
public Object[] getAdditionalProperties( String key )
{
Object value = getAdditionalProperty( key );
return value != new Object[ 0 ] ?
this.graphDbUtil().propertyValueAsArray( key ) : null;
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + getName() + "]";
}
}