/*
   Tamot --- Task Modelling Editor
   Copyright (C) 2000 Commonwealth Scientific and Industrial Research Organisation
   (CSIRO), Australia. All rights reserved. 

   The Software, owned by CSIRO Australia, has been developed by the CSIRO 
   Intelligent Interactive Technology group. 
   For more information, please see http://www.cmis.csiro.au/iit/.

   The Software is a beta-test version for internal research and evaluation purposes 
   by the Licensee. The Software is still at a development stage. 
   It has not undergone complete testing and may have inherent errors,
   bugs or deficiencies that can affect the operation of the Software. 

   We encourage your feedback and suggestions. Any bugs / suggestions found please email to
   Shijian.Lu@cmis.csiro.au and Thomas.Lo@cmis.csiro.au. 

   After you have signed the Beta-Test Software License Agreement with the CSIRO,
   CSIRO grants you a non-exclusive, non-transferable license to use it only for your 
   personal, non-commercial and lawful end use. Implied licenses are negated. 

   Warranty Disclaimer : 

   CSIRO supplies the Software on an "as is" basis and makes no warranties that use of
   the Software by the Licensee will not infringe any third party’s 
   Intellectual Property Rights nor that the Software will be of merchantable quality,
   or suitable for a particular purpose. CSIRO excludes all terms, conditions and
   warranties implied by custom, the general law or statute in relation to the
   Software.
*/

package domainModel;


import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.*;
import taskModellingTool.*;

import org.w3c.dom.*;
import com.ibm.xml.parsers.*;

/** 
* XEntity.java, it acts as a agent for communication
* between the EntityInstance class and DOM DmEntity element
* as defined by the NewDTDFile3.dtd
* ;
*/
public class XEntity
{
	private Document doc = null;
	
	public XEntity(Document aDoc){
		doc = aDoc;	
	}

	
	/**  
	* setDoc(),
	* @PARAM: aDoc, the DOM doc 
	* @return void
	*/
	public void setDoc(Document aDoc)
  	{
		doc = aDoc;

  	} //setDoc()
	
