Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
The coolest XML library for Java around. Define typesafe views (projections) to xml. Use XPath to read and write XML. Bind XML to Java collections. Requires at least Java6, supports Java8 features and has no further runtime dependencies.
/**
* Copyright 2012 Sven Ewald
*
* Licensed 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.xmlbeam;
import java.io.IOException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xmlbeam.XBProjector.InternalProjection;
import org.xmlbeam.annotation.XBDelete;
import org.xmlbeam.annotation.XBDocURL;
import org.xmlbeam.annotation.XBRead;
import org.xmlbeam.annotation.XBUpdate;
import org.xmlbeam.annotation.XBValue;
import org.xmlbeam.annotation.XBWrite;
import org.xmlbeam.dom.DOMAccess;
import org.xmlbeam.types.TypeConverter;
import org.xmlbeam.util.intern.ASMHelper;
import org.xmlbeam.util.intern.DOMHelper;
import org.xmlbeam.util.intern.ReflectionHelper;
/**
* This class implements the "magic" behind projection methods. Each projection is linked with a
* ProjectionInvocatonHandler which handles method invocations on the projections. Notice that this
* class is not part of the public API. You should not get in touch with this class at all. See
* {@link org.xmlbeam.XBProjector} for API usage.
*
* @author Sven Ewald
*/
@SuppressWarnings("serial")
final class ProjectionInvocationHandler implements InvocationHandler, Serializable {
private final static String NONEMPTY = "(?!^$)";
private final static String XML_NAME_START_CHARS = ":A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02ff\\u0370-\\u037d" + "\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f\\u2c00-\\u2fef\\u3001-\\ud7ff" + "\\uf900-\\ufdcf\\ufdf0-\\ufffd"
+ String.valueOf(Character.toChars(0x10000)) + "-" + String.valueOf(Character.toChars(0xEFFFF));
private final static String XML_NAME_CHARS = XML_NAME_START_CHARS + "\\-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
private final static String XML_ELEMENT = "[" + XML_NAME_START_CHARS + "]" + "[" + XML_NAME_CHARS + "]*";
private final static String ELEMENT_PATH = "(/" + XML_ELEMENT + "(\\[@?" + XML_ELEMENT + "='.+'\\])?)";
private final static String ATTRIBUTE_PATH = "(/?@" + XML_ELEMENT + ")";
private final static String PARENT_PATH = "(/\\.\\.)";
private static final Pattern LEGAL_XPATH_SELECTORS_FOR_SETTERS = Pattern.compile(NONEMPTY + "(^\\.?(" + ELEMENT_PATH + "*" + PARENT_PATH + "*)*(" + ATTRIBUTE_PATH + "|(/\\*))?$)");
private static final Pattern DOUBLE_LBRACES = Pattern.compile("{{", Pattern.LITERAL);
private static final Pattern DOUBLE_RBRACES = Pattern.compile("}}", Pattern.LITERAL);
private final Node node;
private final Class> projectionInterface;
private final XBProjector projector;
// Used to handle invocations on Java6 Mixins and Object methods.
private final Map, Object> defaultInvokers;
// Used to handle invocations on Java8 default methods.
private transient Object defaultMethodInvoker;
ProjectionInvocationHandler(final XBProjector projector, final Node node, final Class> projectionInterface, final Map, Object> defaultInvokers) {
this.projector = projector;
this.node = node;
this.projectionInterface = projectionInterface;
this.defaultInvokers = defaultInvokers;
}
/**
* @param typeToSet
* @param collection
* @param parentElement
* @param elementSelector
*/
private int applyCollectionSetOnElement(final Type typeToSet, final Collection> collection, final Element parentElement, final String elementSelector) {
final Document document = parentElement.getOwnerDocument();
DOMHelper.removeAllChildrenBySelector(parentElement, elementSelector);
assert !elementSelector.contains("/") : "Selector should be the trail of the path.";
final String elementName = elementSelector.replaceAll("\\[.*", "");
if (collection == null) {
return 0;
}
Class> componentClass = Object.class;
if (typeToSet instanceof ParameterizedType) {
Type componentType = ((ParameterizedType) typeToSet).getActualTypeArguments()[0];
componentClass = ReflectionHelper.upperBoundAsClass(componentType);
}
for (Object o : collection) {
try {
o = ReflectionHelper.unwrap(componentClass, o);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
if (o == null) {
continue;
}
if (!isStructureChangingValue(o)) {
final Element newElement = document.createElement(elementName);
newElement.setTextContent(o.toString());
parentElement.appendChild(newElement);
continue;
}
if (o instanceof Node) {
Node newNode = ((Node) o).cloneNode(true);
DOMHelper.ensureOwnership(parentElement.getOwnerDocument(), newNode);
parentElement.appendChild(newNode);
continue;
}
final InternalProjection p = (InternalProjection) o;
Element pElement = Node.DOCUMENT_NODE == p.getDOMNode().getNodeType() ? p.getDOMOwnerDocument().getDocumentElement() : (Element) p.getDOMNode();
if (pElement == null) {
continue;
}
Element clone = (Element) pElement.cloneNode(true);
if (!elementName.equals(clone.getNodeName())) {
if (!"*".equals(elementName)) {
clone = DOMHelper.renameElement(clone, elementName);
}
}
DOMHelper.ensureOwnership(document, clone);
parentElement.appendChild(clone);
}
return collection.size();
}
/**
* @param o
* @return
*/
private boolean isStructureChangingValue(final Object o) {
return (o instanceof InternalProjection) || (o instanceof Node);
}
private void applySingleSetElementOnElement(final Element element, final Node parentNode, final String elementSelector) {
//final Element newElement = (Element) projection.getDOMBaseElement().cloneNode(true);
final Element newElement = (Element) element.cloneNode(true);
DOMHelper.removeAllChildrenBySelector(parentNode, elementSelector);
DOMHelper.ensureOwnership(parentNode.getOwnerDocument(), newElement);
parentNode.appendChild(newElement);
}
private List> evaluateAsList(final XPathExpression expression, final Node node, final Method method) throws XPathExpressionException {
final NodeList nodes = (NodeList) expression.evaluate(node, XPathConstants.NODESET);
final List