import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.*;
import org.openscience.cdk.qsar.*;
import org.openscience.cdk.qsar.result.*;
import org.openscience.cdk.interfaces.IChemObjectBuilder;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.interfaces.IMolecule;
import org.openscience.cdk.io.iterator.*;
import org.openscience.cdk.io.MDLWriter;
import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;
import org.openscience.cdk.tools.HydrogenAdder;
import org.openscience.cdk.modeling.builder3d.ModelBuilder3D;

import java.io.*;
import java.util.*;
import java.lang.*;



class Desc_3D
{

public static void main(String[] args) throws CDKException 
{
 
  	BufferedReader sdfile=null;
  	ModelBuilder3D mb3d = new ModelBuilder3D();
  	try 
  	{
  		sdfile= new BufferedReader (new FileReader(new File("all_tb.sdf")));
  	}
    
  	catch (FileNotFoundException e) 
  	{
  		System.err.println("File not found");
  		System.exit(1);
  	}
   
   	 
  	IteratingMDLReader myiter = new IteratingMDLReader(sdfile,DefaultChemObjectBuilder.getInstance());
	Molecule mol = null;
  	
    int k=0;
  
    
    while (myiter.hasNext()) {
  	mol = (Molecule) myiter.next();
  	Molecule molecule = new Molecule (mol);
   	k++;
    
    try {
    	
		HydrogenAdder hAdder=new HydrogenAdder();
	    hAdder.addExplicitHydrogensToSatisfyValency(molecule);
	    mb3d.setTemplateHandler();
	    mb3d.setForceField("mm2");
	    mb3d.setMolecule(molecule, true);
	    mb3d.generate3DCoordinates();
	} catch (Exception e) {
	    throw new CDKException(e.toString());
	}
	
    IMolecule newmolecule = mb3d.getMolecule();
    
    DescriptorEngine de = new DescriptorEngine(DescriptorEngine.MOLECULAR);
	HashMap<String, Object> map = new HashMap<String, Object>();
	String classes = "topological,geometrical,constitutional,electronic,hybrid";
	String[] classlist = classes.split(",");
	List deInstances = de.getDescriptorInstances();
	
	for (Object o : deInstances) 
	{
		IMolecularDescriptor desc = (IMolecularDescriptor)o;
	    DescriptorSpecification spec = desc.getSpecification();

	    String[] comps = spec.getSpecificationReference().split("#");
	    String descName = comps[1];

	    String[] descClasses = de.getDictionaryClass(spec);
	    if (descClasses == null) { continue;}
		
	    // see if the class matches any of our specified classes
	    boolean matches = false;
	    for (String s1 : descClasses) {
		for (String s2 : classlist) {
		    if (s1.equals(s2+"Descriptor")) {
			matches = true;
			break;
		    }
		}
		if (matches) break;
	    }
	    if (!matches) continue;
	    try {
	    
	    DescriptorValue value = desc.calculate(newmolecule);
	    IDescriptorResult result = value.getValue();
		    
		if (result instanceof DoubleResult) {
		    molecule.setProperty(descName, ((DoubleResult) result).doubleValue());
		    map.put(descName, ((DoubleResult) result).doubleValue());
		} else if (result instanceof IntegerResult) {
		    molecule.setProperty(descName, ((IntegerResult) result).intValue());
		    map.put(descName, ((IntegerResult) result).intValue());
		} else if (result instanceof DoubleArrayResult) {
		    for (int i = 0; i < ((DoubleArrayResult) result).size(); i++) {
			molecule.setProperty(descName + "." + i, ((DoubleArrayResult) result).get(i));
			map.put(descName + "." + i, ((DoubleArrayResult) result).get(i));
		    }
		} else if (result instanceof IntegerArrayResult) {
		    for (int i = 0; i < ((IntegerArrayResult) result).size(); i++){
			molecule.setProperty(descName + "." + i, ((IntegerArrayResult) result).get(i));
			map.put(descName + "." + i, ((IntegerArrayResult) result).get(i));
		    }
		}
	    } catch (CDKException e) {
		throw new CDKException(e.toString());
	    }
	} // for 


    
    try {
	    MDLWriter writer = new MDLWriter(new FileWriter(new File("output.sdf")));
	    writer.setSdFields(map);
	    writer.writeMolecule(newmolecule);
	    writer.close();
	} catch (Exception e) {
	    throw new CDKException(e.toString());
	}

 }//while
  }// function
}//class