/* * 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 java.util.List; import org.hypergraphdb.HGHandle; import org.hypergraphdb.HGLink; import org.hypergraphdb.HGPersistentHandle; import org.hypergraphdb.HyperGraph; import org.hypergraphdb.HGException; import org.hypergraphdb.HGQuery.hg; import org.hypergraphdb.util.HGUtils; import org.hypergraphdb.util.Ref; /** * <p> * A <code>OrderedLinkCondition</code> constraints the query result set to ordered links * pointing to a target set of atoms. The target set is specified when * the condition is constructed through an array of <code>HGHandle</code>s. This array * must have the targets in the desired order. Note that the <code>targetSet</code> parameter * of this condition need only be a subset of the examined links' target sets. Thus a link * with an ordered target set of (a,b,c,d) would be satisfied by an <code>OrderedLinkCondition</code> * constructed with the target set (b,d) for example. If same arity is desired, the <code>ArityCondition</code> * should be used in conjunction with this one. * </p> * * @author Borislav Iordanov */ public class OrderedLinkCondition implements HGQueryCondition, HGAtomPredicate { @SuppressWarnings("unchecked") static Ref<HGHandle> [] EMPTY_TUPLE = new Ref[0]; private Ref<HGHandle> [] targetSet = EMPTY_TUPLE; public OrderedLinkCondition() { } @SuppressWarnings("unchecked") public OrderedLinkCondition(HGHandle...targetSet) { if (targetSet == null) throw new HGException("OrderedLinkCondition instantiated with a null target set."); this.targetSet = new Ref[targetSet.length]; for (int i = 0; i < targetSet.length; i++) this.targetSet[i] = hg.constant(targetSet[i]); } public OrderedLinkCondition(Ref<HGHandle>...targetSet) { this.targetSet = targetSet; } @SuppressWarnings("unchecked") public OrderedLinkCondition(List<HGHandle> targetSet) { if (targetSet == null) throw new HGException("OrderedLinkCondition instantiated with a null target set."); this.targetSet = new Ref[targetSet.size()]; int i = 0; for (HGHandle h : targetSet) this.targetSet[i++] = hg.constant(h); } public Ref<HGHandle> [] targets() { return targetSet; } public Ref<HGHandle> [] getTargets() { return targetSet; } public void setTargets(Ref<HGHandle>[] targetSet) { this.targetSet = targetSet; } public void setTarget(int pos, HGHandle newTarget) { targetSet[pos] = hg.constant(newTarget); } public boolean satisfies(HyperGraph hg, HGHandle handle) { // If the atom corresponding to 'handle' is already in the cache, there // is no point fetching it from permanent storage. Otherwise, there's no point // caching the actual atom... if (hg.isLoaded(handle)) { Object atom = hg.get(handle); if (! (atom instanceof HGLink)) return false; HGLink link = (HGLink)atom; int i = 0, j = 0; while (i < link.getArity() && j < targetSet.length) { if (targetSet[j].get().equals(link.getTargetAt(i)) || targetSet[j].get().equals(hg.getHandleFactory().anyHandle())) j++; i++; } return j == targetSet.length; } else { HGPersistentHandle [] A = hg.getStore().getLink(hg.getPersistentHandle(handle)); int i = 2, j = 0; while (i < A.length && j < targetSet.length) { if (targetSet[j].get().equals(A[i]) || targetSet[j].get().equals(hg.getHandleFactory().anyHandle())) j++; i++; } return j == targetSet.length; } } public String toString() { StringBuffer result = new StringBuffer("orderedLinks("); for (int i = 0; i < targetSet.length; i++) { result.append(targetSet[i].get()); if (i < targetSet.length - 1) result.append(","); } result.append(")"); return result.toString(); } public int hashCode() { int x = 0; for (Ref<HGHandle> h : targetSet) x += h.get().hashCode(); return x; } public boolean equals(Object x) { if (! (x instanceof OrderedLinkCondition)) return false; else return HGUtils.eq(targetSet, ((OrderedLinkCondition)x).targetSet); } }