package EDU.neu.ccs.demeter.tools.apstudio.graphedit;
import java.awt.*;
import java.io.*;
import java.util.*;
import EDU.neu.ccs.demeter.*;
import EDU.neu.ccs.demeter.common.tg.*;


import EDU.neu.ccs.demeter.*;
class UGraph {
  protected Package pkg;
  public Package get_pkg() { return pkg; }
  public void set_pkg(Package new_pkg)
    { pkg = new_pkg; }
  protected Import_SList imports;
  public Import_SList get_imports() { return imports; }
  public void set_imports(Import_SList new_imports)
    { imports = new_imports; }
  protected JavaCode preamble;
  public JavaCode get_preamble() { return preamble; }
  public void set_preamble(JavaCode new_preamble)
    { preamble = new_preamble; }
  protected UVertex_List vertices;
  public UVertex_List get_vertices() { return vertices; }
  public void set_vertices(UVertex_List new_vertices)
    { vertices = new_vertices; }
  protected Hashtable idToVertexTable;
  public Hashtable get_idToVertexTable() { return idToVertexTable; }
  public void set_idToVertexTable(Hashtable new_idToVertexTable)
    { idToVertexTable = new_idToVertexTable; }
  protected UEdge_List edges;
  public UEdge_List get_edges() { return edges; }
  public void set_edges(UEdge_List new_edges)
    { edges = new_edges; }
  protected Hashtable idToEdgeTable;
  public Hashtable get_idToEdgeTable() { return idToEdgeTable; }
  public void set_idToEdgeTable(Hashtable new_idToEdgeTable)
    { idToEdgeTable = new_idToEdgeTable; }
  protected Hashtable nameToIdVertexTable;
  public Hashtable get_nameToIdVertexTable() { return nameToIdVertexTable; }
  public void set_nameToIdVertexTable(Hashtable new_nameToIdVertexTable)
    { nameToIdVertexTable = new_nameToIdVertexTable; }
  protected UID firstuid;
  public UID get_firstuid() { return firstuid; }
  public void set_firstuid(UID new_firstuid)
    { firstuid = new_firstuid; }
  UGraph() { super(); }
  public UGraph(Package pkg, Import_SList imports, JavaCode preamble, UVertex_List vertices, Hashtable idToVertexTable, UEdge_List edges, Hashtable idToEdgeTable, Hashtable nameToIdVertexTable, UID firstuid) {
    super();
    set_pkg(pkg);
    set_imports(imports);
    set_preamble(preamble);
    set_vertices(vertices);
    set_idToVertexTable(idToVertexTable);
    set_edges(edges);
    set_idToEdgeTable(idToEdgeTable);
    set_nameToIdVertexTable(nameToIdVertexTable);
    set_firstuid(firstuid);
  }
  public static UGraph parse(java.io.InputStream in) throws ParseException
    { return new Parser(in)._UGraph(); }
  public static UGraph parse(String s) {
    try { return parse(new java.io.ByteArrayInputStream(s.getBytes())); }
    catch (ParseException e) { throw new RuntimeException(e.toString()); }
  }

// Graph management and utility functions

		public int getSize(){return nameToIdVertexTable.size();}
		public void initialize()
		{ 
			set_idToVertexTable(new Hashtable());
			set_idToEdgeTable(new Hashtable());
			set_nameToIdVertexTable(new Hashtable());
		}
    /** Remove all the nodes from this NetList. */
		public void removeAll() 
		{ 
			nameToIdVertexTable.clear();
			idToVertexTable.clear();
			idToEdgeTable.clear();
		}
		public void clearTags()
		{
			for(Enumeration enum = idToVertexTable.elements();enum.hasMoreElements();)
			{
				UVertex uv = (UVertex)enum.nextElement();
				uv.set_vdeco(new Decorator (new Integer(0) , new Vector()));
			}
			for(Enumeration enum = idToEdgeTable.elements();enum.hasMoreElements();)
			{
				UEdge ue = (UEdge)enum.nextElement();
				ue.set_edeco(new Decorator (new Integer(0) , new Vector()));
			}
		}
    //add a UVertex into the UVertex_List
		public void add_uvertex(UVertex uvertex)
		{
			if(get_vertices() != null )
			{
				Nonempty_UVertex_List newlist = new Nonempty_UVertex_List( uvertex , get_vertices().get_first());
				get_vertices().set_first(newlist);
	//get a UVertexList, get a Nonempty_UvertexList , replace 
	// old one with new one, it=uvertex , next = old_Ne_V_L
			}
			else
			{
				Nonempty_UVertex_List newlist = new Nonempty_UVertex_List( uvertex , null);
				set_vertices(new UVertex_List(newlist)); 
			}
		}

    //add a UEdge into the UEdge_Lis	
		public void add_uedge(UEdge uedge)
		{
			if(get_edges() != null )
			{
				Nonempty_UEdge_List newlist = new Nonempty_UEdge_List( uedge , get_edges().get_first());
				get_edges().set_first(newlist);
	//get a UEdgeList, get its Nonempty_UEdgeList , replace 
	// old one with new one, it=uedge , next = old_Ne_V_L
			}
			else 
			{
				Nonempty_UEdge_List newlist = new Nonempty_UEdge_List( uedge , null);
				set_edges(new UEdge_List(newlist));
			}
		}


// Underlying assumption in using hashtables as well as the way it is
// implemented is that node/arc managements are infrequent.

// Vertex/Node management below

		public void addNode(UVertex n)
		{
			String name = n.get_vertexname().get_name().toString();
			UID id = n.get_vid();
// maps name and id. helpes to get id while knowing name in case of subgraph computation.
			nameToIdVertexTable.put(name,id); 			
// archives the node
			idToVertexTable.put(id,n);
		}
		public UVertex getNode(UID id)
		{
			return (UVertex)idToVertexTable.get(id);
		}
		public void removeNode(UID id) 
		{
			UVertex u = getNode(id); 
			String name = u.get_vertexname().get_name().toString();
			nameToIdVertexTable.remove(name);
			idToVertexTable.remove(id);
		}
		public Enumeration vertexEnum(){return idToVertexTable.elements();}
		public void modifyVertexName(String newName,UID id)
		{
			UVertex u=getNode(id);
			nameToIdVertexTable.remove(u.get_vertexname().get_name().toString());
			u.set_vertexname(new UVertexName(new Ident(newName)));
			nameToIdVertexTable.put(newName,id);
		}
		public boolean checkThisOut(String name)
		{
			return nameToIdVertexTable.containsKey(name);
		}
		public UID nameToUID(String name)
		{
			return (UID)nameToIdVertexTable.get(name);
		}

// Edge/Arc management below

		public void addArc(UEdge n)
		{
			idToEdgeTable.put(n.get_eid(),n);
			if(n instanceof UConstEdge)
			{
				if(((UConstEdge)n).get_edgename()!=null)
				{
					UID fromVertex = n.get_fromVertex();
					String edgeLabel = ((UConstEdge)n).get_edgename().get_name().toString();
					((UConstOrAltVertex)getNode(fromVertex)).addEdgeName(edgeLabel);
				}
			}
			else
			{
				UID toVertex = n.get_toVertex();
				getNode(toVertex).setMulInheritance(true);
			}
		}
		public UEdge getArc(UID id)
		{
			return (UEdge)idToEdgeTable.get(id);
		}
  /** Remove an arc by removing its entry from the connected vertices
  This methos is called from ArcPerspective#dispose*/
		public void removeArc(UID id)
		{
			UEdge ue=getArc(id);
			UID fromVertex = ue.get_fromVertex();
			UID toVertex = ue.get_toVertex();
			getNode(fromVertex).removeOutArc(id);
			getNode(toVertex).removeInArc(id);
			if( ue instanceof UConstEdge)
			{
				if(((UConstEdge)ue).get_edgename() != null)
				{
					String edgeLabel = ((UConstEdge)ue).get_edgename().get_name().toString();
					((UConstOrAltVertex)getNode(fromVertex)).removeEdgeName(edgeLabel);
				}
			}
			else
				getNode(toVertex).setMulInheritance(false);

			idToEdgeTable.remove(id);
		}
		public Enumeration edgeEnum(){return idToEdgeTable.elements();}
		public void modifyEdgeName(String newName,UID id)
		{
			UEdge u=getArc(id);
			UID fromVertex = getArc(id).get_fromVertex();
			String oldName = null;
			if(((UConstEdge)u).get_edgename() != null)
				oldName = ((UConstEdge)u).get_edgename().get_name().toString();
			if( oldName!= null)
			{
				((UConstOrAltVertex)getNode(fromVertex)).removeEdgeName(oldName);
			}
			if(newName!=null)
			{
				((UConstEdge)u).set_edgename(new UEdgeName(new Ident(newName)));
				((UConstOrAltVertex)getNode(fromVertex)).addEdgeName(newName);
			}
			else
				((UConstEdge)u).set_edgename(null);
		}
    
