haul 2002/12/16 02:05:51 Modified: src/java/org/apache/cocoon/components/modules/input XMLMetaModule.java Log: <action dev="CH" type="add"> XMLMetaModule returns DocumentWrapper instead of String. </action> Revision Changes Path 1.7 +117 -27 xml-cocoon2/src/java/org/apache/cocoon/components/modules/input/XMLMetaModule.java Index: XMLMetaModule.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/modules/input/XMLMetaModule.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- XMLMetaModule.java 5 Dec 2002 10:01:04 -0000 1.6 +++ XMLMetaModule.java 16 Dec 2002 10:05:51 -0000 1.7 @@ -50,13 +50,26 @@ */ package org.apache.cocoon.components.modules.input; -import org.apache.avalon.framework.configuration.Configuration; -import org.apache.avalon.framework.configuration.ConfigurationException; - import java.util.Iterator; import java.util.Map; +import java.util.HashMap; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.Vector; +import org.apache.avalon.framework.component.Component; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; + +import org.apache.cocoon.xml.dom.DOMUtil; +import org.apache.cocoon.xml.dom.DocumentWrapper; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Request; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + /** * Meta module that obtains values from other module and returns all * parameters as XML. @@ -97,8 +110,7 @@ * </my-root> * </pre> * - * <p>Should produce Objects that are XMLizable and Document one - * day. Currently, produces only Strings.</p> + * <p>Produces Objects of type {@link org.apache.cocoon.xml.dom.DocumentWrapper DocumentWrapper}</p> * * @author <a href="mailto:[EMAIL PROTECTED]">Christian Haul</a> * @version CVS $Id$ @@ -109,6 +121,9 @@ protected String ignore = null; protected String use = null; protected String strip = null; + protected Object config = null; + + protected static final String CACHE_OBJECT_NAME = "org.apache.cocoon.component.modules.input.XMLMetaModule"; final static Vector returnNames; static { @@ -126,6 +141,7 @@ this.ignore = this.inputConf.getAttribute("ignore",this.ignore); this.use = this.inputConf.getAttribute("use",this.use); this.strip = this.inputConf.getAttribute("strip",this.strip); + this.config = config; } @@ -145,6 +161,7 @@ return null; } + // obtain correct configuration objects // default vs dynamic Configuration inputConfig = null; @@ -164,41 +181,114 @@ } } + // see whether the Document is already stored as request + // attribute and return that + Request request = ObjectModelHelper.getRequest(objectModel); + Map cache = (Map) request.getAttribute(CACHE_OBJECT_NAME); + Object key = (modeConf != null ? modeConf : this.config); + Document doc = null; + + if (cache != null && cache.containsKey(key)) { + doc = (Document) cache.get(key); + if (getLogger().isDebugEnabled()) + getLogger().debug("using cached copy "+doc); + return doc; + } + if (getLogger().isDebugEnabled()) + getLogger().debug("no cached copy "+cache+" / "+key); + + + // get InputModule and all attribute names InputModule input = null; if (inputName != null) input = obtainModule(inputName); - StringBuffer sb = new StringBuffer(); - sb.append('<').append(rootName).append('>'); - Iterator names = getNames(objectModel, this.input, this.defaultInput, this.inputConf, input, inputName, inputConfig); + + // first, sort all attribute names that the DOM can be created in one go + // while doing so, remove unwanted attributes + SortedSet set = new TreeSet(); + String aName = null; while (names.hasNext()){ - String attribute = (String) names.next(); - if ((use == null || attribute.startsWith(use)) && - (ignore == null || !attribute.startsWith(ignore))) { - Object[] values = getValues(attribute, objectModel, - this.input, this.defaultInput, this.inputConf, - input, inputName, inputConfig); - - if (strip != null && attribute.startsWith(strip)) - attribute = attribute.substring(strip.length()); - sb.append("<item name=\"").append(attribute).append("\">"); - if (values.length == 1) { - sb.append(values[0]); - } else { - for (int i=0;i<values.length;i++){ - sb.append("<value>").append(values[i]).append("</value>"); + aName = (String) names.next(); + if ((use == null || aName.startsWith(use)) && + (ignore == null || !aName.startsWith(ignore))) { + set.add(aName); + } + } + + try { + names = set.iterator(); + + // create new document and append root node + doc = DOMUtil.createDocument(); + Element elem = doc.createElement(rootName); + doc.appendChild(elem); + + while (names.hasNext()){ + aName = (String) names.next(); + // obtain values from input module + Object[] value = getValues(aName, objectModel, + this.input, this.defaultInput, this.inputConf, + input, inputName, inputConfig); + + // strip unwanted prefix from attribute name if present + if (strip != null && aName.startsWith(strip)) + aName = aName.substring(strip.length()); + + if (value.length > 0) { + // add new node from xpath + // (since the names are in a set, the node cannot exist already) + Node node = DOMUtil.selectSingleNode(doc.getDocumentElement(), aName); + node.appendChild( node.getOwnerDocument().createTextNode(value[0].toString())); + + if (value.length > 1) { + // if more than one value was obtained, append + // further nodes (same name) + + // isolate node name, selection expressions + // "[...]" may not be part of it + int endPos = aName.length() - (aName.endsWith("/") ? 1 : 0); + int startPos = aName.lastIndexOf("/", endPos) +1; + String nodeName = aName.substring(startPos, endPos); + if (nodeName.indexOf("[") != -1) { + endPos = nodeName.lastIndexOf("]"); + startPos = nodeName.indexOf("[") +1; + nodeName = nodeName.substring(startPos, endPos); + } + + // append more nodes + Node parent = node.getParentNode(); + for (int i = 1; i < value.length; i++) { + Node newNode = parent.getOwnerDocument().createElementNS(null, nodeName); + parent.appendChild( newNode ); + newNode.appendChild( newNode.getOwnerDocument().createTextNode(value[i].toString())); + } } } - sb.append("</item>"); } + } catch (Exception e) { + throw new ConfigurationException(e.getMessage()); } + if (input != null) releaseModule(input); - sb.append('<').append('/').append(rootName).append('>'); + // create a wrapped instance that is XMLizable + doc = new DocumentWrapper(doc); - return sb.toString(); + // store Document as request attribute + if (cache == null) + cache = new HashMap(); + if (getLogger().isDebugEnabled()) + getLogger().debug("no cached copy "+cache+" / "+key); + cache.put(key, doc); + request.setAttribute(CACHE_OBJECT_NAME,cache); + + + if (getLogger().isDebugEnabled()) + getLogger().debug("returning "+doc.toString()); + return doc; }
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]