Example usage for org.apache.commons.jxpath.ri.parser XPathParserConstants SLASH

List of usage examples for org.apache.commons.jxpath.ri.parser XPathParserConstants SLASH

Introduction

In this page you can find the example usage for org.apache.commons.jxpath.ri.parser XPathParserConstants SLASH.

Prototype

int SLASH

To view the source code for org.apache.commons.jxpath.ri.parser XPathParserConstants SLASH.

Click Source Link

Usage

From source file:org.fao.geonet.kernel.EditLib.java

private boolean createAndAddFromXPath(Element metadataRecord, MetadataSchema metadataSchema,
        String xpathProperty, AddElemValue value) throws Exception {
    if (xpathProperty.startsWith("/")) {
        xpathProperty = xpathProperty.substring(1);
    }/*  ww  w  .  j av  a 2s .  co  m*/
    if (xpathProperty.startsWith(metadataRecord.getQualifiedName() + "/")) {
        xpathProperty = xpathProperty.substring(metadataRecord.getQualifiedName().length() + 1);
    }
    List<String> xpathParts = Arrays.asList(xpathProperty.split("/"));

    Pair<Element, String> result = findLongestMatch(metadataRecord, metadataRecord, 0, metadataSchema,
            xpathParts.size() / 2, xpathParts);
    final Element elementToAttachTo = result.one();
    final Element clonedMetadata = (Element) elementToAttachTo.clone();

    // Creating the element at the xpath location
    // Walk the XPath from the start until the end or the start of a filter
    // expression.
    // Collect element namespace prefix and name, check element exist and
    // create them according to schema definition.
    final XPathParser xpathParser = new XPathParser(
            new StringReader(clonedMetadata.getQualifiedName() + "/" + result.two()));

    // Start from the root of the metadata document
    Token currentToken = xpathParser.getNextToken();
    Token previousToken = currentToken;

    int depth = 0;
    Element currentNode = clonedMetadata;
    boolean existingElement = true;
    boolean isAttribute = false;
    String currentElementName = "";
    String currentElementNamespacePrefix = "";

    // Stop when token is null, start of an expression is found ie. "["
    //
    // Stop when an expression [ starts
    // The expression is supposed to be part of the XML snippet to insert
    // If an existing element needs to be updated use the _Xref_replace mode
    // this mode is more precise with the geonet:element/@ref.
    while (currentToken != null && currentToken.kind != 0
            && currentToken.kind != XPathParserLocalConstants.SQBRACKET_OPEN) {

        // TODO : check no .., descendant, ... are in the xpath
        // Only full xpath are supported.
        if (XPathParserLocalConstants.ILLEGAL_KINDS.contains(currentToken.kind)) {
            return false;
        }

        // build element name as the parser progress into the xpath ...
        if (currentToken.kind == XPathParserLocalConstants.ATTRIBUTE) {
            isAttribute = true;
        }
        // Match namespace prefix
        if (currentToken.kind == XPathParserLocalConstants.TEXT
                && previousToken.kind == XPathParserConstants.SLASH) {
            // get element namespace if element is text and previous was /
            // means qualified name only is supported
            currentElementNamespacePrefix = currentToken.image;
        } else if (currentToken.kind == XPathParserLocalConstants.TEXT
                && previousToken.kind == XPathParserLocalConstants.NAMESPACE_SEP) {
            // get element name if element is text and previous was /
            currentElementName = currentToken.image;

            // Do not change anything to the root of the
            // metadata record which MUST be the root of
            // the xpath
            if (depth > 0) {
                // If an element name is created
                // Check the element exist in the metadata
                // and create it if needed.
                String qualifiedName = currentElementNamespacePrefix + ":" + currentElementName;
                if (Log.isDebugEnabled(Geonet.EDITORADDELEMENT)) {
                    Log.debug(Geonet.EDITORADDELEMENT,
                            "Check if " + qualifiedName + " exists in " + currentNode.getName());
                }

                Element nodeToCheck = currentNode.getChild(currentElementName,
                        Namespace.getNamespace(metadataSchema.getNS(currentElementNamespacePrefix)));

                if (nodeToCheck != null) {
                    if (Log.isDebugEnabled(Geonet.EDITORADDELEMENT)) {
                        Log.debug(Geonet.EDITORADDELEMENT, " > " + qualifiedName + " found");
                    }
                    // Element found, no need to create it, continue walking the xpath.
                    currentNode = nodeToCheck;
                    existingElement &= true;
                } else {
                    if (Log.isDebugEnabled(Geonet.EDITORADDELEMENT)) {
                        Log.debug(Geonet.EDITORADDELEMENT,
                                " > add new node " + qualifiedName + " inserted in " + currentNode.getName());
                    }

                    if (metadataSchema.getElementValues(qualifiedName,
                            currentNode.getQualifiedName()) != null) {
                        currentNode = addElement(metadataSchema, currentNode, qualifiedName);
                        existingElement = false;
                    } else {
                        // element not in schema so stop!
                        return false;
                    }
                }
            }

            depth++;
            // Reset current element props
            currentElementName = "";
            currentElementNamespacePrefix = "";
        }

        previousToken = currentToken;
        currentToken = xpathParser.getNextToken();
    }

    // The current node is an existing node or newly created one
    // Insert the XML value
    // TODO: deal with attribute ?
    if (value.isXml()) {
        // If current node match the node name to insert
        // Insert the new node in its parent
        if (existingElement) {
            currentNode = addElement(metadataSchema, currentNode.getParentElement(),
                    currentNode.getQualifiedName());
        }

        // clean before update
        // when adding the fragment child nodes or suggestion may also be added.
        // In this case, the snippet only has to be inserted
        currentNode.removeContent();
        doAddFragmentFromXpath(value.getNodeValue(), currentNode);
    } else {
        if (isAttribute) {
            currentNode.setAttribute(previousToken.image, value.getStringValue());
        } else {
            currentNode.setText(value.getStringValue());
        }
    }

    // update worked so now we can update original element...
    elementToAttachTo.removeContent();
    List<Content> toAdd = Lists.newArrayList(clonedMetadata.getContent());
    for (Content content : toAdd) {
        elementToAttachTo.addContent(content.detach());
    }
    return true;
}