/*
 * Created on Apr 5, 2005
 * Copyright (c) 2005 Fujitsu Laboratories of Europe. All rights reserved.
 */

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;

import javax.xml.namespace.QName;

import org.apache.axis.message.MessageElement;
import org.oasis.wsrf.lt.Destroy;
import org.oasis.wsrf.lt.SetTerminationTime;
import org.oasis.wsrf.lt.SetTerminationTimeResponse;
import org.oasis.wsrf.rp.DeleteResourceProperties_Element;
import org.oasis.wsrf.rp.DeleteType;
import org.oasis.wsrf.rp.GetMultipleResourcePropertiesResponse;
import org.oasis.wsrf.rp.GetMultipleResourceProperties_Element;
import org.oasis.wsrf.rp.GetResourcePropertyDocumentResponse;
import org.oasis.wsrf.rp.GetResourcePropertyDocument_Element;
import org.oasis.wsrf.rp.GetResourcePropertyResponse;
import org.oasis.wsrf.rp.InsertResourceProperties_Element;
import org.oasis.wsrf.rp.InsertType;
import org.oasis.wsrf.rp.SetResourceProperties_Element;
import org.oasis.wsrf.rp.UpdateResourceProperties_Element;
import org.oasis.wsrf.rp.UpdateType;
import org.unicore.services.wsrf.lt.ResourceLifetimePortType;
import org.unicore.services.wsrf.rp.ResourcePropertiesPortType;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

//import org.w3c.dom.Node;
//import org.w3c.dom.NodeList;

import com.fujitsu.unicore.services.resourcemgmt.ResourcePropertyObject;
import com.fujitsu.unicore.services.util.JobStatusType;

/**
 * A simple class for WSRF client side operations.
 * 
 * @author Vivian Li, 			Fujitsu Laboratories of Europe
 * @author Dave Snelling,			Fujitsu Laboratories of Europe
 * @author Sven van den Berghe, 	Fujitsu Laboratories of Europe
 *
 * @version $$Id: WSRF_Client.java,v 1.14 2005/06/13 12:33:57 svandenberghe Exp $$
 *  
 */
public class WSRF_Client {
    
    private static boolean TRACE = true;
	
	{
		RPNameConverter.addPrefixNames("wsrl","http://docs.oasis-open.org/wsrf/2004/11/wsrf-WS-ResourceLifetime-1.2-draft-04.xsd");
		RPNameConverter.addPrefixNames("wsrp","http://docs.oasis-open.org/wsrf/2004/11/wsrf-WS-ResourceProperties-1.2-draft-05.xsd");

	}
	
