XmlReader now uses the SAX API to read XML files into HopObjects. SAX is
generally faster than DOM because it doesn't report an intermediary DOM tree, but reports parsing events directly to the application. XmlDatabase now uses a separate, special purpose XmlReader called XmlDatabaseReader which parses only one-level HopObjects and generates NodeHandle objects for all references.
This commit is contained in:
parent
006aebe292
commit
f0d7311b33
3 changed files with 330 additions and 207 deletions
|
@ -12,7 +12,7 @@ import helma.objectmodel.dom.*;
|
||||||
* A simple XML-database
|
* A simple XML-database
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class XmlDatabase implements IDatabase {
|
public final class XmlDatabase implements IDatabase {
|
||||||
|
|
||||||
private String dbHome;
|
private String dbHome;
|
||||||
private File dbBaseDir;
|
private File dbBaseDir;
|
||||||
|
@ -61,8 +61,8 @@ public class XmlDatabase implements IDatabase {
|
||||||
if ( ! f.exists() )
|
if ( ! f.exists() )
|
||||||
throw new ObjectNotFoundException ("Object not found for key "+kstr+".");
|
throw new ObjectNotFoundException ("Object not found for key "+kstr+".");
|
||||||
try {
|
try {
|
||||||
XmlReader reader = new XmlReader (nmgr);
|
XmlDatabaseReader reader = new XmlDatabaseReader (nmgr);
|
||||||
Node node = (Node)reader.read (f, null);
|
Node node = reader.read (f);
|
||||||
return node;
|
return node;
|
||||||
} catch ( RuntimeException x ) {
|
} catch ( RuntimeException x ) {
|
||||||
nmgr.app.logEvent("error reading node from XmlDatbase: " + x.toString() );
|
nmgr.app.logEvent("error reading node from XmlDatbase: " + x.toString() );
|
||||||
|
|
180
src/helma/objectmodel/dom/XmlDatabaseReader.java
Normal file
180
src/helma/objectmodel/dom/XmlDatabaseReader.java
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
package helma.objectmodel.dom;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Date;
|
||||||
|
// import java.util.HashMap;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.xml.parsers.*;
|
||||||
|
|
||||||
|
import org.xml.sax.*;
|
||||||
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
|
import helma.objectmodel.INode;
|
||||||
|
import helma.objectmodel.db.DbKey;
|
||||||
|
import helma.objectmodel.db.ExternalizableVector;
|
||||||
|
import helma.objectmodel.db.Node;
|
||||||
|
import helma.objectmodel.db.NodeHandle;
|
||||||
|
import helma.objectmodel.db.NodeManager;
|
||||||
|
import helma.objectmodel.db.Property;
|
||||||
|
import helma.objectmodel.db.DbMapping;
|
||||||
|
|
||||||
|
public final class XmlDatabaseReader extends DefaultHandler implements XmlConstants {
|
||||||
|
|
||||||
|
private NodeManager nmgr = null;
|
||||||
|
private Node currentNode;
|
||||||
|
|
||||||
|
private String elementType = null;
|
||||||
|
private String elementName = null;
|
||||||
|
private StringBuffer charBuffer = null;
|
||||||
|
|
||||||
|
Hashtable propMap = null;
|
||||||
|
List subnodes = null;
|
||||||
|
|
||||||
|
static SAXParserFactory factory = SAXParserFactory.newInstance ();
|
||||||
|
|
||||||
|
|
||||||
|
public XmlDatabaseReader (NodeManager nmgr) {
|
||||||
|
this.nmgr = nmgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read an InputSource with xml-content.
|
||||||
|
*/
|
||||||
|
public Node read (File file)
|
||||||
|
throws ParserConfigurationException, SAXException, IOException {
|
||||||
|
if (nmgr==null)
|
||||||
|
throw new RuntimeException ("can't create a new Node without a NodeManager");
|
||||||
|
|
||||||
|
SAXParser parser = factory.newSAXParser ();
|
||||||
|
|
||||||
|
currentNode = null;
|
||||||
|
|
||||||
|
parser.parse (file, this);
|
||||||
|
return currentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
|
||||||
|
// System.err.println ("XML-READ: startElement "+namespaceURI+", "+localName+", "+qName+", "+atts.getValue("id"));
|
||||||
|
// discard the first element called xmlroot
|
||||||
|
if ("xmlroot".equals (qName) && currentNode == null)
|
||||||
|
return;
|
||||||
|
// if currentNode is null, this must be the hopobject node
|
||||||
|
if ("hopobject".equals (qName) && currentNode == null) {
|
||||||
|
String id = atts.getValue ("id");
|
||||||
|
String name = atts.getValue ("name");
|
||||||
|
String prototype = atts.getValue ("prototype");
|
||||||
|
if ( "".equals(prototype) )
|
||||||
|
prototype = "hopobject";
|
||||||
|
|
||||||
|
try {
|
||||||
|
long created = Long.parseLong (atts.getValue ("created"));
|
||||||
|
long lastmodified = Long.parseLong (atts.getValue ("lastModified"));
|
||||||
|
currentNode = new Node (name,id,prototype,nmgr.safe,created,lastmodified);
|
||||||
|
} catch ( NumberFormatException e ) {
|
||||||
|
currentNode = new Node (name,id,prototype,nmgr.safe);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// find out what kind of element this is by looking at
|
||||||
|
// the number and names of attributes.
|
||||||
|
String idref = atts.getValue ("idref");
|
||||||
|
if (idref != null) {
|
||||||
|
// a hopobject reference.
|
||||||
|
NodeHandle handle = makeNodeHandle (atts);
|
||||||
|
if ("hop:child".equals (qName)) {
|
||||||
|
if (subnodes == null) {
|
||||||
|
subnodes = new ExternalizableVector ();
|
||||||
|
currentNode.setSubnodes (subnodes);
|
||||||
|
}
|
||||||
|
subnodes.add (handle);
|
||||||
|
} else if ("hop:parent".equals (qName)) {
|
||||||
|
currentNode.setParentHandle (handle);
|
||||||
|
} else {
|
||||||
|
Property prop = new Property (qName, currentNode);
|
||||||
|
prop.setNodeHandle (handle);
|
||||||
|
if (propMap == null) {
|
||||||
|
propMap = new Hashtable ();
|
||||||
|
currentNode.setPropMap (propMap);
|
||||||
|
}
|
||||||
|
propMap.put (qName.toLowerCase(), prop);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// a primitive property
|
||||||
|
elementType = atts.getValue ("type");
|
||||||
|
if (elementType == null)
|
||||||
|
elementType = "string";
|
||||||
|
elementName = qName;
|
||||||
|
if (charBuffer == null)
|
||||||
|
charBuffer = new StringBuffer();
|
||||||
|
else
|
||||||
|
charBuffer.setLength (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void characters (char[] ch, int start, int length)
|
||||||
|
throws SAXException {
|
||||||
|
// append chars to char buffer
|
||||||
|
if (elementType != null)
|
||||||
|
charBuffer.append (ch, start, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endElement(String namespaceURI, String localName, String qName)
|
||||||
|
throws SAXException {
|
||||||
|
if (elementType != null) {
|
||||||
|
Property prop = new Property (elementName, currentNode);
|
||||||
|
String charValue = charBuffer.toString ();
|
||||||
|
charBuffer.setLength (0);
|
||||||
|
if ( "boolean".equals (elementType) ) {
|
||||||
|
if ( "true".equals(charValue) ) {
|
||||||
|
prop.setBooleanValue(true);
|
||||||
|
} else {
|
||||||
|
prop.setBooleanValue(false);
|
||||||
|
}
|
||||||
|
} else if ( "date".equals(elementType) ) {
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat ( DATEFORMAT );
|
||||||
|
try {
|
||||||
|
Date date = format.parse(charValue);
|
||||||
|
prop.setDateValue (date);
|
||||||
|
} catch ( ParseException e ) {
|
||||||
|
prop.setStringValue (charValue);
|
||||||
|
}
|
||||||
|
} else if ( "float".equals(elementType) ) {
|
||||||
|
prop.setFloatValue ((new Double(charValue)).doubleValue());
|
||||||
|
} else if ( "integer".equals(elementType) ) {
|
||||||
|
prop.setIntegerValue ((new Long(charValue)).longValue());
|
||||||
|
} else {
|
||||||
|
prop.setStringValue (charValue);
|
||||||
|
}
|
||||||
|
if (propMap == null) {
|
||||||
|
propMap = new Hashtable ();
|
||||||
|
currentNode.setPropMap (propMap);
|
||||||
|
}
|
||||||
|
propMap.put (elementName.toLowerCase(), prop);
|
||||||
|
elementName = null;
|
||||||
|
elementType = null;
|
||||||
|
charValue = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// create a node handle from a node reference DOM element
|
||||||
|
private NodeHandle makeNodeHandle (Attributes atts) {
|
||||||
|
String idref = atts.getValue ("idref");
|
||||||
|
String protoref = atts.getValue ("prototyperef");
|
||||||
|
DbMapping dbmap = null;
|
||||||
|
if (protoref != null)
|
||||||
|
dbmap = nmgr.getDbMapping(protoref);
|
||||||
|
return new NodeHandle (new DbKey (dbmap, idref));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package helma.objectmodel.dom;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
|
||||||
|
@ -10,37 +11,38 @@ import java.text.SimpleDateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Hashtable;
|
import java.util.Stack;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.w3c.dom.*;
|
import javax.xml.parsers.*;
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
|
import org.xml.sax.*;
|
||||||
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
import helma.objectmodel.INode;
|
import helma.objectmodel.INode;
|
||||||
import helma.objectmodel.db.DbKey;
|
|
||||||
import helma.objectmodel.db.ExternalizableVector;
|
|
||||||
import helma.objectmodel.db.Node;
|
|
||||||
import helma.objectmodel.db.NodeHandle;
|
|
||||||
import helma.objectmodel.db.NodeManager;
|
|
||||||
import helma.objectmodel.db.Property;
|
|
||||||
import helma.objectmodel.db.DbMapping;
|
|
||||||
|
|
||||||
public class XmlReader implements XmlConstants {
|
public final class XmlReader extends DefaultHandler implements XmlConstants {
|
||||||
|
|
||||||
|
private INode rootNode, currentNode;
|
||||||
|
private Stack nodeStack;
|
||||||
private HashMap convertedNodes;
|
private HashMap convertedNodes;
|
||||||
private NodeManager nmgr = null;
|
|
||||||
|
private String elementType = null;
|
||||||
|
private String elementName = null;
|
||||||
|
private StringBuffer charBuffer = null;
|
||||||
|
|
||||||
|
static SAXParserFactory factory = SAXParserFactory.newInstance ();
|
||||||
|
|
||||||
|
boolean parsingHopObject;
|
||||||
|
|
||||||
public XmlReader () {
|
public XmlReader () {
|
||||||
}
|
}
|
||||||
|
|
||||||
public XmlReader (NodeManager nmgr) {
|
|
||||||
this.nmgr = nmgr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* main entry to read an xml-file.
|
* main entry to read an xml-file.
|
||||||
*/
|
*/
|
||||||
public INode read (File file, INode helmaNode) throws RuntimeException {
|
public INode read (File file, INode helmaNode)
|
||||||
|
throws ParserConfigurationException, SAXException, IOException {
|
||||||
try {
|
try {
|
||||||
return read (new FileInputStream(file), helmaNode);
|
return read (new FileInputStream(file), helmaNode);
|
||||||
} catch (FileNotFoundException notfound) {
|
} catch (FileNotFoundException notfound) {
|
||||||
|
@ -52,218 +54,159 @@ public class XmlReader implements XmlConstants {
|
||||||
/**
|
/**
|
||||||
* read an InputStream with xml-content.
|
* read an InputStream with xml-content.
|
||||||
*/
|
*/
|
||||||
public INode read (InputStream in, INode helmaNode) throws RuntimeException {
|
public INode read (InputStream in, INode helmaNode)
|
||||||
|
throws ParserConfigurationException, SAXException, IOException {
|
||||||
return read (new InputSource (in), helmaNode);
|
return read (new InputSource (in), helmaNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read an character reader with xml-content.
|
* read an character reader with xml-content.
|
||||||
*/
|
*/
|
||||||
public INode read (Reader in, INode helmaNode) throws RuntimeException {
|
public INode read (Reader in, INode helmaNode)
|
||||||
|
throws ParserConfigurationException, SAXException, IOException {
|
||||||
return read (new InputSource (in), helmaNode);
|
return read (new InputSource (in), helmaNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read an InputSource with xml-content.
|
* read an InputSource with xml-content.
|
||||||
*/
|
*/
|
||||||
public INode read (InputSource in, INode helmaNode) throws RuntimeException {
|
public INode read (InputSource in, INode helmaNode)
|
||||||
if (helmaNode==null && nmgr==null)
|
throws ParserConfigurationException, SAXException, IOException {
|
||||||
throw new RuntimeException ("can't create a new Node without a NodeManager");
|
if (helmaNode==null)
|
||||||
Document document = XmlUtil.parse (in);
|
throw new RuntimeException ("Can't create a new Node without a root Node");
|
||||||
Element element = XmlUtil.getFirstElement(document);
|
|
||||||
if (element==null)
|
|
||||||
throw new RuntimeException ("corrupted xml-file");
|
|
||||||
|
|
||||||
if (helmaNode==null) {
|
SAXParser parser = factory.newSAXParser ();
|
||||||
return convert (element);
|
|
||||||
|
rootNode = helmaNode;
|
||||||
|
currentNode = null;
|
||||||
|
convertedNodes = new HashMap ();
|
||||||
|
nodeStack = new Stack ();
|
||||||
|
parsingHopObject = true;
|
||||||
|
|
||||||
|
parser.parse (in, this);
|
||||||
|
return rootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
|
||||||
|
throws SAXException {
|
||||||
|
// System.err.println ("XML-READ: startElement "+namespaceURI+", "+localName+", "+qName+", "+atts.getValue("id"));
|
||||||
|
// discard the first element called xmlroot
|
||||||
|
if ("xmlroot".equals (qName) && currentNode == null)
|
||||||
|
return;
|
||||||
|
// if currentNode is null, this must be the hopobject node
|
||||||
|
String id = atts.getValue ("id");
|
||||||
|
if (id != null) {
|
||||||
|
// check if there is a current node.
|
||||||
|
if (currentNode == null) {
|
||||||
|
// If currentNode is null, this is the root node we're parsing.
|
||||||
|
currentNode = rootNode;
|
||||||
|
} else if ("hop:child".equals (qName)) {
|
||||||
|
// it's an anonymous child node
|
||||||
|
nodeStack.push (currentNode);
|
||||||
|
currentNode = currentNode.createNode (null);
|
||||||
|
} else {
|
||||||
|
// it's a named node property
|
||||||
|
nodeStack.push (currentNode);
|
||||||
|
currentNode = currentNode.createNode (qName);
|
||||||
|
}
|
||||||
|
// set the prototype on the current node and
|
||||||
|
// add it to the map of parsed nodes.
|
||||||
|
String name = atts.getValue ("name");
|
||||||
|
String prototype = atts.getValue ("prototype");
|
||||||
|
if ( !"".equals(prototype) && !"hopobject".equals(prototype) )
|
||||||
|
currentNode.setPrototype (prototype);
|
||||||
|
String key = id + "-" + prototype;
|
||||||
|
convertedNodes.put( key, currentNode );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we have a currentNode to set properties on,
|
||||||
|
// otherwise throw exception.
|
||||||
|
if (currentNode == null)
|
||||||
|
throw new SAXException ("Invalid XML: No valid root HopObject found");
|
||||||
|
// check if we are inside a HopObject - otherwise throw an exception
|
||||||
|
if (!parsingHopObject)
|
||||||
|
throw new SAXException ("Invalid XML: Found nested non-HobObject elements");
|
||||||
|
|
||||||
|
// if we got so far, the element is not a hopobject. Set flag to prevent
|
||||||
|
// the hopobject stack to be popped when the element
|
||||||
|
// is closed.
|
||||||
|
parsingHopObject = false;
|
||||||
|
|
||||||
|
// Is it a reference to an already parsed node?
|
||||||
|
String idref = atts.getValue ("idref");
|
||||||
|
if (idref != null) {
|
||||||
|
// a reference to a node that should have been parsed
|
||||||
|
// and lying in our cache of parsed nodes.
|
||||||
|
String prototyperef = atts.getValue ("prototyperef");
|
||||||
|
String key = idref + "-" + prototyperef;
|
||||||
|
INode n = (INode) convertedNodes.get (key);
|
||||||
|
if (n != null) {
|
||||||
|
if ("hop:child".equals (qName)) {
|
||||||
|
// add an already parsed node as child to current node
|
||||||
|
currentNode.addNode (n);
|
||||||
|
} else {
|
||||||
|
// set an already parsed node as node property to current node
|
||||||
|
currentNode.setNode (qName, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
convertedNodes = new HashMap ();
|
// It's a primitive property. Remember the property name and type
|
||||||
INode convertedNode = convert (element, helmaNode);
|
// so we can properly parse/interpret the character data when we
|
||||||
convertedNodes = null;
|
// get it later on.
|
||||||
return convertedNode;
|
elementType = atts.getValue ("type");
|
||||||
|
if (elementType == null)
|
||||||
|
elementType = "string";
|
||||||
|
elementName = qName;
|
||||||
|
if (charBuffer == null)
|
||||||
|
charBuffer = new StringBuffer();
|
||||||
|
else
|
||||||
|
charBuffer.setLength (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void characters (char[] ch, int start, int length) throws SAXException {
|
||||||
* convert children of an Element to a given helmaNode
|
// System.err.println ("CHARACTERS: "+new String (ch, start, length));
|
||||||
*/
|
// append chars to char buffer
|
||||||
public INode convert (Element element, INode helmaNode) {
|
if (elementType != null)
|
||||||
String idref = element.getAttribute("idref");
|
charBuffer.append (ch, start, length);
|
||||||
String key = idref + "-" + element.getAttribute("prototyperef");
|
|
||||||
if( idref!=null && !idref.equals("") ) {
|
|
||||||
if( convertedNodes.containsKey(key) ) {
|
|
||||||
return (INode)convertedNodes.get(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
key = element.getAttribute("id") + "-" + element.getAttribute("prototype");
|
|
||||||
convertedNodes.put( key, helmaNode );
|
|
||||||
String prototype = element.getAttribute("prototype");
|
|
||||||
if( !prototype.equals("") && !prototype.equals("hopobject") ) {
|
|
||||||
helmaNode.setPrototype( prototype );
|
|
||||||
}
|
|
||||||
children(helmaNode, element);
|
|
||||||
return helmaNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void endElement(String namespaceURI, String localName, String qName)
|
||||||
// used by convert(Element,INode)
|
throws SAXException {
|
||||||
private INode children( INode helmaNode, Element element ) {
|
if (elementType != null) {
|
||||||
NodeList list = element.getChildNodes();
|
String charValue = charBuffer.toString ();
|
||||||
int len = list.getLength();
|
charBuffer.setLength (0);
|
||||||
Element childElement;
|
if ( "boolean".equals (elementType) ) {
|
||||||
for ( int i=0; i<len; i++ ) {
|
if ( "true".equals(charValue) ) {
|
||||||
try {
|
currentNode.setBoolean(elementName, true);
|
||||||
childElement = (Element)list.item(i);
|
|
||||||
} catch( ClassCastException e ) {
|
|
||||||
// ignore CDATA, comments etc
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
INode workNode = null;
|
|
||||||
|
|
||||||
if ( childElement.getTagName().equals("hop:child") ) {
|
|
||||||
convert (childElement, helmaNode.createNode(null));
|
|
||||||
} else if ( !"".equals(childElement.getAttribute("id")) ||
|
|
||||||
!"".equals(childElement.getAttribute("idref")) ) {
|
|
||||||
String childTagName = childElement.getTagName();
|
|
||||||
INode newNode = convert (childElement, helmaNode.createNode (childTagName));
|
|
||||||
helmaNode.setNode (childTagName, newNode);
|
|
||||||
} else {
|
|
||||||
String type = childElement.getAttribute("type");
|
|
||||||
String key = childElement.getTagName();
|
|
||||||
String content = XmlUtil.getTextContent(childElement);
|
|
||||||
if ( type.equals("boolean") ) {
|
|
||||||
if ( content.equals("true") ) {
|
|
||||||
helmaNode.setBoolean(key,true);
|
|
||||||
} else {
|
|
||||||
helmaNode.setBoolean(key,false);
|
|
||||||
}
|
|
||||||
} else if ( type.equals("date") ) {
|
|
||||||
SimpleDateFormat format = new SimpleDateFormat ( DATEFORMAT );
|
|
||||||
try {
|
|
||||||
Date date = format.parse(content);
|
|
||||||
helmaNode.setDate(key, date);
|
|
||||||
} catch ( ParseException e ) {
|
|
||||||
helmaNode.setString(key,content);
|
|
||||||
}
|
|
||||||
} else if ( type.equals("float") ) {
|
|
||||||
helmaNode.setFloat(key, (new Double(content)).doubleValue() );
|
|
||||||
} else if ( type.equals("integer") ) {
|
|
||||||
helmaNode.setInteger(key, (new Long(content)).longValue() );
|
|
||||||
} else {
|
} else {
|
||||||
helmaNode.setString(key,content);
|
currentNode.setBoolean(elementName, false);
|
||||||
}
|
}
|
||||||
}
|
} else if ( "date".equals(elementType) ) {
|
||||||
}
|
SimpleDateFormat format = new SimpleDateFormat ( DATEFORMAT );
|
||||||
return helmaNode;
|
try {
|
||||||
}
|
Date date = format.parse(charValue);
|
||||||
|
currentNode.setDate (elementName, date);
|
||||||
|
} catch ( ParseException e ) {
|
||||||
/**
|
currentNode.setString (elementName, charValue);
|
||||||
* This is a basic de-serialization method for XML-2-Node conversion.
|
}
|
||||||
* It reads a Node from a database-like file and should return a Node
|
} else if ( "float".equals(elementType) ) {
|
||||||
* that matches exactly the one dumped to that file before.
|
currentNode.setFloat (elementName, (new Double(charValue)).doubleValue());
|
||||||
* It only supports persistent-capable Nodes (from objectmodel.db-package).
|
} else if ( "integer".equals(elementType) ) {
|
||||||
*/
|
currentNode.setInteger (elementName, (new Long(charValue)).longValue());
|
||||||
public helma.objectmodel.db.Node convert (Element element) {
|
|
||||||
// FIXME: this method should use Element.getAttributeNS():
|
|
||||||
// FIXME: do we need the name value or is it retrieved through mappings anyway?
|
|
||||||
String name = element.getAttribute("name");
|
|
||||||
// String name = null;
|
|
||||||
String id = element.getAttribute("id");
|
|
||||||
String prototype = element.getAttribute("prototype");
|
|
||||||
if ( "".equals(prototype) )
|
|
||||||
prototype = "hopobject";
|
|
||||||
helma.objectmodel.db.Node helmaNode = null;
|
|
||||||
try {
|
|
||||||
long created = Long.parseLong (element.getAttribute ("created"));
|
|
||||||
long lastmodified = Long.parseLong (element.getAttribute ("lastModified"));
|
|
||||||
helmaNode = new helma.objectmodel.db.Node (name,id,prototype,nmgr.safe,created,lastmodified);
|
|
||||||
} catch ( NumberFormatException e ) {
|
|
||||||
helmaNode = new helma.objectmodel.db.Node (name,id,prototype,nmgr.safe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now loop through all child elements and retrieve properties/subnodes for this node.
|
|
||||||
NodeList list = element.getChildNodes();
|
|
||||||
int len = list.getLength();
|
|
||||||
Hashtable propMap = new Hashtable();
|
|
||||||
List subnodes = new ExternalizableVector();
|
|
||||||
|
|
||||||
for ( int i=0; i<len; i++ ) {
|
|
||||||
Element childElement;
|
|
||||||
try {
|
|
||||||
childElement = (Element)list.item(i);
|
|
||||||
} catch( ClassCastException e ) {
|
|
||||||
// ignore CDATA, comments etc
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( childElement.getTagName().equals("hop:child") ) {
|
|
||||||
// add a new NodeHandle, presume all IDs in this objectcache are unique,
|
|
||||||
// a prerequisite for a simple internal database.
|
|
||||||
subnodes.add (makeNodeHandle (childElement) );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( childElement.getTagName().equals("hop:parent") ) {
|
|
||||||
// add a NodeHandle to parent object
|
|
||||||
helmaNode.setParentHandle (makeNodeHandle (childElement) );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we come until here, childelement is a property value
|
|
||||||
// FIXME: Stefan, why are we checking for id, and not just for
|
|
||||||
// idref here? (hns)
|
|
||||||
Property prop = new Property (childElement.getTagName(), helmaNode);
|
|
||||||
if ( !"".equals(childElement.getAttribute("id")) ||
|
|
||||||
!"".equals(childElement.getAttribute("idref")) ) {
|
|
||||||
// we've got an object!
|
|
||||||
prop.setNodeHandle (makeNodeHandle(childElement));
|
|
||||||
} else {
|
} else {
|
||||||
String type = childElement.getAttribute("type");
|
currentNode.setString (elementName, charValue);
|
||||||
String content = XmlUtil.getTextContent(childElement);
|
|
||||||
if ( type.equals("boolean") ) {
|
|
||||||
if ( content.equals("true") ) {
|
|
||||||
prop.setBooleanValue(true);
|
|
||||||
} else {
|
|
||||||
prop.setBooleanValue(false);
|
|
||||||
}
|
|
||||||
} else if ( type.equals("date") ) {
|
|
||||||
SimpleDateFormat format = new SimpleDateFormat ( DATEFORMAT );
|
|
||||||
try {
|
|
||||||
Date date = format.parse(content);
|
|
||||||
prop.setDateValue (date);
|
|
||||||
} catch ( ParseException e ) {
|
|
||||||
prop.setStringValue (content);
|
|
||||||
}
|
|
||||||
} else if ( type.equals("float") ) {
|
|
||||||
prop.setFloatValue ((new Double(content)).doubleValue());
|
|
||||||
} else if ( type.equals("integer") ) {
|
|
||||||
prop.setIntegerValue ((new Long(content)).longValue());
|
|
||||||
} else {
|
|
||||||
prop.setStringValue (content);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
propMap.put (childElement.getTagName().toLowerCase(), prop);
|
elementName = null;
|
||||||
|
elementType = null;
|
||||||
|
charValue = null;
|
||||||
}
|
}
|
||||||
if ( propMap.size()>0 )
|
if (parsingHopObject && !nodeStack.isEmpty ())
|
||||||
helmaNode.setPropMap (propMap);
|
currentNode = (INode) nodeStack.pop ();
|
||||||
else
|
else
|
||||||
helmaNode.setPropMap (null);
|
parsingHopObject = true; // the next element end tag closes a hopobject again
|
||||||
if ( subnodes.size()>0 )
|
|
||||||
helmaNode.setSubnodes (subnodes);
|
|
||||||
else
|
|
||||||
helmaNode.setSubnodes (null);
|
|
||||||
return helmaNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a node handle from a node reference DOM element
|
|
||||||
private NodeHandle makeNodeHandle (Element element) {
|
|
||||||
String idref = element.getAttribute("idref");
|
|
||||||
String protoref = element.getAttribute("prototyperef");
|
|
||||||
DbMapping dbmap = null;
|
|
||||||
if (protoref != null)
|
|
||||||
dbmap = nmgr.getDbMapping(protoref);
|
|
||||||
return new NodeHandle (new DbKey (dbmap, idref));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue