I'm using the attached Graph class to store XML or YAML data and then selecting nodes with a simple path expression:
In case of: <objects> <foo value="1"/> <bar value="2"/> </object> you can do: conf.getString("objects.foo.value"). If you have: <objects> <foo>1</foo> <bar>2</bar> </object> you can do: conf.getString("objects.foo"). This class is different from the Avalon Configuration class, but the same idea (recursivity) could be applied there. And yes, this is the beginning of a common object for both configuration and (a non-XML-specific) DOM :-) For those who don't know about YAML, see www.yaml.org. Rolf.
import java.util.ArrayList; /** This is a generic data structure that can hold XML data but is NOT XML specific. <p>Should be valid for (A subset of) YAML and LDAP data also.</p> <p>This class represents really a node in a graph, but when subnodes are added it can be seen as a graph. We don't speek about child nodes, since this is a graph.</p> @author: Rolf Veen ([EMAIL PROTECTED]> @date: 2001 nov 20 License: Apache 1.1 */ public class Graph { protected String name = null, type = null; protected Object value = null; protected ArrayList nodes = null; protected boolean writable = true; /* Not used at the moment */ public Graph() { } public Graph(String name) { this.name = name; } public Graph(String name, Object value) { this.name = name; this.value = value; } public Graph(String name, Object value, String type) { this.name = name; this.value = value; this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Object getValue() { return value; } public void setValue(Object value) { this.value = value; } public String getType() { return type; } public void setType(String type) { this.type = type; } /** add a subnode */ public void addNode(Graph g) { if (nodes == null) // don't create the Vector before we need it nodes = new ArrayList(); nodes.add(g); } /** add a subnode by specifying its name and value */ public void addNode(String name, Object value) { addNode(new Graph(name, value)); } /** add a subnode by specifying its name, value and type */ public void addNode(String name, Object value, String type) { addNode(new Graph(name, value, type)); } /** add node 'path' and give it value, such that value=get(path) */ public void add(Path path, Object value, String type) { Graph node = this, tmpNode; // reach last known element while (path.next()) { String e = path.getElement(); tmpNode = node.getNode(e); if (tmpNode == null) { path.previous(); break; } node = tmpNode; } // create remaining nodes while (path.next()) { String e = path.getElement(); Graph g = new Graph(e); node.addNode(g); node = g; } node.setValue(value); node.setType(type); } public void add(Path path, Object value) { add(path, value, null); } public void add(String path, Object value, String type) { add(new Path(path), value, type); } public void add(String path, Object value) { add(new Path(path), value, null); } /** put a subnode in place of the first subnode with the same name */ public void setNode(Graph g) throws Exception { String name = g.getName(); if (name == null) throw new Exception("Trying to set and unnamed graph"); int i; for (i = 0; i < size(); i++) { Graph node = (Graph) nodes.get(i); if (name.equals(node.getName())) break; } if (i == size()) addNode(g); else { nodes.set(i, g); } } public void setNode(String name, Object value) throws Exception { setNode(new Graph(name, value)); } /* set the value giving a path */ public void set(Path path, Object value) throws Exception { throw new UnsupportedOperationException("Not yet"); } /* set the value giving a path */ public void set(String path, Object value) throws Exception { set(new Path(path), value); } /** return the number of subnodes */ public int size() { if (nodes == null) return 0; else return nodes.size(); } /** path navigator. This function navigates thru the nodes of the graph until the last path element or last node name is matched. */ public Object get(Path path) throws Exception { Graph node = this, tmpNode; while (path.next()) { String e = path.getElement(); tmpNode = node.getNode(e); if (tmpNode == null) // unknown path return null; node = tmpNode; } if (node.value != null) return node.value; else return node; } public Object get(String path) throws Exception { return get(new Path(path)); } /** get the subnode at index */ public Graph getNode(int index) { return (Graph) nodes.get(index); } /** return the first subnode with this name */ public Graph getNode(String name) { if (name == null) return null; for (int i = 0; i < size(); i++) { Graph node = (Graph) nodes.get(i); if (name.equals(node.name)) return node; } return null; } public String getString(Path path) throws Exception { Object obj = get(path); if (obj != null) return obj.toString(); return null; } public String getString(String path) throws Exception { return getString(new Path(path)); } public float getFloat(String p) throws Exception { return getFloat(new Path(p)); } public float getFloat(Path path) throws Exception { return Float.parseFloat(getString(path)); } public long getLong(String p) throws Exception { return getLong(new Path(p)); } public long getLong(Path path) throws Exception { return Long.parseLong(getNumber(getString(path))); } public int getInt(String p) throws Exception { return getInt(new Path(p)); } public int getInt(Path path) throws Exception { return Integer.parseInt(getNumber(getString(path))); } public boolean getBoolean(String path) throws Exception { return getBoolean(new Path(path)); } public boolean getBoolean(Path path) throws Exception { String value = getString(path); if ("true".equals(value) || "1".equals(value)) return true; else return false; } /** (1) go to the node represented by path, then return subnode values as String[] (2) go to node for path-1, then select nodes with names as the last path element */ public String[] getStringArray(Path path) throws Exception { Graph g = (Graph) get(path); if (g == null) return null; int n = g.size(); if (n == 0) return null; String[] a = new String[n]; for (int i = 0; i < n; i++) a[i] = g.getNode(i).value.toString(); return a; } /** go to the node represented by path, then return subnode values as int[] */ public int[] getIntArray(Path path) throws Exception { Graph g = (Graph) get(path); if (g == null) return null; int n = g.size(); if (n == 0) return null; int[] a = new int[n]; for (int i = 0; i < n; i++) a[i] = Integer.parseInt( g.getNode(i).value.toString() ); // can throw an exception return a; } /** go to the node represented by path, then return subnode values as int[] */ public int[] getIntArray(String path) throws Exception { return getIntArray(new Path(path)); } /** go to the node represented by path, then return subnode values as long[] */ public long[] getLongArray(Path path) throws Exception { Graph g = (Graph) get(path); if (g == null) return null; int n = g.size(); if (n == 0) return null; long[] a = new long[n]; for (int i = 0; i < n; i++) a[i] = Long.parseLong( g.getNode(i).value.toString() ); return a; } /** go to the node represented by path, then return subnode values as long[] */ public long[] getLongArray(String path) throws Exception { return getLongArray(new Path(path)); } /** Nodes in graph g are merged into this graph. */ public void merge(Graph g) { for (int i=0; i<g.size(); i++) addNode(g.getNode(i)); } /** Remove nodes whose value is null and have no subnodes */ public void clean() { int len = size(); for (int i = 0; i < len; i++) { Graph g = getNode(i); if ( g.isNull() ) { nodes.remove(i); i--; len--; } } } /** remove all subnodes with the given name */ public void removeNode(String name) { int len = size(); for (int i = 0; i < len; i++) { Graph g = getNode(i); if (name.equals(g.name)) { nodes.remove(i); i--; len--; } } } /** remove all subnodes with the given name and value */ public void removeNode(String name, String value) { int len = size(); for (int i = 0; i < len; i++) { Graph g = (Graph) nodes.get(i); if (name.equals(g.name) && value.equals(g.value)) { nodes.remove(i); i--; len--; } } } /** return true if this graph has null value and no subnodes */ public boolean isNull() { if (size() == 0 && value == null) return true; return false; } /** return true if this graph has both value and subnodes */ public boolean isInconsistent() { if (size() > 0 && value != null) return true; return false; } /** return true if this graph has value but no subnodes */ public boolean isScalar() { if (size() == 0 && value != null) return true; return false; } /** return true if this node is a vector of scalars. It should have more than one scalar subnode and all subnodes must be scalar or empty. */ public boolean isScalarVector() { int n = 0; for (int i = 0; i < size(); i++) { Graph g = getNode(i); if (g.isScalar()) n++; else if (!g.isNull()) return false; } if (n < 2) return false; return true; } public void print() { print(0); } private void print(int level) { StringBuffer sb = new StringBuffer(); for (int i=0; i<level*2; i++) sb.append(' '); sb.append(name); sb.append(": "); if (value != null) sb.append(value.toString()); System.out.println(sb); sb = null; for (int i=0; i<size(); i++) { Graph g = getNode(i); g.print(level+1); } } /** return only the numeric part of a string */ static String getNumber(String s) { int len = s.length(); StringBuffer sb = new StringBuffer(); for (int i=0; i<len; i++) { if (Character.isDigit(s.charAt(i))) sb.append(s.charAt(i)); else break; } return sb.toString(); } public static void main(String[] args) throws Exception { // example code Graph g = new Graph("example"); Graph g2 = new Graph("disk"); g2.addNode("name","/dev/hda"); Graph node = new Graph("partition"); node.addNode("name","/dev/hda1"); node.addNode("size","819.2 MB"); Graph node2 = new Graph("partition"); node2.addNode("name","/dev/hda2"); node2.addNode("size","603.4 MB"); g2.addNode(node); g2.addNode(node2); g.addNode(g2); g.print(); System.out.println("---"); System.out.println("-> disk.name = "+g.getString("disk.name")); System.out.println("-> disk.partition.size = "+g.getInt("disk.partition.size")); g = (Graph) g.get("disk.partition"); System.out.println("---"); g.print(); } }
import java.util.StringTokenizer; import java.util.ArrayList; /** Simple path tokenizer. @author: Rolf Veen ([EMAIL PROTECTED]> @date: 2001 nov 20 License: Apache 1.1 */ public class Path { ArrayList elements; int index; public Path (String path) { StringTokenizer st = new StringTokenizer(path,"."); elements = new ArrayList(); while (st.hasMoreTokens()) elements.add(st.nextToken()); index = -1; } public boolean next() { index++; return index < elements.size(); } public void previous() { if (--index < -1) index = -1; } public int size() { return elements.size(); } public String getElement() { return (String) elements.get(index); } }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>