001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.woody.binding;
018:
019: import org.apache.avalon.framework.service.ServiceManager;
020: import org.apache.cocoon.components.source.SourceUtil;
021: import org.apache.cocoon.woody.util.DomHelper;
022: import org.apache.excalibur.source.Source;
023: import org.apache.excalibur.source.SourceResolver;
024: import org.apache.excalibur.xml.xpath.XPathProcessor;
025: import org.w3c.dom.Document;
026: import org.w3c.dom.DocumentFragment;
027: import org.w3c.dom.Element;
028: import org.w3c.dom.Node;
029: import org.w3c.dom.NodeList;
030:
031: /**
032: * InsertNodeJXPathBindingBuilder provides a helper class for the Factory
033: * implemented in {@link JXPathBindingManager} that helps construct the
034: * actual {@link InsertNodeJXPathBinding} out of the configuration in the
035: * provided configElement which looks like:
036: * <pre><code>
037: * <wb:insert-node>
038: * <!-- in here comes a template that will be inserted in the target
039: * document -->
040: * </wb:insert-node>
041: * </code></pre>
042: *
043: * @version CVS $Id: InsertNodeJXPathBindingBuilder.java 433543 2006-08-22 06:22:54Z crossley $
044: */
045: public class InsertNodeJXPathBindingBuilder extends
046: JXPathBindingBuilderBase {
047:
048: /**
049: * Creates an instance of {@link InsertNodeJXPathBinding} configured
050: * with the nested template of the bindingElm.
051: */
052: public JXPathBindingBase buildBinding(Element bindingElm,
053: JXPathBindingManager.Assistant assistant)
054: throws BindingException {
055:
056: try {
057: CommonAttributes commonAtts = JXPathBindingBuilderBase
058: .getCommonAttributes(bindingElm);
059:
060: DocumentFragment domTemplate = null;
061:
062: String src = bindingElm.getAttribute("src");
063: if (!src.equals("")) {
064: ServiceManager manager = assistant.getServiceManager();
065: SourceResolver sourceResolver = (SourceResolver) manager
066: .lookup(SourceResolver.ROLE);
067: Source source = null;
068: try {
069: source = sourceResolver.resolveURI(src);
070: Document document = SourceUtil.toDOM(source);
071: Element element = document.getDocumentElement();
072:
073: String xpath = bindingElm.getAttribute("xpath");
074: if (!xpath.equals("")) {
075: XPathProcessor xpathProcessor = (XPathProcessor) manager
076: .lookup(XPathProcessor.ROLE);
077: try {
078: Node node = xpathProcessor
079: .selectSingleNode(document, xpath);
080: if (node == null)
081: throw new BindingException(
082: "XPath expression \""
083: + xpath
084: + "\" didn't return a result.");
085: if (!(node instanceof Element))
086: throw new BindingException(
087: "XPath expression \""
088: + xpath
089: + "\" did not return an element node.");
090: element = (Element) node;
091: } finally {
092: manager.release(xpathProcessor);
093: }
094: }
095: domTemplate = document.createDocumentFragment();
096: domTemplate.appendChild(element);
097: } finally {
098: if (source != null)
099: sourceResolver.release(source);
100: manager.release(sourceResolver);
101: }
102: } else {
103: domTemplate = bindingElm.getOwnerDocument()
104: .createDocumentFragment();
105: NodeList nested = bindingElm.getChildNodes();
106: int size = nested.getLength();
107: for (int i = 0; i < size; i++) {
108: domTemplate.appendChild(nested.item(i).cloneNode(
109: true));
110: }
111: }
112:
113: return new InsertNodeJXPathBinding(commonAtts, domTemplate);
114: } catch (Exception e) {
115: throw new BindingException(
116: "Error building the insert-node binding defined at "
117: + DomHelper.getLocation(bindingElm), e);
118: }
119: }
120: }
|