|
Emmanuel,
Could you let me know if there is any workaround for this issue or if I can do things differently to make it work? It would be nice if you can give me a patch that I can apply to my local build or let me know what needs to be changed in the XMLConfiguration so I can make my own build. Thanks, Vivek, can you please post your complete code for adding the new properties? Based on the fragments you provided I don't really see the parameters (especially the keys) you pass into the addNodes() method.
Let's say we have an existing xml configuration,
<ss> <test> <property name="testProperty"> <value>test</value> <property> </test> </ss> Now I want add a new property under existing <test> tag, <property name="vivekProperty"> <value>vivek</value> </property> I do following, 1) create a node, HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node("property"); node.setValue(null); 2) Find the path where the "property" tag needs to be added. In my case it's "ss.test(0)" 3) I call addNodes on XMLConfiguration instance, conf.addNodes(propertyPath, propertyNode);
//where propertyPath is ss.test(0) and propertyNode is one created in step 1
4) I check how many property tags are under ss.test(0) - in this case it returns me 2 (1 was just added) 5) I create another node object for the name attribute of property, HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node("name"); node.setValue("vivekProperty); node.setAttribute(true); //setting the node as attribute 6) Find the path where this attribute needs to be added. In this case it's "ss.test(0).property(1)" 7) Add the node, conf.addNodes(attrPath, attrNode);
//where attrPath is ss.test(0).property(1) and attrNode is one created in step 5
8) Create another node for the value tag under property, HierarchicalConfiguration.Node node = new HierarchicalConfiguration.Node("value"); node.setValue(""vivek"); 9) Now, when I try to find the index of the newly added property ("property name="vivekProperty") I get -1. So instead of "ss.test(0).property(1)", I get "ss.test(0).property(-1)". -1 in my code basically means it couldn't find that. <=== So this is wrong. This is the code to get the index of the property with a specific attribute name. So I'm trying to find the index of the property with name="vivekProperty", lookupProp = "ss.test(0).property"; synchronized(conf){ elements = conf.configurationsAt(lookupProp); } for (Iterator it = elements.iterator(); it.hasNext();) { HierarchicalConfiguration sub = (HierarchicalConfiguration) it .next(); if(sub != null){ String name = sub.getString("[@" + attrName + "]"); if(name != null){ if (name.equals(propName)) { isPropFound = true; break; } index = index + 1; } } } if (!isPropFound) { index = -1; } 10) Add the node, conf.addNodes(valuePath, valueNode);
//where valuePath is ss.test(0).property(-1) and valueNode is one created in step 8
11) After all this call save on the XMLConfiguration This in 1.5 is giving me structure like, <ss> <test> <property name="testProperty"> <value>test</value> <property> <property> <name>vivekProperty</name> </property> <property> <value>vivek</value> </property> </test> </ss> I'm not sure if I need to do "addNode" 3 time to add this structure or can it be added in one shot. But, all this used to work fine with 1.3. In our application this is a service so I can call any of the above 3 add nodes individaully in case user may just want to add a new value to an existing property. So the problem looks like is the code "node.setAttribute(true);" (in Step 5) is not seems to be doing the right thing. Instead of adding a attribute name, it's adding a new element name under property, which doesn't work in my case. I tried adding attribute as part of the property element itself,
nodeToAdd.addAttribute(new DefaultConfigurationNode(attrName, newPropertyName));
This seems to work fine. So, instead of using "setAttribute(true)" if I just do addAttribute it seems to work fine. May be that's the right way. I'll leave to you guys to see whether there is any issue in 1.5 or it used to work in 1.3 because of some bug, which has been fixed in 1.5. For me the workaround is working fine now. There was indeed a bug in XMLConfiguration, which prevented attribute nodes from being added using the addNodes() method. A fix was applied. Thank you for spotting this.
Regarding your use case, I think you do not need the addNodes() method, but you can achieve the same effect in an easer way using addProperty(). For instance, in the unit test I wrote to demonstrate this bug I created a structure similar to your test configuration with the following code: conf.addProperty("testAddNodes.property[@name]", "prop1"); conf.addProperty("testAddNodes.property(0).value", "value1"); conf.addProperty("testAddNodes.property(-1)[@name]", "prop2"); conf.addProperty("testAddNodes.property(1).value", "value2"); This creates two <property> structures. If you look at the last two statements, the first one creates a new property node and the name attribute at the same time. The index -1 means that a new node is to be created. The following statement adds the value child node. Here the index of the last property node must be specified. Hope that helps. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||
is supposed to be,
In my code,
1) I first add the <property> tag under the <test> element - by calling conf.addNodes
2) Then I add the name attribute to the newly added property - again by calling conf.addNodes
3) Then I add the value tag under property - again by calling conf.addNodes
I do create a new HierarchicalConfiguration.Node every time to add it.
It all used to work fine in 1.3, but it's failing in 1.5.
Note, my reloading strategy is false - not sure if that has anything to do with this.