Return-Path: X-Original-To: apmail-commons-commits-archive@minotaur.apache.org Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 42BA56653 for ; Fri, 29 Jul 2011 19:23:37 +0000 (UTC) Received: (qmail 12985 invoked by uid 500); 29 Jul 2011 19:23:36 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 12672 invoked by uid 500); 29 Jul 2011 19:23:36 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 12665 invoked by uid 99); 29 Jul 2011 19:23:35 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 29 Jul 2011 19:23:35 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 29 Jul 2011 19:23:32 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id BDEF123889E3 for ; Fri, 29 Jul 2011 19:23:10 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1152343 - in /commons/proper/configuration/trunk/src: java/org/apache/commons/configuration/tree/xpath/ test/org/apache/commons/configuration/tree/xpath/ Date: Fri, 29 Jul 2011 19:23:10 -0000 To: commits@commons.apache.org From: oheger@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110729192310.BDEF123889E3@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: oheger Date: Fri Jul 29 19:23:09 2011 New Revision: 1152343 URL: http://svn.apache.org/viewvc?rev=1152343&view=rev Log: [CONFIGURATION-452] XPathExpressionEngine now supports keys for adding or setting properties without a whitespace. Added: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngineInConfig.java (with props) Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngine.java Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java?rev=1152343&r1=1152342&r2=1152343&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/xpath/XPathExpressionEngine.java Fri Jul 29 19:23:09 2011 @@ -129,6 +129,12 @@ public class XPathExpressionEngine imple + ATTR_DELIMITER; /** + * Constant for a space which is used as delimiter in keys for adding + * properties. + */ + private static final String SPACE = " "; + + /** * Executes a query. The passed in property key is directly passed to a * JXPath context. * @@ -213,18 +219,15 @@ public class XPathExpressionEngine imple "prepareAdd: key must not be null!"); } - int index = key.length() - 1; - while (index >= 0 && !Character.isWhitespace(key.charAt(index))) - { - index--; - } + String addKey = key; + int index = findKeySeparator(addKey); if (index < 0) { - throw new IllegalArgumentException( - "prepareAdd: Passed in key must contain a whitespace!"); + addKey = generateKeyForAdd(root, addKey); + index = findKeySeparator(addKey); } - List nodes = query(root, key.substring(0, index).trim()); + List nodes = query(root, addKey.substring(0, index).trim()); if (nodes.size() != 1) { throw new IllegalArgumentException( @@ -233,7 +236,7 @@ public class XPathExpressionEngine imple NodeAddData data = new NodeAddData(); data.setParent((ConfigurationNode) nodes.get(0)); - initNodeAddData(data, key.substring(index).trim()); + initNodeAddData(data, addKey.substring(index).trim()); return data; } @@ -324,6 +327,37 @@ public class XPathExpressionEngine imple } /** + * Tries to generate a key for adding a property. This method is called if a + * key was used for adding properties which does not contain a space + * character. It splits the key at its single components and searches for + * the last existing component. Then a key compatible for adding properties + * is generated. + * + * @param root the root node of the configuration + * @param key the key in question + * @return the key to be used for adding the property + */ + private String generateKeyForAdd(ConfigurationNode root, String key) + { + int pos = key.lastIndexOf(PATH_DELIMITER, key.length()); + + while (pos >= 0) + { + String keyExisting = key.substring(0, pos); + if (!query(root, keyExisting).isEmpty()) + { + StringBuffer buf = new StringBuffer(key.length() + 1); + buf.append(keyExisting).append(SPACE); + buf.append(key.substring(pos + 1)); + return buf.toString(); + } + pos = key.lastIndexOf(PATH_DELIMITER, pos - 1); + } + + return SPACE + key; + } + + /** * Helper method for throwing an exception about an invalid path. * * @param path the invalid path @@ -335,6 +369,23 @@ public class XPathExpressionEngine imple + "\" " + msg); } + /** + * Determines the position of the separator in a key for adding new + * properties. If no delimiter is found, result is -1. + * + * @param key the key + * @return the position of the delimiter + */ + private static int findKeySeparator(String key) + { + int index = key.length() - 1; + while (index >= 0 && !Character.isWhitespace(key.charAt(index))) + { + index--; + } + return index; + } + // static initializer: registers the configuration node pointer factory static { Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngine.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngine.java?rev=1152343&r1=1152342&r2=1152343&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngine.java (original) +++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngine.java Fri Jul 29 19:23:09 2011 @@ -20,6 +20,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import junit.framework.TestCase; + import org.apache.commons.configuration.tree.ConfigurationNode; import org.apache.commons.configuration.tree.DefaultConfigurationNode; import org.apache.commons.configuration.tree.NodeAddData; @@ -27,8 +29,6 @@ import org.apache.commons.jxpath.JXPathC import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl; import org.apache.commons.jxpath.ri.model.NodePointerFactory; -import junit.framework.TestCase; - /** * Test class for XPathExpressionEngine. * @@ -256,23 +256,6 @@ public class TestXPathExpressionEngine e } /** - * Tests an add operation where the passed in key has an invalid format: it - * does not contain a whitspace. This will cause an error. - */ - public void testPrepareAddInvalidFormat() - { - try - { - engine.prepareAdd(ROOT, "anInvalidKey"); - fail("Could add an invalid key!"); - } - catch (IllegalArgumentException iex) - { - // ok - } - } - - /** * Tests an add operation with an empty path for the new node. */ public void testPrepareAddEmptyPath() Added: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngineInConfig.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngineInConfig.java?rev=1152343&view=auto ============================================================================== --- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngineInConfig.java (added) +++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngineInConfig.java Fri Jul 29 19:23:09 2011 @@ -0,0 +1,111 @@ +/* + * 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.configuration.tree.xpath; + +import junit.framework.TestCase; + +import org.apache.commons.configuration.XMLConfiguration; + +/** + * A test class for XPathExpressionEngine that tests the engine integrated into + * a hierarchical configuration. + * + * @author Commons + * Configuration team + * @version $Id$ + */ +public class TestXPathExpressionEngineInConfig extends TestCase +{ + /** Constant for a test key. */ + private static final String KEY = "test/expression/xpath"; + + /** Constant for a value for test properties. */ + private static final String VALUE = "success"; + + /** The test configuration. */ + private XMLConfiguration config; + + protected void setUp() throws Exception + { + super.setUp(); + config = new XMLConfiguration(); + config.setExpressionEngine(new XPathExpressionEngine()); + } + + /** + * Tests whether an already existing property can be changed using + * setProperty(). + */ + public void testSetPropertyExisting() + { + config.addProperty(" " + KEY, "failure"); + config.setProperty(KEY, VALUE); + assertEquals("Value not changed", VALUE, config.getString(KEY)); + } + + /** + * Tests setProperty() if the specified path partly exists. + */ + public void testSetPropertyPartlyExisting() + { + final String testKey = KEY + "/sub"; + config.addProperty(" " + KEY, "test"); + config.setProperty(testKey, VALUE); + assertEquals("Value not set", VALUE, config.getString(testKey)); + } + + /** + * Tests whether setProperty() can be used to add a new attribute. + */ + public void testSetPropertyNewAttribute() + { + final String keyAttr = KEY + "/@attr"; + config.addProperty(" " + KEY, "test"); + config.setProperty(keyAttr, VALUE); + assertEquals("Value not set", VALUE, config.getString(keyAttr)); + } + + /** + * Tests whether setProperty() can be used to create a completely new key. + */ + public void testSetPropertyNewKey() + { + config.setProperty(KEY, VALUE); + assertEquals("Value not set", VALUE, config.getString(KEY)); + } + + /** + * Tests whether addProperty() can be used to create more complex + * hierarchical structures. + */ + public void testAddPropertyComplexStructures() + { + config.addProperty("tables/table/name", "tasks"); + config.addProperty("tables/table[last()]/@type", "system"); + config.addProperty("tables/table[last()]/fields/field/name", "taskid"); + config.addProperty("tables/table[last()]/fields/field[last()]/@type", + "int"); + config.addProperty("tables table/name", "documents"); + assertEquals("Wrong table 1", "tasks", + config.getString("tables/table[1]/name")); + assertEquals("Wrong table 2", "documents", + config.getString("tables/table[2]/name")); + assertEquals("Wrong field type", "int", + config.getString("tables/table[1]/fields/field[1]/@type")); + } +} Propchange: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngineInConfig.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngineInConfig.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/tree/xpath/TestXPathExpressionEngineInConfig.java ------------------------------------------------------------------------------ svn:mime-type = text/plain