alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * Copyright 1999-2004 The Apache Software Foundation
 *
 * 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.apache.commons.jxpath.ri.model;

import org.apache.commons.jxpath.AbstractFactory;
import org.apache.commons.jxpath.IdentityManager;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathException;
import org.apache.commons.jxpath.JXPathTestCase;
import org.apache.commons.jxpath.Pointer;
import org.apache.commons.jxpath.Variables;
import org.apache.commons.jxpath.xml.DocumentContainer;

/**
 * Abstract superclass for pure XPath 1.0.  Subclasses
 * apply the same XPaths to contexts using different models:
 * DOM, JDOM etc.
 *
 * @author Dmitri Plotnikov
 * @version $Revision: 1.23 $ $Date: 2004/06/30 00:29:13 $
 */

public abstract class XMLModelTestCase extends JXPathTestCase {
    protected JXPathContext context;

    /**
     * Construct a new instance of this test case.
     *
     * @param name Name of the test case
     */
    public XMLModelTestCase(String name) {
        super(name);
    }

    public void setUp() {
        if (context == null) {
            DocumentContainer docCtr = createDocumentContainer();
            context = createContext();
            Variables vars = context.getVariables();
            vars.declareVariable("document", docCtr.getValue());
            vars.declareVariable("container", docCtr);
            vars.declareVariable(
                "element",
                context.getPointer("vendor/location/address/street").getNode());
        }
    }

    protected abstract String getModel();

    protected DocumentContainer createDocumentContainer() {
        return new DocumentContainer(
                JXPathTestCase.class.getResource("Vendor.xml"),
                getModel());
    }
    
    protected abstract AbstractFactory getAbstractFactory();
        
    protected JXPathContext createContext() {
        JXPathContext context =
            JXPathContext.newContext(createDocumentContainer());
        context.setFactory(getAbstractFactory());
        context.registerNamespace("product", "productNS");
        return context;
    }

    /**
     * An XML signature is used to determine if we have the right result
     * after a modification of XML by JXPath.  It is basically a piece
     * of simplified XML.
     */
    protected abstract String getXMLSignature(
        Object node,
        boolean elements,
        boolean attributes,
        boolean text,
        boolean pi);

    protected void assertXMLSignature(
        JXPathContext context,
        String path,
        String signature,
        boolean elements,
        boolean attributes,
        boolean text,
        boolean pi) 
    {
        Object node = context.getPointer(path).getNode();
        String sig = getXMLSignature(node, elements, attributes, text, pi);
        assertEquals("XML Signature mismatch: ", signature, sig);
    }

    // ------------------------------------------------ Individual Test Methods

    public void testDocumentOrder() {
        assertDocumentOrder(
            context,
            "vendor/location",
            "vendor/location/address/street",
            -1);

        assertDocumentOrder(
            context,
            "vendor/location[@id = '100']",
            "vendor/location[@id = '101']",
            -1);

        assertDocumentOrder(
            context,
            "vendor//price:amount",
            "vendor/location",
            1);
    }
    

    public void testSetValue() {
        assertXPathSetValue(
            context,
            "vendor/location[@id = '100']",
            "New Text");

        assertXMLSignature(
            context,
            "vendor/location[@id = '100']",
            "New Text",
            false,
            false,
            true,
            false);

        assertXPathSetValue(
            context,
            "vendor/location[@id = '101']",
            "Replacement Text");

        assertXMLSignature(
            context,
            "vendor/location[@id = '101']",
            "Replacement Text",
            false,
            false,
            true,
            false);
    }

    /**
     * Test JXPathContext.createPath() with various arguments
     */
    public void testCreatePath() {
        // Create a DOM element
        assertXPathCreatePath(
            context,
            "/vendor[1]/location[3]",
            "",
            "/vendor[1]/location[3]");

        // Create a DOM element with contents
        assertXPathCreatePath(
            context,
            "/vendor[1]/location[3]/address/street",
            "",
            "/vendor[1]/location[3]/address[1]/street[1]");

        // Create a DOM attribute
        assertXPathCreatePath(
            context,
            "/vendor[1]/location[2]/@manager",
            "",
            "/vendor[1]/location[2]/@manager");

        assertXPathCreatePath(
            context,
            "/vendor[1]/location[1]/@name",
            "local",
            "/vendor[1]/location[1]/@name");

         assertXPathCreatePathAndSetValue(
            context,
            "/vendor[1]/location[4]/@manager",
            "",
            "/vendor[1]/location[4]/@manager");
         
         context.registerNamespace("price", "priceNS");
         
         // Create a DOM element
         assertXPathCreatePath(
             context,
             "/vendor[1]/price:foo/price:bar",
             "",
             "/vendor[1]/price:foo[1]/price:bar[1]");
    }

    /**
     * Test JXPath.createPathAndSetValue() with various arguments
     */
    public void testCreatePathAndSetValue() {
        // Create a XML element
        assertXPathCreatePathAndSetValue(
            context,
            "vendor/location[3]",
            "",
            "/vendor[1]/location[3]");

        // Create a DOM element with contents
        assertXPathCreatePathAndSetValue(
            context,
            "vendor/location[3]/address/street",
            "Lemon Circle",
            "/vendor[1]/location[3]/address[1]/street[1]");

        // Create an attribute
        assertXPathCreatePathAndSetValue(
            context,
            "vendor/location[2]/@manager",
            "John Doe",
            "/vendor[1]/location[2]/@manager");

        assertXPathCreatePathAndSetValue(
            context,
            "vendor/location[1]/@manager",
            "John Doe",
            "/vendor[1]/location[1]/@manager");
        
        assertXPathCreatePathAndSetValue(
            context,
            "/vendor[1]/location[4]/@manager",
            "James Dow",
            "/vendor[1]/location[4]/@manager");
        
        assertXPathCreatePathAndSetValue(
            context,
            "vendor/product/product:name/attribute::price:language",
            "English",
            "/vendor[1]/product[1]/product:name[1]/@price:language");
        
        context.registerNamespace("price", "priceNS");
        
        // Create a DOM element
        assertXPathCreatePathAndSetValue(
            context,
            "/vendor[1]/price:foo/price:bar",
            "123.20",
            "/vendor[1]/price:foo[1]/price:bar[1]");
    }

    /**
     * Test JXPathContext.removePath() with various arguments
     */
    public void testRemovePath() {
        // Remove XML nodes
        context.removePath("vendor/location[@id = '101']//street/text()");
        assertEquals(
            "Remove DOM text",
            "",
            context.getValue("vendor/location[@id = '101']//street"));

        context.removePath("vendor/location[@id = '101']//street");
        assertEquals(
            "Remove DOM element",
            new Double(0),
            context.getValue("count(vendor/location[@id = '101']//street)"));

        context.removePath("vendor/location[@id = '100']/@name");
        assertEquals(
            "Remove DOM attribute",
            new Double(0),
            context.getValue("count(vendor/location[@id = '100']/@name)"));
    }

    public void testID() {
        context.setIdentityManager(new IdentityManager() {
            public Pointer getPointerByID(JXPathContext context, String id) {
                NodePointer ptr = (NodePointer) context.getPointer("/");
                ptr = ptr.getValuePointer(); // Unwrap the container
                return ptr.getPointerByID(context, id);
            }
        });

        assertXPathValueAndPointer(
            context,
            "id(101)//street",
            "Tangerine Drive",
            "id('101')/address[1]/street[1]");

        assertXPathPointerLenient(
            context,
            "id(105)/address/street",
            "id(105)/address/street");
    }

    public void testAxisChild() {
        assertXPathValue(
            context,
            "vendor/location/address/street",
            "Orchard Road");

        // child:: - first child does not match, need to search
        assertXPathValue(
            context,
            "vendor/location/address/city",
            "Fruit Market");
        
        // local-name(qualified)
        assertXPathValue(
            context,
            "local-name(vendor/product/price:amount)",
            "amount");
        
        // local-name(non-qualified)
        assertXPathValue(context, "local-name(vendor/location)", "location");

        // name (qualified)
        assertXPathValue(
            context,
            "name(vendor/product/price:amount)",
            "value:amount");

        // name (non-qualified)
        assertXPathValue(
            context,
            "name(vendor/location)",
            "location");

        // namespace-uri (qualified)
        assertXPathValue(
            context,
            "namespace-uri(vendor/product/price:amount)",
            "priceNS");

        // default namespace does not affect search
        assertXPathValue(context, "vendor/product/prix", "934.99");
        
        assertXPathValue(context, "/vendor/contact[@name='jim']", "Jim");
        
        boolean nsv = false;
        try {
            context.setLenient(false);
            context.getValue("/vendor/contact[@name='jane']");
        }
        catch (JXPathException ex) {
            nsv = true;
        }
        assertTrue("No such value: /vendor/contact[@name='jim']", nsv);
                
        nsv = false;
        try {
            context.setLenient(false);
            context.getValue("/vendor/contact[@name='jane']/*");
        }
        catch (JXPathException ex) {
            nsv = true;
        }
        assertTrue("No such value: /vendor/contact[@name='jane']/*", nsv);
        
        // child:: with a wildcard
        assertXPathValue(
            context,
            "count(vendor/product/price:*)",
            new Double(2));

        // child:: with the default namespace
        assertXPathValue(context, "count(vendor/product/*)", new Double(4));

        // child:: with a qualified name
        assertXPathValue(context, "vendor/product/price:amount", "45.95");
    }

    public void testAxisChildIndexPredicate() {
        assertXPathValue(
            context,
            "vendor/location[2]/address/street",
            "Tangerine Drive");
    }

    public void testAxisDescendant() {
        // descendant::
        assertXPathValue(context, "//street", "Orchard Road");

        // descendent:: with a namespace and wildcard
        assertXPathValue(context, "count(//price:*)", new Double(2));

        assertXPathValueIterator(context, "vendor//saleEnds", list("never"));

        assertXPathValueIterator(context, "vendor//promotion", list(""));

        assertXPathValueIterator(
            context,
            "vendor//saleEnds[../@stores = 'all']",
            list("never"));

        assertXPathValueIterator(
            context,
            "vendor//promotion[../@stores = 'all']",
            list(""));
    }
    
//    public void testAxisDescendantDocumentOrder() {
//        Iterator iter = context.iteratePointers("//*");
//        while (iter.hasNext()) {
//            System.err.println(iter.next());
//        }
//    }

    public void testAxisParent() {
        // parent::
        assertXPathPointer(
            context,
            "//street/..",
            "/vendor[1]/location[1]/address[1]");

        // parent:: (note reverse document order)
        assertXPathPointerIterator(
            context,
            "//street/..",
            list(
                "/vendor[1]/location[2]/address[1]",
                "/vendor[1]/location[1]/address[1]"));

        // parent:: with a namespace and wildcard
        assertXPathValue(
            context,
            "vendor/product/price:sale/saleEnds/parent::price:*" + "/saleEnds",
            "never");
    }

    public void testAxisFollowingSibling() {
        // following-sibling::
        assertXPathValue(
            context,
            "vendor/location[.//employeeCount = 10]/"
                + "following-sibling::location//street",
            "Tangerine Drive");

        // following-sibling:: produces the correct pointer
        assertXPathPointer(
            context,
            "vendor/location[.//employeeCount = 10]/"
                + "following-sibling::location//street",
            "/vendor[1]/location[2]/address[1]/street[1]");
    }

    public void testAxisPrecedingSibling() {
        // preceding-sibling:: produces the correct pointer
        assertXPathPointer(
            context,
            "//location[2]/preceding-sibling::location//street",
            "/vendor[1]/location[1]/address[1]/street[1]");
    }

    public void testAxisAttribute() {
        // attribute::
        assertXPathValue(context, "vendor/location/@id", "100");

        // attribute:: produces the correct pointer
        assertXPathPointer(
            context,
            "vendor/location/@id",
            "/vendor[1]/location[1]/@id");

        // iterate over attributes
        assertXPathValueIterator(
            context,
            "vendor/location/@id",
            list("100", "101"));

        // Using different prefixes for the same namespace
        assertXPathValue(
            context,
            "vendor/product/price:amount/@price:discount",
            "10%");
        
        // namespace uri for an attribute
        assertXPathValue(
            context,
            "namespace-uri(vendor/product/price:amount/@price:discount)",
            "priceNS");

        // local name of an attribute
        assertXPathValue(
            context,
            "local-name(vendor/product/price:amount/@price:discount)",
            "discount");

        // name for an attribute
        assertXPathValue(
            context,
            "name(vendor/product/price:amount/@price:discount)",
            "price:discount");

        // attribute:: with the default namespace
        assertXPathValue(
            context,
            "vendor/product/price:amount/@discount",
            "20%");

        // namespace uri of an attribute with the default namespace
        assertXPathValue(
            context,
            "namespace-uri(vendor/product/price:amount/@discount)",
            "");

        // local name of an attribute with the default namespace
        assertXPathValue(
            context,
            "local-name(vendor/product/price:amount/@discount)",
            "discount");

        // name of an attribute with the default namespace
        assertXPathValue(
            context,
            "name(vendor/product/price:amount/@discount)",
            "discount");

        // attribute:: with a namespace and wildcard
        assertXPathValueIterator(
            context,
            "vendor/product/price:amount/@price:*",
            list("10%"));

        // attribute:: with a wildcard
        assertXPathValueIterator(
            context,
            "vendor/location[1]/@*",
            set("100", "", "local"));

        // attribute:: with default namespace and wildcard
        assertXPathValueIterator(
            context,
            "vendor/product/price:amount/@*",
            list("20%"));

        // Empty attribute
        assertXPathValue(context, "vendor/location/@manager", "");

        // Missing attribute
        assertXPathValueLenient(context, "vendor/location/@missing", null);

        // Missing attribute with namespace
        assertXPathValueLenient(context, "vendor/location/@miss:missing", null);

        // Using attribute in a predicate
        assertXPathValue(
            context,
            "vendor/location[@id='101']//street",
            "Tangerine Drive");
        
        assertXPathValueIterator(
            context,
            "/vendor/location[1]/@*[name()!= 'manager']", list("100",
            "local"));
    }

    public void testAxisNamespace() {
        // namespace::
        assertXPathValueAndPointer(
            context,
            "vendor/product/prix/namespace::price",
            "priceNS",
            "/vendor[1]/product[1]/prix[1]/namespace::price");

        // namespace::*
        assertXPathValue(
            context,
            "count(vendor/product/namespace::*)",
            new Double(3));

        // name of namespace
        assertXPathValue(
            context,
            "name(vendor/product/prix/namespace::price)",
            "price");

        // local name of namespace
        assertXPathValue(
            context,
            "local-name(vendor/product/prix/namespace::price)",
            "price");
    }

    public void testAxisAncestor() {
        // ancestor::
        assertXPathValue(
            context,
            "vendor/product/price:sale/saleEnds/"
                + "ancestor::price:sale/saleEnds",
            "never");

        // ancestor:: with a wildcard
        assertXPathValue(
            context,
            "vendor/product/price:sale/saleEnds/ancestor::price:*"
                + "/saleEnds",
            "never");
    }

    public void testAxisAncestorOrSelf() {
        // ancestor-or-self::
        assertXPathValue(
            context,
            "vendor/product/price:sale/"
                + "ancestor-or-self::price:sale/saleEnds",
            "never");
    }

    public void testAxisFollowing() {
        assertXPathValueIterator(
            context,
            "vendor/contact/following::location//street",
            list("Orchard Road", "Tangerine Drive"));

        // following:: with a namespace
        assertXPathValue(
            context,
            "//location/following::price:sale/saleEnds",
            "never");
    }

    public void testAxisSelf() {
        // self:: with a namespace
        assertXPathValue(
            context,
            "//price:sale/self::price:sale/saleEnds",
            "never");

        // self:: with an unmatching name
        assertXPathValueLenient(context, "//price:sale/self::x/saleEnds", null);
    }

