// File: SEdgeNode.java
// Classes: SEdgeNode
// Author: Kedar Patankar

package edu.neu.ccs.demeter.tools.apstudio.graphedit;

import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;

/* Purpose : This class represents strategy edge */

public class SEdgeNode implements Behdata
{
	public final static int PARTIAL = 0;
	public final static int VALID = 1;
	public final static int INVALID = 2;

	private Editor _editor;
	private String _name;

	private Vector _fromID,_toID,_bypassingID,_onlyThruID;
	
	private Vector _fromV,_toV,_bypassingV,_onlyThruV;
	private Vector _bypassingE,_onlyThruE;

	private String _currentTraversal;
	private int _status;

	public SEdgeNode(Editor editor,String name)
	{
		_editor=editor;
		_name = name;

		_status = SEdgeNode.PARTIAL;
		_fromV = new Vector();
		_toV = new Vector();
		_bypassingV = new Vector();
		_onlyThruV = new Vector();
		_bypassingE = new Vector();
		_onlyThruE = new Vector();
	}

	public String toString()
	{
		if(_status == SEdgeNode.VALID)
			return getFromString()+":"+getToString().substring(2);
		else
			return _name;
	}

	public void setName(String name){_name = name;}

	public void setMenu(){_editor.getmenu().setMenuforSEdge();}

	public void addFrom(String name)
	{
		if(!_fromV.removeElement(name))
			_fromV.addElement(name);
		setStatus();
	}
	public void addTo(String name)
	{
		if(!_toV.removeElement(name))
			_toV.addElement(name);
		setStatus();
	}	
	public void addBypassV(String name)
	{
		if(!_bypassingV.removeElement(name))
			_bypassingV.addElement(name);
		setStatus();
	}
	public void addOnlyThroughV(String name)
	{
		if(!_onlyThruV.removeElement(name))
			_onlyThruV.addElement(name);
		setStatus();
	}
	public void addBypassE(String from,String name,String to)
	{
		ConstraintEdge be = new	ConstraintEdge(from,name,to);
		if(!_bypassingE.removeElement(be))
			_bypassingE.addElement(be);
		setStatus();
	}
	public void addOnlyThroughE(String from,String name,String to)
	{
		ConstraintEdge be = new	ConstraintEdge(from,name,to);
		if(!_onlyThruE.removeElement(be))
			_onlyThruE.addElement(be);
		setStatus();
	}
	
	public boolean checkIntegrity()
	{
		UGraph ue = _editor.curDocument().net();

		for(int i=0;i<_fromV.size();i++)
		{
			UID uid = ue.nameToUID((String)_fromV.elementAt(i));
			if(uid==null)
				return false;
		}
		
		for(int i=0;i<_toV.size();i++)
		{
			UID uid = ue.nameToUID((String)_toV.elementAt(i));
			if(uid==null)
				return false;
		}
		
		for(int i=0;i<_bypassingV.size();i++)
		{
			UID uid = ue.nameToUID((String)_bypassingV.elementAt(i));
			if(uid==null)
				return false;
		}

		for(int i=0;i<_onlyThruV.size();i++)
		{
			UID uid = ue.nameToUID((String)_onlyThruV.elementAt(i));
			if(uid==null)
				return false;
		}


		Enumeration enum = _bypassingE.elements();
		while(enum.hasMoreElements())
		{
			ConstraintEdge be = (ConstraintEdge)enum.nextElement();
			String from = be.get_from();
			UID from_id = ue.nameToUID(from);
			if(from_id==null) return false;
			String to = be.get_to();
			UID to_id = ue.nameToUID(to);
			if(to_id==null) return false;

			UVertex uv = ue.getNode(from_id);
			Vector outList = uv.get_outArcIdList();
			int j=outList.size();
			boolean matched = false;
			for(int i=0;i<j&&!matched;i++)
			{
				UID edge_id = (UID)outList.elementAt(i);
				UEdge edge = ue.getArc(edge_id);
				UID id = edge.get_toVertex();
				if(id.equals(to_id))
				{
					String name = be.get_name();
					if(name==null)
						matched = true;
					else
					{
						String edgename = ((UConstEdge)edge).get_edgename().get_name().toString();
						if(name.equals(edgename))
							matched = true;
						else
							return false;
					}
				}
			}
			if(!matched)
				return matched;
		}

		enum = _onlyThruE.elements();
		while(enum.hasMoreElements())
		{
			ConstraintEdge be = (ConstraintEdge)enum.nextElement();
			String from = be.get_from();
			UID from_id = ue.nameToUID(from);
			if(from_id==null) return false;
			String to = be.get_to();
			UID to_id = ue.nameToUID(to);
			if(to_id==null) return false;

			UVertex uv = ue.getNode(from_id);
			Vector outList = uv.get_outArcIdList();
			int j=outList.size();
			boolean matched = false;
			for(int i=0;i<j&&!matched;i++)
			{
				UID edge_id = (UID)outList.elementAt(i);
				UEdge edge = ue.getArc(edge_id);
				UID id = edge.get_toVertex();
				if(id.equals(to_id))
				{
					String name = be.get_name();
					if(name==null)
						matched = true;
					else
					{
						String edgename = ((UConstEdge)edge).get_edgename().get_name().toString();
						if(name.equals(edgename))
							matched = true;
						else
							return false;
					}
				}
			}
			if(!matched)
				return matched;
		}
		return true;
	}