	void hashinit(Hashtable vtable, Hashtable etable)
	{
		superInitVisitor hcv = new HashCreateVisitor(vtable , etable);
		toVertEdge(hcv);

	}
	
	
	public String getPreString()
	{
		String w = null;
	/*	if(get_preamble() != null)
			w = "\n(@" + get_preamble().get_code() + "@" + ")\n\n";
		if(get_pkg() != null)
			w = get_pkg().getPreString() + w ;*/	//TODO
		return w;
	}
	  public String getCdString() {
    __V_UGraph_getCdString v0 = new __V_UGraph_getCdString();
    v0.start();
    __trav_getCdString(v0);
    v0.finish();
    return v0.get_return_val();
  }


	/**
	Returns the string representation of the gcd(graph) object
	*/
	public String GetGraphString()
	{
		SaveGraphVisitor sgv= new SaveGraphVisitor(new String());
		this.saveGraph(sgv);
		return sgv.get_graphString();
	}
	  public String GetMarkedGraphString() {
	{
		SelectMarkedVisitor v = new SelectMarkedVisitor(false, false, false," "," ");
		this.saveMarkedGraph(v);
		return v.get_graphString();
	}
	}

		public VertexContainer GetAllVertices()
		{
		  ReadVertexVisitor rvv = new ReadVertexVisitor( new VertexContainer(new Vector(),new Vector(),new Vector()));
		  this.ReadAllVertices(rvv);
		  return rvv.get_elements();
		}
	