	/**  
	* getDoc(),
	* @return Document
	*/
	public Document getDoc()
  	{
		return doc;

  	} //getDoc()

  	
  	/** 
  	* enToEle, to get a EntityInstance object as input 
  	* and return a DOM DmEntity element. 
  	* 
  	*/
	public  Element enToEle(EntityInstance aEntity){
		if (aEntity == null) return null;
		Element elem = null;		
		try {
			String entityTag= XDmTag.getEntityT(); //"DmEntity";
			
			// create the DmEntity element with the right attributes
	  		elem = doc.createElement(entityTag);
	      	elem.setAttribute(XDmTag.getDmIdT(), aEntity.getID());
	      	
	      	// replace special XML characters
		    String sTemp =aEntity.getName();
		    sTemp=XMLUtility.convertForEntities(sTemp);
		    
	      	elem.setAttribute(XDmTag.getDmNameT(), sTemp);	//aEntity.getName());
//	      	elem.setAttribute(XDmTag.getDmLexRT(), aEntity.getLexItem()); //shijian 2001-1-15
	      	elem.setAttribute(XDmTag.getCardiT(), aEntity.getCardinality());

	      if (aEntity.getConceptOf() != null)
	      	elem.setAttribute(XDmTag.getConceptOfT(), aEntity.getConceptOf().getID());
	      	
	      //shijian 2001-1-15 getDeterminatorT
	      if (aEntity.getDirty() )
	      	elem.setAttribute(XDmTag.getDirtyT(), XManager._XML_YES);
	      else
	      	elem.setAttribute(XDmTag.getDirtyT(), XManager._XML_NO);
	      	
	      	if (aEntity.getPreModifier() != null){
				sTemp =aEntity.getPreModifier();
		    	sTemp=XMLUtility.convertForEntities(sTemp);
	      		elem.setAttribute(XDmTag.getPremodifierT(),sTemp);	// aEntity.getPreModifier());
	      	}

	      	if (aEntity.getLabel() != null){
				sTemp =aEntity.getLabel();
		    	sTemp=XMLUtility.convertForEntities(sTemp);
	      		elem.setAttribute(XDmTag.getLabelT(),sTemp);;
	      	}

	      	if (aEntity.getPostModifier() != null){
				sTemp =aEntity.getPostModifier();
		    	sTemp=XMLUtility.convertForEntities(sTemp);

	      		elem.setAttribute(XDmTag.getPostmodifierT(), sTemp);	//aEntity.getPostModifier());
	      	} 
	      	
	      	if (!(aEntity instanceof InterfaceInstance)){
		      	if (aEntity.getDeterminator() != null){
					sTemp =aEntity.getDeterminator();
			    	sTemp=XMLUtility.convertForEntities(sTemp);
		      	}else {
		      		sTemp =XDmTag.getNoDeterminatorT();
		      	}
		      	
		      	elem.setAttribute(XDmTag.getDeterminatorT(),sTemp);;
	      	}
	    /*  	
	      	if (aEntity instanceof InterfaceInstance){
	      		InterfaceInstance ii = (InterfaceInstance)aEntity;
	      		
	      		if (ii.getLabel() != null){
	      			String lab = ii.getLabel().trim();
	      			if (lab.equals(""))
	      				elem.setAttribute(XDmTag.getLabelT(), 
	      					XDmTag.getInterfaceNoLabelT());	
	      			else 
	      				elem.setAttribute(XDmTag.getLabelT(), lab);
	      		}
	      	}
		*/
	      //create the entityRelations for the DmEntity
			TreeMap relationInstances = aEntity.getEntityRelations();
			if(relationInstances.size() != 0){
		      	Element elemERel = doc.createElement(XDmTag.getERelT());
				elem.appendChild(elemERel);
				
				//create specific ERelationInstances
				DmRelation relM = DmRelation.getInstance();
				String allEnRle[] = relM.getAllEntityRelations();
				String relName,insID=null;
				DmInstance inst = null;
				for (int i = 0; i < allEnRle.length; i++) {
					relName=allEnRle[i];
					inst = (DmInstance) relationInstances.get(relName);
		
					if (inst != null){
						insID = inst.getID();
						//System.out.println("     "+relName+" Instance: " +
		    			//	inst.getName());
		    			if(relName.equals(DmRelation.getPartOf())){
		      				Element elemPartOf = doc.createElement(XDmTag.getPartOfT());
		      				elemPartOf.appendChild(doc.createTextNode(insID));
		      				elemERel.appendChild(elemPartOf);
		    				
		    			}
		    			else{
		      				Element elemNewR = doc.createElement(XDmTag.getNewERelT());
		      				elemNewR.setAttribute(XDmTag.getERNameT(), relName);
		      				elemNewR.setAttribute(XDmTag.getERValueT(), insID);
		      				elemERel.appendChild(elemNewR);
		    				
		    				
		    			}
					}
		    		
		       }
			
			}
		
	      
	      //create Note element
			if (aEntity.getNote() != null && (!aEntity.getNote().trim().equals("")) ){
				sTemp =aEntity.getNote();
		    	sTemp=XMLUtility.convertForEntities(sTemp);

		      	Element elemNote = doc.createElement(XDmTag.getDmNoteT());
		      	elemNote.appendChild(doc.createTextNode(sTemp));	//aEntity.getNote()));
		      	elem.appendChild(elemNote);
			}
	      
		}
		catch (Exception e)
		{
			System.err.println(e);
		}
		return elem;
  	}//enToEle()
  	  	
