package edu.neu.ccs.demeter.dj;

import java.util.*;

/** A graph whose nodes are objects and whose edges are part-of
    relationships (properties), with a single distinguished root object.
    An object graph has a class graph to which it conforms. */
public class ObjectGraph {
  protected ClassGraph cg;
  protected Object root;
  /** The object graph rooted at o with respect to c. */
  public ObjectGraph(Object o, ClassGraph c)
    { cg = c; root = o; }

  /** The class graph that this object graph is an instance of. */
  public ClassGraph getClassGraph() { return cg; }
  /** The root of the graph. */
  public Object getRoot() { return root; }

  /** The subgraph of the object graph determined by s. */
  public ObjectGraphSlice slice(Strategy s) {
    try {
      return new ObjectGraphSlice(this, s);
    } catch (TraversalException e) {
      // FIXME: make a new exception type?
      throw new RuntimeException(e.getMessage());
    }
  }
  /** Traverse the subgraph of the object graph determined by s using
      v, returning the value of v.getReturnValue() at the end of the
      traversal. */
  public Object traverse(Strategy s, Visitor v)
    { return slice(s).traverse(v); }
  /** Traverse the subgraph of the object graph determined by s using
      visitors in array v in parallel, returning the value of
      v[0].getReturnValue() at the end of the traversal. */
  public Object traverse(Strategy s, Visitor v[])
    { return slice(s).traverse(v); }
  /** Fetch the object in the object graph corresponding to the target of s. */
  public Object fetch(Strategy s) throws FetchException
    { return slice(s).fetch(); }
  /** Gather (copy) the objects in the object graph corresponding to the
      target of s into a List. */
  public List gather(Strategy s)
    { return slice(s).gather(); }
  /** View (without copying) the objects in the object graph
      corresponding to the target of s as a List. */
  public List asList(Strategy s)
    { return slice(s).asList(); }

  /** The subgraph of the object graph determined by strategy s. */
  public ObjectGraphSlice slice(String s)
    { return slice(new Strategy(s)); }
  /** Traverse the subgraph of the object graph determined by strategy
      s using v, returning the value of v.getReturnValue() at the end
      of the traversal. */
  public Object traverse(String s, Visitor v)
    { return slice(s).traverse(v); }
  /** Traverse the subgraph of the object graph determined by strategy
      s using visitors in array v in parallel, returning the value of
      v[0].getReturnValue() at the end of the traversal. */
  public Object traverse(String s, Visitor v[])
    { return slice(s).traverse(v); }
  /** Fetch the object in the object graph corresponding to the target
      of stragegy s. */
  public Object fetch(String s) throws FetchException
    { return slice(s).fetch(); }
  /** Gather (copy) the objects in the object graph corresponding to the
      target of strategy s into a List. */
  public List gather(String s)
    { return slice(s).gather(); }
  /** View (without copying) the objects in the object graph
      corresponding to the target of strategy s as a List. */
  public List asList(String s)
    { return slice(s).asList(); }
}
