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

Reply via email to