/*
* 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.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import org.hypergraphdb.HGHandle;
import org.hypergraphdb.HGSearchResult;
import org.hypergraphdb.util.Pair;
/**
* <p>
* A breadth-first like traversal that will return the same atom
* multiple times - once for each distinct link leading to it.
* </p>
* @author Borislav Iordanov
*
*/
public class CopyGraphTraversal implements HGTraversal
{
private HGHandle startAtom;
private int maxDistance; // the maximum reachable distance from the starting node
// The following maps contains all atoms that have been reached: if they have
// been actually visited (i.e. returned by the 'next' method), they map to
// Boolean.TRUE, otherwise they map to Boolean.FALSE.
private Map<Pair<HGHandle, HGHandle>, Boolean> examined =
new HashMap<Pair<HGHandle, HGHandle>, Boolean>();
private Queue<Pair<Pair<HGHandle, HGHandle>, Integer>> to_explore =
new LinkedList<Pair<Pair<HGHandle, HGHandle>, Integer>>();
private HGALGenerator adjListGenerator;
private boolean initialized = false;
private void init()
{
this.maxDistance = Integer.MAX_VALUE;
examined.put(new Pair<HGHandle, HGHandle>(null, startAtom), Boolean.TRUE);
advance(startAtom, 0);
initialized = true;
}
private void advance(HGHandle from, int distance)
{
if (distance >= maxDistance)
return;
HGSearchResult<Pair<HGHandle, HGHandle>> i = adjListGenerator.generate(from);
try
{
Integer dd = distance + 1;
while (i.hasNext())
{
Pair<HGHandle, HGHandle> curr = i.next();
if (!examined.containsKey(curr))
{
to_explore.add(new Pair<Pair<HGHandle, HGHandle>, Integer>(curr, dd));
examined.put(curr, Boolean.FALSE);
}
}
}
finally
{
i.close();
}
}
public void setStartAtom(HGHandle startAtom)
{
this.startAtom = startAtom;
}
public HGHandle getStartAtom()
{
return startAtom;
}
public HGALGenerator getAdjListGenerator()
{
return adjListGenerator;
}
public void setAdjListGenerator(HGALGenerator adjListGenerator)
{
this.adjListGenerator = adjListGenerator;
}
public void remove()
{
throw new UnsupportedOperationException();
}
public CopyGraphTraversal()
{
}
public CopyGraphTraversal(HGHandle startAtom, HGALGenerator adjListGenerator)
{
this(startAtom, adjListGenerator, Integer.MAX_VALUE);
}
public CopyGraphTraversal(HGHandle startAtom, HGALGenerator adjListGenerator, int maxDistance)
{
this.maxDistance = maxDistance;
this.startAtom = startAtom;
this.adjListGenerator = adjListGenerator;
init();
}
public boolean hasNext()
{
if (!initialized)
init();
return !to_explore.isEmpty();
}
public boolean isVisited(HGHandle handle)
{
Boolean b = examined.get(handle);
return b != null && b;
}
public Pair<HGHandle, HGHandle> next()
{
if (!initialized)
init();
Pair<HGHandle, HGHandle> rvalue = null;
if (!to_explore.isEmpty())
{
Pair<Pair<HGHandle, HGHandle>, Integer> x = to_explore.remove();
rvalue = x.getFirst();
examined.put(rvalue, Boolean.TRUE);
advance(rvalue.getSecond(), x.getSecond());
}
return rvalue;
}
public void reset()
{
examined.clear();
to_explore.clear();
init();
}}