/**********************************************************************
Copyright (C) 2006 by Virtual Computational Chemistry Laboratory,  http://www.vcclab.org
Authors: Igor V. Tetko and Dmitry Samorodov

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
***********************************************************************/

/*
This is a sample code to perform ALOGPS calculations at http://www.vcclab.org site
It requires Java 1.5, 
AXIS libraries from AXIS project http://ws.apache.org/axis/
options.jar (library) for command-line processing from http://www.javaworld.com/javaworld/jw-08-2004/jw-0816-command.html.
mail.jar from http://java.sun.com/products/javamail/downloads/index.html
and activation.jar from http://java.sun.com/products/beans/glasgow/jaf.html

The input file is molecule(s) in any OpenBabel format (http://openbabel.sourceforge.net/)
The output file is XML file produced by the ALOGPS program.

ALOGPS will perform conversion to SMILES using OpenBabel and will 
calculate the logP and aqueous solubility values using SMILES representation.

Notice, that this is an experimental Web Service and it may change in the future. 
Consult http://www.vcclab.org/web for details.

On LINUX/MacOsX:

to compile program 
javac -classpath .:options.jar:axis-ant.jar:axis-schema.jar:axis.jar:commons-discovery-0.2.jar:commons-logging-1.0.4.jar:jaxrpc.jar:log4j-1.2.8.jar:saaj.jar:wsdl4j-1.5.1.jar:mail.jar:activation.jar VcclabALOGPS.java
to run program use
java -classpath .:options.jar:axis-ant.jar:axis-schema.jar:axis.jar:commons-discovery-0.2.jar:commons-logging-1.0.4.jar:jaxrpc.jar:log4j-1.2.8.jar:saaj.jar:wsdl4j-1.5.1.jar:mail.jar:activation.jar VcclabALOGPS FILE_SMILES output.xml

where FILE_SMILES is file with molecuels in SMILES format

On Windows :

to compile program 
javac -classpath .;options.jar;axis-ant.jar;axis-schema.jar;axis.jar;commons-discovery-0.2.jar;commons-logging-1.0.4.jar;jaxrpc.jar;log4j-1.2.8.jar;saaj.jar;wsdl4j-1.5.1.jar;mail.jar;activation.jar VcclabALOGPS.java
to run program use
java -classpath .;options.jar;axis-ant.jar;axis-schema.jar;axis.jar;commons-discovery-0.2.jar;commons-logging-1.0.4.jar;jaxrpc.jar;log4j-1.2.8.jar;saaj.jar;wsdl4j-1.5.1.jar;mail.jar;activation.jar VcclabALOGPS FILE_SMILES output.xml

In this command all libraries are from the AXIS project (the other versions may have different names, just use all libraries) with an exception of 
	options.jar, which is available from http://www.javaworld.com/javaworld/jw-08-2004/jw-0816-command.html.

The default input file is a list of SMILES: one SMILES per line.
*/


import java.io.*;
import java.util.*;
import java.net.URL;
import org.apache.axis.client.Service;
import org.apache.axis.client.Call;
import org.apache.axis.utils.XMLUtils;
import org.apache.axis.message.SOAPBodyElement;
import org.w3c.dom.Element;
import org.w3c.dom.Document;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;

import ml.options.*;
import ml.options.Options.*;

public class VcclabALOGPS{

  final static String SMILES="smi", SDF="sdf", MOL2="mol2";

  String inputFile = null, 
  		outputFile = null,
  		fileFormat = SMILES;
  
  public VcclabALOGPS() {}

  public void getAlogpsXmlResults() throws Exception {

    File source = new File(inputFile);
	if (!source.exists()) {
		System.err.println("Error: \"" + inputFile + "\" does not exist!");
		System.exit(8);
		}

    ArrayList<String> molecules = new ArrayList<String> ();
    try{
    BufferedReader br = new BufferedReader(new FileReader(source));
    String line,mol="";boolean ok=false;
    while ( (line = br.readLine()) != null) {
    	if(fileFormat.equals(SMILES)){
	      mol=line.trim();
	      if (mol.length() > 0)molecules.add(mol+"\n");
    	  continue;
    	  }

    	if(fileFormat.equals(SDF)){
      	  mol=mol+line+"\n";
      	  if(line.trim().length()>0)ok=true;
    	  if(line.startsWith("$$$$")){molecules.add(mol);mol="";ok=false;}
    	  continue;
    	  }
    	
    	if(fileFormat.equals(MOL2)){
    	  if(line.startsWith("@<TRIPOS>MOLECULE")){molecules.add(mol);mol="";}
      	  mol=mol+line+"\n";
    	  continue;
    	  }

   	    mol=mol+line+"\n";ok=true;
    	}

	if(fileFormat.equals(MOL2)||ok)molecules.add(mol);
    br.close();
    }catch(Exception e) {
    	System.out.println("There is an exception when reading molecules from file "+inputFile+"\n"+e.getMessage());
    	}

    if ( molecules.isEmpty()) {
      System.err.println("Error \"" + inputFile + "\" is empty");
      System.exit(8);
    }

    Service service = new Service();
    Call call = (Call) service.createCall();
    String endpoint = "http://www.vcclab.org/web/services/ALOGPS";    
    call.setTargetEndpointAddress(new URL(endpoint));

    int size = molecules.size();

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.newDocument();
    Element rootElement = doc.createElement("MOLECULES");
    rootElement.setAttribute("FORMAT",fileFormat);

    for (int i = 0; i < size; i++){
      Element molecule = doc.createElement("MOLECULE");
      molecule.appendChild(doc.createTextNode(molecules.get(i)));
      rootElement.appendChild(molecule);
    }
    doc.appendChild(rootElement);
    
    SOAPBodyElement[] input = new SOAPBodyElement[1];
    input[0] = new SOAPBodyElement(doc.getDocumentElement());

    Vector elems = (Vector) call.invoke(input);
    SOAPBodyElement element = (SOAPBodyElement) elems.get(0);
    Element e = element.getAsDOM();

    File target = new File(outputFile);
    Transformer t = TransformerFactory.newInstance().newTransformer();
    t.transform(new DOMSource(e), new StreamResult(new FileOutputStream(target)));
  }

  public static void main(String[] args) throws Exception {

	Options opt = new Options(args,Multiplicity.ZERO_OR_ONE, 2);
	opt.getSet().addOption("f", Separator.BLANK);

	if (!opt.check()) {
		System.out.println("Usage: java VcclabALOGPS [-f babelFormat] <inputfile> <outputfile>\nsmi is default format (SMILES)\nFor other formats openBabel will be used to perform file conversion\n"); 
		System.exit(1);
	}
	
   VcclabALOGPS alogps = new VcclabALOGPS();

	if (opt.getSet().isSet("f")) {
		alogps.fileFormat = opt.getSet().getOption("f").getResultValue(0);
		}
	
	alogps.inputFile  = opt.getSet().getData().get(0);
	alogps.outputFile = opt.getSet().getData().get(1);
	
    alogps.getAlogpsXmlResults();
  }

}