    public void testNodeTypeComment() {
        // comment()
        assertXPathValue(
            context,
            "//product/comment()",
            "We are not buying this product, ever");
    }

    public void testNodeTypeText() {
        // text()
        assertXPathValue(
            context,
            "//product/text()[. != '']",
            "We love this product.");

        // text() pointer
        assertXPathPointer(
            context,
            "//product/text()",
            "/vendor[1]/product[1]/text()[1]");

    }

    public void testNodeTypeProcessingInstruction() {
        // processing-instruction() without an argument
        assertXPathValue(
            context,
            "//product/processing-instruction()",
            "do not show anybody");

        // processing-instruction() with an argument
        assertXPathValue(
            context,
            "//product/processing-instruction('report')",
            "average only");

        // processing-instruction() pointer without an argument
        assertXPathPointer(
            context,
            "//product/processing-instruction('report')",
            "/vendor[1]/product[1]/processing-instruction('report')[1]");

        // processing-instruction name
        assertXPathValue(
            context,
            "name(//product/processing-instruction()[1])",
            "security");
    }

    public void testLang() {
        // xml:lang built-in attribute
        assertXPathValue(context, "//product/prix/@xml:lang", "fr");

        // lang() used the built-in xml:lang attribute
        assertXPathValue(context, "//product/prix[lang('fr')]", "934.99");

        // Default language
        assertXPathValue(
            context,
            "//product/price:sale[lang('en')]/saleEnds",
            "never");
    }

    public void testDocument() {
        assertXPathValue(
            context,
            "$document/vendor/location[1]//street",
            "Orchard Road");

        assertXPathPointer(
            context,
            "$document/vendor/location[1]//street",
            "$document/vendor[1]/location[1]/address[1]/street[1]");

        assertXPathValue(context, "$document/vendor//street", "Orchard Road");
    }

    public void testContainer() {
        assertXPathValue(context, "$container/vendor//street", "Orchard Road");

        assertXPathValue(context, "$container//street", "Orchard Road");

        assertXPathPointer(
            context,
            "$container//street",
            "$container/vendor[1]/location[1]/address[1]/street[1]");

        // Conversion to number
        assertXPathValue(
            context,
            "number(vendor/location/employeeCount)",
            new Double(10));
    }

    public void testElementInVariable() {
        assertXPathValue(context, "$element", "Orchard Road");
    }

    public void testTypeConversions() {
        // Implicit conversion to number
        assertXPathValue(
            context,
            "vendor/location/employeeCount + 1",
            new Double(11));

        // Implicit conversion to boolean
        assertXPathValue(
            context,
            "vendor/location/employeeCount and true()",
            Boolean.TRUE);
    }

    public void testBooleanFunction() {
        assertXPathValue(
            context,
            "boolean(vendor//saleEnds[../@stores = 'all'])",
            Boolean.TRUE);

        assertXPathValue(
            context,
            "boolean(vendor//promotion[../@stores = 'all'])",
            Boolean.TRUE);

        assertXPathValue(
            context,
            "boolean(vendor//promotion[../@stores = 'some'])",
            Boolean.FALSE);
    }
    
    public void testFunctionsLastAndPosition() {
        assertXPathPointer(
                context,
                "vendor//location[last()]",
                "/vendor[1]/location[2]");
    }

    public void testNamespaceMapping() {
        context.registerNamespace("rate", "priceNS");
        context.registerNamespace("goods", "productNS");

        assertEquals("Context node namespace resolution", 
                "priceNS", 
                context.getNamespaceURI("price"));        
        
        assertEquals("Registered namespace resolution", 
                "priceNS", 
                context.getNamespaceURI("rate"));

        // child:: with a namespace and wildcard
        assertXPathValue(context, 
                "count(vendor/product/rate:*)", 
                new Double(2));

        // Preference for externally registered namespace prefix
        assertXPathValueAndPointer(context,
                "//product:name",
                "Box of oranges",
                "/vendor[1]/product[1]/goods:name[1]");
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.