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]>