		public EdgeContainer GetAllEdges()
		{
			ReadEdgeVisitor rev= new ReadEdgeVisitor( new EdgeContainer(new Vector(),new Vector()));
			this.ReadAllEdges(rev);
			return rev.get_elements();
		}
      boolean computeSubgraph(StrategyGraph sg) {
		TraversalGraph tg = new TraversalGraph();
		initialize(); //create new hashtables
		hashinit(get_idToVertexTable(),get_idToEdgeTable()); //fill 'em 
		makeTgGraph(tg);
		if(!markSubgraph(sg,tg))
			return false;
		updateUGraph();
		return true;
		}
  void makeTgGraph(TraversalGraph g) {
    TGCreateVisitor v0 = new TGCreateVisitor();
    v0.set_g(g);
    v0.start();
    toUEdgeVertex(v0);
    v0.finish();
  }
  boolean markSubgraph(StrategyGraph sg, TraversalGraph tg) {
		tg.makeCopies(sg.size());
		tg.addIntercopyEdges(sg);
		sg.markReachableForwardFromSources(tg);
		sg.markReachableBackwardFromTargets(tg);
		if (!sg.allSourcesAndTargetsMarked(tg)) {
			System.err.println("Error: No path found.");
			return false;
		}
		return true;
		}
  void updateUGraph() {
    TGUpdateVisitor v0 = new TGUpdateVisitor();
    v0.start();
    toVertEdge(v0);
    v0.finish();
  }
  void universal_trv0_bef(UniversalVisitor _v_) {
    _v_.before(this);
  }
  void universal_trv0_aft(UniversalVisitor _v_) {
    _v_.after(this);
  }
  void universal_trv0(UniversalVisitor _v_) {
    universal_trv0_bef(_v_);
    if (pkg != null) {
      _v_.before_pkg(this, pkg);
    pkg.universal_trv0(_v_);
      _v_.after_pkg(this, pkg);
    }
    if (imports != null) {
      _v_.before_imports(this, imports);
    imports.universal_trv0(_v_);
      _v_.after_imports(this, imports);
    }
    if (preamble != null) {
      _v_.before_preamble(this, preamble);
    preamble.universal_trv0(_v_);
      _v_.after_preamble(this, preamble);
    }
    if (vertices != null) {
      _v_.before_vertices(this, vertices);
    vertices.universal_trv0(_v_);
      _v_.after_vertices(this, vertices);
    }
    _v_.before_idToVertexTable(this, idToVertexTable);
    _v_.after_idToVertexTable(this, idToVertexTable);
    if (edges != null) {
      _v_.before_edges(this, edges);
    edges.universal_trv0(_v_);
      _v_.after_edges(this, edges);
    }
    _v_.before_idToEdgeTable(this, idToEdgeTable);
    _v_.after_idToEdgeTable(this, idToEdgeTable);
    _v_.before_nameToIdVertexTable(this, nameToIdVertexTable);
    _v_.after_nameToIdVertexTable(this, nameToIdVertexTable);
    if (firstuid != null) {
      _v_.before_firstuid(this, firstuid);
    firstuid.universal_trv0(_v_);
      _v_.after_firstuid(this, firstuid);
    }
    universal_trv0_aft(_v_);
  }
  public void toVertEdge(superInitVisitor v) {
    toVertEdge_UGraph_trv(v);
  }
  void toVertEdge_UGraph_trv_bef(superInitVisitor v) {
    v.before(this);
  }
  void toVertEdge_UGraph_trv_aft(superInitVisitor v) {
    v.after(this);
  }
  void toVertEdge_UGraph_trv(superInitVisitor v) {
    toVertEdge_UGraph_trv_bef(v);
    if (vertices != null) {
    vertices.toVertEdge_UGraph_trv(v);
    }
    if (edges != null) {
    edges.toVertEdge_UGraph_trv(v);
    }
    toVertEdge_UGraph_trv_aft(v);
  }
  public void saveGraph(SaveGraphVisitor sgv) {
    saveGraph_UGraph_trv(sgv);
  }
  void saveGraph_UGraph_trv_bef(SaveGraphVisitor sgv) {
    sgv.before(this);
  }
  void saveGraph_UGraph_trv_aft(SaveGraphVisitor sgv) {  }
  void saveGraph_UGraph_trv(SaveGraphVisitor sgv) {
    saveGraph_UGraph_trv_bef(sgv);
    if (pkg != null) {
    pkg.saveGraph_UGraph_trv(sgv);
    }
    if (imports != null) {
    imports.saveGraph_UGraph_trv(sgv);
    }
    if (preamble != null) {
    preamble.saveGraph_UGraph_trv(sgv);
    }
    if (vertices != null) {
    vertices.saveGraph_UGraph_trv(sgv);
    }
    if (edges != null) {
    edges.saveGraph_UGraph_trv(sgv);
    }
    if (firstuid != null) {
    firstuid.saveGraph_UGraph_trv(sgv);
    }
    saveGraph_UGraph_trv_aft(sgv);
  }
  public void saveMarkedGraph(SelectMarkedVisitor v) {
    saveMarkedGraph_UGraph_trv(v);
  }
  void saveMarkedGraph_UGraph_trv_bef(SelectMarkedVisitor v) {
    v.before(this);
  }
  void saveMarkedGraph_UGraph_trv_aft(SelectMarkedVisitor v) {  }
  void saveMarkedGraph_UGraph_trv(SelectMarkedVisitor v) {
    saveMarkedGraph_UGraph_trv_bef(v);
    if (pkg != null) {
    pkg.saveMarkedGraph_UGraph_trv(v);
    }
    if (imports != null) {
    imports.saveMarkedGraph_UGraph_trv(v);
    }
    if (preamble != null) {
    preamble.saveMarkedGraph_UGraph_trv(v);
    }
    if (vertices != null) {
    vertices.saveMarkedGraph_UGraph_trv(v);
    }
    if (edges != null) {
    edges.saveMarkedGraph_UGraph_trv(v);
    }
    if (firstuid != null) {
    firstuid.saveMarkedGraph_UGraph_trv(v);
    }
    saveMarkedGraph_UGraph_trv_aft(v);
  }
  public void ReadAllVertices(ReadVertexVisitor rvv) {
    ReadAllVertices_UGraph_trv(rvv);
  }
  void ReadAllVertices_UGraph_trv_bef(ReadVertexVisitor rvv) {  }
  void ReadAllVertices_UGraph_trv_aft(ReadVertexVisitor rvv) {  }
  void ReadAllVertices_UGraph_trv(ReadVertexVisitor rvv) {
    ReadAllVertices_UGraph_trv_bef(rvv);
    if (vertices != null) {
    vertices.ReadAllVertices_UGraph_trv(rvv);
    }
    ReadAllVertices_UGraph_trv_aft(rvv);
  }
  public void ReadAllEdges(ReadEdgeVisitor rev) {
    ReadAllEdges_UGraph_trv(rev);
  }
  void ReadAllEdges_UGraph_trv_bef(ReadEdgeVisitor rev) {  }
  void ReadAllEdges_UGraph_trv_aft(ReadEdgeVisitor rev) {  }
  void ReadAllEdges_UGraph_trv(ReadEdgeVisitor rev) {
    ReadAllEdges_UGraph_trv_bef(rev);
    if (edges != null) {
    edges.ReadAllEdges_UGraph_trv(rev);
    }
    ReadAllEdges_UGraph_trv_aft(rev);
  }
  public void toUEdgeVertex(TGCreateVisitor tg) {
    toUEdgeVertex_UGraph_trv(tg);
  }
  void toUEdgeVertex_UGraph_trv_bef(TGCreateVisitor tg) {
    tg.before(this);
  }
  void toUEdgeVertex_UGraph_trv_aft(TGCreateVisitor tg) {  }
  void toUEdgeVertex_UGraph_trv(TGCreateVisitor tg) {
    toUEdgeVertex_UGraph_trv_bef(tg);
    if (vertices != null) {
    vertices.toUEdgeVertex_UGraph_trv(tg);
    }
    if (edges != null) {
    edges.toUEdgeVertex_UGraph_trv(tg);
    }
    toUEdgeVertex_UGraph_trv_aft(tg);
  }
  public void __trav_getCdString(__V_UGraph_getCdString __v0) {
    __trav_getCdString_UGraph_trv(__v0);
  }
  void __trav_getCdString_UGraph_trv_bef(__V_UGraph_getCdString __v0) {
    __v0.before(this);
  }
  void __trav_getCdString_UGraph_trv_aft(__V_UGraph_getCdString __v0) {  }
  void __trav_getCdString_UGraph_trv(__V_UGraph_getCdString __v0) {
    __trav_getCdString_UGraph_trv_bef(__v0);
    if (vertices != null) {
    vertices.__trav_getCdString_UGraph_trv(__v0);
    }
    __trav_getCdString_UGraph_trv_aft(__v0);
  }
  void toUVertex_PlacementVisitor_trv_bef(PlaceVertexVisitor pvv) {  }
  void toUVertex_PlacementVisitor_trv_aft(PlaceVertexVisitor pvv) {  }
  void toUVertex_PlacementVisitor_trv(PlaceVertexVisitor pvv) {
    toUVertex_PlacementVisitor_trv_bef(pvv);
    if (vertices != null) {
    vertices.toUVertex_PlacementVisitor_trv(pvv);
    }
    toUVertex_PlacementVisitor_trv_aft(pvv);
  }
  void toAllEnds_PlacementVisitor_trv_bef(superInitVisitor siv) {
    siv.before(this);
  }
  void toAllEnds_PlacementVisitor_trv_aft(superInitVisitor siv) {
    siv.after(this);
  }
  void toAllEnds_PlacementVisitor_trv(superInitVisitor siv) {
    toAllEnds_PlacementVisitor_trv_bef(siv);
    if (vertices != null) {
    vertices.toAllEnds_PlacementVisitor_trv(siv);
    }
    if (edges != null) {
    edges.toAllEnds_PlacementVisitor_trv(siv);
    }
    toAllEnds_PlacementVisitor_trv_aft(siv);
  }
}

