001/*
002 * Dictionary.java July 2006
003 *
004 * Copyright (C) 2006, Niall Gallagher <niallg@users.sf.net>
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
015 * implied. See the License for the specific language governing 
016 * permissions and limitations under the License.
017 */
018
019package org.simpleframework.xml.util;
020
021import java.util.AbstractSet;
022import java.util.HashMap;
023import java.util.Iterator;
024import java.util.LinkedHashMap;
025
026/**
027 * The <code>Dictionary</code> object represents a mapped set of entry
028 * objects that can be serialized and deserialized. This is used when
029 * there is a need to load a list of objects that can be mapped using 
030 * a name attribute. Using this object avoids the need to implement a
031 * commonly required pattern of building a map of XML element objects.
032 * <pre>
033 *
034 *    &lt;dictionary&gt;
035 *       &lt;entry name="example"&gt;
036 *          &lt;element&gt;example text&lt;/element&gt;
037 *       &lt;/entry&gt;
038 *       &lt;entry name="example"&gt;
039 *          &lt;element&gt;example text&lt;/element&gt;
040 *       &lt;/entry&gt;       
041 *    &lt;/dictionary&gt;
042 * 
043 * </pre>
044 * This can contain implementations of the <code>Entry</code> object 
045 * which contains a required "name" attribute. Implementations of the
046 * entry object can add further XML attributes an elements. This must
047 * be annotated with the <code>ElementList</code> annotation in order
048 * to be serialized and deserialized as an object field.
049 * 
050 * @author Niall Gallagher
051 *
052 * @see org.simpleframework.xml.util.Entry
053 */ 
054public class Dictionary<T extends Entry> extends AbstractSet<T> {
055
056   /**
057    * Used to map the entries to their configured names.
058    */         
059   protected final Table<T> map;
060        
061   /**
062    * Constructor for the <code>Dictionary</code> object. This 
063    * is used to create a set that contains entry objects mapped 
064    * to an XML attribute name value. Entry objects added to this
065    * dictionary can be retrieved using its name value.
066    */ 
067   public Dictionary() {
068      this.map = new Table<T>();           
069   }
070
071   /**
072    * This method is used to add the provided entry to this set. If
073    * an entry of the same name already existed within the set then
074    * it is replaced with the specified <code>Entry</code> object.
075    * 
076    * @param item this is the entry object that is to be inserted
077    */ 
078   public boolean add(T item) {
079      return map.put(item.getName(), item) != null;           
080   }
081
082   /**
083    * This returns the number of <code>Entry</code> objects within
084    * the dictionary. This will use the internal map to acquire the
085    * number of entry objects that have been inserted to the map.
086    *
087    * @return this returns the number of entry objects in the set
088    */ 
089   public int size() {
090      return map.size();            
091   }
092
093   /**
094    * Returns an iterator of <code>Entry</code> objects which can be
095    * used to remove items from this set. This will use the internal
096    * map object and return the iterator for the map values.
097    * 
098    * @return this returns an iterator for the entry objects
099    */ 
100   public Iterator<T> iterator() {
101      return map.values().iterator();            
102   }
103
104   /**
105    * This is used to acquire an <code>Entry</code> from the set by
106    * its name. This uses the internal map to look for the entry, if
107    * the entry exists it is returned, if not this returns null.
108    * 
109    * @param name this is the name of the entry object to retrieve
110    *
111    * @return this returns the entry mapped to the specified name
112    */ 
113   public T get(String name) {
114      return map.get(name);           
115   }
116
117   /**
118    * This is used to remove an <code>Entry</code> from the set by
119    * its name. This uses the internal map to look for the entry, if
120    * the entry exists it is returned and removed from the map.
121    * 
122    * @param name this is the name of the entry object to remove
123    *
124    * @return this returns the entry mapped to the specified name
125    */ 
126   public T remove(String name) {
127      return map.remove(name);           
128   }
129 
130   /**
131    * The <code>Table</code> object is used to represent a map of
132    * entries mapped to a string name. Each implementation of the
133    * entry must contain a name attribute, which is used to insert
134    * the entry into the map. This acts as a typedef.
135    *
136    * @see org.simpleframework.xml.util.Entry
137    */
138   // ConversionTest assumes that order of add() is preserved, so this has to be a LinkedHashMap.
139   private static class Table<T> extends LinkedHashMap<String, T> {
140      
141      /**
142       * Constructor for the <code>Table</code> object. This will
143       * create a map that is used to store the entry objects that
144       * are serialized and deserialized to and from an XML source.
145       */
146      public Table() {
147         super();
148      }         
149   }     
150}