001/*
002// $Id: //open/util/resgen/src/org/eigenbase/xom/DefWalker.java#3 $
003// Package org.eigenbase.xom is an XML Object Mapper.
004// Copyright (C) 2005-2005 The Eigenbase Project
005// Copyright (C) 2005-2005 Disruptive Tech
006// Copyright (C) 2005-2005 LucidEra, Inc.
007// Portions Copyright (C) 2000-2005 Kana Software, Inc. and others.
008//
009// This library is free software; you can redistribute it and/or modify it
010// under the terms of the GNU Lesser General Public License as published by the
011// Free Software Foundation; either version 2 of the License, or (at your
012// option) any later version approved by The Eigenbase Project.
013//
014// This library is distributed in the hope that it will be useful, 
015// but WITHOUT ANY WARRANTY; without even the implied warranty of
016// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017// GNU Lesser General Public License for more details.
018// 
019// You should have received a copy of the GNU Lesser General Public License
020// along with this library; if not, write to the Free Software
021// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
022//
023// dsommerfield, 18 February, 2001
024*/
025
026package org.eigenbase.xom;
027
028import java.lang.reflect.Array;
029import java.util.Vector;
030
031/**
032 * DefWalker is a class designed to help users of plugin elements and elements
033 * with content type ANY.  It walks through an array of ElementDef, searching
034 * for and returning portions as the correct types.
035 */
036public class DefWalker {
037
038    private NodeDef[] defs;
039    private int pos;
040
041    /**
042     * Construct a DefWalker, attaching it to a NodeDef array and
043     * specifying a PrintWriter to display error messages for later
044     * consumption.
045     * @param defs a NodeDef array to walk.  All returned objects
046     * come from this array.
047     */
048    public DefWalker(NodeDef[] defs)
049    {
050        this.defs = defs;
051        pos = 0;
052    }
053
054    /**
055     * Returns the next node in the defs array, but only if it matches
056     * the provided class <i>elemType</i>.
057     * @param elemType the Class of NodeDef to expect.  This class will
058     * always be assignable from the returned object.
059     * @throws XOMException if there are no more nodes in the defs
060     * array or if the next node is of an incorrect type.
061     */
062    public NodeDef expect(Class elemType)
063        throws XOMException
064    {
065        if(pos >= defs.length)
066            throw new XOMException("Expecting a Node of type "
067                                      + elemType.getName() + " but no "
068                                      + "Nodes remain.");
069        if(!(elemType.isAssignableFrom(defs[pos].getClass())))
070            throw new XOMException("Expecting a Node of type "
071                                      + elemType.getName() + " but "
072                                      + "found a Node of type "
073                                      + defs[pos].getClass().getName());
074        return defs[pos++];
075    }
076
077    /**
078     * Returns a portion of the remaining nodes in the defs array as an
079     * array.  All nodes in the array will be of the specified class
080     * <i>elemType</i>.  The nodes are returned as a generic NodeDef[]
081     * array and may need to be explicitly converted to an array of the
082     * appropriate type by the caller.
083     * @param elemType the Class of NodeDef to expect and return.  This
084     * class will always be assignable from each returned object in the
085     * array.
086     */
087    public NodeDef[] expectArray(Class elemType)
088    {
089        Vector found = new Vector();
090        while(pos < defs.length &&
091              elemType.isAssignableFrom(defs[pos].getClass()))
092            found.addElement(defs[pos++]);
093
094        NodeDef[] ret = new NodeDef[found.size()];
095        for(int i=0; i<found.size(); i++)
096            ret[i] = (NodeDef)(found.elementAt(i));
097        return ret;
098    }
099
100    /**
101     * Returns a portion of the remaining nodes in the defs array as an
102     * array.  All nodes in the array will be of the specified class
103     * <i>elemType</i>.  The nodes are in an array of the specified type,
104     * which will be returned as an object (which must be cast to the
105     * appropriate array type by the caller when needed.
106     * @param elemType the Class of NodeDef to expect and return.  This
107     * class will always be assignable from each returned object in the
108     * array.
109     */
110    public Object expectTypeArray(Class elemType)
111    {
112        Vector found = new Vector();
113        while(pos < defs.length &&
114              elemType.isAssignableFrom(defs[pos].getClass()))
115            found.addElement(defs[pos++]);
116
117        Object ret = Array.newInstance(elemType, found.size());
118        for(int i=0; i<found.size(); i++)
119            Array.set(ret, i, found.elementAt(i));
120        return ret;
121    }
122}
123
124
125// End DefWalker.java