/* * 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.HGHandle; import org.hypergraphdb.HGQuery.hg; import org.hypergraphdb.HyperGraph; import org.hypergraphdb.util.HGUtils; import org.hypergraphdb.util.Ref; /** * * <p> * This is a <code>HGQueryCondition</code> that constrains the value of an * atom as well as its type. In general, the HyperGraph type system allows * values to have multiple types. Two atoms <code>X</code> and * <code>Y</code> can share the same value <code>V</code> without however * having the same type. <code>X</code> may be of type <code>T</code> and * <code>Y</code> may be of type <code>S</code> different than <code>T</code>. * In such situations, when performing a query by value, a <code>TypedValueCondition<code> * should be used instead of <code>AtomValueCondition</code>. * </p> * * @author Borislav Iordanov * */ public class TypedValueCondition extends AtomValueCondition implements TypeCondition { private Ref<?> type; public TypedValueCondition() { } public TypedValueCondition(Ref<?> type, Ref<Object> value) { this(type, value, ComparisonOperator.EQ); } public TypedValueCondition(HGHandle typeHandle, Object value) { this(hg.constant(typeHandle), hg.constant(value), ComparisonOperator.EQ); } public TypedValueCondition(Class<?> javaClass, Object value) { this(hg.constant(javaClass), hg.constant(value), ComparisonOperator.EQ); } public TypedValueCondition(Ref<?> type, Ref<Object> value, ComparisonOperator op) { super(value, op); this.type = type; } public TypedValueCondition(HGHandle typeHandle, Object value, ComparisonOperator op) { this(hg.constant(typeHandle), hg.constant(value), op); } public TypedValueCondition(Class<?> javaClass, Object value, ComparisonOperator op) { this(hg.constant(javaClass), hg.constant(value), op); } public boolean satisfies(HyperGraph hg, HGHandle handle) { Object atom = hg.get(handle); if (atom == null) return false; HGHandle atomType = hg.getTypeSystem().getTypeHandle(handle); HGHandle typeHandle = null; Object t = type.get(); if (t == null) throw new NullPointerException("AtomTypeCondition with null type."); else if (t instanceof HGHandle) typeHandle = (HGHandle)t; else typeHandle = hg.getTypeSystem().getTypeHandle((Class)t); return atomType.equals(typeHandle) && compareToValue(hg, atom); } public Ref<?> getTypeReference() { return type; } public void setTypeReference(Ref<?> type) { this.type = type; } 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 String toString() { StringBuffer result = new StringBuffer("valueIs("); result.append(getOperator()); result.append(","); result.append(String.valueOf(getValue())); result.append(" with type "); result.append(getJavaClass() != null ? getJavaClass().getName() : getTypeHandle().getPersistent()); result.append(")"); return result.toString(); } public int hashCode() { return super.hashCode() + (type == null ? 0 : HGUtils.hashIt(type.get())); } public boolean equals(Object x) { if (! (x instanceof TypedValueCondition)) return false; else if (!super.equals(x)) return false; else { TypedValueCondition c = (TypedValueCondition)x; return type == null ? c.type == null : c.type == null ? false : HGUtils.eq(type.get(), c.type.get()); } } }