KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > runtime > EnumSet


1 /*
2 Copyright (c) 2004, Dennis M. Sosnoski
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.runtime;
30
31 import java.util.Arrays JavaDoc;
32 import java.util.Comparator JavaDoc;
33
34 /**
35  * Named value set support class. This provides convenience methods to support
36  * working with a set of named <code>static final int</code> values, including
37  * translating them to and from <code>String</code> representations. It's
38  * intended for use with relatively small nonnegative int values.
39  *
40  * @author Dennis M. Sosnoski
41  * @version 1.0
42  */

43
44 public class EnumSet
45 {
46     /** Maximum <code>int</code> value supported for enumerations. */
47     public static final int VALUE_LIMIT = 512;
48     
49     /** Actual item definitions (used for extensions). */
50     private final EnumItem[] m_items;
51     
52     /** Enumeration names in index number order. */
53     private final String JavaDoc[] m_indexedNames;
54     
55     /** Enumeration names in sort order. */
56     private final String JavaDoc[] m_orderedNames;
57     
58     /** Index values corresponding to sorted names. */
59     private final int[] m_orderedIndexes;
60
61     /**
62      * Constructor from array of enumeration items. The supplied items can be in
63      * any order, and the numeric values do not need to be contiguous (but must
64      * be unique, nonnegative, and should be fairly small). Note that this
65      * constructor will reorder the items in the supplied array as a side
66      * effect.
67      *
68      * @param items array of enumeration items (will be reordered)
69      */

70      
71     public EnumSet(EnumItem[] items) {
72         m_items = items;
73         if (items.length > 0) {
74             
75             // first sort items in ascending name order
76
Arrays.sort(items, new Comparator JavaDoc() {
77                 public int compare(Object JavaDoc a, Object JavaDoc b) {
78                     return ((EnumItem)a).m_name.compareTo(((EnumItem)b).m_name);
79                 }
80             });
81             
82             // populate arrays for name lookup
83
m_orderedNames = new String JavaDoc[items.length];
84             m_orderedIndexes = new int[items.length];
85             int high = -1;
86             for (int i = 0; i < items.length; i++) {
87                 EnumItem item = items[i];
88                 if (item.m_value < 0) {
89                     throw new IllegalArgumentException JavaDoc("Negative item value " +
90                         item.m_value + " not allowed");
91                 } else if (item.m_value > high) {
92                     high = item.m_value;
93                     if (high >= VALUE_LIMIT) {
94                         throw new IllegalArgumentException JavaDoc
95                             ("Enumeration with value " +
96                             high + " too large to be used.");
97                     }
98                 }
99                 m_orderedNames[i] = item.m_name;
100                 m_orderedIndexes[i] = item.m_value;
101             }
102             
103             // populate array for indexed lookup of names
104
m_indexedNames = new String JavaDoc[high+1];
105             for (int i = 0; i < items.length; i++) {
106                 EnumItem item = items[i];
107                 if (m_indexedNames[item.m_value] == null) {
108                     m_indexedNames[item.m_value] = item.m_name;
109                 } else {
110                     throw new IllegalArgumentException JavaDoc
111                         ("Duplicate index value " + item.m_value);
112                 }
113             }
114             
115         } else {
116             m_indexedNames = new String JavaDoc[0];
117             m_orderedNames = new String JavaDoc[0];
118             m_orderedIndexes = new int[0];
119         }
120     }
121
122     /**
123      * Constructor from array of names. The value associated with each name is
124      * just the position index in the array added to the start value.
125      *
126      * @param start item value for first added name
127      * @param names array of names (no <code>null</code> entries allowed)
128      */

129      
130     public EnumSet(int start, String JavaDoc[] names) {
131         this(buildItems(start, names));
132     }
133
134     /**
135      * Constructor from existing enumeration with added names. The value
136      * associated with each name is just the position index in the array added
137      * to the start value.
138      *
139      * @param base base enumeration to be extended
140      * @param start item value for first added name
141      * @param names array of names (no <code>null</code> entries allowed)
142      */

143      
144     public EnumSet(EnumSet base, int start, String JavaDoc[] names) {
145         this(mergeItems(base, start, names));
146     }
147
148     /**
149      * Generate array of enumeration items from array of names. The value
150      * associated with each name is just the position index in the array added
151      * to the start value.
152      *
153      * @param start item value for first added name
154      * @param names array of names (no <code>null</code> entries allowed)
155      */

156      
157     private static EnumItem[] buildItems(int start, String JavaDoc[] names) {
158         EnumItem[] items = new EnumItem[names.length];
159         for (int i = 0; i < items.length; i++) {
160             items[i] = new EnumItem(start+i, names[i]);
161         }
162         return items;
163     }
164
165     /**
166      * Generate array of enumeration items from base enumeration and array of
167      * names. The value associated with each name is just the position index in
168      * the array added to the start value.
169      *
170      * @param base base enumeration to be extended
171      * @param start item value for first added name
172      * @param names array of names (no <code>null</code> entries allowed)
173      */

174      
175     private static EnumItem[] mergeItems(EnumSet base, int start,
176         String JavaDoc[] names) {
177         int prior = base.m_items.length;
178         EnumItem[] merges = new EnumItem[prior + names.length];
179         System.arraycopy(base.m_items, 0, merges, 0, prior);
180         for (int i = 0; i < names.length; i++) {
181             merges[prior+i] = new EnumItem(start+i, names[i]);
182         }
183         return merges;
184     }
185     
186     /**
187      * Get name for value.
188      *
189      * @param value enumeration value
190      * @return name for value
191      */

192      
193             
194     public String JavaDoc getName(int value) {
195         if (value >= 0 && value < m_indexedNames.length) {
196             String JavaDoc name = m_indexedNames[value];
197             if (name != null) {
198                 return name;
199             }
200         }
201         throw new IllegalArgumentException JavaDoc("Value " + value + " not defined");
202     }
203     
204     /**
205      * Get value for name if defined.
206      *
207      * @param name possible enumeration name
208      * @return value for name, or <code>-1</code> if not found in enumeration
209      */

210      
211     public int getValue(String JavaDoc name) {
212         int base = 0;
213         int limit = m_orderedNames.length - 1;
214         while (base <= limit) {
215             int cur = (base + limit) >> 1;
216             int diff = name.compareTo(m_orderedNames[cur]);
217             if (diff < 0) {
218                 limit = cur - 1;
219             } else if (diff > 0) {
220                 base = cur + 1;
221             } else if (m_orderedIndexes != null) {
222                 return m_orderedIndexes[cur];
223             } else {
224                 return cur;
225             }
226         }
227         return -1;
228     }
229     
230     /**
231      * Get value for name. If the supplied name is not present in the
232      * enumeration this throws an exception.
233      *
234      * @param name enumeration name
235      * @return value for name
236      */

237      
238     public int getValueChecked(String JavaDoc name) {
239         int index = getValue(name);
240         if (index >= 0) {
241             return index;
242         } else {
243             throw new IllegalArgumentException JavaDoc("Name " + name + " not defined");
244         }
245     }
246     
247     /**
248      * Enumeration pair information. This gives an <code>int</code> value along
249      * with the associated <code>String</code> representation.
250      */

251      
252     public static class EnumItem {
253         public final int m_value;
254         public final String JavaDoc m_name;
255         
256         public EnumItem(int value, String JavaDoc name) {
257             m_value = value;
258             m_name = name;
259         }
260     }
261 }
Popular Tags