// You can redistribute this software and/or modify it under the terms of // the Infozone Software License version 2 published by the Infozone Group // (http://www.infozone-group.org). // // Copyright (C) 2000 by The Infozone Group. All rights reserved. // // $Id: XUpdateQueryImpl.java,v 1.6 2000/12/07 21:12:54 andreas Exp $ package org.infozone.lexus; import org.infozone.lexus.commands.*; import org.infozone.tools.xml.queries.XUpdateQuery; import java.io.*; import java.lang.*; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.Parser; import org.xml.sax.helpers.ParserAdapter; import org.w3c.dom.*; import org.w3c.dom.traversal.NodeFilter; import org.jdom.Document; import org.jdom.input.DOMBuilder; import org.jdom.output.XMLOutputter; /* just for main method */ import org.apache.xerces.parsers.DOMParser; /** * <b>Note:</b> * If the DOM implementation you use does not support DOM-Level 2, some * features will not work properly. XUpdate uses the method * <code>getNamespaceURI</code> of the <code>org.w3c.dom.Node</code> * interface. This method returns <code>null</code> if the current Node * has no namespace. Your DOM implementation should implement this method * and alway return null, then XUpdate should work better. Nevertheless * you cannot use some features. Inserting elements and attributes just * works, if you omit the optional attribute called namespace. For more * detail about XUpdate look at the * <a href="http://www.xmldb.org/xupdate/xupdate-wd.html">XUpdate Working Draft</a>. */ public class XUpdateQueryImpl implements XUpdateQuery { /* The XUpdate namespace-uri. */ public final static String NAMESPACE_URI = "http://www.xmldb.org/xupdate"; /* Another representation of the query. It is faster than many String comparisons.*/ protected Vector _query[] = null; /* Representation of commands and instructions as IDs. */ protected CommandConstants _commands = null; /* */ protected NodeFilter _filter = null; /* */ protected Node _namespace = null; /** * */ public XUpdateQueryImpl( ) { _commands = new CommandConstants( ); } /** * */ public void setQString( String query ) throws SAXException { XUpdateQueryParser xuParser = new XUpdateQueryParser( _commands ); try { SAXParser parser = SAXParserFactory.newInstance( ).newSAXParser( ); ParserAdapter saxParser = new ParserAdapter( parser.getParser( ) ); saxParser.setContentHandler( xuParser ); saxParser.parse( new InputSource( new StringReader( query ) ) ); } catch (Exception e) { throw new SAXException( e.getMessage( ) ); } _query = xuParser.getCachedQuery( ); if (_query[0].size()==0) { throw new SAXException( "query contains no XUpdateOperation !" ); } } /** * */ public void setNamespace( Node node ) { _namespace = node; } /** * */ public void setNodeFilter( NodeFilter filter ) { _filter = filter; } /** * */ public void execute( Node contextNode ) throws Exception { CommandObject currentCommand = new DefaultCommand( contextNode ); Enumeration commands = _query[0].elements( ); Enumeration attributes = _query[1].elements( ); Enumeration characters = _query[2].elements( ); while (commands.hasMoreElements( )) { int id = ((Integer)commands.nextElement( )).intValue( ); if (id>0) { switch ( id ) { case _commands.ATTRIBUTES: currentCommand.submitAttributes( (Hashtable)attributes.nextElement( ) ); break; case _commands.CHARACTERS: currentCommand.submitCharacters( (String)characters.nextElement( ) ); break; default: if (!currentCommand.submitInstruction( id )) { _commands.setContextNode( contextNode ); currentCommand = _commands.commandForID( id ); if (currentCommand==null) { throw new Exception( "operation can not have any XUpdate-instruction !" ); } currentCommand.reset( ); } } } else { if (!currentCommand.executeInstruction( )) { contextNode = currentCommand.execute( ); currentCommand = new DefaultCommand( contextNode ); } } } } /** * Main-method. You can manually test your update operations. */ public static void main( String args[] ) throws Exception { if ( args.length==0 ) { System.err.println( "usage: java org.infozone.lexus.XUpdateQueryImpl update document" ); System.err.println( " update - filename of the file which contains XUpdate operations" ); System.err.println( " document - filename of the file which contains the content to update" ); System.exit( 0 ); } // parse the update file File file = new File( args[0] ); BufferedReader br = new BufferedReader( new FileReader ( file ) ); char[] characters = new char[ new Long(file.length()).intValue() ]; br.read( characters, 0, new Long( file.length() ).intValue() ); String queryStr = new String( characters ); // parse the document file Node myDocument = null; DOMParser parser = new DOMParser(); parser.setIncludeIgnorableWhitespace(false); parser.parse(args[1]); myDocument = parser.getDocument(); // update the document and print time used for the updates XUpdateQueryImpl xq = new XUpdateQueryImpl(); System.err.println("Starting updates..."); long timeStart = System.currentTimeMillis(); xq.setQString ( queryStr ); xq.execute(myDocument); DOMBuilder db = new DOMBuilder(); org.jdom.Document doc = db.build((org.w3c.dom.Document) myDocument); org.jdom.output.XMLOutputter xo = new org.jdom.output.XMLOutputter(" "); xo.output(doc,System.out); long timeEnd = System.currentTimeMillis(); System.err.println("Updates done in "+(timeEnd-timeStart)+" ms ..."); } }