001/*
002// $Id: //open/util/resgen/src/org/eigenbase/xom/GenericDef.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) 2001-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// jhyde, 3 October, 2001
024*/
025
026package org.eigenbase.xom;
027import java.io.PrintWriter;
028import java.util.Hashtable;
029import java.util.Vector;
030
031/**
032 * A <code>GenericDef</code> is a {@link ElementDef} whose attributes and
033 * children are stored in collections, not generated members.  It is convenient
034 * for building XML documents, but is not strongly typed.
035 *
036 * @author jhyde
037 * @since 3 October, 2001
038 * @version $Id: //open/util/resgen/src/org/eigenbase/xom/GenericDef.java#3 $
039 **/
040public class GenericDef extends ElementDef {
041    private String tagName;
042    private Vector children;
043    private OrderedStringMap attributes;
044
045    public GenericDef(String tagName)
046    {
047        this.tagName = tagName;
048        this.children = new Vector();
049        this.attributes = new OrderedStringMap();
050    }
051
052    // implement ElementDef
053    public void display(PrintWriter out, int indent)
054    {
055        out.println(getName());
056        for (int i = 0, count = attributes.size(); i < count; i++) {
057            String key = attributes.keyAt(i);
058            Object value = attributes.valueAt(i);
059            displayAttribute(out, key, value.toString(), indent + 1);
060        }
061        for (int i = 0, count = children.size(); i < count; i++) {
062            ElementDef child = (ElementDef) children.elementAt(i);
063            displayElement(out, "?", child, indent + 1);
064        }
065    }
066
067    // implement NodeDef
068    public void displayXML(XMLOutput out, int indent)
069    {
070        out.beginBeginTag(tagName);
071        for (int i = 0, count = attributes.size(); i < count; i++) {
072            String key = attributes.keyAt(i);
073            Object value = attributes.valueAt(i);
074            out.attribute(key, value.toString());
075        }
076        out.endBeginTag(tagName);
077        for (int i = 0, count = children.size(); i < count; i++) {
078            NodeDef child = (NodeDef) children.elementAt(i);
079            child.displayXML(out, indent + 1);
080        }
081        out.endTag(tagName);
082    }
083
084    // override ElementDef
085    public int getType()
086    {
087        return DOMWrapper.ELEMENT;
088    }
089
090    /**
091     * Returns the tag name of this element, or null for TEXT elements.
092     */
093    public String getName()
094    {
095        return tagName;
096    }
097
098    public void addChild(NodeDef element)
099    {
100        children.addElement(element);
101    }
102
103    public NodeDef[] getChildren()
104    {
105        NodeDef[] a = new NodeDef[children.size()];
106        children.copyInto(a);
107        return a;
108    }
109
110    public void setAttribute(String key, Object value)
111    {
112        attributes.put(key, value);
113    }
114
115    public Object getAttribute(String key)
116    {
117        return attributes.get(key);
118    }
119
120    private static class OrderedStringMap
121    {
122        Vector v;
123        Hashtable h;
124
125        OrderedStringMap()
126        {
127            v = new Vector();
128            h = new Hashtable();
129        }
130        int size()
131        {
132            return v.size();
133        }
134        Object get(String key)
135        {
136            return h.get(key);
137        }
138        void put(String key, Object value)
139        {
140            if (h.put(key, value) == null) {
141                // attribute does not have a value; append to vector
142                v.addElement(new StringMapEntry(key,value));
143            } else {
144                // attribute already has a value; replace it
145                for (int i = 0, count = v.size(); i < count; i++) {
146                    StringMapEntry entry = (StringMapEntry) v.elementAt(i);
147                    if (entry.key.equals(key)) {
148                        entry.value = value;
149                        return;
150                    }
151                }
152                throw new Error(
153                    "key " + key + " not found in OrderedStringMap");
154            }
155        }
156        String keyAt(int i)
157        {
158            return ((StringMapEntry) v.elementAt(i)).key;
159        }
160        Object valueAt(int i)
161        {
162            return ((StringMapEntry) v.elementAt(i)).value;
163        }
164    };
165
166    private static class StringMapEntry
167    {
168        String key;
169        Object value;
170        StringMapEntry(String key, Object value)
171        {
172            this.key = key;
173            this.value = value;
174        }
175    }
176}
177
178
179// End GenericDef.java