blob: 5e979f704f778923e5c15d34bf7a3afefcd242e7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.util.jxpath;
import org.apache.commons.jxpath.AbstractFactory;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.Pointer;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* A <a href="http://jakarta.apache.org/commons/jxpath">JXPath</a> <code>AbstractFactory</code>
* that creates DOM elements.
*
* @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
* @version $Id$
*/
public class DOMFactory extends AbstractFactory {
/**
* Return <b>false</b> if this factory cannot create the requested object.
*/
public boolean createObject(
JXPathContext context,
Pointer pointer,
Object parent,
String name,
int index)
{
//FIXME: JXPath automatically creates attributes if the element already exists,
//but does not call this method if the element does not exit
addDOMElement((Node) parent, index, name);
return true;
}
private void addDOMElement(Node parent, int index, String tag) {
int pos = tag.indexOf(':');
String prefix = null;
if (pos != -1) {
prefix = tag.substring(0, pos);
}
String uri = null;
Node child = parent.getFirstChild();
int count = 0;
while (child != null) {
if (child.getNodeName().equals(tag)) {
count++;
}
child = child.getNextSibling();
}
Document doc = parent.getOwnerDocument();
if (doc != null) {
uri = getNamespaceURI((Element)parent, prefix);
} else {
if (parent instanceof Document) {
doc = (Document)parent;
if (prefix != null) {
throw new RuntimeException("Cannot map non-null prefix " +
"when creating a document element");
}
} else { // Shouldn't happen (must be a DocumentType object)
throw new RuntimeException("Node of class " +
parent.getClass().getName() + " has null owner document " +
"but is not a Document");
}
}
// Keep inserting new elements until we have index + 1 of them
while (count <= index) {
Node newElement = doc.createElementNS(uri, tag);
parent.appendChild(newElement);
count++;
}
}
public String getNamespaceURI(Element element, String prefix) {
Node tmp = element;
String nsAttr = prefix == null ? "xmlns" : "xmlns:" + prefix;
while (tmp != null && tmp.getNodeType() == Node.ELEMENT_NODE) {
element = (Element)tmp;
// First test element prefixes
if (prefix == null) {
if (element.getPrefix() == null) {
return element.getNamespaceURI();
}
} else if(prefix.equals(element.getPrefix())) {
return element.getNamespaceURI();
}
// Note: stupid DOM api returns "" when an attribute doesn't exist, so we use the Attr node.
Attr nsAttrNode = ((Element)tmp).getAttributeNode(nsAttr);
if (nsAttrNode != null) {
return nsAttrNode.getValue();
}
tmp = tmp.getParentNode();
}
return null;
}
public boolean declareVariable(JXPathContext context, String name) {
return false;
}
}