package org.openscience.cdk.io;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Vector;
import nu.xom.Attribute;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.ProcessingInstruction;
import nu.xom.Text;
import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.annotations.TestClass;
import org.openscience.cdk.annotations.TestMethod;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IAtomContainerSet;
import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.interfaces.IChemFile;
import org.openscience.cdk.interfaces.IChemModel;
import org.openscience.cdk.interfaces.IChemObject;
import org.openscience.cdk.interfaces.IChemSequence;
import org.openscience.cdk.interfaces.ICrystal;
import org.openscience.cdk.interfaces.IMolecule;
import org.openscience.cdk.interfaces.IMoleculeSet;
import org.openscience.cdk.interfaces.IReaction;
import org.openscience.cdk.interfaces.IReactionSet;
import org.openscience.cdk.io.formats.CMLRSSFormat;
import org.openscience.cdk.io.formats.IResourceFormat;
import org.openscience.cdk.libio.cml.Convertor;
/**
* Generates an RSS feed. It the object is a {@link IMoleculeSet}, the molecules
* are put in separately. All other objects are made CML and put in.
*
* @cdk.module libiocml
* @cdk.githash
* @cdk.builddepends xom-1.0.jar
*
* @author Stefan Kuhn
*
* @cdk.keyword RSS
*/
@TestClass("org.openscience.cdk.io.RssWriterTest")
public class RssWriter extends DefaultChemObjectWriter {
private final static String NS_RSS10 = "http://purl.org/rss/1.0/";
private final static String NS_RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
private final static String NS_DCELEMENTS = "http://purl.org/dc/elements/1.1/";
private BufferedWriter writer;
private Map linkmap=new HashMap();
private Map datemap=new HashMap();
private Map titlemap=new HashMap();
private Map creatormap=new HashMap();
private Map inchimap=new HashMap();
private String creator="";
private String title="";
private String link="";
private String description="";
private String publisher="";
private String imagelink="";
private String about="";
private String timezone="+01:00";
private Map multiMap=new HashMap();
/**
* Flushes the output and closes this object.
*/
@TestMethod("testClose")
public void close() throws IOException {
writer.close();
}
@TestMethod("testGetFormat")
public IResourceFormat getFormat() {
return CMLRSSFormat.getInstance();
}
public void setWriter(Writer out) throws CDKException {
if (out instanceof BufferedWriter) {
writer = (BufferedWriter)out;
} else {
writer = new BufferedWriter(out);
}
}
public void setWriter(OutputStream output) throws CDKException {
setWriter(new OutputStreamWriter(output));
}
@TestMethod("testAccepts")
public boolean accepts(Class classObject) {
return true;
}
/**
* Writes a IChemObject to the MDL molfile formated output.
*
* @param object Best choice is a set of molecules
*/
/* (non-Javadoc)
* @see org.openscience.cdk.io.IChemObjectWriter#write(org.openscience.cdk.interfaces.IChemObject)
*/
public void write(IChemObject object) throws CDKException {
try{
ProcessingInstruction processingInstruction =new ProcessingInstruction("xml-stylesheet", "href=\"http://www.w3.org/2000/08/w3c-synd/style.css\" type=\"text/css\"");
Element rdfElement = new Element("rdf:RDF",NS_RDF);
rdfElement.addNamespaceDeclaration("",NS_RSS10);
rdfElement.addNamespaceDeclaration("mn","http://usefulinc.com/rss/manifest/");
rdfElement.addNamespaceDeclaration("dc",NS_DCELEMENTS);
rdfElement.addNamespaceDeclaration("cml",Convertor.NS_CML);
Document doc = new Document(rdfElement);
doc.insertChild(processingInstruction,0);
Element channelElement = new Element("channel",NS_RSS10);
Element titleElement = new Element("title",NS_RSS10);
titleElement.appendChild(new Text(title));
channelElement.appendChild(titleElement);
Element linkElement = new Element("link",NS_RSS10);
linkElement.appendChild(new Text(link));
channelElement.appendChild(linkElement);
Element descriptionElement = new Element("description",NS_RSS10);
descriptionElement.appendChild(new Text(description));
channelElement.appendChild(descriptionElement);
Element publisherElement = new Element("dc:publisher",NS_DCELEMENTS);
publisherElement.appendChild(new Text(publisher));
channelElement.appendChild(publisherElement);
Element creatorElement = new Element("dc:creator",NS_DCELEMENTS);
creatorElement.appendChild(new Text(creator));
channelElement.appendChild(creatorElement);
Element imageElement = new Element("image",NS_RSS10);
imageElement.addAttribute(new Attribute("rdf:resource",NS_RDF,imagelink));
channelElement.appendChild(imageElement);
Element itemsElement = new Element("items",NS_RSS10);
Element seqElement = new Element("rdf:Seq",NS_RDF);
itemsElement.appendChild(seqElement);
channelElement.appendChild(itemsElement);
channelElement.addAttribute(new Attribute("rdf:about",NS_RDF,about));
rdfElement.appendChild(channelElement);
List list =new Vector();
if(object instanceof IAtomContainerSet){
for(int i=0;i<((IAtomContainerSet)object).getAtomContainerCount();i++){
list.add(((IAtomContainerSet)object).getAtomContainer(i));
}
}else{
list.add(object);
}
for(int i=0;i<list.size();i++){
IChemObject chemObject =(IChemObject)list.get(i);
Element itemElement = new Element("item",NS_RSS10);
String easylink=(String)linkmap.get(chemObject);
if(easylink!=null)
itemElement.addAttribute(new Attribute("rdf:about",NS_RDF,easylink));
Element link2Element = new Element("link",NS_RSS10);
link2Element.appendChild(new Text(easylink));
itemElement.appendChild(link2Element);
String title=(String)chemObject.getProperties().get(CDKConstants.TITLE);
if(titlemap.get(chemObject)!=null){
Element title2Element = new Element("title",NS_RSS10);
title2Element.appendChild(new Text((String)titlemap.get(chemObject)));
itemElement.appendChild(title2Element);
}
if(title!=null){
Element description2Element = new Element("description",NS_RSS10);
description2Element.appendChild(new Text(title));
itemElement.appendChild(description2Element);
Element subjectElement = new Element("dc:subject",NS_DCELEMENTS);
subjectElement.appendChild(new Text(title));
itemElement.appendChild(subjectElement);
}
if(datemap.get(chemObject)!=null){
Element dateElement = new Element("dc:date",NS_DCELEMENTS);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
dateElement.appendChild(new Text(formatter.format((Date)datemap.get(chemObject))+timezone));
itemElement.appendChild(dateElement);
}
Element creator2Element =new Element("dc:creator",NS_DCELEMENTS);
creator2Element.appendChild(new Text((String)creatormap.get(chemObject)));
itemElement.appendChild(creator2Element);
// add the InChI to the CMLRSS feed
if (inchimap.get(chemObject)!=null) {
Element inchiElement = new Element("cml:identifier","http://www.xml-cml.org/schema/cml2/core/");
inchiElement.appendChild(new Text((String)inchimap.get(chemObject)));
itemElement.appendChild(inchiElement);
}
Element root=null;
Convertor convertor=new Convertor(true,null);
object=(IChemObject)list.get(i);
if (object instanceof IMolecule) {
root = convertor.cdkMoleculeToCMLMolecule((IMolecule)object);
}else if (object instanceof IAtomContainer) {
root = convertor.cdkAtomContainerToCMLMolecule((IAtomContainer)object);
} else if (object instanceof ICrystal) {
root = convertor.cdkCrystalToCMLMolecule((ICrystal)object);
} else if (object instanceof IAtom) {
root = convertor.cdkAtomToCMLAtom(null, (IAtom)object);
} else if (object instanceof IBond) {
root = convertor.cdkBondToCMLBond((IBond)object);
} else if (object instanceof IReaction) {
root = convertor.cdkReactionToCMLReaction((IReaction)object);
} else if (object instanceof IReactionSet) {
root = convertor.cdkReactionSetToCMLReactionList((IReactionSet)object);
} else if (object instanceof IMoleculeSet) {
root = convertor.cdkMoleculeSetToCMLList((IMoleculeSet)object);
} else if (object instanceof IChemSequence) {
root = convertor.cdkChemSequenceToCMLList((IChemSequence)object);
} else if (object instanceof IChemModel) {
root = convertor.cdkChemModelToCMLList((IChemModel)object);
} else if (object instanceof IChemFile) {
root = convertor.cdkChemFileToCMLList((IChemFile)object);
} else {
throw new CDKException("Unsupported chemObject: " + object.getClass().getName());
}
itemElement.appendChild(root);
if(multiMap.get(chemObject)!=null){
Collection coll=(Collection)multiMap.get(chemObject);
Iterator iterator =coll.iterator();
while(iterator.hasNext()){
itemElement.appendChild((Element)iterator.next());
}
}
rdfElement.appendChild(itemElement);
Element imageElement2 = new Element("rdf:li",NS_RDF);
imageElement2.addAttribute(new Attribute("rdf:resource",NS_RDF,(String)linkmap.get(chemObject)));
seqElement.appendChild(imageElement2);
}
writer.write(doc.toXML());
writer.flush();
}catch(IOException ex){
throw new CDKException(ex.getMessage(), ex);
}
}
/**
* @return the datemap. If you put a java.util.Date in this map with one of the objects you want to write as key, it will be added as a date to this object (no validity check is done)
*/
public Map getDatemap() {
return datemap;
}
/**
* @param datemap the datemap. If you put a java.uitl.Date in this map with one of the objects you want to write as key, it will be added as a datek to this object (no validity check is done)
*/
public void setDatemap(Map datemap) {
this.datemap = datemap;
}
/**
* @return the linkmap. If you put a String in this map with one of the objects you want to write as key, it will be added as a link to this object (no validity check is done)
*/
public Map getLinkmap() {
return linkmap;
}
/**
* @param linkmap the linkmap. If you put a String in this map with one of the objects you want to write as key, it will be added as a link to this object (no validity check is done)
*/
public void setLinkmap(Map linkmap) {
this.linkmap = linkmap;
}
/**
* @return the titlemap. If you put a String in this map with one of the objects you want to write as key, it will be added as a title to this object (no validity check is done)
*/
public Map getTitlemap() {
return titlemap;
}
/**
* @param titlemap the titlemap. If you put a String in this map with one of the objects you want to write as key, it will be added as a titel to this object (no validity check is done)
*/
public void setTitlemap(Map titlemap) {
this.titlemap = titlemap;
}
/**
* @return the creatoremap. If you put a String in this map with one of the objects you want to write as key, it will be added as a creator to this object (no validity check is done)
*/
public Map getCreatormap() {
return creatormap;
}
/**
* @param creatormap the creatormap. If you put a String in this map with one of the objects you want to write as key, it will be added as a creator to this object (no validity check is done)
*/
public void setCreatormap(Map creatormap) {
this.creatormap = creatormap;
}
/**
* @param about This will be the about for the rss feed
*/
public void setAbout(String about) {
this.about = about;
}
/**
* @param creator This will be the creator for the rss feed
*/
public void setCreator(String creator) {
this.creator = creator;
}
/**
* @param description This will be the description for the rss feed
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @param imagelink This will be the imagelink for the rss feed
*/
public void setImagelink(String imagelink) {
this.imagelink = imagelink;
}
/**
* @param link This will be the link for the rss feed
*/
public void setLink(String link) {
this.link = link;
}
/**
* @param publisher This will be the publisher for the rss feed
*/
public void setPublisher(String publisher) {
this.publisher = publisher;
}
/**
* @param title This will be the title for the rss feed
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @return the multimap. If you put any number of nu.xom.Elements in this map with one of the objects you want to write as key, it will be added as a child to the same node as the cml code of the object
*/
public Map getMultiMap() {
return multiMap;
}
/**
* @param multiMap If you put any number of nu.xom.Elements in this map with one of the objects you want to write as key, it will be added as a child to the same node as the cml code of the object
*/
public void setMultiMap(Map multiMap) {
this.multiMap = multiMap;
}
/**
* @param timezone This will be added to the data as timezone. format according to 23c. Examples "+01:00" "-05:00"
*/
public void setTimezone(String timezone) {
this.timezone = timezone;
}
/**
* @return inchimap If you put any number of Strings in this map with one of the objects you want to write as key, it will be added as a child to the same node as the cml code of the object
*/
public Map getInchimap() {
return inchimap;
}
/**
* @param inchimap If you put any number of Strings in this map with one of the objects you want to write as key, it will be added as a child to the same node as the cml code of the object
*/
public void setInchimap(Map inchimap) {
this.inchimap = inchimap;
}
}