| /* |
| * 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.struts2.views.xslt; |
| |
| import org.apache.logging.log4j.LogManager; |
| import org.apache.logging.log4j.Logger; |
| import org.apache.struts2.StrutsException; |
| import org.w3c.dom.*; |
| |
| import java.util.ArrayList; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| /** |
| * AbstractAdapterNode is the base for childAdapters that expose a read-only view |
| * of a Java object as a DOM Node. This class implements the core parent-child |
| * and sibling node traversal functionality shared by all adapter type nodes |
| * and used in proxy node support. |
| * |
| * @see AbstractAdapterElement |
| */ |
| public abstract class AbstractAdapterNode implements AdapterNode { |
| |
| private static final NamedNodeMap EMPTY_NAMEDNODEMAP = |
| new NamedNodeMap() { |
| public int getLength() { |
| return 0; |
| } |
| |
| public Node item(int index) { |
| return null; |
| } |
| |
| public Node getNamedItem(String name) { |
| return null; |
| } |
| |
| public Node removeNamedItem(String name) throws DOMException { |
| return null; |
| } |
| |
| public Node setNamedItem(Node arg) throws DOMException { |
| return null; |
| } |
| |
| public Node setNamedItemNS(Node arg) throws DOMException { |
| return null; |
| } |
| |
| public Node getNamedItemNS(String namespaceURI, String localName) { |
| return null; |
| } |
| |
| public Node removeNamedItemNS(String namespaceURI, String localName) throws DOMException { |
| return null; |
| } |
| }; |
| |
| private List<Node> childAdapters; |
| private Logger log = LogManager.getLogger(this.getClass()); |
| |
| // The domain object that we are adapting |
| private Object propertyValue; |
| private String propertyName; |
| private AdapterNode parent; |
| private AdapterFactory adapterFactory; |
| |
| |
| public AbstractAdapterNode() { |
| if (LogManager.getLogger(getClass()).isDebugEnabled()) { |
| LogManager.getLogger(getClass()).debug("Creating " + this); |
| } |
| } |
| |
| /** |
| * |
| * @param adapterFactory the adapter factory |
| * @param parent the parent adapter node |
| * @param propertyName the property name |
| * @param value value |
| */ |
| protected void setContext(AdapterFactory adapterFactory, AdapterNode parent, String propertyName, Object value) { |
| setAdapterFactory(adapterFactory); |
| setParent(parent); |
| setPropertyName(propertyName); |
| setPropertyValue(value); |
| } |
| |
| /** |
| * subclasses override to produce their children |
| * |
| * @return List of child adapters. |
| */ |
| protected List<Node> buildChildAdapters() { |
| return new ArrayList<Node>(); |
| } |
| |
| /** |
| * Lazily initialize child childAdapters |
| * |
| * @return node list |
| */ |
| protected List<Node> getChildAdapters() { |
| if (childAdapters == null) { |
| childAdapters = buildChildAdapters(); |
| } |
| return childAdapters; |
| } |
| |
| public Node getChildBeforeOrAfter(Node child, boolean before) { |
| log.debug("getChildBeforeOrAfter: "); |
| List adapters = getChildAdapters(); |
| if (log.isDebugEnabled()) { |
| log.debug("childAdapters = {}", adapters); |
| log.debug("child = {}", child); |
| } |
| int index = adapters.indexOf(child); |
| if (index < 0) |
| throw new StrutsException(child + " is no child of " + this); |
| int siblingIndex = before ? index - 1 : index + 1; |
| return ((0 < siblingIndex) && (siblingIndex < adapters.size())) ? |
| ((Node) adapters.get(siblingIndex)) : null; |
| } |
| |
| public Node getChildAfter(Node child) { |
| log.trace("getChildAfter"); |
| return getChildBeforeOrAfter(child, false/*after*/); |
| } |
| |
| public Node getChildBefore(Node child) { |
| log.trace("getChildBefore"); |
| return getChildBeforeOrAfter(child, true/*after*/); |
| } |
| |
| public NodeList getElementsByTagName(String tagName) { |
| if (tagName.equals("*")) { |
| return getChildNodes(); |
| } else { |
| LinkedList<Node> filteredChildren = new LinkedList<>(); |
| |
| for (Node adapterNode : getChildAdapters()) { |
| if (adapterNode.getNodeName().equals(tagName)) { |
| filteredChildren.add(adapterNode); |
| } |
| } |
| |
| return new SimpleNodeList(filteredChildren); |
| } |
| } |
| |
| public NodeList getElementsByTagNameNS(String string, String string1) { |
| // TODO: |
| return null; |
| } |
| |
| // Begin Node methods |
| |
| public NamedNodeMap getAttributes() { |
| return EMPTY_NAMEDNODEMAP; |
| } |
| |
| public NodeList getChildNodes() { |
| NodeList nl = new SimpleNodeList(getChildAdapters()); |
| log.debug("getChildNodes for tag: {} num children: {}", getNodeName(), nl.getLength()); |
| return nl; |
| } |
| |
| public Node getFirstChild() { |
| return (getChildNodes().getLength() > 0) ? getChildNodes().item(0) : null; |
| } |
| |
| public Node getLastChild() { |
| return (getChildNodes().getLength() > 0) ? getChildNodes().item(getChildNodes().getLength() - 1) : null; |
| } |
| |
| |
| public String getLocalName() { |
| return null; |
| } |
| |
| public String getNamespaceURI() { |
| return null; |
| } |
| |
| public void setNodeValue(String string) throws DOMException { |
| throw operationNotSupported(); |
| } |
| |
| public String getNodeValue() throws DOMException { |
| throw operationNotSupported(); |
| } |
| |
| public Document getOwnerDocument() { |
| return null; |
| } |
| |
| public Node getParentNode() { |
| log.trace("getParentNode"); |
| return getParent(); |
| } |
| |
| public AdapterNode getParent() { |
| return parent; |
| } |
| |
| public void setParent(AdapterNode parent) { |
| this.parent = parent; |
| } |
| |
| public Object getPropertyValue() { |
| return propertyValue; |
| } |
| |
| public void setPropertyValue(Object prop) { |
| this.propertyValue = prop; |
| } |
| |
| public void setPrefix(String string) throws DOMException { |
| throw operationNotSupported(); |
| } |
| |
| public String getPrefix() { |
| return null; |
| } |
| |
| public Node getNextSibling() { |
| Node next = getParent().getChildAfter(this); |
| if (log.isTraceEnabled()) { |
| log.trace("getNextSibling on " + getNodeName() + ": " |
| + ((next == null) ? "null" : next.getNodeName())); |
| } |
| |
| return next; |
| } |
| |
| public Node getPreviousSibling() { |
| return getParent().getChildBefore(this); |
| } |
| |
| public String getPropertyName() { |
| return propertyName; |
| } |
| |
| public void setPropertyName(String name) { |
| this.propertyName = name; |
| } |
| |
| public AdapterFactory getAdapterFactory() { |
| return adapterFactory; |
| } |
| |
| public void setAdapterFactory(AdapterFactory adapterFactory) { |
| this.adapterFactory = adapterFactory; |
| } |
| |
| public boolean isSupported(String string, String string1) { |
| throw operationNotSupported(); |
| } |
| |
| public Node appendChild(Node node) throws DOMException { |
| throw operationNotSupported(); |
| } |
| |
| public Node cloneNode(boolean b) { |
| log.trace("cloneNode"); |
| throw operationNotSupported(); |
| } |
| |
| public boolean hasAttributes() { |
| return false; |
| } |
| |
| public boolean hasChildNodes() { |
| return false; |
| } |
| |
| public Node insertBefore(Node node, Node node1) throws DOMException { |
| throw operationNotSupported(); |
| } |
| |
| public void normalize() { |
| log.trace("normalize"); |
| throw operationNotSupported(); |
| } |
| |
| public Node removeChild(Node node) throws DOMException { |
| throw operationNotSupported(); |
| } |
| |
| public Node replaceChild(Node node, Node node1) throws DOMException { |
| throw operationNotSupported(); |
| } |
| |
| // Begin DOM 3 methods |
| |
| public boolean isDefaultNamespace(String string) { |
| throw operationNotSupported(); |
| } |
| |
| public String lookupNamespaceURI(String string) { |
| throw operationNotSupported(); |
| } |
| |
| public String getNodeName() { |
| throw operationNotSupported(); |
| } |
| |
| public short getNodeType() { |
| throw operationNotSupported(); |
| } |
| |
| public String getBaseURI() { |
| throw operationNotSupported(); |
| } |
| |
| public short compareDocumentPosition(Node node) throws DOMException { |
| throw operationNotSupported(); |
| } |
| |
| public String getTextContent() throws DOMException { |
| throw operationNotSupported(); |
| } |
| |
| public void setTextContent(String string) throws DOMException { |
| throw operationNotSupported(); |
| |
| } |
| |
| public boolean isSameNode(Node node) { |
| throw operationNotSupported(); |
| } |
| |
| public String lookupPrefix(String string) { |
| throw operationNotSupported(); |
| } |
| |
| public boolean isEqualNode(Node node) { |
| throw operationNotSupported(); |
| } |
| |
| public Object getFeature(String string, String string1) { |
| throw operationNotSupported(); |
| } |
| |
| public Object setUserData(String string, Object object, UserDataHandler userDataHandler) { |
| throw operationNotSupported(); |
| } |
| |
| public Object getUserData(String string) { |
| throw operationNotSupported(); |
| } |
| |
| // End node methods |
| |
| protected StrutsException operationNotSupported() { |
| return new StrutsException("Operation not supported."); |
| } |
| |
| public String toString() { |
| return getClass() + ": " + getNodeName() + " parent=" + getParentNode(); |
| } |
| } |