package client.java_and_ws.dynamic;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.bea.dsp.das.DASResult;

import weblogic.jndi.Environment;
import java.io.StringWriter;
import java.util.List;
import java.util.ArrayList;
/*
 * DSP Client - run in a webapp or stand-alone, uses either java or web service mediator
 * 
 * Everything you need to know is in the run() method.
 * 
 * You will need in your classpath
 * aldsp_3.2/ld-client.jar, 
 * wlserver_10.0/weblogic.jar, 
 * wlserver_10.0/wlclient.jar, 
 * wlserver_10.0/wls-api.jar,
 * modules/com.bea.core.sdo*.jar
 * 
 * If you are running as a Java Application from your 
 * Dynamic Web Project, make sure that "WebLogic System Libraries"
 * are *NOT* in the classpath.
 * 
 */
public class ClientComplexArgs_andCRUD {

	String locator="http://localhost:7001/RetailDataspace/RetailApplication/CustomerManagement/ProfileService.ws?WSDL";
	String dsLocator=null;
	String uri=null;
	String username= "weblogic";
	String password="weblogic";
	java.io.Writer out=new java.io.PrintWriter(System.out);
	String className=this.getClass().getName().substring(this.getClass().getName().lastIndexOf('.')+1);
	String runningIn=this.getClass().getClassLoader().equals(com.bea.dsp.das.DASResult.class.getClassLoader()) ? "standalone" : "webapp";
	String contextCacheKey=null;
	enum ClientType {java, webservice, control};
	ClientType clientType=ClientType.java;
	enum ClassloaderType { noclassloader, currentthread, other};
	ClassloaderType classloaderType=ClassloaderType.noclassloader;

	public ClientComplexArgs_andCRUD(){
		this((String)null,(String)null,(String)null, (String)null, null, null);
	}
	public ClientComplexArgs_andCRUD(java.io.Writer out){
		this((String)null,(String)null,(String)null, (String)null, out, null);
	}
	public ClientComplexArgs_andCRUD(String locator){
		this(locator,(String)null,(String)null, (String)null, null, null);
	}
	public ClientComplexArgs_andCRUD(String locator, java.io.Writer out, String classloadertypeStr){
		this(locator,(String)null,(String)null, (String)null, out, classloadertypeStr);
	}
	public ClientComplexArgs_andCRUD(String cType, String locator, String username, String password, java.io.Writer out, String classloadertypeStr){
		if(cType != null) this.clientType=ClientType.valueOf(cType);
		if(locator!=null) this.locator=locator;
		if(username!=null) this.username=username;
		if(password!=null)this.password=password;
		if(out!=null) this.out=out;
		if(classloadertypeStr != null) this.classloaderType=ClassloaderType.valueOf(classloadertypeStr);
	}
	public static void main(String[] args) {
		String locator=args.length > 0 ? args[0] : null;
		String uri=args.length > 1 ? args[1] : null;
		String username=args.length > 2 ? args[2] : null;
		String password=args.length > 3 ? args[3] : null;
		String classloadertypeStr=args.length > 4 ? args[4] : null;
		Client c=new Client(locator, uri, username, password, null, classloadertypeStr);
		c.run();
	}

