// Copyright 2000-2005, FreeHEP.
package hep.graphics.heprep.xml;
import hep.graphics.heprep.HepRep;
import hep.graphics.heprep.HepRepAction;
import hep.graphics.heprep.HepRepAttDef;
import hep.graphics.heprep.HepRepAttValue;
import hep.graphics.heprep.HepRepAttribute;
import hep.graphics.heprep.HepRepConstants;
import hep.graphics.heprep.HepRepDefinition;
import hep.graphics.heprep.HepRepInstance;
import hep.graphics.heprep.HepRepInstanceTree;
import hep.graphics.heprep.HepRepPoint;
import hep.graphics.heprep.HepRepTreeID;
import hep.graphics.heprep.HepRepType;
import hep.graphics.heprep.HepRepTypeTree;
import hep.graphics.heprep.HepRepWriter;
import hep.graphics.heprep.util.HepRepUtil;
import hep.graphics.heprep.wbxml.BHepRepWriter;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.freehep.util.io.NoCloseOutputStream;
/**
*
* @author M.Donszelmann
*
* @version $Id: XMLHepRepWriter.java 8584 2006-08-10 23:06:37Z duns $
*/
public class XMLHepRepWriter implements HepRepWriter {
private static final String nameSpace = "heprep";
// JHEPREP-17: deprecated now that we have a binary format.
private boolean bitEncoding; // flags if the doubles should be HexBit encoded
private OutputStream cos; // closeable stream
private ZipOutputStream zip; // zip stream if applicable
private OutputStream out; // pointer to top-most stream (zip, gzip or os)
private XMLTagWriter xml;
private long fileNumber;
protected Map/*<String, String>*/ properties;
XMLHepRepWriter(OutputStream os, boolean randomAccess, boolean compress) throws IOException {
super();
if (randomAccess) {
zip = new ZipOutputStream(os);
zip.setMethod(compress ? ZipOutputStream.DEFLATED : ZipOutputStream.STORED);
cos = zip;
} else if (compress) {
cos = new GZIPOutputStream(os);
} else {
cos = os;
}
out = new NoCloseOutputStream(cos);
bitEncoding = false;
properties = new HashMap();
fileNumber = 1;
}
/*
XMLHepRepWriter(Writer out) {
super();
init(out);
}
*/
/**
* Switches bitencoding
* @param bitEncoding set bitencoding on
* @deprecated use binary heprep (bheprep) instead.
*/
public void setBitEncoding(boolean bitEncoding) {
this.bitEncoding = bitEncoding;
if (bitEncoding) System.err.println("setBitEncoding is deprecated, use binary heprep files instead.");
}
public void addProperty(String key, String value) throws IOException {
properties.put(key, value);
}
public void close() throws IOException {
if (zip != null) {
zip.putNextEntry(new ZipEntry("heprep.properties"));
PrintStream ps = new PrintStream(zip);
for (Iterator i=properties.keySet().iterator(); i.hasNext(); ) {
String key = (String)i.next();
ps.println(key+"="+(String)properties.get(key));
}
zip.closeEntry();
zip.close();
}
cos.close();
}
/**
* Write any known type of HepRep Object. HepRep themselves are written as numbered bheprep files with name: File-#.bheprep
* @param object anby HepRep object
* @throws IOException in case of an I/O error
*/
public void write(Object object) throws IOException {
if (object instanceof HepRep) {
write((HepRep)object, "File-"+fileNumber+".bheprep");
fileNumber++;
} else if (object instanceof HepRepTreeID) {
write((HepRepTreeID)object);
} else if (object instanceof List/*<String>*/) {
write((List/*<String>*/)object);
} else if (object instanceof HepRepAction) {
write((HepRepAction)object);
} else if (object instanceof HepRepTypeTree) {
write((HepRepTypeTree)object);
} else if (object instanceof HepRepType) {
write((HepRepType)object);
} else if (object instanceof HepRepInstanceTree) {
write((HepRepInstanceTree)object);
} else if (object instanceof HepRepInstance) {
write((HepRepInstance)object);
} else if (object instanceof HepRepPoint) {
write((HepRepPoint)object);
} else {
System.err.println("XMLHepRepWriter: do not know how to write object of type: "+object.getClass());
}
}
public void write(HepRep heprep, String name) throws IOException {
if (zip != null) {
zip.putNextEntry(new ZipEntry(name));
}
if (name.endsWith(".bheprep")) {
xml = new BHepRepWriter(new BufferedOutputStream(out));
bitEncoding = false;
} else {
xml = new ASCIIHepRepWriter(new BufferedWriter(new OutputStreamWriter(out)), " ", nameSpace);
}
xml.openDoc();
xml.setAttribute("version", "2.0");
String schemaLocation = "http://java.freehep.org/schemas/heprep/2.0";
xml.setAttribute("xmlns", schemaLocation);
xml.setAttribute("xmlns", "xsi", "http://www.w3.org/2001/XMLSchema-instance");
xml.setAttribute("xsi", "schemaLocation", schemaLocation+" "+schemaLocation+"/HepRep.xsd");
xml.openTag(nameSpace, "heprep");
write(heprep.getLayerOrder());
for (Iterator i=heprep.getTypeTreeList().iterator(); i.hasNext(); ) {
write((HepRepTypeTree)i.next());
}
for (Iterator i=heprep.getInstanceTreeList().iterator(); i.hasNext(); ) {
write((HepRepInstanceTree)i.next());
}
xml.closeTag();
xml.closeDoc();
xml.close();
if (zip != null) {
zip.closeEntry();
}
}
public void write(List/*<String>*/ layers) throws IOException {
StringBuffer layerOrder = new StringBuffer();
String layerName = null;
for (Iterator i=layers.iterator(); i.hasNext(); ) {
if (layerName != null) layerOrder.append(", ");
layerName = (String)i.next();
layerOrder.append(layerName);
}
xml.setAttribute("order", layerOrder.toString());
xml.printTag(nameSpace, "layer");
}
public void write(HepRepTypeTree typeTree) throws IOException {
xml.setAttribute("name", typeTree.getName());
xml.setAttribute("version", typeTree.getVersion());
xml.openTag(nameSpace, "typetree");
for (Iterator i=typeTree.getTypeList().iterator(); i.hasNext(); ) {
write((HepRepType)i.next());
}
xml.closeTag();
}
public void write(HepRepType type) throws IOException {
if (type == null) return;
xml.setAttribute("name", type.getName());
xml.openTag(nameSpace, "type");
write((HepRepDefinition)type);
write((HepRepAttribute)type);
for (Iterator i=type.getTypeList().iterator(); i.hasNext(); ) {
write((HepRepType)i.next());
}
xml.closeTag();
}
public void write(HepRepTreeID treeID) throws IOException {
xml.setAttribute("qualifier", treeID.getQualifier());
xml.setAttribute("name", treeID.getName());
xml.setAttribute("version", treeID.getVersion());
xml.printTag(nameSpace, "treeid");
}
public void write(HepRepAction action) throws IOException {
xml.setAttribute("name", action.getName());
xml.setAttribute("expression", action.getExpression());
xml.printTag(nameSpace, "action");
}
public void write(HepRepInstanceTree instanceTree) throws IOException {
xml.setAttribute("name", instanceTree.getName());
xml.setAttribute("version", instanceTree.getVersion());
xml.setAttribute("typetreename", instanceTree.getTypeTree().getName());
xml.setAttribute("typetreeversion", instanceTree.getTypeTree().getVersion());
xml.openTag(nameSpace, "instancetree");
// refs
for (Iterator i=instanceTree.getInstanceTreeList().iterator(); i.hasNext(); ) {
write((HepRepTreeID)i.next());
}
// instances
for (Iterator i=instanceTree.getInstances().iterator(); i.hasNext(); ) {
write((HepRepInstance)i.next());
}
xml.closeTag();
}
public void write(HepRepInstance instance) throws IOException {
// FIXME JHEPREP-11
xml.setAttribute("type", instance.getType().getFullName());
xml.openTag(nameSpace, "instance");
write((HepRepAttribute)instance);
for (Iterator i=instance.getPoints().iterator(); i.hasNext(); ) {
write((HepRepPoint)i.next());
}
for (Iterator i=instance.getInstances().iterator(); i.hasNext(); ) {
write((HepRepInstance)i.next());
}
xml.closeTag();
}
public void write(HepRepPoint point) throws IOException {
if (bitEncoding) {
xml.setAttribute("x", encodeNumber(point.getX()));
xml.setAttribute("y", encodeNumber(point.getY()));
xml.setAttribute("z", encodeNumber(point.getZ()));
} else {
xml.setAttribute("x", point.getX());
xml.setAttribute("y", point.getY());
xml.setAttribute("z", point.getZ());
}
if (point.getAttValuesFromNode().iterator().hasNext()) {
xml.openTag(nameSpace, "point");
write((HepRepAttribute)point);
xml.closeTag();
} else {
xml.printTag(nameSpace, "point");
}
}
public void write(HepRepAttribute attribute) throws IOException {
for (Iterator i = attribute.getAttValuesFromNode().iterator(); i.hasNext(); ) {
HepRepAttValue attValue = (HepRepAttValue)i.next();
write(attValue);
}
}
public void write(HepRepDefinition definition) throws IOException {
for (Iterator i = definition.getAttDefsFromNode().iterator(); i.hasNext(); ) {
HepRepAttDef attDef = (HepRepAttDef)i.next();
write(attDef);
}
}
private String encodeNumber(double d) {
return "0ds"+HepRepUtil.encodeSpecial(Double.doubleToLongBits(d));
// return "0d0x"+Long.toHexString(Double.doubleToLongBits(d));
// return "0d"+Double.doubleToLongBits(d);
}
public void write(HepRepAttValue attValue) throws IOException {
String name = attValue.getName();
xml.setAttribute("name", name);
switch(attValue.getType()) {
default:
xml.setAttribute("value", attValue.getAsString());
break;
case HepRepAttValue.TYPE_STRING:
xml.setAttribute("value", attValue.getString());
break;
case HepRepAttValue.TYPE_LONG:
xml.setAttribute("value", attValue.getLong());
break;
case HepRepAttValue.TYPE_INT:
xml.setAttribute("value", attValue.getInteger());
break;
case HepRepAttValue.TYPE_DOUBLE:
if (bitEncoding) {
xml.setAttribute("value", encodeNumber(attValue.getDouble()));
} else {
xml.setAttribute("value", attValue.getDouble());
}
break;
case HepRepAttValue.TYPE_BOOLEAN:
xml.setAttribute("value", attValue.getBoolean());
break;
case HepRepAttValue.TYPE_COLOR:
xml.setAttribute("value", attValue.getColor());
break;
}
if (attValue.showLabel() != HepRepConstants.SHOW_NONE) {
xml.setAttribute("showlabel", attValue.showLabel());
}
xml.printTag(nameSpace, "attvalue");
}
public void write(HepRepAttDef attDef) throws IOException {
xml.setAttribute("name", attDef.getName());
xml.setAttribute("desc", attDef.getDescription());
xml.setAttribute("category", attDef.getCategory());
xml.setAttribute("extra", attDef.getExtra());
xml.printTag(nameSpace, "attdef");
}
}