/* * Copyright The National Archives 2005-2006. All rights reserved. * See Licence.txt for full licence details. * * Developed by: * Tessella Support Services plc * 3 Vineyard Chambers * Abingdon, OX14 3PX * United Kingdom * http://www.tessella.com * * Tessella/NPD/4305 * PRONOM 4 * * SAXModelBuilder.java * * $Id: SAXModelBuilder.java,v 1.7 2006/03/13 15:15:29 linb Exp $ * * $Log: SAXModelBuilder.java,v $ * Revision 1.7 2006/03/13 15:15:29 linb * Changed copyright holder from Crown Copyright to The National Archives. * Added reference to licence.txt * Changed dates to 2005-2006 * * Revision 1.6 2006/02/09 15:31:23 linb * Updates to javadoc and code following the code review * * Revision 1.5 2006/01/31 16:47:30 linb * Added log messages that were missing due to the log keyword being added too late * * Revision 1.4 2006/01/31 16:21:20 linb * Removed the dollars from the log lines generated by the previous message, so as not to cause problems with subsequent commits * * Revision 1.3 2006/01/31 16:19:07 linb * Added Log and Id tags to these files * * Revision 1.2 2006/01/31 16:11:37 linb * Add support for XML namespaces to: * 1) The reading of the config file, spec file and file-list file * 2) The writing of the config file and file-list file * - The namespaces still need to be set to their proper URIs (currently set to example.com...) * - Can still read in files without namespaces* * */ package uk.gov.nationalarchives.droid.xmlReader; import java.lang.reflect.Method; import java.util.Stack; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import uk.gov.nationalarchives.droid.MessageDisplay; /** * reads and parses data from an XML file * * @version 4.0.0 */ public class SAXModelBuilder extends DefaultHandler { Stack stack = new Stack(); SimpleElement element; String myObjectPackage = "uk.gov.nationalarchives.droid.signatureFile"; StringBuffer textBuffer; String namespace = ""; boolean useNamespace = false; boolean allowGlobalNamespace = true; public void setObjectPackage(String theObjectPackage) { myObjectPackage = theObjectPackage; } /** * Set up XML namespace handling. * <p/> * <p>If <code>allowGlobalNamespace</code> is set to <code>true</code>, elements * that do not have a namespace specified are parsed; attributes that don't * have a namespace specified are parsed. If it is <code>false</code>, for * it to be parsed, an element must have a namespace specifed (by default or * with a prefix); an attribute must have a namespace specified with a prefix. * * @param namespace the XML namespace to use * @param allowGlobalNamespace allow the parser to recognise elements/ attributes that aren't in any namespace */ public void setupNamespace(String namespace, boolean allowGlobalNamespace) { if (namespace == null) { throw new IllegalArgumentException("Namespace cannot be null"); } this.namespace = namespace; this.useNamespace = true; this.allowGlobalNamespace = allowGlobalNamespace; } /** * Handle names in a namespace-aware fashion. * <p/> * <p>If an element/ attribute is in a namespace, qname is not required to be set. * We must, therefore, use the localname if the namespace is set, and qname if it isn't. * * @param namespace the namespace uri * @param localname the local part of the name * @param qname a qualified name * @return the local part or the qualified name, as appropriate */ private String handleNameNS(String namespace, String localname, String qname) { if (this.useNamespace && this.namespace.equals(namespace)) { // Name is in the specified namespace return localname; } else if (this.allowGlobalNamespace && "".equals(namespace)) { // Name is in the global namespace return qname; } else { // Ignore return null; } } public void startElement(String namespace, String localname, String qname, Attributes atts) throws SAXException { String elementName = handleNameNS(namespace, localname, qname); if (elementName == null) { return; } SimpleElement element = null; try { element = (SimpleElement) Class.forName(myObjectPackage + "." + elementName).newInstance(); } catch (Exception e) { } if (element == null) { element = new SimpleElement(); } for (int i = 0; i < atts.getLength(); i++) { String attributeName = handleNameNS(atts.getURI(i), atts.getLocalName(i), atts.getQName(i)); if (attributeName == null) { continue; } element.setAttributeValue(attributeName, atts.getValue(i)); } stack.push(element); } public void endElement(String namespace, String localname, String qname) throws SAXException { String elementName = handleNameNS(namespace, localname, qname); if (elementName == null) { return; } element = (SimpleElement) stack.pop(); element.completeElementContent(); if (!stack.empty()) { try { setProperty(elementName, stack.peek(), element); } catch (SAXException e) { throw new SAXException(e); } } } public void characters(char[] ch, int start, int len) { if (!stack.empty()) { // Ignore character data if we don't have an element to put it in. String text = new String(ch, start, len); ((SimpleElement) (stack.peek())).setText(text); } } void setProperty(String name, Object target, Object value) throws SAXException { Method method = null; try { method = target.getClass().getMethod( "add" + name, new Class[]{value.getClass()}); } catch (NoSuchMethodException e) { } if (method == null) { try { method = target.getClass().getMethod( "set" + name, new Class[]{value.getClass()}); } catch (NoSuchMethodException e) { } } if (method == null) { try { value = ((SimpleElement) value).getText(); method = target.getClass().getMethod( "add" + name, new Class[]{String.class}); } catch (NoSuchMethodException e) { } } try { if (method == null) { method = target.getClass().getMethod( "set" + name, new Class[]{String.class}); } method.invoke(target, value); } catch (NoSuchMethodException e) { MessageDisplay.unknownElementWarning(name, ((SimpleElement) target).getElementName()); } catch (Exception e) { throw new SAXException(e); } } public SimpleElement getModel() { return element; } }