  	/** 
  	* eleToEn, is get a DOM EntityInstance element as input 
  	* and return a EntityInstance object. 
  	* 
  	*/
	public  EntityInstance eleToEn(Element ele){
		if (ele == null) return null;
		EntityInstance aEntity = null;
		//System.out.println("element tag: "+ele.getTagName() + "\"");
		//System.out.println("defined tag; \""+ XDmTag.getEntityT()+ "\"");



		if (ele.getTagName().equals(XDmTag.getEntityT())){	// if it is a EntityInstance element
			try{
				
				// retrieve entity attributes
				String enId= ele.getAttribute(XDmTag.getDmIdT());
				if (enId == null || enId == "") System.out.println("no ID");
				//2001-8-20
				//chech if the entity instance is already in store
	         	EntityInstance tempEn = DmManager.getInstance().
	         		getEInstance(enId.trim());
	         	if (tempEn != null) return tempEn;

	         	String enName= ele.getAttribute(XDmTag.getDmNameT());
//				String enLex= ele.getAttribute(XDmTag.getDmLexRT());
				String cardinality= ele.getAttribute(XDmTag.getCardiT());
				String conceptOf= ele.getAttribute(XDmTag.getConceptOfT());
				String dirty= ele.getAttribute(XDmTag.getDirtyT());
				String premodifier= ele.getAttribute(XDmTag.getPremodifierT());
				String postModifier= ele.getAttribute(XDmTag.getPostmodifierT());
				String label= ele.getAttribute(XDmTag.getLabelT());
				String determinator= ele.getAttribute(XDmTag.getDeterminatorT());
				
	      	//System.out.println("element Tag name: "+ele.getTagName());

				//retrieve "ERelations"
				String partOf = null;
				//Element eRel= null;
	         TreeMap newRel= new TreeMap();
	         String newRelName, newRelValue;
				
				NodeList children = ele.getElementsByTagName(XDmTag.getPartOfT());
	         if (children != null && children.getLength() >0 ) 
	         	partOf =children.item(0).getFirstChild().getNodeValue();
	         	
	         children = ele.getElementsByTagName(XDmTag.getNewERelT());
	         if (children != null && children.getLength() >0 ) {
	         	for (int i = 0; i< children.getLength(); i++){
	         		newRelName = ((Element)children.item(i)).getAttribute(XDmTag.getERNameT());
	         		newRelValue = ((Element)children.item(i)).getAttribute(XDmTag.getERValueT());
	         		newRel.put(newRelName,newRelValue);
	         	}
	         	
	         }
		         

	         
	         
	         //retrieve "note"
				String enNote = null;
	         children = ele.getElementsByTagName(XDmTag.getDmNoteT());
	         if (children != null && children.getLength() >0 ) 
	         	if(children.item(0)!= null)
	         		if (children.item(0).getFirstChild() != null)
	         			if (children.item(0).getFirstChild().getNodeValue()!= null)
	         				enNote =children.item(0).getFirstChild().getNodeValue(); 
	         
	         	// create the EntityInstance object
	         enName= XMLUtility.checkAndConvertForEntities(enName);
	 //17-10-2001
	         /*
	        if (label != null && label.trim() != ""){
	         	aEntity = new InterfaceInstance(enId,enName);
	         	if (!(label.equals(XDmTag.getInterfaceNoLabelT())))
	         		((InterfaceInstance)aEntity).setLabel(label);
	        } else 
	         	aEntity = new EntityInstance(enId,enName);
		*/
	        if (determinator != null && determinator.trim() != ""){
	         	aEntity = new EntityInstance(enId,enName);
	         	if (!(determinator.equals(XDmTag.getNoDeterminatorT())))
	         		aEntity.setDeterminator(determinator);
	        } else 
	         	aEntity = new InterfaceInstance(enId,enName);

//	         if (enLex != null) 			//shijian 2001-1-15
//					aEntity.setLexItem(enLex);
	         if (cardinality != null)
	        		aEntity.setCardinality(cardinality);
	         if (enNote != null){
	         	enNote= XMLUtility.checkAndConvertForEntities(enNote);
	         	aEntity.setNote(enNote);
	         }
	         
	         //2001-8-17
	         //should not create a separate copy of concept 
	         // should use the concept ID to refer the concept
	         // created before
	         DmConcept con= null;
	         if (conceptOf != null){
	         	con = DmManager.getInstance().getConcept(conceptOf.trim());
	         	//XConcept xCon= new XConcept(getDoc());
	        	//	aEntity.setConceptOf(xCon.eleToCon(getDoc().getElementById(conceptOf.trim())));
	         }
	         if (con == null)
	         	con = DmConcept.getDefaultEntityConcept();
	         aEntity.setConceptOf(con);
	         
	         if (dirty.equals(XManager._XML_YES) )
	        		aEntity.setDirty(true);
	        	else
	        		aEntity.setDirty(false);
	        		
	        if (premodifier != null && premodifier.trim() != ""){
	        	premodifier= XMLUtility.checkAndConvertForEntities(premodifier);
	         	aEntity.setPreModifier(premodifier);
			}
	        if (label != null && label.trim() != ""){
	        	if (!(label.equals(XDmTag.getInterfaceNoLabelT()))){
	        		label= XMLUtility.checkAndConvertForEntities(label);
	         		aEntity.setLabel(label);
	        	}
			}
	         if (postModifier != null && postModifier.trim() != ""){
	        	postModifier= XMLUtility.checkAndConvertForEntities(postModifier);
	         	aEntity.setPostModifier(postModifier);
			}
			
	         //2001-8-20
	         //should not create a separate copy of relation en 
	         // should use the concept ID to refer the concept
	         // created before
			 tempEn = null;
	         if (partOf != null){
	         	tempEn= eleToEn(getDoc().getElementById(partOf.trim()));
	         	XManager.addToStore(tempEn);
	         	
	        	aEntity.setEntityRelation(DmRelation.getPartOf(),tempEn);
	         }
        	if (newRel != null && newRel.size() > 0 ){
        		Iterator it = newRel.keySet().iterator();	
        		while ( it.hasNext()){
        			tempEn = null;
        			
        			newRelName = (String)it.next(); 	
        			newRelValue = (String)newRel.get(newRelName); 	
        			
        			tempEn=eleToEn(getDoc().getElementById(newRelValue.trim()));
 	         		XManager.addToStore(tempEn);
       				aEntity.setEntityRelation(newRelName,tempEn);
        		}
        	}
	 	         
			}
			catch (Exception e)
			{
				System.err.println(e);
			}
			
		}
		return aEntity;
	}//eleToEn()
  	
  	
  	/** 
  	* add(), add an entity element to the doc. it 
  	* first try to add before the first Action element, 
  	* if no Action elements present, then  simply append to 
  	* the Domain_model's children list. If Domain_model element
  	* is not present, the element is not added.
  	*/
  	public boolean add(Element ele){
		if (getDoc() == null || ele == null) return false;
		if (!(XManager.insertBAction(getDoc(), ele)))
			if (!(XManager.append(getDoc(), ele))) return false;
	 	return true;
  	}//add()
  	
  	/** 
  	* remove(), remove an element from Domain_model's chidren 
  	* list if it exists. 
  	*/
  	public void remove(String iD){
		if (doc == null || iD == null) return;
		try {
	      //get the Domain_model element.
	      Element theE = doc.getElementById(iD);
	    	if (theE != null)
	    	{	
	         theE.getParentNode().removeChild(theE);
	    	}
		}
		catch (Exception e)
		{
			System.err.println(e);
		}
  		
  	}//remove()
  	
  	
  	

  	/**
  	* Main program entry point. 
  	*/
  public static void main(String argv[]) 
  {
    if (argv.length == 0)
    {
      System.out.println("Usage:  java XEntity uri");
      System.out.println("   where uri is the URI of the XML document you want to print.");
      System.out.println("   Sample:  java XEntity sonnet.xml");
      System.exit(1);
    }
    
		//testing xConcept
    	XConcept d1 = new XConcept(XManager.parse(argv[0]));
    	DmConcept dia = new DmConcept("dialog", "entity type");
    	DmConcept win = new DmConcept("window", "entity type");
	 	win.setNote("this is a test for adding concept with DOM");
	 
  		XManager.insertBAction(d1.getDoc(),d1.conToEle(win));
  		XManager.insertBEntity(d1.getDoc(),d1.conToEle(dia));
  	
  		Element c1 = d1.getDoc().getElementById("dmC1");
  		if (c1 == null) System.out.println("no element");
  		XManager.remove(d1.getDoc(),"dmC1");
  		if (d1.eleToCon(c1) == null) System.out.println("no concept");
  		XManager.insertBEntity(d1.getDoc(),d1.conToEle(d1.eleToCon(c1)));

		//testing XEntity 
    	XEntity e1 = new XEntity(d1.getDoc());
    	
    	EntityInstance ei1= new EntityInstance ("main");
		ei1.setConceptOf(win);	
		
		EntityInstance ei2= new EntityInstance ("save");
		ei2.setConceptOf(dia);
		ei2.setEntityRelation(DmRelation.getPartOf(),ei1);
		
  		XManager.insertBAction(e1.getDoc(),e1.enToEle(ei1));
  		XManager.append(e1.getDoc(),e1.enToEle(ei2));
  		
  		Element ele = e1.getDoc().getElementById("dmE1");
  		
  		XManager.remove(e1.getDoc(),"dmE1");
  		if (e1.eleToEn(ele) == null) System.out.println("no entity");
  		XManager.append(e1.getDoc(),e1.enToEle(e1.eleToEn(ele)));


  		XManager.printDOMTree(e1.getDoc());


  }//main()
}//class: XEntity