001    /* ========================================================================
002     * JCommon : a free general purpose class library for the Java(tm) platform
003     * ========================================================================
004     *
005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006     * 
007     * Project Info:  http://www.jfree.org/jcommon/index.html
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 
011     * the Free Software Foundation; either version 2.1 of the License, or 
012     * (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but 
015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
017     * License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this library; if not, write to the Free Software
021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
022     * USA.  
023     *
024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
025     * in the United States and other countries.]
026     * 
027     * ------------------
028     * AttributeList.java
029     * ------------------
030     * (C)opyright 2003-2005, by Thomas Morgner and Contributors.
031     *
032     * Original Author:  Thomas Morgner;
033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
034     *
035     * $Id: AttributeList.java,v 1.3 2005/10/18 13:35:06 mungady Exp $
036     *
037     * Changes
038     * -------
039     * 25-Sep-2003 : Initial version (TM);
040     * 26-Nov-2003 : Javadoc updates (DG);
041     *
042     */
043    
044    package org.jfree.xml.writer;
045    
046    import java.util.Iterator;
047    import java.util.List;
048    
049    /**
050     * The attribute list is used by a writer to specify the attributes
051     * of an XML element in a certain order.
052     *
053     * @author Thomas Morgner
054     */
055    public class AttributeList {
056    
057        /**
058         * A name/value pair of the attribute list.
059         */
060        private static class AttributeEntry {
061            
062            /** The name of the attribute entry. */
063            private String name;
064            
065            /** The value of the attribute entry. */
066            private String value;
067    
068            /**
069             * Creates a new attribute entry for the given name and value.
070             *
071             * @param name  the attribute name (<code>null</code> not permitted).
072             * @param value the attribute value (<code>null</code> not permitted).
073             */
074            public AttributeEntry(final String name, final String value) {
075                if (name == null) {
076                    throw new NullPointerException("Name must not be null. [" 
077                                                   + name + ", " + value + "]");
078                }
079                if (value == null) {
080                    throw new NullPointerException("Value must not be null. [" 
081                                                   + name + ", " + value + "]");
082                }
083                this.name = name;
084                this.value = value;
085            }
086    
087            /**
088             * Returns the attribute name.
089             * 
090             * @return the name.
091             */
092            public String getName() {
093                return this.name;
094            }
095    
096            /**
097             * Returns the value of this attribute entry.
098             * 
099             * @return the value of the entry.
100             */
101            public String getValue() {
102                return this.value;
103            }
104    
105            /**
106             * Checks whether the given object is an attribute entry with the same name.
107             * 
108             * @param o  the suspected other attribute entry.
109             * 
110             * @return <code>true</code> if the given object is equal, <code>false</code> otherwise.
111             */
112            public boolean equals(final Object o) {
113                if (this == o) {
114                    return true;
115                }
116                if (!(o instanceof AttributeEntry)) {
117                    return false;
118                }
119    
120                final AttributeEntry attributeEntry = (AttributeEntry) o;
121                if (!this.name.equals(attributeEntry.name)) {
122                    return false;
123                }
124                return true;
125            }
126    
127            /**
128             * Computes an hashcode for this entry.
129             * 
130             * @return the hashcode.
131             */
132            public int hashCode() {
133                return this.name.hashCode();
134            }
135        }
136    
137        /**
138         * An iterator over the attribute names of this list.
139         */
140        private static class AttributeIterator implements Iterator {
141            
142            /** The backend is an iterator over the attribute entries. */
143            private Iterator backend;
144    
145            /**
146             * Creates a new attribute iterator using the given iterator as backend.
147             * 
148             * @param backend  an iterator over the attribute entries (<code>null</code> not permitted).
149             */
150            public AttributeIterator(final Iterator backend) {
151                if (backend == null) {
152                    throw new NullPointerException();
153                }
154                this.backend = backend;
155            }
156    
157            /**
158             * Returns <tt>true</tt> if the iteration has more elements. (In other
159             * words, returns <tt>true</tt> if <tt>next</tt> would return an element
160             * rather than throwing an exception.)
161             *
162             * @return <tt>true</tt> if the iterator has more elements.
163             */
164            public boolean hasNext() {
165                return this.backend.hasNext();
166            }
167    
168            /**
169             * Returns the next element in the iteration.
170             *
171             * @return the next element in the iteration.
172             */
173            public Object next() {
174                final AttributeEntry entry = (AttributeEntry) this.backend.next();
175                if (entry != null) {
176                    return entry.getName();
177                }
178                return entry;
179            }
180    
181            /**
182             *
183             * Removes from the underlying collection the last element returned by the
184             * iterator (optional operation).  This method can be called only once per
185             * call to <tt>next</tt>.  The behavior of an iterator is unspecified if
186             * the underlying collection is modified while the iteration is in
187             * progress in any way other than by calling this method.
188             */
189            public void remove() {
190                this.backend.remove();
191            }
192        }
193    
194        /** The storage for all entries of this list. */
195        private List entryList;
196    
197        /**
198         * Creates an empty attribute list with no default values.
199         */
200        public AttributeList() {
201            this.entryList = new java.util.ArrayList();
202        }
203    
204        /**
205         * Returns an iterator over all attribute names. The names are returned
206         * in their oder of addition to the list. The iterator contains strings.
207         *
208         * @return the iterator over all attribute names.
209         */
210        public Iterator keys() {
211            return new AttributeIterator(this.entryList.iterator());
212        }
213    
214        /**
215         * Defines an attribute.
216         * 
217         * @param name the name of the attribute to be defined
218         * @param value the value of the attribute.
219         */
220        public synchronized void setAttribute(final String name, final String value) {
221            final AttributeEntry entry = new AttributeEntry(name, value);
222            final int pos = this.entryList.indexOf(entry);
223            if (pos != -1) {
224                this.entryList.remove(pos);
225            }
226            this.entryList.add(entry);
227        }
228    
229        /**
230         * Returns the attribute value for the given attribute name or null,
231         * if the attribute is not defined in this list.
232         *
233         * @param name the name of the attribute
234         * @return the attribute value or null.
235         */
236        public synchronized String getAttribute(final String name) {
237            return getAttribute(name, null);
238        }
239    
240        /**
241         * Returns the attribute value for the given attribute name or the given
242         * defaultvalue, if the attribute is not defined in this list.
243         *
244         * @param name the name of the attribute.
245         * @param defaultValue  the default value.
246         * 
247         * @return the attribute value or the defaultValue.
248         */
249        public synchronized String getAttribute(final String name, final String defaultValue) {
250            for (int i = 0; i < this.entryList.size(); i++) {
251                final AttributeEntry ae = (AttributeEntry) this.entryList.get(i);
252                if (ae.getName().equals(name)) {
253                    return ae.getValue();
254                }
255            }
256            return defaultValue;
257        }
258    
259        /**
260         * Removes the attribute with the given name from the list.
261         *
262         * @param name the name of the attribute which should be removed..
263         */
264        public synchronized void removeAttribute(final String name) {
265            for (int i = 0; i < this.entryList.size(); i++) {
266                final AttributeEntry ae = (AttributeEntry) this.entryList.get(i);
267                if (ae.getName().equals(name)) {
268                    this.entryList.remove(ae);
269                    return;
270                }
271            }
272        }
273    }