Skip to content

Commit

Permalink
Attempt to follow suggestion from https://issues.apache.org/jira/brow…
Browse files Browse the repository at this point in the history
  • Loading branch information
vicnevicne committed Feb 21, 2023
1 parent db457cf commit 3c9d711
Show file tree
Hide file tree
Showing 10 changed files with 1,607 additions and 0 deletions.
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,11 @@
<version>1.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6.1</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ public class JXPathContextReferenceImpl extends JXPathContext {
nodeFactories.add(jdomFactory);
}

// JDOM2 factory is only registered if JDOM2 is on the classpath
final Object jdom2Factory = allocateConditionally(
"org.apache.commons.jxpath.ri.model.jdom2.JDOMPointerFactory",
"org.jdom2.Document");
if (jdom2Factory != null) {
nodeFactories.add(jdom2Factory);
}

// DynaBean factory is only registered if BeanUtils are on the classpath
final Object dynaBeanFactory =
allocateConditionally(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* 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.commons.jxpath.ri.model.jdom2;

import org.apache.commons.jxpath.ri.QName;
import org.apache.commons.jxpath.ri.model.NodeIterator;
import org.apache.commons.jxpath.ri.model.NodePointer;
import org.jdom2.Attribute;
import org.jdom2.Element;
import org.jdom2.Namespace;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* An iterator of attributes of a DOM Node.
*/
public class JDOMAttributeIterator implements NodeIterator {
private NodePointer parent;
private List attributes;
private int position = 0;

/**
* Create a new JDOMAttributeIterator.
* @param parent pointer
* @param name test
*/
public JDOMAttributeIterator(final NodePointer parent, final QName name) {
this.parent = parent;
if (parent.getNode() instanceof Element) {
final Element element = (Element) parent.getNode();
final String prefix = name.getPrefix();
Namespace ns = null;
if (prefix != null) {
if (prefix.equals("xml")) {
ns = Namespace.XML_NAMESPACE;
}
else {
final String uri = parent.getNamespaceResolver().getNamespaceURI(prefix);
if (uri != null) {
ns = Namespace.getNamespace(prefix, uri);
}
if (ns == null) {
// TBD: no attributes
attributes = Collections.EMPTY_LIST;
return;
}
}
}
else {
ns = Namespace.NO_NAMESPACE;
}

final String lname = name.getName();
if (!lname.equals("*")) {
attributes = new ArrayList();
final Attribute attr = element.getAttribute(lname, ns);
if (attr != null) {
attributes.add(attr);
}
}
else {
attributes = new ArrayList();
final List allAttributes = element.getAttributes();
for (int i = 0; i < allAttributes.size(); i++) {
final Attribute attr = (Attribute) allAttributes.get(i);
if (ns == Namespace.NO_NAMESPACE
|| attr.getNamespace().equals(ns)) {
attributes.add(attr);
}
}
}
}
}

@Override
public NodePointer getNodePointer() {
if (position == 0) {
if (!setPosition(1)) {
return null;
}
position = 0;
}
int index = position - 1;
if (index < 0) {
index = 0;
}
return new JDOMAttributePointer(
parent,
(Attribute) attributes.get(index));
}

@Override
public int getPosition() {
return position;
}

@Override
public boolean setPosition(final int position) {
if (attributes == null) {
return false;
}
this.position = position;
return position >= 1 && position <= attributes.size();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* 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.commons.jxpath.ri.model.jdom2;

import org.apache.commons.jxpath.ri.QName;
import org.apache.commons.jxpath.ri.model.NodePointer;
import org.apache.commons.jxpath.util.TypeUtils;
import org.jdom2.Attribute;

/**
* A Pointer that points to a DOM node.
*/
public class JDOMAttributePointer extends NodePointer {
private final Attribute attr;

private static final long serialVersionUID = 8896050354479644028L;

/**
* Create a JDOMAttributePointer.
* @param parent NodePointer parent
* @param attr JDOM Attribute
*/
public JDOMAttributePointer(final NodePointer parent, final Attribute attr) {
super(parent);
this.attr = attr;
}

@Override
public QName getName() {
return new QName(
JDOMNodePointer.getPrefix(attr),
JDOMNodePointer.getLocalName(attr));
}

@Override
public String getNamespaceURI() {
String uri = attr.getNamespaceURI();
if (uri != null && uri.equals("")) {
uri = null;
}
return uri;
}

@Override
public Object getValue() {
return attr.getValue();
}

@Override
public Object getBaseValue() {
return attr;
}

@Override
public boolean isCollection() {
return false;
}

@Override
public int getLength() {
return 1;
}

@Override
public Object getImmediateNode() {
return attr;
}

@Override
public boolean isActual() {
return true;
}

@Override
public boolean isLeaf() {
return true;
}

@Override
public void setValue(final Object value) {
attr.setValue((String) TypeUtils.convert(value, String.class));
}

@Override
public void remove() {
attr.getParent().removeAttribute(attr);
}

@Override
public String asPath() {
final StringBuffer buffer = new StringBuffer();
if (parent != null) {
buffer.append(parent.asPath());
if (buffer.length() == 0
|| buffer.charAt(buffer.length() - 1) != '/') {
buffer.append('/');
}
}
buffer.append('@');
buffer.append(getName());
return buffer.toString();
}

@Override
public int hashCode() {
return System.identityHashCode(attr);
}

@Override
public boolean equals(final Object object) {
return object == this || object instanceof JDOMAttributePointer
&& ((JDOMAttributePointer) object).attr == attr;
}

@Override
public int compareChildNodePointers(
final NodePointer pointer1,
final NodePointer pointer2) {
// Won't happen - attributes don't have children
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* 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.commons.jxpath.ri.model.jdom2;

import org.apache.commons.jxpath.ri.model.NodeIterator;
import org.apache.commons.jxpath.ri.model.NodePointer;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* An iterator of namespaces of a DOM Node.
*/
public class JDOMNamespaceIterator implements NodeIterator {
private final NodePointer parent;
private List namespaces;
private Set prefixes;
private int position = 0;

/**
* Create a new JDOMNamespaceIterator.
* @param parent the parent NodePointer.
*/
public JDOMNamespaceIterator(final NodePointer parent) {
this.parent = parent;
Object node = parent.getNode();
if (node instanceof Document) {
node = ((Document) node).getRootElement();
}
if (node instanceof Element) {
namespaces = new ArrayList();
prefixes = new HashSet();
collectNamespaces((Element) node);
}
}

/**
* Collect the namespaces from a JDOM Element.
* @param element the source Element
*/
private void collectNamespaces(final Element element) {
Namespace ns = element.getNamespace();
if (ns != null && !prefixes.contains(ns.getPrefix())) {
namespaces.add(ns);
prefixes.add(ns.getPrefix());
}
final List others = element.getAdditionalNamespaces();
for (int i = 0; i < others.size(); i++) {
ns = (Namespace) others.get(i);
if (ns != null && !prefixes.contains(ns.getPrefix())) {
namespaces.add(ns);
prefixes.add(ns.getPrefix());
}
}
final Object elementParent = element.getParent();
if (elementParent instanceof Element) {
collectNamespaces((Element) elementParent);
}
}

@Override
public NodePointer getNodePointer() {
if (position == 0) {
if (!setPosition(1)) {
return null;
}
position = 0;
}
int index = position - 1;
if (index < 0) {
index = 0;
}
final Namespace ns = (Namespace) namespaces.get(index);
return new JDOMNamespacePointer(parent, ns.getPrefix(), ns.getURI());
}

@Override
public int getPosition() {
return position;
}

@Override
public boolean setPosition(final int position) {
if (namespaces == null) {
return false;
}
this.position = position;
return position >= 1 && position <= namespaces.size();
}
}
Loading

0 comments on commit 3c9d711

Please sign in to comment.