	/**
	 * wsrf lifetime destroy operation
	 *  
	 * @param service_instance a web service instance 
	 */
	protected void destroy(Object service_instance) {
	    
	    if(TRACE) System.out.println("Destroy called.");
		
		try {
			((ResourceLifetimePortType)service_instance).destroy(new Destroy());
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * wsrf lifetime destroy operation
	 * 
	 * @param service_instance 	a web service instance
	 * @param offset 			termination time to be added on the old time (in minute) 
	 */
	protected void settt(Object service_instance, int offset) {
		
		if(TRACE) System.out.println("Set termination time. Offset <"+offset+">");
		
		try {
			GregorianCalendar req_tt = new GregorianCalendar();
			req_tt.add(Calendar.MINUTE, offset);

			SetTerminationTime settt = new SetTerminationTime();
			settt.setRequestedTerminationTime(req_tt);
			
			SetTerminationTimeResponse settr = ((ResourceLifetimePortType)service_instance).setTerminationTime(settt);
			
			if(TRACE) {
			    System.out.println("Successful");
			    System.out.println("New Termination Time = "+settr.getNewTerminationTime().getTime().toString());
			    System.out.println("Current Time         = "+settr.getCurrentTime().getTime().toString());
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * wsrf resource property getResourceProperty operation
	 * 
	 * @param service_instance	a web service instance
	 * @param rn					a resource property name
	 */
	protected void grp(Object service_instance, String rn) {
		
		if(TRACE) System.out.println("Get resource property <"+rn+">");		
		
		QName qn =null;	
		try {
			qn=RPNameConverter.makeQName(rn);
		} catch (Exception e) {
		    System.err.println("Get Resource Property failed making QName");
			e.printStackTrace();
		    return;
		}
		
		GetResourcePropertyResponse rpr= null;	
		try {	
			rpr = ((ResourcePropertiesPortType)service_instance).getResourceProperty(qn);
			
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}

		MessageElement[] rp = rpr.get_any();
		for(int i=0; i<rp.length;i++) {
			if(rp[i].getValue()!=null){
				System.out.println("<"+rp[i].getLocalName()+"> "+rp[i].getValue());
			}else {	
				print_rp(rp[i]);
			}			
		}
	}
	
	/**
	 * wsrf resource property getMutipleResourceProperty operation
	 * 
	 * @param service_instance	a web service instance
	 * @param names				resource property names
	 */
	protected void gmrp(Object service_instance, String[] names) {

		QName [] qnames = new QName [names.length];

		for(int i=0; i<names.length; i++) {
		    if(TRACE) System.out.println("Get (multiple) resource property <"+names[i]+">");		
			try {
				qnames[i]=RPNameConverter.makeQName(names[i]);
			} catch (Exception e) {
			    System.err.println("Get (multiple) Resource Property failed making QName from <"+names[i]+">");
				e.printStackTrace();
			}
		}

		GetMultipleResourceProperties_Element gmrp_e= new GetMultipleResourceProperties_Element();
		gmrp_e.setResourceProperty(qnames);
		
		GetMultipleResourcePropertiesResponse resp = null;		
		try {
			resp = ((ResourcePropertiesPortType)service_instance).getMultipleResourceProperties(gmrp_e);
					
		} catch (Exception e) {
			e.printStackTrace(); 
			return;
		}
		
		MessageElement[] rps = resp.get_any();
		for(int i=0; i<rps.length; i++) {
			if(rps[i].getValue()!=null){
				System.out.println("<"+rps[i].getLocalName()+"> "+rps[i].getValue());
			}else {	
				print_rp(rps[i]);
			}	
		}
	}
	
	/**
	 * wsrf resource property getResourcePropertyDocument operation
	 * 
	 * @param service_instance a web service instance
	 */
	
	protected void grpd(Object service_instance){
	    
	    if(TRACE) System.out.println("Get Resource property Document");
		
		GetResourcePropertyDocumentResponse grpdr = null;
		try{
			grpdr = ((ResourcePropertiesPortType)service_instance).getResourcePropertyDocument(new GetResourcePropertyDocument_Element());
			
		}catch(Exception re){
			re.printStackTrace(); 
			return;
		}
		
		MessageElement[] me = grpdr.get_any();
		for (int i=0; i<me.length;i++){		
			Iterator iterator;	
			try {
				iterator = me[i].getChildElements();
				while (iterator.hasNext()){				
					MessageElement rp = (MessageElement)(iterator.next());
					if(rp.getValue()!=null){
						System.out.println("<"+rp.getLocalName()+"> "+rp.getValue());
					}else {	
						print_rp(rp);
					}	
				}
			} catch (Exception e) {
				e.printStackTrace();
			}		
		}
	}
	
	/**
	 * wsrf setResourceProperties operation
	 * 
	 * @param service_instance		a web service instance
	 * @param insert					insertType
	 * @param update					updateType
	 * @param delete					deleteType
	 */
	
	protected void srp(Object service_instance, InsertType[] insert, UpdateType[] update, DeleteType[] delete) {
		
		if(TRACE) System.out.println("Set Resource Properties");
		
		SetResourceProperties_Element srp_e = new SetResourceProperties_Element();
		if(insert!=null)
			srp_e.setInsert(insert);
		if(update!=null)
			srp_e.setUpdate(update);
		if(delete!=null)
			srp_e.setDelete(delete);

		try {
			((ResourcePropertiesPortType)service_instance).setResourceProperties(srp_e);
		}
		catch(Exception ex) {
			ex.printStackTrace();
		}				
	}
	
	/**
	 * wsrf insertResourceProperties operation
	 * 
	 * @param service_instance		a web service instance
	 * @param values					a list contains resource property name to be inserted and its value
	 */		
	protected void insertrp (Object service_instance, List values){
	    
		//TODO: check if the list contains nested elements, and the instance type
		MessageElement[] me = new MessageElement[values.size()/2];
		Iterator i = values.iterator();
		int counter=0;
		while(i.hasNext()) {
			
			QName rp_name = null;
			try {
				rp_name = RPNameConverter.makeQName(i.next().toString());
			} catch (Exception e) {
			    System.err.println("Error making QName in insert RP");
				e.printStackTrace();
				return;
			}
			
			ResourcePropertyObject rpo =
				new ResourcePropertyObject (rp_name, i.next());
			me[counter]=new MessageElement(rpo.getName(),rpo.getProperty());
			
			if(TRACE) System.out.println("Insert ResourceProperties "+me[counter].getName()+":\n"+me[counter].getValue().trim());
			
			counter++;
		}
		
		InsertType insert = new InsertType(me);
		
		InsertResourceProperties_Element insertRequest =new InsertResourceProperties_Element();
		insertRequest.setInsert(insert);
		try{
			((ResourcePropertiesPortType)service_instance).insertResourceProperties(insertRequest);
			
		}catch(Exception re){
			re.printStackTrace(); 
			return;
		}
		
	}
	
	/**
	 * wsrf updateResourceProperties operation
	 * 
	 * @param service_instance		a web service instance
	 * @param values					a list contains resource property name to be updated and its value
	 */
	protected void updaterp (Object service_instance, List values){
	
		MessageElement[] me = new MessageElement[values.size()/2];
		Iterator i = values.iterator();
		
		int counter=0;
		while(i.hasNext()) {
			
			QName rp_name = null;
			
			try {
				rp_name= RPNameConverter.makeQName(i.next().toString());
			} catch (Exception e) {
			    System.err.println("Failed converting QName in Update RP");
				e.printStackTrace();
				return;
			}
			
			ResourcePropertyObject rpo =
				new ResourcePropertyObject (rp_name, i.next());
			me[counter]=new MessageElement(rpo.getName(),rpo.getProperty());
			
			if(TRACE) System.out.println("Update ResourceProperties <"+me[counter].getName()+":"+me[counter].getValue()+">");
			
			counter++;
		}
		
		UpdateType update = new UpdateType(me);

		UpdateResourceProperties_Element updateRequest = new UpdateResourceProperties_Element();
		updateRequest.setUpdate(update);	
		
		try{
			((ResourcePropertiesPortType)service_instance).updateResourceProperties(updateRequest);
	
		}catch(Exception re){
			re.printStackTrace(); 
			return;
		}
	}
	
	
	/**
	 * wsrf deleteResourceProperty operation
	 * 
	 * @param service_instance	a web service instance
	 * @param prop_name			resource property name to be deleted
	 */
	protected void deleterp(Object service_instance, String prop_name){
		
		if(TRACE) System.out.println("DeleteResourceProperties <"+prop_name+">");
	
		QName qname =  null;
		try {
			qname = RPNameConverter.makeQName(prop_name);
		} catch (Exception e) {
		    System.err.println("Failed converting QName in Delete RP");
			e.printStackTrace();
		}
		
		DeleteType delete = new DeleteType(qname);
		
		DeleteResourceProperties_Element deleteRequest = new DeleteResourceProperties_Element();
		deleteRequest.setDelete(delete);
		
		try{
			((ResourcePropertiesPortType)service_instance).deleteResourceProperties(deleteRequest);			
			System.out.println("Delete resource property OK.");
			
		}catch(Exception re){
			re.printStackTrace(); return;
		}
	}

	/**
	 * to print message elements returned from response messages,
	 * include those with child nodes, mainly from grp, gmrp, grpd methods
	 * 
	 * @param rp		messageElement to be printed
	 */
	protected void print_rp(MessageElement rp){

		Object rpo = null;
		
		try {
		    if(rp.getLocalName().equals("JobStatus"))
		        rpo=rp.getValueAsType(RPNameConverter.getQNameType(rp.getLocalName()),JobStatusType.class);
		    else if(rp.getLocalName().equals("JobReference")){
		        System.out.println("<JobReference>");
		        NodeList nl = rp.getAsDOM().getChildNodes();
		        
		        for(int i=0; i<nl.getLength(); i++){
		            Node node = nl.item(i);
		            if(node.getLocalName().equals("Address")){
		                System.out.println(" <Address>"+
                    					node.getLastChild().getNodeValue());
		        		}else if(node.getLocalName().equals("ReferenceProperties")){ 
		                System.out.println(" <"+node.getLocalName()+">\n"+
		                        			"   <"+node.getFirstChild().getNodeName()+">"+
		                        					node.getFirstChild().getLastChild().getNodeValue()+
		                        			 "\n <"+node.getLocalName()+">"+
		                        			 "\n<JobReference>");
		            }
		        }
		        		        
//		        System.out.println("<"+rp.getLocalName()+"> "+
//		                "\n  <"+rp.getFirstChild().getNodeName()+">"+rp.getFirstChild().getNodeValue());	        
		        
		    }else
		        rpo=rp.getValueAsType(RPNameConverter.getQNameType(rp.getLocalName()));
		    
			if(rpo instanceof org.apache.axis.message.addressing.EndpointReferenceType){
				System.out.println("<"+rp.getLocalName()+"> "+
					((org.apache.axis.message.addressing.EndpointReferenceType)rpo).getAddress().toString());
			
			}else if (rpo instanceof JobStatusType){
			    System.out.println("<"+rp.getLocalName()+"> "+"\n"+ 
			            				"  <Status> "+((JobStatusType)rpo).getStatus()+"\n"+
			            				"  <JobReference>\n"+
			            				"     <Address> "+((JobStatusType)rpo).getJobReference().getAddress().toString()+"\n"+
			            				"     <ReferenceProperties>\n"+
			            				"       "+((JobStatusType)rpo).getJobReference().getProperties().get_any()[0].getAsString()+"\n"+
			            				"     </ReferenceProperties>\n"+
			            				"     </Address>\n"+
			            				"  <JobReference>\n"+
			            				"  <JobName> "+((JobStatusType)rpo).getJobName()+"\n"+
			    						"</JobStatus>");
			}    
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}

//
//						Copyright (c) Fujitsu Ltd 2000 - 2005
//
//					Use and distribution is subject a License.
//A copy was supplied with the distribution (see documentation or the jar file).
//
//This product includes software developed by Fujitsu Limited (http://www.fujitsu.com).