Unimplement org.w3c.dom.Node for Xml wrapper
This is to help extend the Node interface later on. This class' implementing both interfaces helped nothing but would certainly have caused conflicts wrt method names and incompatible return types. For example, adding a method `Node getFirstChild()` to our Node interface would have conflicted with the getFirstChild of the w3c interface.
This commit is contained in:
@ -1,257 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.xml.ast;
|
||||
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.UserDataHandler;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.AbstractNode;
|
||||
|
||||
|
||||
/**
|
||||
* Moves boilerplate out of {@link XmlNodeWrapper}.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.1.0
|
||||
*/
|
||||
public abstract class AbstractDomNodeProxy extends AbstractNode implements org.w3c.dom.Node {
|
||||
|
||||
protected final org.w3c.dom.Node node;
|
||||
|
||||
|
||||
protected AbstractDomNodeProxy(Node node) {
|
||||
super(0);
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getNodeName() {
|
||||
return node.getNodeName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getNodeValue() throws DOMException {
|
||||
return node.getNodeValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setNodeValue(String nodeValue) throws DOMException {
|
||||
node.setNodeValue(nodeValue);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("PMD.AvoidUsingShortType")
|
||||
@Override
|
||||
public short getNodeType() {
|
||||
return node.getNodeType();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node getParentNode() {
|
||||
return node.getParentNode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NodeList getChildNodes() {
|
||||
return node.getChildNodes();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node getFirstChild() {
|
||||
return node.getFirstChild();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node getLastChild() {
|
||||
return node.getLastChild();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node getPreviousSibling() {
|
||||
return node.getPreviousSibling();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node getNextSibling() {
|
||||
return node.getNextSibling();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NamedNodeMap getAttributes() {
|
||||
return node.getAttributes();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Document getOwnerDocument() {
|
||||
return node.getOwnerDocument();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node insertBefore(org.w3c.dom.Node newChild, org.w3c.dom.Node refChild) throws DOMException {
|
||||
return node.insertBefore(newChild, refChild);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node replaceChild(org.w3c.dom.Node newChild, org.w3c.dom.Node oldChild) throws DOMException {
|
||||
return node.replaceChild(newChild, oldChild);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node removeChild(org.w3c.dom.Node oldChild) throws DOMException {
|
||||
return node.removeChild(oldChild);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node appendChild(org.w3c.dom.Node newChild) throws DOMException {
|
||||
return node.appendChild(newChild);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasChildNodes() {
|
||||
return node.hasChildNodes();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node cloneNode(boolean deep) {
|
||||
return node.cloneNode(deep);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void normalize() {
|
||||
node.normalize();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSupported(String feature, String version) {
|
||||
return node.isSupported(feature, version);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getNamespaceURI() {
|
||||
return node.getNamespaceURI();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return node.getPrefix();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setPrefix(String prefix) throws DOMException {
|
||||
node.setPrefix(prefix);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getLocalName() {
|
||||
return node.getLocalName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasAttributes() {
|
||||
return node.hasAttributes();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getBaseURI() {
|
||||
return node.getBaseURI();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("PMD.AvoidUsingShortType")
|
||||
@Override
|
||||
public short compareDocumentPosition(org.w3c.dom.Node other) throws DOMException {
|
||||
return node.compareDocumentPosition(other);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getTextContent() throws DOMException {
|
||||
return node.getTextContent();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setTextContent(String textContent) throws DOMException {
|
||||
node.setTextContent(textContent);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSameNode(org.w3c.dom.Node other) {
|
||||
return node.isSameNode(other);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String lookupPrefix(String namespaceURI) {
|
||||
return node.lookupPrefix(namespaceURI);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDefaultNamespace(String namespaceURI) {
|
||||
return node.isDefaultNamespace(namespaceURI);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String lookupNamespaceURI(String prefix) {
|
||||
return node.lookupNamespaceURI(prefix);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isEqualNode(org.w3c.dom.Node arg) {
|
||||
return node.isEqualNode(arg);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getFeature(String feature, String version) {
|
||||
return node.getFeature(feature, version);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object setUserData(String key, Object data, UserDataHandler handler) {
|
||||
return node.setUserData(key, data, handler);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getUserData(String key) {
|
||||
return node.getUserData(key);
|
||||
}
|
||||
|
||||
}
|
@ -15,29 +15,31 @@ import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.ProcessingInstruction;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.SourceCodePositioner;
|
||||
import net.sourceforge.pmd.lang.xml.ast.XmlParser.RootXmlNode;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class DOMLineNumbers {
|
||||
private final Document document;
|
||||
private final RootXmlNode document;
|
||||
private String xmlString;
|
||||
private SourceCodePositioner sourceCodePositioner;
|
||||
|
||||
DOMLineNumbers(Document document, String xmlString) {
|
||||
this.document = document;
|
||||
DOMLineNumbers(RootXmlNode root, String xmlString) {
|
||||
this.document = root;
|
||||
this.xmlString = xmlString;
|
||||
this.sourceCodePositioner = new SourceCodePositioner(xmlString);
|
||||
}
|
||||
|
||||
public void determine() {
|
||||
void determine() {
|
||||
determineLocation(document, 0);
|
||||
}
|
||||
|
||||
private int determineLocation(Node n, int index) {
|
||||
private int determineLocation(XmlNodeWrapper wrapper, int index) {
|
||||
int nextIndex = index;
|
||||
int nodeLength = 0;
|
||||
int textLength = 0;
|
||||
org.w3c.dom.Node n = wrapper.getNode();
|
||||
if (n.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
|
||||
nextIndex = xmlString.indexOf("<!DOCTYPE", nextIndex);
|
||||
} else if (n.getNodeType() == Node.COMMENT_NODE) {
|
||||
@ -65,14 +67,14 @@ class DOMLineNumbers {
|
||||
} else if (n.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
|
||||
nextIndex = xmlString.indexOf("&" + n.getNodeName() + ";", nextIndex);
|
||||
}
|
||||
setBeginLocation(n, nextIndex);
|
||||
setBeginLocation(wrapper, nextIndex);
|
||||
|
||||
nextIndex += nodeLength;
|
||||
|
||||
if (n.hasChildNodes()) {
|
||||
NodeList childs = n.getChildNodes();
|
||||
for (int i = 0; i < childs.getLength(); i++) {
|
||||
nextIndex = determineLocation(childs.item(i), nextIndex);
|
||||
int numChildren = wrapper.jjtGetNumChildren();
|
||||
for (int i = 0; i < numChildren; i++) {
|
||||
nextIndex = determineLocation((XmlNodeWrapper) wrapper.jjtGetChild(i), nextIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +106,7 @@ class DOMLineNumbers {
|
||||
ProcessingInstruction pi = (ProcessingInstruction) n;
|
||||
nextIndex += "<?".length() + pi.getTarget().length() + "?>".length() + pi.getData().length();
|
||||
}
|
||||
setEndLocation(n, nextIndex - 1);
|
||||
setEndLocation(wrapper, nextIndex - 1);
|
||||
return nextIndex;
|
||||
}
|
||||
|
||||
@ -146,21 +148,21 @@ class DOMLineNumbers {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void setBeginLocation(Node n, int index) {
|
||||
private void setBeginLocation(XmlNodeWrapper n, int index) {
|
||||
if (n != null) {
|
||||
int line = sourceCodePositioner.lineNumberFromOffset(index);
|
||||
int column = sourceCodePositioner.columnFromOffset(line, index);
|
||||
n.setUserData(XmlNode.BEGIN_LINE, line, null);
|
||||
n.setUserData(XmlNode.BEGIN_COLUMN, column, null);
|
||||
n.setBeginLine(line);
|
||||
n.setBeginColumn(column);
|
||||
}
|
||||
}
|
||||
|
||||
private void setEndLocation(Node n, int index) {
|
||||
private void setEndLocation(XmlNodeWrapper n, int index) {
|
||||
if (n != null) {
|
||||
int line = sourceCodePositioner.lineNumberFromOffset(index);
|
||||
int column = sourceCodePositioner.columnFromOffset(line, index);
|
||||
n.setUserData(XmlNode.END_LINE, line, null);
|
||||
n.setUserData(XmlNode.END_COLUMN, column, null);
|
||||
n.setEndLine(line);
|
||||
n.setEndColumn(column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,17 +5,12 @@
|
||||
package net.sourceforge.pmd.lang.xml.ast;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.ast.xpath.AttributeNode;
|
||||
|
||||
/**
|
||||
* This interface represents all XML AST nodes. They are essentially thin
|
||||
* wrappers around the underlying DOM nodes.
|
||||
*/
|
||||
public interface XmlNode extends Node, AttributeNode {
|
||||
String BEGIN_LINE = "pmd:beginLine";
|
||||
String BEGIN_COLUMN = "pmd:beginColumn";
|
||||
String END_LINE = "pmd:endLine";
|
||||
String END_COLUMN = "pmd:endColumn";
|
||||
public interface XmlNode extends Node {
|
||||
|
||||
/**
|
||||
* Provide access to the underlying DOM node.
|
||||
|
@ -16,6 +16,7 @@ import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.AbstractNode;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.ast.xpath.Attribute;
|
||||
import net.sourceforge.pmd.lang.dfa.DataFlowNode;
|
||||
@ -28,14 +29,16 @@ import net.sourceforge.pmd.util.CompoundIterator;
|
||||
* @author Clément Fournier
|
||||
* @since 6.1.0
|
||||
*/
|
||||
public class XmlNodeWrapper extends AbstractDomNodeProxy implements XmlNode {
|
||||
public class XmlNodeWrapper extends AbstractNode implements XmlNode {
|
||||
|
||||
private final XmlParser parser;
|
||||
private Object userData;
|
||||
private final org.w3c.dom.Node node;
|
||||
|
||||
|
||||
public XmlNodeWrapper(XmlParser parser, org.w3c.dom.Node domNode) {
|
||||
super(domNode);
|
||||
super(0);
|
||||
this.node = domNode;
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
@ -120,30 +123,6 @@ public class XmlNodeWrapper extends AbstractDomNodeProxy implements XmlNode {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getBeginLine() {
|
||||
return (int) getUserData(BEGIN_LINE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getBeginColumn() {
|
||||
return (int) getUserData(BEGIN_COLUMN);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getEndLine() {
|
||||
return (int) getUserData(END_LINE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getEndColumn() {
|
||||
return (int) getUserData(END_COLUMN);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DataFlowNode getDataFlowNode() {
|
||||
throw new UnsupportedOperationException();
|
||||
@ -249,18 +228,28 @@ public class XmlNodeWrapper extends AbstractDomNodeProxy implements XmlNode {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getXPathAttributesIterator()}
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public Iterator<Attribute> getAttributeIterator() {
|
||||
return getXPathAttributesIterator();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public org.w3c.dom.Node getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
// package private, open only to DOMLineNumbers
|
||||
|
||||
void setBeginLine(int i) {
|
||||
this.beginLine = i;
|
||||
}
|
||||
|
||||
void setBeginColumn(int i) {
|
||||
this.beginColumn = i;
|
||||
}
|
||||
|
||||
void setEndLine(int i) {
|
||||
this.endLine = i;
|
||||
}
|
||||
|
||||
void setEndColumn(int i) {
|
||||
this.endColumn = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,8 +25,9 @@ import net.sourceforge.pmd.lang.xml.XmlParserOptions;
|
||||
|
||||
|
||||
public class XmlParser {
|
||||
protected final XmlParserOptions parserOptions;
|
||||
protected Map<org.w3c.dom.Node, XmlNode> nodeCache = new HashMap<>();
|
||||
|
||||
private final XmlParserOptions parserOptions;
|
||||
private Map<org.w3c.dom.Node, XmlNode> nodeCache = new HashMap<>();
|
||||
|
||||
|
||||
public XmlParser(XmlParserOptions parserOptions) {
|
||||
@ -34,10 +35,9 @@ public class XmlParser {
|
||||
}
|
||||
|
||||
|
||||
protected Document parseDocument(Reader reader) throws ParseException {
|
||||
private Document parseDocument(String xmlData) throws ParseException {
|
||||
nodeCache.clear();
|
||||
try {
|
||||
String xmlData = IOUtils.toString(reader);
|
||||
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setNamespaceAware(parserOptions.isNamespaceAware());
|
||||
@ -51,10 +51,7 @@ public class XmlParser {
|
||||
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
|
||||
documentBuilder.setEntityResolver(parserOptions.getEntityResolver());
|
||||
Document document = documentBuilder.parse(new InputSource(new StringReader(xmlData)));
|
||||
DOMLineNumbers lineNumbers = new DOMLineNumbers(document, xmlData);
|
||||
lineNumbers.determine();
|
||||
return document;
|
||||
return documentBuilder.parse(new InputSource(new StringReader(xmlData)));
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
throw new ParseException(e);
|
||||
}
|
||||
@ -62,8 +59,16 @@ public class XmlParser {
|
||||
|
||||
|
||||
public XmlNode parse(Reader reader) {
|
||||
Document document = parseDocument(reader);
|
||||
XmlNode root = new RootXmlNode(this, document);
|
||||
String xmlData;
|
||||
try {
|
||||
xmlData = IOUtils.toString(reader);
|
||||
} catch (IOException e) {
|
||||
throw new ParseException(e);
|
||||
}
|
||||
Document document = parseDocument(xmlData);
|
||||
RootXmlNode root = new RootXmlNode(this, document);
|
||||
DOMLineNumbers lineNumbers = new DOMLineNumbers(root, xmlData);
|
||||
lineNumbers.determine();
|
||||
nodeCache.put(document, root);
|
||||
return root;
|
||||
}
|
||||
|
Reference in New Issue
Block a user