KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > util > KeywordValueTable


1
2 /*
3  * Enhydra Java Application Server Project
4  *
5  * The contents of this file are subject to the Enhydra Public License
6  * Version 1.1 (the "License"); you may not use this file except in
7  * compliance with the License. You may obtain a copy of the License on
8  * the Enhydra web site ( http://www.enhydra.org/ ).
9  *
10  * Software distributed under the License is distributed on an "AS IS"
11  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
12  * the License for the specific terms governing rights and limitations
13  * under the License.
14  *
15  * The Initial Developer of the Enhydra Application Server is Lutris
16  * Technologies, Inc. The Enhydra Application Server and portions created
17  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
18  * All Rights Reserved.
19  *
20  * Contributor(s):
21  *
22  * $Id: KeywordValueTable.java,v 1.3 2005/03/24 12:23:18 slobodan Exp $
23  */

24
25
26
27
28
29 package com.lutris.util;
30
31 import java.lang.reflect.Array JavaDoc;
32 import java.lang.reflect.Method JavaDoc;
33 import java.util.Enumeration JavaDoc;
34 import java.util.Hashtable JavaDoc;
35 import java.util.Vector JavaDoc;
36
37 /**
38  * Class that implements a recursive keyword/value table. The key is a string
39  * that is restricted to be a valid Java identifier. That is, starting with
40  * an letter and containing letters or digits. The characters '_' and '$'
41  * are also allowed and are treated as letters. The value maybe any object.
42  * A keyword and its value are collectively referred to as a <I>field</I>
43  *
44  * The table is recursive. Values of class KeywordValueTable are referred to as
45  * <I>sections</I>. A field of a section maybe addressed from the parent
46  * object using a dot ('.') separated name path.
47  *
48  * @version $Revision: 1.3 $
49  * @author Mark Diekhans
50  * @since Harmony 1.0
51  */