	private String getFromString()
	{
		String from = new String();
		if(_fromV.size()>0)
		{
			for(int i=0;i<_fromV.size();i++)
			{
				if(i>0)
					from +=" , ";
				from += _fromV.elementAt(i);
				from +=" ";
			}
		}
		if(_fromV.size()>1)
			return " { " + from+" } ";
		return from;
	}
	private String getToString()
	{
		String to = new String();
		if(_toV.size()>0)
		{
			for(int i=0;i<_toV.size();i++)
			{
				if(i>0)
					to +=" , ";
				to += _toV.elementAt(i);
				to +=" ";
			}
		}
		if(_toV.size()>1)
			return "-> { "+to+" } ";
		else
		if(_toV.size()==1)
			return "-> "+to;

		return to;
	}

	private String getBypassingString()
	{
		String bypassing = new String();
		if(_bypassingV.size()+_bypassingE.size()>0)
		{
			boolean multiple = false;
			for(int i=0;i<_bypassingV.size();i++)
			{
				if(i>0)
					bypassing +=" , ";
				bypassing += _bypassingV.elementAt(i);
				bypassing +=" ";
				multiple = true;
			}
			for(Enumeration enum = _bypassingE.elements();enum.hasMoreElements();)
			{
				if(multiple)
					bypassing +=" , ";
				ConstraintEdge be = (ConstraintEdge)enum.nextElement();
				bypassing +=be.toString();
				bypassing+=" ";
				multiple = true;
			}
		}
		if(_bypassingV.size()+_bypassingE.size()>1)
			return " bypassing { "+bypassing+" } ";
		else
		if(_bypassingV.size()+_bypassingE.size()>0)
			return " bypassing "+bypassing;
		else
			return bypassing;
	}

	private String getOnlyThruString()
	{
		String onlyThru = new String();
		if(_onlyThruV.size()+_onlyThruE.size()>0)
		{
			boolean multiple = false;
			for(int i=0;i<_onlyThruV.size();i++)
			{
				if(i>0)
					onlyThru +=" , ";
				onlyThru += _onlyThruV.elementAt(i);
				onlyThru +=" ";
				multiple = true;
			}
			for(Enumeration enum = _onlyThruE.elements();enum.hasMoreElements();)
			{
				if(multiple)
					onlyThru +=" , ";
				ConstraintEdge be = (ConstraintEdge)enum.nextElement();
				onlyThru +=be.toString();
				onlyThru+=" ";
				multiple = true;
			}
		}

		if(_onlyThruV.size()+_onlyThruE.size()>1)
			return " only-through { "+onlyThru+" } ";
		else
		if(_onlyThruV.size()+_onlyThruE.size()>0)
			return " only-through "+onlyThru;
		else
			return onlyThru;
	}

	public String getDescription()
	{
		String desc = new String();
		
		String from = getFromString();

		String to = getToString();

		String bypassing = getBypassingString();

		String onlyThru = getOnlyThruString();

		desc = from + to + bypassing + onlyThru;
		desc = desc.trim();
		if(!(desc.length()>0))
			desc = "<<Not yet defined>>";
		return desc;
	}
	
	public int get_status(){return _status;}

	public void setStatus()
	{
		int bypass = _bypassingV.size()+_bypassingE.size();
		int onlythru= _onlyThruV.size()+_onlyThruE.size();
		if(bypass > 0 && onlythru >0 )
		{
			_status = SEdgeNode.INVALID;
			return;
		}
		int from = _fromV.size();
		int to = _toV.size();

		if(from > 0 && to >0 )
			_status = SEdgeNode.VALID;
		else
			_status = SEdgeNode.PARTIAL;
	}
} /* end class SEdgeNode */