	public void run(){

		if(! locator.startsWith("http://")){
			out("locator must be http://... (wsdl URL)");
			return;
		}
		DASResult dasResult = null;
		
		try {
			
			System.err.println("--------------------------------------------------------------");
			out("-----------------------------------------------------------------------------");
			
			// The DSP webservice client identifies DataAccessService by the url of the wsdl
			// The DSP java client identifies DataAccessServices by the dataspace name
			// These examples parse the wsdl url to get the necessary strings for the java client
			// http://localhost:7001/RetailDataspace/RetailApplication/CustomerManagement/ProfileService.ws?WSDL

			com.bea.dsp.das.DataAccessService das = null;
			if("webservice".equals(clientType)){
				contextCacheKey=locator; // for webservice mediator, the whole wsdl url
				if(classloaderType==ClassloaderType.currentthread)
					com.bea.dsp.das.HelperContextCache.setClassLoader(contextCacheKey, Thread.currentThread().getContextClassLoader());

				das=
					com.bea.dsp.das.DataAccessServiceFactory
						.newDataAccessService(new java.util.Hashtable(), locator);
			}	else {
				/* set uri, contextCacheKey, dsLocator - normally you would just use strings instead of obtaining from the wsdl url*/
				splitLocator(locator);
				if(classloaderType==ClassloaderType.currentthread)
					com.bea.dsp.das.HelperContextCache.setClassLoader(contextCacheKey, Thread.currentThread().getContextClassLoader());
				Context ctx = getInitialContext(uri, username,password);
				das =
					com.bea.dsp.das.DataAccessServiceFactory
						.newDataAccessService(ctx, "RetailDataspace",
						"ld:RetailApplication/CustomerManagement/ProfileService");
			}
			
			commonj.sdo.helper.HelperContext hc=com.bea.dsp.das.HelperContextCache.get(contextCacheKey);
			commonj.sdo.helper.XMLHelper xh = hc.getXMLHelper();
			commonj.sdo.helper.DataFactory factory = hc.getDataFactory();

			List<commonj.sdo.DataObject> profileServices = new ArrayList<commonj.sdo.DataObject>();

			commonj.sdo.DataObject profileService = null;
			commonj.sdo.DataObject profile1 = null;
			commonj.sdo.DataObject profile2 = null;

			profileService = factory.create("urn:retailer", "PROFILE_SERVICE");
			profileServices.add(profileService);
			com.bea.dsp.sdo.SDOUtil.setElementName(profileService,
					"urn:retailer", "PROFILE");
			profile1 = profileService.createDataObject("PROFILE");
			profile1.set("CustomerID", "CUSTOMER44"); 
			profile1.set("FirstName", "dummyFirstName44");
			profile1.set("LastName", "dummyLastName44");
			profile1.set("CustomerSince", "2001-01-01");
			profile1.set("EmailAddress", "dummyEmailAddress");
			profile1.set("TelephoneNumber", "8885551212");

			profileService = factory.create("urn:retailer", "PROFILE_SERVICE");
			profileServices.add(profileService);
			com.bea.dsp.sdo.SDOUtil.setElementName(profileService,
					"urn:retailer", "PROFILE");
			profile2 = profileService.createDataObject("PROFILE");
			profile2.set("CustomerID", "CUSTOMER55"); 
			profile2.set("FirstName", "dummyFirstName55"); 
			profile2.set("LastName", "dummyLastName55");
			profile2.set("CustomerSince", "2001-01-01");
			profile2.set("EmailAddress", "dummyEmailAddress");
			profile2.set("TelephoneNumber", "8885551212");
			
			dasResult = (com.bea.dsp.das.DASResult) das.invoke("getCustomerByCustID",
					new Object[] { "CUSTOMER44" });

			if(!dasResult.hasNext()) {
				out("ADDING: ");

				dasResult = (com.bea.dsp.das.DASResult) das.invoke("createPROFILE",
						new Object[] { profileServices.toArray() });
	
				while( dasResult.hasNext()){
					out("DataObject : " + dataObjectToString(xh,(commonj.sdo.DataObject)dasResult.next()));
				}

			} else {
				commonj.sdo.DataObject dObj=(commonj.sdo.DataObject)dasResult.next();
				if("dummyLastName44".equals(dObj.get("PROFILE/LastName"))){
					out("UPDATING: ");
					out("DataObject : " + dataObjectToString(xh,dObj));
					com.bea.dsp.sdo.SDOUtil.enableChanges(dObj);
					dObj.set("PROFILE/LastName", "Smith");
					dasResult = (com.bea.dsp.das.DASResult) das.invoke("updatePROFILE",
							new Object[] { dObj });
					

				} else {
					out("DELETING: ");
					out("DataObject : " + dataObjectToString(xh,dObj));
					dasResult = (com.bea.dsp.das.DASResult) das.invoke("deletePROFILE",
							new Object[] { dObj });
					
					dasResult = (com.bea.dsp.das.DASResult) das.invoke("getCustomerByCustID",
							new Object[] { "CUSTOMER55" });
					
					if(dasResult.hasNext()){
						dObj=(commonj.sdo.DataObject)dasResult.next();
						out("DataObject : " + dataObjectToString(xh,dObj));
						dasResult = (com.bea.dsp.das.DASResult) das.invoke("deletePROFILE",
								new Object[] { dObj });
					}
		
				}
			}

			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					if(dasResult!=null) dasResult.dispose();
				} catch(Exception e){e.printStackTrace();}
				
			}
		}

	public void out(String s){
		try{
			if(out instanceof javax.servlet.jsp.JspWriter)
				s=s.replace("&","&amp;").replace("<", "&lt;").replace(">", "&gt;");
			out.write(className+"/"+runningIn+"/"+clientType+"/"+classloaderType+" "+s+"\n");
			out.flush();
		}catch (Exception e){
			e.printStackTrace();
		}
	}

	public static InitialContext getInitialContext(String url, String username,
		String password) throws NamingException {
		Environment env = new Environment();
		env.setProviderUrl(url);
		env.setInitialContextFactory("weblogic.jndi.WLInitialContextFactory");
		env.setSecurityPrincipal(username);
		env.setSecurityCredentials(password);
		return new InitialContext(env.getInitialContext().getEnvironment());
	}

	static String dataObjectToString(commonj.sdo.helper.XMLHelper xh, commonj.sdo.DataObject dObj) {
		try {
			com.bea.sdo.PropertyXML element = ((com.bea.sdo.DataObjectXML) dObj)
					.getContainmentPropertyXML();
			String elementName = element.getXMLName();
			String elementURI = element.getXMLNamespaceURI();
			commonj.sdo.helper.XMLDocument xmlDocument = xh.createDocument(dObj, elementURI,
					elementName);
			StringWriter outputWriter = new StringWriter();
			xh.save(xmlDocument, outputWriter, null);
			return outputWriter.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	boolean isWebServiceClient(){
		return clientType==ClientType.webservice;
	}
	
	void splitLocator(String locator) throws Exception {
		uri=null;
		contextCacheKey=null;
		dsLocator=null;
		for(int i=0, j=0, last=0;i<locator.length(); i++){
			if(locator.charAt(i) == '/'){
				j++;
				if(j==2)
					last=i;
				if(j==3){
					uri="t3://"+locator.substring(last+1,i);
					last=i;
				}
				if(j==4){
					contextCacheKey=locator.substring(last+1,i);
					dsLocator="ld:"+locator.substring(i+1).replace(".ws?WSDL", "");
					break;
				}
			}
		}
		if(uri==null || contextCacheKey== null || dsLocator==null)
			throw new Exception("locator not valid : "+locator);
		return;
	}
}