52 public class KeywordValueTable implements java.io.Serializable JavaDoc {
53     private Hashtable JavaDoc hashTable; // Table keyed by keyword component.
54

55     /**
56      * Constructor.
57      */

58     public KeywordValueTable() {
59         hashTable = new Hashtable JavaDoc();
60     }
61
62     
63     /**
64      * Recursively locate the section named by a keyword path. This finds
65      * the section containing the last component of the path.
66      *
67      * @param keywordPath The parsed keyword to locate.
68      * @param create If <CODE>true</CODE>, create missing section, if
69      * <CODE>false</CODE> return null on a missing section.
70      * @param pathIdx Current index in keywordPath. Zero for top level call.
71      * @return A reference to the section. For a single component keyword,
72      * <CODE>this</CODE> is returned. If the second is not found.
73      * @exception KeywordValueException If a non-leaf
74      * element of the keyword is not a section.
75      */

76     private synchronized KeywordValueTable findSection(String JavaDoc[] keywordPath,
77                                                        boolean create,
78                                                        int pathIdx)
79             throws KeywordValueException {
80         /*
81          * We don't return the leaf key, stop one above.
82          */

83         if (pathIdx == keywordPath.length - 1) {
84             return this;
85         }
86
87         /*
88          * Recurse down to the leaf's section.
89          */

90         Object JavaDoc value = hashTable.get(keywordPath [pathIdx]);
91         if (value != null) {
92             /*
93              * If its a different type, then replace if create otherwise its
94              * an error.
95              */

96             if (!(value instanceof KeywordValueTable)) {
97                 if (!create) {
98                     String JavaDoc msg = "keyword specifies a non-leaf component " +
99                         "that is not a KeywordValueTable: " +
100                         KeywordParser.join (keywordPath) +
101                         " (component #" + pathIdx + ")";
102                     throw new KeywordValueException(msg);
103                 }
104                 value = newSection();
105                 hashTable.put(keywordPath [pathIdx], value);
106             }
107         } else {
108             /*
109              * Value does not exist.
110              */

111             if (!create) {
112                 return null;
113             }
114             value = newSection();
115             hashTable.put(keywordPath [pathIdx], value);
116         }
117         return ((KeywordValueTable) value).findSection(keywordPath,
118                                                        create,
119                                                        pathIdx + 1);
120     }
121     
122     /**
123      * Allocate a new section. The default implementation of this
124      * method returns a new KeywordValueTable object. A class derived
125      * from KeywordValueTable overrides this method to create a new
126      * object of the derived type. Sections are only allocated by
127      * this method.
128      *
129      * @return A reference to a new section.
130      */

131     protected KeywordValueTable newSection() {
132         return new KeywordValueTable();
133     }
134
135     /**
136      * Get the value of a field as an object.
137      *
138      * @param keyword The keyword of the field. This can be a simple keyword
139      * or a recursive, dot-seperated keyword path.
140      * @return The object value or null if its not found.
141      * @exception KeywordValueException If the keyword is not syntactically
142      * legal or is a non-leaf element of the keyword is not a section.
143      */

144     public synchronized Object JavaDoc get(String JavaDoc keyword)
145         throws KeywordValueException {
146         
147         String JavaDoc [] keywordPath = KeywordParser.parse(keyword);
148         KeywordValueTable section = findSection(keywordPath,
149                                                 false, // create
150
0);
151         if (section == null) {
152             return null;
153         }
154         return section.hashTable.get(keywordPath [keywordPath.length - 1]);
155     }
156
157     /**
158      * Get the value of a field as an object, return a default if it
159      * does not exist.
160      *
161      * @param keyword The keyword of the field. This can be a simple keyword
162      * or a recursive, dot-seperated keyword path.
163      * @param defaultValue The default value to return it the keyword does not
164      * exist.
165      * @return The object value or <CODE>defaultValue</CODE> if its not found.
166      * @exception KeywordValueException If the keyword is not syntactically
167      * legal or is a non-leaf element of the keyword is not a section.
168      */

169     public synchronized Object JavaDoc get(String JavaDoc keyword,
170                                    Object JavaDoc defaultValue)
171         throws KeywordValueException {
172
173         Object JavaDoc value;
174         String JavaDoc [] keywordPath = KeywordParser.parse (keyword);
175         KeywordValueTable section = findSection(keywordPath,
176                                                 false, // create
177
0);
178         if (section == null) {
179             value = defaultValue;
180         } else {
181             value = section.hashTable.get(keywordPath [keywordPath.length - 1]);
182             if (value == null) {
183                 value = defaultValue;
184             }
185         }
186         return value;
187     }
188
189     /**
190      * Get the value of a field as a string
191      *
192      * @param keyword The keyword of the field. This can be a simple keyword
193      * or a recursive, dot-seperated keyword path.
194      * @return The result of calling toString on the value object
195      * or null if its not found.
196      * @exception KeywordValueException If the keyword is not syntactically
197      * legal or is a non-leaf element of the keyword is not a section.
198      */

199     public synchronized String JavaDoc getString(String JavaDoc keyword)
200         throws KeywordValueException {
201         
202         Object JavaDoc value = get(keyword);
203         if (value == null) {
204             return null;
205         }
206         return value.toString();
207     }
208
209     /**
210      * Get the value of a field as a string, return a default if it
211      * does not exist.
212      *
213      * @param keyword The keyword of the field. This can be a simple keyword
214      * or a recursive, dot-seperated keyword path.
215      * @return The result of calling toString on the value object
216      * or <CODE>defaultValue</CODE> if its not found.
217      * @exception KeywordValueException If the keyword is not syntactically
218      * legal or the value object is not a String.
219      */

220     public synchronized String JavaDoc getString(String JavaDoc keyword,
221                                          String JavaDoc defaultValue)
222         throws KeywordValueException {
223         
224         Object JavaDoc value = get(keyword);
225         if (value == null) {
226             return defaultValue;
227         }
228         return value.toString();
229     }
230
231     /**
232      * Get the value of a section. The section is a value that is another
233      * KeywordValueTable object.
234      *
235      * @param keyword The keyword of the field. This can be a simple keyword
236      * or a recursive, dot-seperated keyword path.
237      * @return A reference to the section object or null if not found.
238      * @exception KeywordValueException If the keyword is not syntactically
239      * legal or a non-leaf element of the
240      * keyword is not a section or the value object is not a
241      * KeywordValueTable.
242      */

243     public synchronized KeywordValueTable getSection(String JavaDoc keyword)
244             throws KeywordValueException {
245         
246         Object JavaDoc value = get(keyword);
247         if (value == null) {
248             return null;
249         }
250         if (!(value instanceof KeywordValueTable)) {
251             String JavaDoc msg = "Value of field \"" + keyword +
252                 " is not a KeywordValueTable; it is " +
253                 value.getClass().getName ();
254             throw new KeywordValueException(msg);
255         }
256         return (KeywordValueTable)value;
257     }
258
259     /**
260      * Set the value of a field. If a keyword path is specified and the
261      * subsections do not exist, they are created. If a field other than
262      * a KeywordValueTable is one of the intermediate sections in the path, it
263      * will be deleted and replaced by a section.
264      *
265      * @param keyword The keyword of the field. This can be a simple keyword
266      * or a recursive, dot-seperated keyword path.
267      * @param value The value to associate with the keyword. The value may
268      * not be null.
269      * @exception KeywordValueException If the keyword is not syntactically
270      * legal.
271      */

272     public synchronized void set(String JavaDoc keyword,
273                                  Object JavaDoc value)
274         throws KeywordValueException {
275
276         String JavaDoc [] keywordPath = KeywordParser.parse(keyword);
277         KeywordValueTable section = findSection(keywordPath,
278                                                 true, // create
279
0);
280         section.hashTable.put (keywordPath[keywordPath.length - 1],
281                                value);
282     }
283
284
285     /**
286      * Sets a default value for a keyword. This method only sets a value
287      * for the specified keyword if a value is <B>not</B> already set for
288      * that keyword. If a value is not set for the keyword, then
289      * if a keyword path is specified and the
290      * subsections do not exist, they are created. If a field other than
291      * a KeywordValueTable is one of the intermediate sections in the path, it
292      * will be deleted and replaced by a section.
293      *
294      * @param keyword The keyword of the field. This can be a simple keyword
295      * or a recursive, dot-seperated keyword path.
296      * @param defaultValue The default value to associate with the keyword.
297      * The default value may not be null. The default value is only
298      * set if the specified keyword does
299      * not already have a value associated with it.
300      * @exception KeywordValueException If the keyword is not syntactically
301      * legal.
302      */

303     public synchronized void setDefault(String JavaDoc keyword,
304                                         Object JavaDoc defaultValue)
305         throws KeywordValueException
306     {
307         if (!containsKey(keyword))
308             set(keyword, defaultValue);
309     }
310     
311     /**
312      * Determine if the a field with the specified keyword exists.
313      *
314      * @param keyword The keyword of the field. This can be a simple keyword
315      * or a recursive, dot-seperated keyword path.
316      * @return <CODE>true</CODE> if the code is in the table;
317      * <CODE>false</CODE> if its not.
318      * @exception KeywordValueException If the keyword is not syntactically
319      * legal.
320      */

321     public synchronized boolean containsKey (String JavaDoc keyword)
322             throws KeywordValueException {
323
324         String JavaDoc [] keywordPath = KeywordParser.parse (keyword);
325         KeywordValueTable section = findSection(keywordPath,
326                                                 false, // create
327
0);
328         if (section == null) {
329             return false;
330         }
331         return section.hashTable.containsKey(keywordPath [keywordPath.length - 1]);
332     }
333
334     /**
335      * Get the keywords in the table. This is only the keywords at the top
336      * level, its doesn't recurse.
337      *
338      * @return An string array of the keywords.
339      */

340     public synchronized String JavaDoc[] keys() {
341         Enumeration JavaDoc keyEnum = hashTable.keys();
342
343         /*
344          * Build list as vector then convert it to a array when size is known.
345          */

346         Vector JavaDoc keyList = new Vector JavaDoc ();
347         while (keyEnum.hasMoreElements()) {
348             keyList.addElement (keyEnum.nextElement());
349         }
350         
351         String JavaDoc [] keyStrings = new String JavaDoc [keyList.size()];
352         for (int idx = 0; idx < keyList.size (); idx++) {
353             keyStrings [idx] = (String JavaDoc) keyList.elementAt (idx);
354         }
355         return keyStrings;
356     }
357   
358     /**
359      * Recursively get the keywords for the entire table. This returns the
360      * full keyword of all leaf values.
361      *
362      * @return An string array of the keywords.
363      */

364     public synchronized String JavaDoc [] leafKeys() {
365         Enumeration JavaDoc keyEnum = hashTable.keys ();
366
367         /*
368          * Build list as vector then convert it to a array when size is known.
369          * Recurse down each value if its another table.
370          */

371         Vector JavaDoc keyList = new Vector JavaDoc ();
372         while (keyEnum.hasMoreElements()) {
373             String JavaDoc key = (String JavaDoc)keyEnum.nextElement();
374             Object JavaDoc value = hashTable.get(key);
375
376             if (value instanceof KeywordValueTable) {
377                 String JavaDoc subKeys [] = ((KeywordValueTable) value).leafKeys ();
378                 for (int idx = 0; idx < subKeys.length; idx++) {
379                     keyList.addElement(KeywordParser.concat(key,
380                                                             subKeys[idx]));
381                 }
382             } else {
383                 keyList.addElement(key);
384             }
385         }
386         
387         String JavaDoc [] keyStrings = new String JavaDoc[keyList.size()];
388         for (int idx = 0; idx < keyList.size(); idx++) {
389             keyStrings [idx] = (String JavaDoc)keyList.elementAt(idx);
390         }
391         return keyStrings;
392     }
393   
394     /**
395      * Delete a field, if the field does not exist, the operation is ignored.
396      *
397      * @param keyword The keyword of the field. This can be a simple keyword
398      * or a recursive, dot-seperated keyword path.
399      * @exception KeywordValueException If the keyword is not syntactically
400      * legal.
401      */

402     public synchronized void remove(String JavaDoc keyword)
403         throws KeywordValueException {
404
405         String JavaDoc [] keywordPath = KeywordParser.parse(keyword);
406         KeywordValueTable section = findSection(keywordPath,
407                                                 false, // create
408
0);
409         if (section != null) {
410             section.hashTable.remove(keywordPath[keywordPath.length - 1]);
411         }
412     }
413
414     /**
415      * Convert to a string.
416      *
417      * @return Generate a string representation of this object.
418      */

419     public synchronized String JavaDoc toString () {
420         return hashTable.toString();
421     }
422
423     /**
424      * Convert to an Html representation.
425      *
426      * @return the generated Html.
427      */

428     public synchronized String JavaDoc toHtml() {
429
430     StringBuffer JavaDoc html = new StringBuffer JavaDoc();
431         Enumeration JavaDoc keyEnum = hashTable.keys();
432
433         html.append ("<UL>\n");
434         Vector JavaDoc keyList = new Vector JavaDoc();
435         if (!keyEnum.hasMoreElements())
436             return ""; // This makes it possible to detect empty tables.
437
while (keyEnum.hasMoreElements()) {
438             String JavaDoc key = (String JavaDoc)keyEnum.nextElement();
439             Object JavaDoc value = hashTable.get(key);
440
441             html.append("<LI> <TT>");
442             html.append(key);
443             html.append(": </TT>");
444             html.append(formatFieldAsHtml(value));
445             html.append ("\n");
446         }
447         html.append ("</UL>\n");
448
449     return html.toString();
450     }
451
452     /**
453      * Format an array section as a HTML ordered list, appending it
454      * to the list.
455      *
456      * @param arrayObj Field array object to format.
457      * @return generated Html
458      */

459     private String JavaDoc formatArrayAsHtml(Object JavaDoc arrayObj) {
460
461     StringBuffer JavaDoc html = new StringBuffer JavaDoc();
462
463     html.append("<OL START=0>\n");
464     for (int idx = 0; idx < Array.getLength(arrayObj); idx++) {
465             html.append("<LI>");
466             html.append(formatFieldAsHtml(Array.get(arrayObj, idx)));
467             html.append("\n");
468     }
469     html.append("</OL>\n");
470     
471     return html.toString();
472     }
473
474     /**
475      * Format an object as HTML. Known printable objects are converted
476      * to a string, while others are simple listed as &lt;Object&gt;.
477      *
478      * @param obj Field array object to format.
479      * @return generated Html
480      */

481     private String JavaDoc formatObjectAsHtml(Object JavaDoc obj) {
482     String JavaDoc html;
483
484     if (obj instanceof String JavaDoc) {
485             html = obj.toString();
486     } else if (obj instanceof Integer JavaDoc) {
487         html = "<I><FONT SIZE=-1>(Integer)</FONT></I>" + obj.toString();
488     } else if (obj instanceof Boolean JavaDoc) {
489         html = "<I><FONT SIZE=-1>(Boolean)</FONT></I>" + obj.toString();
490     } else if (obj instanceof Double JavaDoc) {
491         html = "<I><FONT SIZE=-1>(Double)</FONT></I>" + obj.toString();
492     } else if (obj instanceof Long JavaDoc) {
493         html = "<I><FONT SIZE=-1>(Long)</FONT></I>" + obj.toString();
494     } else if (obj instanceof Short JavaDoc) {
495         html = "<I><FONT SIZE=-1>(Short)</FONT></I>" + obj.toString();
496     } else if (obj instanceof Float JavaDoc) {
497         html = "<I><FONT SIZE=-1>(Float)</FONT></I>" + obj.toString();
498     } else if (obj instanceof Character JavaDoc) {
499         html = "<I><FONT SIZE=-1>(Character)</FONT></I>" + obj.toString();
500     } else {
501         // If object has a toHtml() method then call it,
502
// else print nothing.
503
try {
504             Class JavaDoc objClass = obj.getClass();
505             Class JavaDoc [] params = null;
506             Method JavaDoc toHtmlMethod = objClass.getMethod("toHtml", params);
507             Object JavaDoc [] args = null;
508         html = new String JavaDoc ("<I><FONT SIZE=-1>(Object)" +
509                    toHtmlMethod.invoke(obj, args) +
510                    "</FONT></I>");
511         } catch (Exception JavaDoc e) {
512         html = "<I><FONT SIZE=-1>(Object)</FONT></I>";
513         }
514     }
515     
516     return html;
517     }
518     
519     /**
520      * Format an field. Normally just append toString the object.
521      * However, arrays and recursive data are formatted.
522      *
523      * @param fieldObj Field object to format.
524      * @return generated Html
525      */

526     private String JavaDoc formatFieldAsHtml(Object JavaDoc fieldObj) {
527
528     String JavaDoc html;
529
530         if (fieldObj instanceof KeywordValueTable) {
531             html = ((KeywordValueTable)fieldObj).toHtml();
532         } else if (fieldObj.getClass().isArray()) {
533             html = formatArrayAsHtml(fieldObj);
534         } else {
535             html = formatObjectAsHtml(fieldObj);
536         }
537
538     return html;
539     }
540 }
541
Popular Tags