// Copyright FreeHEP, 2005. package hep.graphics.heprep.wbxml; import java.awt.Color; import java.io.*; import java.util.*; import org.kxml2.wap.Wbxml; import hep.graphics.heprep.xml.XMLTagWriter; /** * @author Mark Donszelmann * @version $Id: BHepRepWriter.java 8584 2006-08-10 23:06:37Z duns $ */ public class BHepRepWriter implements XMLTagWriter, Wbxml { /** * WBXML version number */ public static final int WBXML_VERSION = 0x03; /** * WBXML Constant for Unknown PID */ public static final int UNKNOWN_PID = 0x01; /** * WBXML Constant for UTF 8 */ public static final int UTF8 = 0x6a; /** * Content Mask */ public static final int CONTENT = 0x40; /** * Attribute Mask */ public static final int ATTRIBUTE = 0x80; /** * BHepRep String Define code */ public static final int STR_D = EXT_I_0; /** * BHepRep String Reference code */ public static final int STR_R = EXT_T_0; private static Map/*<String, String>*/ tags; private static Map/*<String, String>*/ attributes; private static Map/*<String, String>*/ values; static { // tags tags = new HashMap(); tags.put("heprep" , new Integer(0x05)); tags.put("attdef" , new Integer(0x06)); tags.put("attvalue" , new Integer(0x07)); tags.put("instance" , new Integer(0x08)); tags.put("treeid" , new Integer(0x09)); tags.put("action" , new Integer(0x0a)); tags.put("instancetree" , new Integer(0x0b)); tags.put("type" , new Integer(0x0c)); tags.put("typetree" , new Integer(0x0d)); tags.put("layer" , new Integer(0x0e)); tags.put("point" , new Integer(0x0f)); // attribute names attributes = new HashMap(); attributes.put("version" , new Integer(0x05)); attributes.put("xmlns" , new Integer(0x06)); attributes.put("xmlns:xsi" , new Integer(0x07)); attributes.put("xsi:schemaLocation" , new Integer(0x08)); attributes.put("valueString" , new Integer(0x10)); attributes.put("valueColor" , new Integer(0x11)); attributes.put("valueLong" , new Integer(0x12)); attributes.put("valueInt" , new Integer(0x13)); attributes.put("valueBoolean" , new Integer(0x14)); attributes.put("valueDouble" , new Integer(0x15)); attributes.put("name" , new Integer(0x20)); attributes.put("type" , new Integer(0x22)); attributes.put("showlabel" , new Integer(0x23)); attributes.put("desc" , new Integer(0x24)); attributes.put("category" , new Integer(0x25)); attributes.put("extra" , new Integer(0x26)); attributes.put("x" , new Integer(0x27)); attributes.put("y" , new Integer(0x28)); attributes.put("z" , new Integer(0x29)); attributes.put("qualifier" , new Integer(0x2a)); attributes.put("expression" , new Integer(0x2b)); attributes.put("typetreename" , new Integer(0x2c)); attributes.put("typetreeversion" , new Integer(0x2d)); attributes.put("order" , new Integer(0x2e)); // for PI attributes.put("eof" , new Integer(0x7f)); // attribute values values = new HashMap(); values.put("drawas" , new Integer(0x85)); values.put("drawasoptions" , new Integer(0x86)); values.put("visibility" , new Integer(0x87)); values.put("label" , new Integer(0x88)); values.put("fontname" , new Integer(0x89)); values.put("fontstyle" , new Integer(0x8a)); values.put("fontsize" , new Integer(0x8b)); values.put("fontcolor" , new Integer(0x8c)); values.put("fonthasframe" , new Integer(0x8d)); values.put("fontframecolor" , new Integer(0x8e)); values.put("fontframewidth" , new Integer(0x8f)); values.put("fonthasbanner" , new Integer(0x90)); values.put("fontbannercolor" , new Integer(0x91)); values.put("color" , new Integer(0x92)); values.put("framecolor" , new Integer(0x93)); values.put("layer" , new Integer(0x94)); values.put("markname" , new Integer(0x95)); values.put("marksize" , new Integer(0x96)); values.put("marksizemultiplier" , new Integer(0x97)); values.put("marktype" , new Integer(0x98)); values.put("hasframe" , new Integer(0x99)); values.put("framecolor" , new Integer(0x9a)); values.put("framewidth" , new Integer(0x9b)); values.put("linestyle" , new Integer(0x9c)); values.put("linewidth" , new Integer(0x9d)); values.put("linewidthmultiplier" , new Integer(0x9e)); values.put("linehasarrow" , new Integer(0x9f)); values.put("fillcolor" , new Integer(0xa0)); values.put("filltype" , new Integer(0xa1)); values.put("fill" , new Integer(0xa2)); values.put("radius" , new Integer(0xa3)); values.put("phi" , new Integer(0xa4)); values.put("theta" , new Integer(0xa5)); values.put("omega" , new Integer(0xa6)); values.put("radius1" , new Integer(0xa7)); values.put("radius2" , new Integer(0xa8)); values.put("radius3" , new Integer(0xa9)); values.put("curvature" , new Integer(0xaa)); values.put("flylength" , new Integer(0xab)); values.put("faces" , new Integer(0xac)); values.put("text" , new Integer(0xad)); values.put("hpos" , new Integer(0xae)); values.put("vpos" , new Integer(0xaf)); values.put("halign" , new Integer(0xb0)); values.put("valign" , new Integer(0xb1)); values.put("ispickable" , new Integer(0xb2)); values.put("showparentvalues" , new Integer(0xb3)); values.put("pickparent" , new Integer(0xb4)); // attvalue values values.put("false" , new Integer(0xd0)); values.put("true" , new Integer(0xd1)); values.put("point" , new Integer(0xd2)); values.put("line" , new Integer(0xd3)); values.put("helix" , new Integer(0xd4)); values.put("polygon" , new Integer(0xd5)); values.put("circle" , new Integer(0xd6)); values.put("curve" , new Integer(0xd7)); values.put("ellipse" , new Integer(0xd8)); values.put("ellipsoid" , new Integer(0xd9)); values.put("prism" , new Integer(0xda)); values.put("cylinder" , new Integer(0xdb)); values.put("ellipseprism" , new Integer(0xdc)); values.put("text" , new Integer(0xdd)); values.put("nonzero" , new Integer(0xde)); values.put("evenodd" , new Integer(0xdf)); values.put("circle" , new Integer(0xe0)); values.put("box" , new Integer(0xe1)); values.put("uptriangle" , new Integer(0xe2)); values.put("dntriangle" , new Integer(0xe3)); values.put("diamond" , new Integer(0xe4)); values.put("cross" , new Integer(0xe5)); values.put("star" , new Integer(0xe6)); values.put("plus" , new Integer(0xe7)); values.put("hline" , new Integer(0xe8)); values.put("vline" , new Integer(0xe9)); values.put("solid" , new Integer(0xea)); values.put("dotted" , new Integer(0xeb)); values.put("dashed" , new Integer(0xec)); values.put("dotdash" , new Integer(0xed)); values.put("none" , new Integer(0xee)); values.put("start" , new Integer(0xef)); values.put("end" , new Integer(0xf0)); values.put("both" , new Integer(0xf1)); values.put("serif" , new Integer(0xf2)); values.put("sansserif" , new Integer(0xf3)); values.put("monotype" , new Integer(0xf4)); values.put("symbol" , new Integer(0xf5)); values.put("plain" , new Integer(0xf6)); values.put("bold" , new Integer(0xf7)); values.put("italic" , new Integer(0xf8)); values.put("top" , new Integer(0xf9)); values.put("baseline" , new Integer(0xfa)); values.put("center" , new Integer(0xfb)); values.put("bottom" , new Integer(0xfc)); values.put("left" , new Integer(0xfd)); values.put("right" , new Integer(0xfe)); values.put("default" , new Integer(0xff)); } // outputstream variables private DataOutputStream os; private boolean singlePrecision; // document variables private Map/*<String, Integer>*/ stringValues; // tag variables Map/*<String, String>*/ stringAttributes; Map/*<String, Color>*/ colorAttributes; Map/*<String, Long>*/ longAttributes; Map/*<String, Integer>*/ intAttributes; Map/*<String, Boolean>*/ booleanAttributes; Map/*<String, Double>*/ doubleAttributes; // point array List/*<Double>*/ points; /** * Create a Binary HepRep Writer for given stream * @param os stream to write to */ public BHepRepWriter(OutputStream os) { this.os = (os instanceof DataOutputStream) ? (DataOutputStream)os : new DataOutputStream(os); singlePrecision = true; stringValues = new HashMap(); stringAttributes = new HashMap(); colorAttributes = new HashMap(); longAttributes = new HashMap(); intAttributes = new HashMap(); booleanAttributes = new HashMap(); doubleAttributes = new HashMap(); points = new ArrayList(); } public void openTag(String ns, String name) throws IOException { openTag(ns.equals("heprep") ? name : ns+":"+name); } public void printTag(String ns, String name) throws IOException { openTag(ns.equals("heprep") ? name : ns+":"+name); } public void setAttribute(String ns, String name, String value) { setAttribute(ns.equals("heprep") ? name : ns+":"+name, value); } public void setAttribute(String ns, String name, double value) { setAttribute(ns.equals("heprep") ? name : ns+":"+name, value); } public void close() throws IOException { } public void openDoc() throws IOException { openDoc("BinaryHepRep/1.0", "UTF-8", false); } public void openDoc(String version, String encoding, boolean standalone) throws IOException { stringValues.clear(); // header writeByte(WBXML_VERSION); writeMultiByteInt(UNKNOWN_PID); writeMultiByteInt(UTF8); version = "BinaryHepRep/1.0"; // string table writeMultiByteInt(version.length()+1); // BHepRep Header (as part of the string table) writeString(version); } public void closeDoc() throws IOException { writeByte(PI); writeByte((Integer)attributes.get("eof")); writeByte(END); } public void openTag(String name) throws IOException { writeTag(name, true); } public void closeTag() throws IOException { writePoints(); writeByte(END); } public void printTag(String name) throws IOException { writeTag(name, false); } private void writeTag(String tagName, boolean hasContent) throws IOException { String s = tagName.toLowerCase(); // find tag Integer tag = (Integer)tags.get(s); if (tag == null) { throw new IOException("Cannot find tag '" + s + "' in tags table."); } // write tag boolean isPoint = s.equals("point"); boolean hasAttributes = (stringAttributes.size() > 0) || (doubleAttributes.size() > (isPoint ? 3 : 0)); if (!hasAttributes && isPoint) { // store the point for the future points.add((Double)doubleAttributes.get("x")); points.add((Double)doubleAttributes.get("y")); points.add((Double)doubleAttributes.get("z")); return; } writePoints(); writeByte(tag.intValue() | ((hasContent || isPoint) ? CONTENT : 0x00) | (hasAttributes ? ATTRIBUTE : 0x00)); // write attributes if (hasAttributes) { // write string attributes for (Iterator i = stringAttributes.keySet().iterator(); i.hasNext(); ) { String name = (String)i.next(); String value = (String)stringAttributes.get(name); // write ATTRSTART writeByte((Integer)attributes.get(name)); String v = value.toLowerCase(); if (values.get(v) != null) { // write ATTRVALUE writeByte((Integer)values.get(v)); } else { if (stringValues.get(value) == null) { // define this new string writeStringDefine(value); int index = stringValues.size(); stringValues.put(value, new Integer(index)); } else { // write string ref writeByte(STR_R); writeMultiByteInt((Integer)stringValues.get(value)); } } } stringAttributes.clear(); // write color attributes for (Iterator i = colorAttributes.keySet().iterator(); i.hasNext(); ) { String name = (String)i.next(); Color value = (Color)colorAttributes.get(name); // write ATTRSTART writeByte((Integer)attributes.get(name)); // write OPAQUE writeByte(OPAQUE); writeMultiByteInt(value.getAlpha() < 0xFF ? 4 : 3); writeByte(value.getRed()); writeByte(value.getGreen()); writeByte(value.getBlue()); if (value.getAlpha() < 0xFF) writeByte(value.getAlpha()); } colorAttributes.clear(); // write long attributes for (Iterator i = longAttributes.keySet().iterator(); i.hasNext(); ) { String name = (String)i.next(); Long value = (Long)longAttributes.get(name); // write ATTRSTART writeByte((Integer)attributes.get(name)); // write OPAQUE writeByte(OPAQUE); writeMultiByteInt(8); writeLong(value); } longAttributes.clear(); // write int attributes for (Iterator i = intAttributes.keySet().iterator(); i.hasNext(); ) { String name = (String)i.next(); Integer value = (Integer)intAttributes.get(name); // write ATTRSTART writeByte((Integer)attributes.get(name)); // write OPAQUE writeByte(OPAQUE); writeMultiByteInt(4); writeInt(value); } intAttributes.clear(); // write boolean attributes for (Iterator i = booleanAttributes.keySet().iterator(); i.hasNext(); ) { String name = (String)i.next(); Boolean value = (Boolean)booleanAttributes.get(name); // write ATTRSTART writeByte((Integer)attributes.get(name)); // write ATTRVALUE writeByte(value.booleanValue() ? (Integer)values.get("true") : (Integer)values.get("false")); } booleanAttributes.clear(); // write double attributes for (Iterator i = doubleAttributes.keySet().iterator(); i.hasNext(); ) { String name = (String)i.next(); Double value = (Double)doubleAttributes.get(name); if (!isPoint && !name.equals("x") && !name.equals("y") && !name.equals("z")) { // write ATTRSTART writeByte((Integer)attributes.get(name)); // write OPAQUE writeByte(OPAQUE); writeMultiByteInt(singlePrecision ? 4 : 8); writeReal(value); } } doubleAttributes.clear(); // end of attributes writeByte(END); } if (s == "point") { writeByte(OPAQUE); writeMultiByteInt(singlePrecision ? 12 : 24); writeReal((Double)doubleAttributes.get("x")); writeReal((Double)doubleAttributes.get("y")); writeReal((Double)doubleAttributes.get("z")); } if (isPoint && !hasContent) { // end this tag writeByte(END); } } private void writePoints() throws IOException { if (points.size() <= 0) return; writeByte(((Integer)tags.get("point")).intValue() | CONTENT); writeByte(OPAQUE); writeMultiByteInt(points.size()*(singlePrecision ? 4 : 8)); for (Iterator i = points.iterator(); i.hasNext(); ) { writeReal((Double)i.next()); } writeByte(END); points.clear(); } public void setAttribute(String name, String value) { if (name.equals("value")) name += "String"; // make sure the attribute name is defined if (attributes.get(name) == null) { throw new RuntimeException("Cannot find attribute name '" + name + "' in attributes table."); } stringAttributes.put(name, value); } public void setAttribute(String name, Color value) { if (name.equals("value")) name += "Color"; // make sure the attribute name is defined if (attributes.get(name) == null) { throw new RuntimeException("Cannot find attribute name '" + name + "' in attributes table."); } colorAttributes.put(name, value); } public void setAttribute(String name, long value) { if (name.equals("value")) name += "Long"; // make sure the attribute name is defined if (attributes.get(name) == null) { throw new RuntimeException("Cannot find attribute name '" + name + "' in attributes table."); } longAttributes.put(name, new Long(value)); } public void setAttribute(String name, int value) { if (name.equals("value")) name += "Int"; // make sure the attribute name is defined if (attributes.get(name) == null) { throw new RuntimeException("Cannot find attribute name '" + name + "' in attributes table."); } intAttributes.put(name, new Integer(value)); } public void setAttribute(String name, boolean value) { if (name.equals("value")) name += "Boolean"; // make sure the attribute name is defined if (attributes.get(name) == null) { throw new RuntimeException("Cannot find attribute name '" + name + "' in attributes table."); } booleanAttributes.put(name, new Boolean(value)); } public void setAttribute(String name, double value) { if (name.equals("value")) name += "Double"; // make sure the attribute name is defined if (attributes.get(name) == null) { throw new RuntimeException("Cannot find attribute name '" + name + "' in attributes table."); } doubleAttributes.put(name, new Double(value)); } private void writeStringDefine(String s) throws IOException { writeByte(STR_D); writeString(s); } private void writeMultiByteInt(Number n) throws IOException { writeMultiByteInt(n.longValue()); } private void writeMultiByteInt(long ui) throws IOException { int buf[] = new int[5]; int idx = 0; do { buf[idx++] = (int) (ui & 0x7f); ui = ui >> 7; } while (ui != 0); while (idx > 1) { writeByte(buf[--idx] | 0x80); } writeByte(buf[0]); } private void writeReal(Double d) throws IOException { if (singlePrecision) { os.writeFloat(d.floatValue()); } else { os.writeDouble(d.doubleValue()); } } private void writeLong(Long i) throws IOException { os.writeLong(i.longValue()); } private void writeInt(Integer i) throws IOException { os.writeInt(i.intValue()); } private void writeByte(Integer b) throws IOException { writeByte(b.intValue()); } private void writeByte(int b) throws IOException { os.writeByte(b); } private void writeString(String s) throws IOException { os.writeBytes(s); os.writeByte(0); } }