// Copyright 2000-2005, FreeHEP.
package hep.graphics.heprep.xml;
import java.io.*;
import java.net.*;
import java.util.*;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.freehep.util.VersionComparator;
import hep.graphics.heprep.*;
import hep.graphics.heprep.ref.*;
import hep.graphics.heprep.util.*;
/**
*
* @author M.Donszelmann
*
* @version $Id: XMLHepRepHandler.java 8584 2006-08-10 23:06:37Z duns $
*/
public class XMLHepRepHandler extends DefaultHandler {
/**
* Minimum expected HepRep version number.
*/
public static final String expectedVersion = "2.0";
private boolean isHepRep2 = false;
private HepRepFactory factory;
private HepRep heprep;
private int level = 0;
private HepRepTypes types;
private HepRepTypeTree currentTypeTree = null;
private HepRepTreeID currentTypeTreeRef = null;
private HepRepInstanceTree instanceTree = null;
private HepRepPoint currentPoint = null;
private Stack/*<HepRepInstance>*/ instanceStack = new Stack();
private HepRepInstance currentInstance = null;
private Stack/*<HepRepType>*/ typeStack = new Stack();
private HepRepType currentType = null;
XMLHepRepHandler(HepRep heprep) {
this.heprep = heprep;
factory = new XMLHepRepFactory();
}
public void startDocument() throws SAXException {
types = new HepRepTypes();
currentTypeTree = null;
currentTypeTreeRef = null;
instanceTree = null;
currentPoint = null;
instanceStack = new Stack();
currentInstance = null;
typeStack = new Stack();
currentType = null;
level = 0;
}
public void startElement(String namespace, String tag, String qName, Attributes atts) throws SAXException {
level++;
tag = tag.intern();
// System.out.println(namespace+", "+tag+", "+qName);
if (tag == "point") {
double x = HepRepUtil.decodeNumber(atts.getValue("x"));
double y = HepRepUtil.decodeNumber(atts.getValue("y"));
double z = HepRepUtil.decodeNumber(atts.getValue("z"));
currentPoint = factory.createHepRepPoint(currentInstance, x, y, z);
} else if (tag == "instancetree") {
String name = atts.getValue("name");
String version = atts.getValue("version");
currentTypeTreeRef = factory.createHepRepTreeID(atts.getValue("typetreename"), atts.getValue("typetreeversion"));
instanceTree = factory.createHepRepInstanceTree(name, version, currentTypeTreeRef);
heprep.addInstanceTree(instanceTree);
// System.out.println("Created Instance Tree: "+name+", "+version);
} else if (tag == "treeid") {
String name = atts.getValue("name");
String version = atts.getValue("version");
String qualifier = atts.getValue("qualifier");
instanceTree.addInstanceTree(factory.createHepRepTreeID(name, version, qualifier));
} else if (tag == "action") {
String name = atts.getValue("name");
String expression = atts.getValue("expression");
// FIXME: JHEPREP-3
factory.createHepRepAction(name, expression);
} else if (tag == "layer") {
String order = atts.getValue("order");
StringTokenizer st = new StringTokenizer(order,",");
while (st.hasMoreTokens()) {
heprep.addLayer(st.nextToken().trim());
}
} else if (tag == "instance") {
String typeName = atts.getValue("type");
if (typeName == null) {
throw new SAXException("[XMLHepRepReader] Instance cannot exist without referring to a type.");
}
HepRepType type = types.getType(currentTypeTreeRef, typeName, currentInstance);
if (type == null) {
throw new SAXException("[XMLHepRepReader] Cannot find type: '"+typeName+"' "+
"in tree: '"+types.getID(currentTypeTreeRef)+"'");
}
instanceStack.push(currentInstance);
if (currentInstance != null) {
currentInstance = factory.createHepRepInstance(currentInstance, type);
} else {
currentInstance = factory.createHepRepInstance(instanceTree, type);
}
} else if (tag == "typetree") {
isHepRep2 = true;
String name = atts.getValue("name");
String version = atts.getValue("version");
HepRepTreeID id = factory.createHepRepTreeID(name, version);
currentTypeTree = factory.createHepRepTypeTree(id);
heprep.addTypeTree(currentTypeTree);
types.put(id, currentTypeTree);
// System.out.println("Created Type Tree: "+name+", "+version);
} else if (tag == "type") {
// if we did not get a typetree, no heprep2.
if (!isHepRep2) {
throw new SAXException(
new HepRepVersionException(getClass()+": Could not deduce heprep version, expected version '"+expectedVersion+"'.")
);
}
String name = atts.getValue("name");
typeStack.push(currentType);
if (currentType != null) {
currentType = factory.createHepRepType(currentType, name);
} else {
currentType = factory.createHepRepType(currentTypeTree, name);
}
types.put(currentTypeTree, name, currentType);
} else if (tag == "heprep") {
// heprep already created, check version
String version = atts.getValue("version");
if (version != null) {
isHepRep2 = true;
VersionComparator comparator = new VersionComparator();
if (comparator.versionNumberCompare(version,expectedVersion) < 0) {
throw new SAXException(
new HepRepVersionException(getClass()+": Found version '"+version+"' while expected version '"+expectedVersion+"'.")
);
}
} else {
// check for hepreps with no versions attribute
String xmlns = atts.getValue("xmlns");
if ((xmlns != null) && xmlns.startsWith("http://java.freehep.org/schemas/heprep/2")) {
isHepRep2 = true;
}
}
} else if (tag == "attvalue") {
String name = atts.getValue("name");
String value = atts.getValue("value");
String type = DefaultHepRepAttValue.guessType(name, value, atts.getValue("type"));
// Here for backward compatibility with G4.5.0 we keep the cased showLabel around
String showLabelString = atts.getValue("showlabel");
if (showLabelString == null) showLabelString = atts.getValue("showLabel");
int showLabel = DefaultHepRepAttValue.toShowLabel(showLabelString);
HepRepAttValue attValue = new DefaultHepRepAttValue(name, value, type, showLabel);
if (currentPoint != null) {
currentPoint.addAttValue(attValue);
} else if (currentInstance != null) {
currentInstance.addAttValue(attValue);
} else {
if (currentType == null) {
throw new SAXException("[XMLHepRepReader] Cannot use 'attvalue' outside 'type' tag.");
}
currentType.addAttValue(attValue);
}
} else if (tag == "attdef") {
if (!isHepRep2) {
throw new SAXException(
new HepRepVersionException(getClass()+": Found a probable HepRep1 version while expected version '"+expectedVersion+"'.")
);
}
if (currentType == null) {
throw new SAXException("[XMLHepRepReader] Cannot use 'attdef' outside 'type' tag.");
}
String name = atts.getValue("name");
String desc = atts.getValue("desc");
String category = atts.getValue("category");
String extra = atts.getValue("extra");
currentType.addAttDef(name, desc, category, extra);
} else {
throw new SAXException("[XMLHepRepReader] Unknown tag: <"+
((namespace != null) ? namespace+":" : "")+
tag+"> qualifiedName: '"+qName+"'");
}
if (Thread.interrupted()) throw new SAXException(new InterruptedException());
}
public void endElement(String namespace, String tag, String qName) throws SAXException {
try {
// System.out.println("/"+namespace+", "+tag+", "+qName);
if (tag.lastIndexOf(':') >= 0) tag = tag.substring(tag.lastIndexOf(':')+1);
tag = tag.intern();
if (tag == "point") {
currentPoint = null;
} else if (tag == "instancetree") {
instanceTree = null;
currentTypeTreeRef = null;
} else if (tag == "treeid") {
} else if (tag == "layer") {
} else if (tag == "instance") {
if (currentInstance instanceof DefaultHepRepInstance) ((DefaultHepRepInstance)currentInstance).optimize();
currentInstance = (HepRepInstance)instanceStack.pop();
} else if (tag == "typetree") {
currentTypeTree = null;
} else if (tag == "type") {
currentType = (HepRepType)typeStack.pop();
} else if (tag == "heprep") {
// ignored, toplevel already stored
} else if (tag == "attvalue") {
} else if (tag == "attdef") {
} else {
throw new SAXException("[XMLHepRepReader] Unknown tag: "+tag);
}
} catch (Exception e) {
throw new SAXException(e);
}
if (Thread.interrupted()) throw new SAXException(new InterruptedException());
// make sure this is at the end, and that heprep is set!
level--;
// if (level == 0) throw new DocumentFinishedException();
}
public InputSource resolveEntity(String publicId, String systemId) {
if (publicId != null) {
return null;
}
// try to open systemId directly
InputStream is = null;
URL url = null;
try {
url = new URL(systemId);
is = url.openStream();
} catch (MalformedURLException mfue) {
return null;
} catch (IOException ioe) {
// try to resolve systemId relative to object or class
String file = url.getFile().substring(url.getFile().lastIndexOf('/')+1);
is = getClass().getResourceAsStream(file);
}
return new InputSource(is);
}
}