/* * 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.algorithms; import java.util.Iterator; import org.hypergraphdb.HGLink; import org.hypergraphdb.HGSearchResult; import org.hypergraphdb.HGHandle; import org.hypergraphdb.HyperGraph; import org.hypergraphdb.util.Pair; import org.hypergraphdb.util.TempLink; /** * <p> * The <code>SimpleALGenerator</code> produces all atoms linked to the given atom, * regardless of the link type and regardless of how an outgoing set is ordered. * </p> * * @author Borislav Iordanov */ public class SimpleALGenerator implements HGALGenerator { protected HyperGraph graph; private TempLink tempLink = new TempLink(HyperGraph.EMPTY_HANDLE_SET); private AdjIterator currIterator = null; protected class AdjIterator implements HGSearchResult<Pair<HGHandle,HGHandle>> { HGHandle src; Iterator<HGHandle> linksIterator; HGHandle hCurrLink; HGLink currLink; Pair<HGHandle,HGHandle> current; int currLinkPos; boolean closeResultSet; private void getNextLink() { // loop makes sure that we skip links that only point to our 'src' atom and nothing else for (boolean done = false; !done; done = currLink.getArity() > 1) { if (!linksIterator.hasNext()) { currLink = null; if (closeResultSet) ((HGSearchResult<HGHandle>)linksIterator).close(); return; } hCurrLink = linksIterator.next(); if (graph.isLoaded(hCurrLink)) currLink = (HGLink)graph.get(hCurrLink); else { tempLink.setHandleArray(graph.getStore().getLink(graph.getPersistentHandle(hCurrLink)), 2); currLink = tempLink; } } if (currLink.getTargetAt(0).equals(src)) currLinkPos = 1; else currLinkPos = 0; } public AdjIterator(HGHandle src, Iterator<HGHandle> linksIterator, boolean closeResultSet) { this.src = src; this.linksIterator = linksIterator; this.closeResultSet = closeResultSet; getNextLink(); } public void remove() { throw new UnsupportedOperationException(); } public boolean hasNext() { return currLink != null; } public Pair<HGHandle,HGHandle> next() { current = new Pair<HGHandle,HGHandle>(hCurrLink, currLink.getTargetAt(currLinkPos)); // advance within link, then check whether we're pointing to 'src' and, if so, advance again if (++currLinkPos == currLink.getArity()) getNextLink(); else if (currLink.getTargetAt(currLinkPos).equals(src)) if (++currLinkPos == currLink.getArity()) getNextLink(); return current; } public void close() { if (closeResultSet) ((HGSearchResult<HGHandle>)linksIterator).close(); } public Pair<HGHandle,HGHandle> current() { return current; } public boolean isOrdered() { return false; } public boolean hasPrev() { throw new UnsupportedOperationException(); } public Pair<HGHandle,HGHandle> prev() { throw new UnsupportedOperationException(); } } /** * <p> * Empty constructor - you will need to set the graph (see {@link setGraph}) before * the instance becomes usable. * </p> */ public SimpleALGenerator() { } /** * <p>Construct a <code>SimpleALGenerator</code> for the given HyperGraph instance.</p> * * @param hg The HyperGraph instance. */ public SimpleALGenerator(HyperGraph hg) { this.graph = hg; } public HGSearchResult<Pair<HGHandle,HGHandle>> generate(HGHandle h) { return new AdjIterator( h, graph.getIncidenceSet(h).getSearchResult(), true); } public void close() { if (currIterator != null && currIterator.closeResultSet) ((HGSearchResult<HGHandle>)currIterator.linksIterator).close(); } public void setGraph(HyperGraph graph) { this.graph = graph; } public HyperGraph getGraph() { return this.graph; } }