/*
* This file is part of the HyperGraphDB source distribution. This is copyrighted
* software. For permitted uses, licensing options and redistribution, please see
* the LicensingInformation file at the root level of the distribution.
*
* Copyright (c) 2005-2010 Kobrix Software, Inc. All rights reserved.
*/
package org.hypergraphdb.query;
import org.hypergraphdb.HGException;
import org.hypergraphdb.HGHandle;
import org.hypergraphdb.HyperGraph;
import org.hypergraphdb.HGQuery.hg;
import org.hypergraphdb.util.HGUtils;
import org.hypergraphdb.util.Ref;
/**
* <p>
* An <code>AtomTypeCondition</code> examines the type of a given atom
* and evaluates to <code>true</code> or <code>false</code> depending on
* whether the type of the atom matches exactly (i.e. has the same type
* handle) as that of the condition. Note that this condition looks at the
* concrete type of the atom and ignores and sub-typing relationships.
* </p>
*
* <p>
* The type can be specified either as a HyperGraph handle or as a Java class.
* In the latter, the corresponding HyperGraph will be retrieved at appropriate
* times. However, those two properties overlap each other, in the sense the you
* can set one or the other, but not both at the same time. If you set the type
* as a Java class, the corresponding {@link HGHandle} will be retrieved every time
* it is needed. In particular, if this is used as a filtering condition applied
* iteratively over a large result set, performance will be hurt by the extra step.
* </p>
*
* @author Borislav Iordanov
*/
public class AtomTypeCondition implements HGQueryCondition, HGAtomPredicate, TypeCondition
{
private Ref<?> type;
public AtomTypeCondition()
{
}
/**
* <p>Construct a new atom type condition.</p>
*
* @param typeRef A {@link Ref} to a Java <code>Class</code> or a {@link HGHandle}.
*/
public AtomTypeCondition(Ref<?> typeRef)
{
this.type = typeRef;
}
public AtomTypeCondition(Class<?> javaClass)
{
this(hg.constant(javaClass));
}
public AtomTypeCondition(HGHandle typeHandle)
{
this(hg.constant(typeHandle));
}
public void setJavaClass(Class<?> c)
{
this.type = hg.constant(c);
}
public Class<?> getJavaClass()
{
Object t = type.get();
return t instanceof Class ? (Class<?>)t : null;
}
public void setTypeHandle(HGHandle handle)
{
this.type = hg.constant(handle);
}
public HGHandle getTypeHandle()
{
Object t = type.get();
return t instanceof HGHandle ? (HGHandle)t : null;
}
public HGHandle getTypeHandle(HyperGraph graph)
{
Object t = type.get();
if (t instanceof HGHandle)
return (HGHandle)t;
else
return graph.getTypeSystem().getTypeHandle((Class<?>)t);
}
public Ref<?> getTypeReference()
{
return type;
}
public void setTypeReference(Ref<?> type)
{
this.type = type;
}
public boolean satisfies(HyperGraph hg, HGHandle value)
{
HGHandle h = null;
Object t = type.get();
if (t == null)
throw new NullPointerException("AtomTypeCondition with null type.");
else if (t instanceof HGHandle)
h = (HGHandle)t;
else
h = hg.getTypeSystem().getTypeHandle((Class)t);
HGHandle typeOfValue = hg.getType(value);
if (typeOfValue == null)
throw new HGException("Could not get type of atom " + value);
return typeOfValue.equals(h);
}
public int hashCode()
{
return type == null ? 0 : HGUtils.hashIt(type.get());
}
public boolean equals(Object x)
{
if (! (x instanceof AtomTypeCondition))
return false;
else
{
AtomTypeCondition cond = (AtomTypeCondition)x;
return type == null ? cond.type == null :
cond.type == null ? false : HGUtils.eq(type.get(), cond.type.get());
}
}
public String toString()
{
StringBuffer result = new StringBuffer("typeIs(");
result.append(getJavaClass() != null ? getJavaClass().getName() : getTypeHandle().getPersistent());
result.append(")");
return result.toString();
}
}