Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/util/ParameterDatabase.java @ 10501

Last change on this file since 10501 was 6152, checked in by bfarka, 14 years ago

added ecj and custom statistics to communicate with the okb services #1441

File size: 87.9 KB
RevLine 
[6152]1/*
2  Copyright 2006 by Sean Luke
3  Licensed under the Academic Free License version 3.0
4  See the file "LICENSE" for more information
5*/
6
7
8package ec.util;
9
10import java.io.File;
11import java.io.FileInputStream;
12import java.io.FileNotFoundException;
13import java.io.IOException;
14import java.io.PrintStream;
15import java.io.PrintWriter;
16import java.io.Serializable;
17import java.util.Comparator;
18import java.util.Enumeration;
19import java.util.Hashtable;
20import java.util.Iterator;
21import java.util.HashSet;
22import java.util.Properties;
23import java.util.Set;
24import java.util.StringTokenizer;
25import java.util.Vector;
26
27import javax.swing.tree.DefaultMutableTreeNode;
28import javax.swing.tree.DefaultTreeModel;
29import javax.swing.tree.TreeModel;
30
31/*
32
33 * ParameterDatabase.java
34 * Created: Sat Aug  7 12:09:19 1999
35 */
36
37/**
38 *
39 * <p>
40 * This extension of the Properties class allows you to set, get, and delete
41 * Parameters in a hierarchical tree-like database. The database consists of a
42 * list of Parameters, plus an array of "parent databases" which it falls back
43 * on when it can't find the Parameter you're looking for. Parents may also have
44 * arrays of parents, and so on..
45 *
46 * <p>
47 * The parameters are loaded from a Java property-list file, which is basically
48 * a collection of parameter=value pairs, one per line. Empty lines and lines
49 * beginning with # are ignored. These parameters and their values are
50 * <b>case-sensitive </b>, and whitespace is trimmed I believe.
51 *
52 * <p>
53 * An optional set of parameters, "parent. <i>n </i>", where <i>n </i> are
54 * consecutive integers starting at 0, define the filenames of the database's
55 * parents.
56 *
57 * <p>
58 * An optional set of parameters, "print-params", specifies whether or not
59 * parameters should be printed as they are used (through one of the get(...)
60 * methods). If print-params is unset, or set to false or FALSE, nothing is
61 * printed. If set to non-false, then the parameters are printed prepended with a "P:"
62 * when their values are requested,  "E:" when their existence is tested.  Prior to the
63 * "P:" or "E:" you may see a "!" (meaning that the parameter isn't in the database),
64 * or a "&lt;" (meaning that the parameter was a default parameter which was never
65 * looked up because the primary parameter contained the value).
66 *
67 * <p>
68 * <p>
69 * When you create a ParameterDatabase using new ParameterDatabase(), it is
70 * created thus:
71 *
72 * <p>
73 * <table border=0 cellpadding=0 cellspacing=0>
74 * <tr>
75 * <td><tt>DATABASE:</tt></td>
76 * <td><tt>&nbsp;database</tt></td>
77 * </tr>
78 * <tr>
79 * <td><tt>FROM:</tt></td>
80 * <td><tt>&nbsp;(empty)</tt></td>
81 * </tr>
82 * </table>
83 *
84 *
85 * <p>
86 * When you create a ParameterDatabase using new ParameterDatabase( <i>file
87 * </i>), it is created by loading the database file, and its parent file tree,
88 * thus:
89 *
90 * <p>
91 * <table border=0 cellpadding=0 cellspacing=0>
92 * <tr>
93 * <td><tt>DATABASE:</tt></td>
94 * <td><tt>&nbsp;database</tt></td>
95 * <td><tt>&nbsp;-&gt;</tt></td>
96 * <td><tt>&nbsp;parent0</tt></td>
97 * <td><tt>&nbsp;+-&gt;</tt></td>
98 * <td><tt>&nbsp;parent0</tt></td>
99 * <td><tt>&nbsp;+-&gt;</tt></td>
100 * <td><tt>&nbsp;parent0</tt></td>
101 * <td><tt>&nbsp;+-&gt;</tt></td>
102 * <td><tt>&nbsp;....</tt></td>
103 * </tr>
104 * <tr>
105 * <td><tt>FROM:</tt></td>
106 * <td><tt>&nbsp;(empty)</tt></td>
107 * <td><tt>&nbsp;</tt></td>
108 * <td><tt>&nbsp;(file)</tt></td>
109 * <td><tt>&nbsp;|</tt></td>
110 * <td><tt>&nbsp;(parent.0)</tt></td>
111 * <td><tt>&nbsp;|</tt></td>
112 * <td><tt>&nbsp;(parent.0)</tt></td>
113 * <td><tt>&nbsp;</tt></td>
114 * <td><tt>&nbsp;....</tt></td>
115 * </tr>
116 * <tr>
117 * <td><tt>&nbsp;</tt></td>
118 * <td><tt>&nbsp;</tt></td>
119 * <td><tt>&nbsp;</tt></td>
120 * <td><tt>&nbsp;</tt></td>
121 * <td><tt>&nbsp;|</tt></td>
122 * <td><tt>&nbsp;</tt></td>
123 * <td><tt>&nbsp;+-&gt;</tt></td>
124 * <td><tt>&nbsp;parent1</tt></td>
125 * <td><tt>&nbsp;+-&gt;</tt></td>
126 * <td><tt>&nbsp;....</tt></td>
127 * </tr>
128 * <tr>
129 * <td><tt>&nbsp;</tt></td>
130 * <td><tt>&nbsp;</tt></td>
131 * <td><tt>&nbsp;</tt></td>
132 * <td><tt>&nbsp;</tt></td>
133 * <td><tt>&nbsp;|</tt></td>
134 * <td><tt>&nbsp;</tt></td>
135 * <td><tt>&nbsp;|</tt></td>
136 * <td><tt>&nbsp;(parent.1)</tt></td>
137 * <td><tt>&nbsp;</tt></td>
138 * <td><tt>&nbsp;</tt></td>
139 * </tr>
140 * <tr>
141 * <td><tt>&nbsp;</tt></td>
142 * <td><tt>&nbsp;</tt></td>
143 * <td><tt>&nbsp;</tt></td>
144 * <td><tt>&nbsp;</tt></td>
145 * <td><tt>&nbsp;|</tt></td>
146 * <td><tt>&nbsp;</tt></td>
147 * <td><tt>&nbsp;....</tt></td>
148 * <td><tt>&nbsp;</tt></td>
149 * <td><tt>&nbsp;</tt></td>
150 * <td><tt>&nbsp;</tt></td>
151 * </tr>
152 * <tr>
153 * <td><tt>&nbsp;</tt></td>
154 * <td><tt>&nbsp;</tt></td>
155 * <td><tt>&nbsp;</tt></td>
156 * <td><tt>&nbsp;</tt></td>
157 * <td><tt>&nbsp;|</tt></td>
158 * <td><tt>&nbsp;</tt></td>
159 * <td><tt>&nbsp;</tt></td>
160 * <td><tt>&nbsp;</tt></td>
161 * <td><tt>&nbsp;</tt></td>
162 * <td><tt>&nbsp;</tt></td>
163 * </tr>
164 * <tr>
165 * <td><tt>&nbsp;</tt></td>
166 * <td><tt>&nbsp;</tt></td>
167 * <td><tt>&nbsp;</tt></td>
168 * <td><tt>&nbsp;</tt></td>
169 * <td><tt>&nbsp;+-&gt;</tt></td>
170 * <td><tt>&nbsp;parent1</tt></td>
171 * <td><tt>&nbsp;+-&gt;</tt></td>
172 * <td><tt>&nbsp;....</tt></td>
173 * <td><tt>&nbsp;</tt></td>
174 * <td><tt>&nbsp;</tt></td>
175 * </tr>
176 * <tr>
177 * <td><tt>&nbsp;</tt></td>
178 * <td><tt>&nbsp;</tt></td>
179 * <td><tt>&nbsp;</tt></td>
180 * <td><tt>&nbsp;</tt></td>
181 * <td><tt>&nbsp;|</tt></td>
182 * <td><tt>&nbsp;(parent.1)</tt></td>
183 * <td><tt>&nbsp;</tt></td>
184 * <td><tt>&nbsp;</tt></td>
185 * <td><tt>&nbsp;</tt></td>
186 * <td><tt>&nbsp;</tt></td>
187 * </tr>
188 * <tr>
189 * <td><tt>&nbsp;</tt></td>
190 * <td><tt>&nbsp;</tt></td>
191 * <td><tt>&nbsp;</tt></td>
192 * <td><tt>&nbsp;</tt></td>
193 * <td><tt>&nbsp;....</tt></td>
194 * <td><tt>&nbsp;</tt></td>
195 * <td><tt>&nbsp;</tt></td>
196 * <td><tt>&nbsp;</tt></td>
197 * <td><tt>&nbsp;</tt></td>
198 * <td><tt>&nbsp;</tt></td>
199 * </tr>
200 * </table>
201 *
202 *
203 * <p>
204 * When you create a ParameterDatabase using new ParameterDatabase( <i>file,argv
205 * </i>), the preferred way, it is created thus:
206 *
207 *
208 * <p>
209 * <table border=0 cellpadding=0 cellspacing=0>
210 * <tr>
211 * <td><tt>DATABASE:</tt></td>
212 * <td><tt>&nbsp;database</tt></td>
213 * <td><tt>&nbsp;-&gt;</tt></td>
214 * <td><tt>&nbsp;parent0</tt></td>
215 * <td><tt>&nbsp;+-&gt;</tt></td>
216 * <td><tt>&nbsp;parent0</tt></td>
217 * <td><tt>&nbsp;+-&gt;</tt></td>
218 * <td><tt>&nbsp;parent0</tt></td>
219 * <td><tt>&nbsp;+-&gt;</tt></td>
220 * <td><tt>&nbsp;parent0</tt></td>
221 * <td><tt>&nbsp;+-&gt;</tt></td>
222 * <td><tt>&nbsp;....</tt></td>
223 * </tr>
224 * <tr>
225 * <td><tt>FROM:</tt></td>
226 * <td><tt>&nbsp;(empty)</tt></td>
227 * <td><tt>&nbsp;</tt></td>
228 * <td><tt>(argv)</tt></td>
229 * <td><tt>&nbsp;</tt></td>
230 * <td><tt>&nbsp;(file)</tt></td>
231 * <td><tt>&nbsp;|</tt></td>
232 * <td><tt>&nbsp;(parent.0)</tt></td>
233 * <td><tt>&nbsp;|</tt></td>
234 * <td><tt>&nbsp;(parent.0)</tt></td>
235 * <td><tt>&nbsp;</tt></td>
236 * <td><tt>&nbsp;....</tt></td>
237 * </tr>
238 * <tr>
239 * <td><tt>&nbsp;</tt></td>
240 * <td><tt>&nbsp;</tt></td>
241 * <td><tt>&nbsp;</tt></td>
242 * <td><tt>&nbsp;</tt></td>
243 * <td><tt>&nbsp;</tt></td>
244 * <td><tt>&nbsp;</tt></td>
245 * <td><tt>&nbsp;|</tt></td>
246 * <td><tt>&nbsp;</tt></td>
247 * <td><tt>&nbsp;+-&gt;</tt></td>
248 * <td><tt>&nbsp;parent1</tt></td>
249 * <td><tt>&nbsp;+-&gt;</tt></td>
250 * <td><tt>&nbsp;....</tt></td>
251 * </tr>
252 * <tr>
253 * <td><tt>&nbsp;</tt></td>
254 * <td><tt>&nbsp;</tt></td>
255 * <td><tt>&nbsp;</tt></td>
256 * <td><tt>&nbsp;</tt></td>
257 * <td><tt>&nbsp;</tt></td>
258 * <td><tt>&nbsp;</tt></td>
259 * <td><tt>&nbsp;|</tt></td>
260 * <td><tt>&nbsp;</tt></td>
261 * <td><tt>&nbsp;|</tt></td>
262 * <td><tt>&nbsp;(parent.1)</tt></td>
263 * <td><tt>&nbsp;</tt></td>
264 * <td><tt>&nbsp;</tt></td>
265 * </tr>
266 * <tr>
267 * <td><tt>&nbsp;</tt></td>
268 * <td><tt>&nbsp;</tt></td>
269 * <td><tt>&nbsp;</tt></td>
270 * <td><tt>&nbsp;</tt></td>
271 * <td><tt>&nbsp;</tt></td>
272 * <td><tt>&nbsp;</tt></td>
273 * <td><tt>&nbsp;|</tt></td>
274 * <td><tt>&nbsp;</tt></td>
275 * <td><tt>&nbsp;....</tt></td>
276 * <td><tt>&nbsp;</tt></td>
277 * <td><tt>&nbsp;</tt></td>
278 * <td><tt>&nbsp;</tt></td>
279 * </tr>
280 * <tr>
281 * <td><tt>&nbsp;</tt></td>
282 * <td><tt>&nbsp;</tt></td>
283 * <td><tt>&nbsp;</tt></td>
284 * <td><tt>&nbsp;</tt></td>
285 * <td><tt>&nbsp;</tt></td>
286 * <td><tt>&nbsp;</tt></td>
287 * <td><tt>&nbsp;|</tt></td>
288 * <td><tt>&nbsp;</tt></td>
289 * <td><tt>&nbsp;</tt></td>
290 * <td><tt>&nbsp;</tt></td>
291 * <td><tt>&nbsp;</tt></td>
292 * <td><tt>&nbsp;</tt></td>
293 * </tr>
294 * <tr>
295 * <td><tt>&nbsp;</tt></td>
296 * <td><tt>&nbsp;</tt></td>
297 * <td><tt>&nbsp;</tt></td>
298 * <td><tt>&nbsp;</tt></td>
299 * <td><tt>&nbsp;</tt></td>
300 * <td><tt>&nbsp;</tt></td>
301 * <td><tt>&nbsp;+-&gt;</tt></td>
302 * <td><tt>&nbsp;parent1</tt></td>
303 * <td><tt>&nbsp;+-&gt;</tt></td>
304 * <td><tt>&nbsp;....</tt></td>
305 * <td><tt>&nbsp;</tt></td>
306 * <td><tt>&nbsp;</tt></td>
307 * </tr>
308 * <tr>
309 * <td><tt>&nbsp;</tt></td>
310 * <td><tt>&nbsp;</tt></td>
311 * <td><tt>&nbsp;</tt></td>
312 * <td><tt>&nbsp;</tt></td>
313 * <td><tt>&nbsp;</tt></td>
314 * <td><tt>&nbsp;</tt></td>
315 * <td><tt>&nbsp;|</tt></td>
316 * <td><tt>&nbsp;(parent.1)</tt></td>
317 * <td><tt>&nbsp;</tt></td>
318 * <td><tt>&nbsp;</tt></td>
319 * <td><tt>&nbsp;</tt></td>
320 * <td><tt>&nbsp;</tt></td>
321 * </tr>
322 * <tr>
323 * <td><tt>&nbsp;</tt></td>
324 * <td><tt>&nbsp;</tt></td>
325 * <td><tt>&nbsp;</tt></td>
326 * <td><tt>&nbsp;</tt></td>
327 * <td><tt>&nbsp;</tt></td>
328 * <td><tt>&nbsp;</tt></td>
329 * <td><tt>&nbsp;....</tt></td>
330 * <td><tt>&nbsp;</tt></td>
331 * <td><tt>&nbsp;</tt></td>
332 * <td><tt>&nbsp;</tt></td>
333 * <td><tt>&nbsp;</tt></td>
334 * <td><tt>&nbsp;</tt></td>
335 * </tr>
336 * </table>
337 *
338 *
339 * <p>
340 * ...that is, the actual top database is empty, and stores parameters added
341 * programmatically; its parent is a database formed from arguments passed in on
342 * the command line; <i>its </i> parent is the parameter database which actually
343 * loads from foo. This allows you to programmatically add parameters which
344 * override those in foo, then delete them, thus bringing foo's parameters back
345 * in view.
346 *
347 * <p>
348 * Once a parameter database is loaded, you query it with the <tt>get</tt>
349 * methods. The database, then its parents, are searched until a match is found
350 * for your parameter. The search rules are thus: (1) the root database is
351 * searched first. (2) If a database being searched doesn't contain the data, it
352 * searches its parents recursively, starting with parent 0, then moving up,
353 * until all searches are exhausted or something was found. (3) No database is
354 * searched twice.
355 *
356 * <p>The various <tt>get</tt> methods all take two parameters.  The first
357 * parameter is fetched and retrieved first.  If that fails, the second one
358 * (known as the <i>default parameter</i>) is fetched and retrieved.  You
359 * can pass in <tt>null</tt> for the default parameter if you don't have one.
360 *
361 * <p>You can test a parameter for existence with the <tt>exists</tt> methods.
362 *
363 * <p>
364 * You can set a parameter (in the topmost database <i>only </i> with the
365 * <tt>set</tt> command. The <tt>remove</tt> command removes a parameter
366 * from the topmost database only. The <tt>removeDeeply</tt> command removes
367 * that parameter from every database.
368 *
369 * <p>
370 * The values stored in a parameter database must not contain "#", "=",
371 * non-ascii values, or whitespace.
372 *
373 * <p>
374 * <b>Note for JDK 1.1 </b>. Finally recovering from stupendous idiocy, JDK 1.2
375 * included parseDouble() and parseFloat() commands; now you can READ A FLOAT
376 * FROM A STRING without having to create a Float object first! Anyway, you will
377 * need to modify the getFloat() method below if you're running on JDK 1.1, but
378 * understand that large numbers of calls to the method may be inefficient.
379 * Sample JDK 1.1 code is given with those methods, but is commented out.
380 *
381 *
382 * @author Sean Luke
383 * @version 1.0
384 */
385
386public class ParameterDatabase extends Properties implements Serializable
387    {
388    public static final String C_HERE = "$";
389    public static final String UNKNOWN_VALUE = "";
390    public static final String PRINT_PARAMS = "print-params";
391    public static final int PS_UNKNOWN = -1;
392    public static final int PS_NONE = 0;
393    public static final int PS_PRINT_PARAMS = 1;
394    public int printState = PS_UNKNOWN;
395    Vector parents;
396    File directory;
397    String filename;
398    boolean checked;
399    Hashtable gotten;
400    Hashtable accessed;
401    Vector listeners;
402
403    /**
404     * Searches down through databases to find a given parameter, whose value
405     * must be a full Class name, and the class must be a descendent of but not
406     * equal to <i>mustCastTosuperclass </i>. Loads the class and returns an
407     * instance (constructed with the default constructor), or throws a
408     * ParamClassLoadException if there is no such Class. If the parameter is
409     * not found, the defaultParameter is used. The parameter chosen is marked
410     * "used".
411     */
412    public Object getInstanceForParameter(Parameter parameter, Parameter defaultParameter, Class mustCastTosuperclass) throws ParamClassLoadException
413        {
414        printGotten(parameter, defaultParameter, false);
415        Parameter p;
416        if (_exists(parameter))
417            p = parameter;
418        else if (_exists(defaultParameter))
419            p = defaultParameter;
420        else
421            throw new ParamClassLoadException(
422                "No class name provided.\nPARAMETER: "
423                + parameter
424                + (defaultParameter == null ? "" : "\n     ALSO: "
425                    + defaultParameter));
426        try
427            {
428            Class c = Class.forName(get(p));
429            if (!mustCastTosuperclass.isAssignableFrom(c))
430                throw new ParamClassLoadException("The class "
431                    + c.getName()
432                    + "\ndoes not cast into the superclass "
433                    + mustCastTosuperclass.getName()
434                    + "\nPARAMETER: "
435                    + parameter
436                    + (defaultParameter == null ? "" : "\n     ALSO: "
437                        + defaultParameter));
438            if (mustCastTosuperclass == c)
439                throw new ParamClassLoadException("The class "
440                    + c.getName()
441                    + "\nmust not be the same as the required superclass "
442                    + mustCastTosuperclass.getName()
443                    + "\nPARAMETER: "
444                    + parameter
445                    + (defaultParameter == null ? "" : "\n     ALSO: "
446                        + defaultParameter));
447            return c.newInstance();
448            }
449        catch (ClassNotFoundException e)
450            {
451            throw new ParamClassLoadException("Class not found: "
452                + get(p)
453                + "\nPARAMETER: "
454                + parameter
455                + (defaultParameter == null ? "" : "\n     ALSO: "
456                    + defaultParameter) + "\nEXCEPTION: \n\n" + e);
457            }
458        catch (IllegalArgumentException e)
459            {
460            throw new ParamClassLoadException("Could not load class: "
461                + get(p)
462                + "\nPARAMETER: "
463                + parameter
464                + (defaultParameter == null ? "" : "\n     ALSO: "
465                    + defaultParameter) + "\nEXCEPTION: \n\n" + e);
466            }
467        catch (InstantiationException e)
468            {
469            throw new ParamClassLoadException(
470                "The requested class is an interface or an abstract class: "
471                + get(p)
472                + "\nPARAMETER: "
473                + parameter
474                + (defaultParameter == null ? "" : "\n     ALSO: "
475                    + defaultParameter) + "\nEXCEPTION: \n\n"
476                + e);
477            }
478        catch (IllegalAccessException e)
479            {
480            throw new ParamClassLoadException(
481                "The requested class cannot be initialized with the default initializer: "
482                + get(p)
483                + "\nPARAMETER: "
484                + parameter
485                + (defaultParameter == null ? "" : "\n     ALSO: "
486                    + defaultParameter) + "\nEXCEPTION: \n\n"
487                + e);
488            }
489        }
490
491    /**
492     * Searches down through databases to find a given parameter, whose value
493     * must be a full Class name, and the class must be a descendent, or equal
494     * to, <i>mustCastTosuperclass </i>. Loads the class and returns an instance
495     * (constructed with the default constructor), or throws a
496     * ParamClassLoadException if there is no such Class. The parameter chosen
497     * is marked "used".
498     */
499    public Object getInstanceForParameterEq(Parameter parameter,
500        Parameter defaultParameter, Class mustCastTosuperclass)
501        throws ParamClassLoadException
502        {
503        printGotten(parameter, defaultParameter, false);
504        Parameter p;
505        if (_exists(parameter))
506            p = parameter;
507        else if (_exists(defaultParameter))
508            p = defaultParameter;
509        else
510            throw new ParamClassLoadException(
511                "No class name provided.\nPARAMETER: "
512                + parameter
513                + "\n     ALSO: "
514                + (defaultParameter == null ? "" : "\n     ALSO: "
515                    + defaultParameter));
516        try
517            {
518            Class c = Class.forName(get(p));
519            if (!mustCastTosuperclass.isAssignableFrom(c))
520                throw new ParamClassLoadException("The class "
521                    + c.getName()
522                    + "\ndoes not cast into the superclass "
523                    + mustCastTosuperclass.getName()
524                    + "\nPARAMETER: "
525                    + parameter
526                    + "\n     ALSO: "
527                    + (defaultParameter == null ? "" : "\n     ALSO: "
528                        + defaultParameter));
529            return c.newInstance();
530            }
531        catch (ClassNotFoundException e)
532            {
533            throw new ParamClassLoadException("Class not found: "
534                + get(p)
535                + "\nPARAMETER: "
536                + parameter
537                + "\n     ALSO: "
538                + (defaultParameter == null ? "" : "\n     ALSO: "
539                    + defaultParameter) + "\nEXCEPTION: \n\n" + e);
540            }
541        catch (IllegalArgumentException e)
542            {
543            throw new ParamClassLoadException("Could not load class: "
544                + get(p)
545                + "\nPARAMETER: "
546                + parameter
547                + "\n     ALSO: "
548                + (defaultParameter == null ? "" : "\n     ALSO: "
549                    + defaultParameter) + "\nEXCEPTION: \n\n" + e);
550            }
551        catch (InstantiationException e)
552            {
553            throw new ParamClassLoadException(
554                "The requested class is an interface or an abstract class: "
555                + get(p)
556                + "\nPARAMETER: "
557                + parameter
558                + "\n     ALSO: "
559                + (defaultParameter == null ? "" : "\n     ALSO: "
560                    + defaultParameter) + "\nEXCEPTION: \n\n"
561                + e);
562            }
563        catch (IllegalAccessException e)
564            {
565            throw new ParamClassLoadException(
566                "The requested class cannot be initialized with the default initializer: "
567                + get(p)
568                + "\nPARAMETER: "
569                + parameter
570                + "\n     ALSO: "
571                + (defaultParameter == null ? "" : "\n     ALSO: "
572                    + defaultParameter) + "\nEXCEPTION: \n\n"
573                + e);
574            }
575        }
576
577    /**
578     * Searches down through databases to find a given parameter. The value
579     * associated with this parameter must be a full Class name, and the class
580     * must be a descendent of but not equal to <i>mustCastTosuperclass </i>.
581     * Loads and returns the associated Class, or throws a
582     * ParamClassLoadException if there is no such Class. If the parameter is
583     * not found, the defaultParameter is used. The parameter chosen is marked
584     * "used".
585     */
586    public Object getClassForParameter(Parameter parameter,
587        Parameter defaultParameter, Class mustCastTosuperclass)
588        throws ParamClassLoadException
589        {
590        printGotten(parameter, defaultParameter, false);
591        Parameter p;
592        if (_exists(parameter))
593            p = parameter;
594        else if (_exists(defaultParameter))
595            p = defaultParameter;
596        else
597            throw new ParamClassLoadException(
598                "No class name provided.\nPARAMETER: "
599                + parameter
600                + "\n     ALSO: "
601                + (defaultParameter == null ? "" : "\n     ALSO: "
602                    + defaultParameter));
603        try
604            {
605            Class c = Class.forName(get(p));
606            if (!mustCastTosuperclass.isAssignableFrom(c))
607                throw new ParamClassLoadException("The class "
608                    + c.getName()
609                    + "\ndoes not cast into the superclass "
610                    + mustCastTosuperclass.getName()
611                    + "\nPARAMETER: "
612                    + parameter
613                    + "\n     ALSO: "
614                    + (defaultParameter == null ? "" : "\n     ALSO: "
615                        + defaultParameter));
616            return c;
617            }
618        catch (ClassNotFoundException e)
619            {
620            throw new ParamClassLoadException("Class not found: "
621                + get(p)
622                + "\nPARAMETER: "
623                + parameter
624                + "\n     ALSO: "
625                + (defaultParameter == null ? "" : "\n     ALSO: "
626                    + defaultParameter) + "\nEXCEPTION: \n\n" + e);
627            }
628        catch (IllegalArgumentException e)
629            {
630            throw new ParamClassLoadException("Could not load class: "
631                + get(p)
632                + "\nPARAMETER: "
633                + parameter
634                + "\n     ALSO: "
635                + (defaultParameter == null ? "" : "\n     ALSO: "
636                    + defaultParameter) + "\nEXCEPTION: \n\n" + e);
637            }
638        }
639
640    /**
641     * Searches down through databases to find a given parameter; If the
642     * parameter does not exist, defaultValue is returned. If the parameter
643     * exists, and it is set to "false" (case insensitive), false is returned.
644     * Else true is returned. The parameter chosen is marked "used" if it
645     * exists.
646     */
647    public boolean getBoolean(Parameter parameter,
648        Parameter defaultParameter, boolean defaultValue)
649        {
650        printGotten(parameter, defaultParameter, false);
651        if (_exists(parameter))
652            return getBoolean(parameter, defaultValue);
653        else
654            return getBoolean(defaultParameter, defaultValue);
655        }
656
657    /**
658     * Searches down through databases to find a given parameter; If the
659     * parameter does not exist, defaultValue is returned. If the parameter
660     * exists, and it is set to "false" (case insensitive), false is returned.
661     * Else true is returned. The parameter chosen is marked "used" if it
662     * exists.
663     */
664    boolean getBoolean(Parameter parameter, boolean defaultValue)
665        {
666        if (!_exists(parameter))
667            return defaultValue;
668        return (!get(parameter).equalsIgnoreCase("false"));
669        }
670
671    /**
672     * Parses an integer from a string, either in decimal or (if starting with
673     * an x) in hex
674     */
675    // we assume that the string has been trimmed already
676    /*protected*/ int parseInt(String string)
677        throws NumberFormatException
678        {
679        char c;
680        if (string != null && string.length() > 0
681            && ((string.charAt(0) == (c = 'x')) || c == 'X'))
682            {
683            // it's a hex int, load it as hex
684            return Integer.parseInt(string.substring(1), 16);
685            }
686        else
687            {
688            try
689                {
690                // it's decimal
691                return Integer.parseInt(string);
692                }
693            catch (NumberFormatException e)
694                {
695                // maybe it's a double ending in .0, which should be okay
696                try
697                    {
698                    double d = Double.parseDouble(string);
699                    if (d == (int) d) return (int) d;  // looking fine
700                    else throw e;
701                    }
702                catch (NumberFormatException e2)
703                    {
704                    throw e;
705                    }
706                }
707            }
708        }
709
710    /**
711     * Parses a long from a string, either in decimal or (if starting with an x)
712     * in hex
713     */
714    // we assume that the string has been trimmed already
715    /*protected*/ long parseLong(String string)
716        throws NumberFormatException
717        {
718        char c;
719        if (string != null && string.length() > 0
720            && ((string.charAt(0) == (c = 'x')) || c == 'X'))
721            {
722            // it's a hex int, load it as hex
723            return Long.parseLong(string.substring(1), 16);
724            }
725        else
726            {
727            try
728                {
729                // it's decimal
730                return Long.parseLong(string);
731                }
732            catch (NumberFormatException e)
733                {
734                // maybe it's a double ending in .0, which should be okay
735                try
736                    {
737                    double d = Double.parseDouble(string);
738                    if (d == (long) d) return (long) d;  // looking fine
739                    else throw e;
740                    }
741                catch (NumberFormatException e2)
742                    {
743                    throw e;
744                    }
745                }
746            }
747        }
748
749    /**
750     * Searches down through databases to find a given parameter, whose value
751     * must be an integer. It returns the value, else throws a
752     * NumberFormatException exception if there is an error in parsing the
753     * parameter. The parameter chosen is marked "used" if it exists. Integers
754     * may be in decimal or (if preceded with an X or x) in hexadecimal.
755     */
756    /*protected*/ int getInt(Parameter parameter)
757        throws NumberFormatException
758        {
759        if (_exists(parameter))
760            {
761            try
762                {
763                return parseInt(get(parameter));
764                }
765            catch (NumberFormatException e)
766                {
767                throw new NumberFormatException("Bad integer ("
768                    + get(parameter) + " ) for parameter " + parameter);
769                }
770            }
771        else
772            throw new NumberFormatException(
773                "Integer does not exist for parameter " + parameter);
774        }
775
776    /**
777     * Searches down through databases to find a given parameter, whose value
778     * must be an integer. It returns the value, else throws a
779     * NumberFormatException exception if there is an error in parsing the
780     * parameter. The parameter chosen is marked "used" if it exists. Integers
781     * may be in decimal or (if preceded with an X or x) in hexadecimal.
782     */
783    public int getInt(Parameter parameter, Parameter defaultParameter)
784        throws NumberFormatException
785        {
786        printGotten(parameter, defaultParameter, false);
787        if (_exists(parameter))
788            return getInt(parameter);
789        else if (_exists(defaultParameter))
790            return getInt(defaultParameter);
791        else
792            throw new NumberFormatException(
793                "Integer does not exist for either parameter " + parameter
794                + "\nor\n" + defaultParameter);
795        }
796
797    /**
798     * Searches down through databases to find a given parameter, whose value
799     * must be an integer >= minValue. It returns the value, or minValue-1 if
800     * the value is out of range or if there is an error in parsing the
801     * parameter. The parameter chosen is marked "used" if it exists. Integers
802     * may be in decimal or (if preceded with an X or x) in hexadecimal.
803     */
804    public int getInt(Parameter parameter, Parameter defaultParameter,
805        int minValue)
806        {
807        printGotten(parameter, defaultParameter, false);
808        if (_exists(parameter))
809            return getInt(parameter, minValue);
810        else
811            return getInt(defaultParameter, minValue);
812        }
813
814    /**
815     * Searches down through databases to find a given parameter, whose value
816     * must be an integer >= minValue. It returns the value, or minValue-1 if
817     * the value is out of range or if there is an error in parsing the
818     * parameter. The parameter chosen is marked "used" if it exists. Integers
819     * may be in decimal or (if preceded with an X or x) in hexadecimal.
820     */
821    /*protected*/ int getInt(Parameter parameter, int minValue)
822        {
823        if (_exists(parameter))
824            {
825            try
826                {
827                int i = parseInt(get(parameter));
828                if (i < minValue)
829                    return minValue - 1;
830                return i;
831                }
832            catch (NumberFormatException e)
833                {
834                return minValue - 1;
835                }
836            }
837        else
838            return minValue - 1;
839        }
840
841    /**
842     * Searches down through databases to find a given parameter, which must be
843     * an integer. If there is an error in parsing the parameter, then default
844     * is returned. The parameter chosen is marked "used" if it exists. Integers
845     * may be in decimal or (if preceded with an X or x) in hexadecimal.
846     */
847    public int getIntWithDefault(Parameter parameter,
848        Parameter defaultParameter, int defaultValue)
849        {
850        printGotten(parameter, defaultParameter, false);
851        if (_exists(parameter))
852            return getIntWithDefault(parameter, defaultValue);
853        else
854            return getIntWithDefault(defaultParameter, defaultValue);
855        }
856
857    /**
858     * Searches down through databases to find a given parameter, which must be
859     * an integer. If there is an error in parsing the parameter, then default
860     * is returned. The parameter chosen is marked "used" if it exists. Integers
861     * may be in decimal or (if preceded with an X or x) in hexadecimal.
862     */
863    int getIntWithDefault(Parameter parameter, int defaultValue)
864        {
865        if (_exists(parameter))
866            {
867            try
868                {
869                return parseInt(get(parameter));
870                }
871            catch (NumberFormatException e)
872                {
873                return defaultValue;
874                }
875            }
876        else
877            return defaultValue;
878        }
879
880    /**
881     * Searches down through databases to find a given parameter, whose value
882     * must be an integer >= minValue and <= maxValue. It returns the value, or
883     * minValue-1 if the value is out of range or if there is an error in
884     * parsing the parameter. The parameter chosen is marked "used" if it
885     * exists. Integers may be in decimal or (if preceded with an X or x) in
886     * hexadecimal.
887     */
888    public int getIntWithMax(Parameter parameter,
889        Parameter defaultParameter, int minValue, int maxValue)
890        {
891        printGotten(parameter, defaultParameter, false);
892        if (_exists(parameter))
893            return getIntWithMax(parameter, minValue, maxValue);
894        else
895            return getIntWithMax(defaultParameter, minValue, maxValue);
896        }
897
898    /**
899     * Searches down through databases to find a given parameter, whose value
900     * must be an integer >= minValue and <= maxValue. It returns the value, or
901     * minValue-1 if the value is out of range or if there is an error in
902     * parsing the parameter. The parameter chosen is marked "used" if it
903     * exists. Integers may be in decimal or (if preceded with an X or x) in
904     * hexadecimal.
905     */
906    int getIntWithMax(Parameter parameter, int minValue, int maxValue)
907        {
908        if (_exists(parameter))
909            {
910            try
911                {
912                int i = parseInt(get(parameter));
913                if (i < minValue)
914                    return minValue - 1;
915                if (i > maxValue)
916                    return minValue - 1;
917                return i;
918                }
919            catch (NumberFormatException e)
920                {
921                return minValue - 1;
922                }
923            }
924        else
925            return minValue - 1;
926        }
927
928
929    float getFloat(Parameter parameter) throws NumberFormatException
930        {
931        if (_exists(parameter))
932            {
933            try
934                {
935                // For JDK 1.2 and later, this is more efficient...
936                // float i = Float.parseFloat(get(parameter));
937                // ...but we can't use it and still be compatible with JDK 1.1
938                return Float.valueOf(get(parameter)).floatValue(); // what stupidity...
939                }
940            catch (NumberFormatException e)
941                {
942                throw new NumberFormatException("Bad float ("
943                    + get(parameter) + " ) for parameter " + parameter);
944                }
945            }
946        else
947            throw new NumberFormatException(
948                "Float does not exist for parameter " + parameter);
949        }
950
951    /*
952     * Searches down through databases to find a given parameter, whose value
953     * must be a float. It returns the value, else throws a
954     * NumberFormatException exception if there is an error in parsing the
955     * parameter. The parameter chosen is marked "used" if it exists.
956     */
957    public float getFloat(Parameter parameter, Parameter defaultParameter)
958        throws NumberFormatException
959        {
960        printGotten(parameter, defaultParameter, false);
961        if (_exists(parameter))
962            return getFloat(parameter);
963        else if (_exists(defaultParameter))
964            return getFloat(defaultParameter);
965        else
966            throw new NumberFormatException(
967                "Float does not exist for either parameter " + parameter
968                + "\nor\n" + defaultParameter);
969        }
970       
971
972    /**
973     * Searches down through databases to find a given parameter, whose value
974     * must be a float >= minValue. If not, this method returns minvalue-1, else
975     * it returns the parameter value. The parameter chosen is marked "used" if
976     * it exists.
977     */
978
979    public float getFloat(Parameter parameter,
980        Parameter defaultParameter, double minValue)
981        {
982        printGotten(parameter, defaultParameter, false);
983        if (_exists(parameter))
984            return getFloat(parameter, minValue);
985        else
986            return getFloat(defaultParameter, minValue);
987        }
988
989    /**
990     * Searches down through databases to find a given parameter, whose value
991     * must be a float >= minValue. If not, this method returns minvalue-1, else
992     * it returns the parameter value. The parameter chosen is marked "used" if
993     * it exists.
994     */
995
996    float getFloat(Parameter parameter, double minValue)
997        {
998        if (_exists(parameter))
999            {
1000            try
1001                {
1002                float i = Float.valueOf(get(parameter)).floatValue(); // what stupidity...
1003
1004                // For JDK 1.2 and later, this is more efficient...
1005                // float i = Float.parseFloat(get(parameter));
1006                // ...but we can't use it and still be compatible with JDK 1.1
1007
1008                if (i < minValue)
1009                    return (float) (minValue - 1);
1010                return i;
1011                }
1012            catch (NumberFormatException e)
1013                {
1014                return (float) (minValue - 1);
1015                }
1016            }
1017        else
1018            return (float) (minValue - 1);
1019        }
1020
1021    /**
1022     * Searches down through databases to find a given parameter, which must be
1023     * a float. If there is an error in parsing the parameter, then default is
1024     * returned. The parameter chosen is marked "used" if it exists.
1025     */
1026    public float getFloatWithDefault(Parameter parameter,
1027        Parameter defaultParameter, double defaultValue)
1028        {
1029        printGotten(parameter, defaultParameter, false);
1030        if (_exists(parameter))
1031            return getFloatWithDefault(parameter, defaultValue);
1032        else
1033            return getFloatWithDefault(defaultParameter, defaultValue);
1034        }
1035
1036    /**
1037     * Searches down through databases to find a given parameter, which must be
1038     * a float. If there is an error in parsing the parameter, then default is
1039     * returned. The parameter chosen is marked "used" if it exists.
1040     */
1041    float getFloatWithDefault(Parameter parameter, double defaultValue)
1042        {
1043        if (_exists(parameter))
1044            {
1045            try
1046                {
1047                // For JDK 1.2 and later, this is more efficient...
1048                // return Float.parseFloat(get(parameter));
1049                // ...but we can't use it and still be compatible with JDK 1.1
1050                return Float.valueOf(get(parameter)).floatValue(); // what stupidity...
1051                }
1052            catch (NumberFormatException e)
1053                {
1054                return (float) (defaultValue);
1055                }
1056            }
1057        else
1058            return (float) (defaultValue);
1059        }
1060
1061    /**
1062     * Searches down through databases to find a given parameter, whose value
1063     * must be a float >= minValue and <= maxValue. If not, this method returns
1064     * minvalue-1, else it returns the parameter value. The parameter chosen is
1065     * marked "used" if it exists.
1066     */
1067
1068    public float getFloatWithMax(Parameter parameter,
1069        Parameter defaultParameter, double minValue, double maxValue)
1070        {
1071        printGotten(parameter, defaultParameter, false);
1072        if (_exists(parameter))
1073            return getFloat(parameter, minValue, maxValue);
1074        else
1075            return getFloat(defaultParameter, minValue, maxValue);
1076        }
1077
1078    /**
1079     * Searches down through databases to find a given parameter, whose value
1080     * must be a float >= minValue and <= maxValue. If not, this method returns
1081     * minvalue-1, else it returns the parameter value. The parameter chosen is
1082     * marked "used" if it exists.
1083     *
1084     * @deprecated Use getFloatWithMax instead
1085     */
1086
1087    public float getFloat(Parameter parameter,
1088        Parameter defaultParameter, double minValue, double maxValue)
1089        {
1090        return getFloatWithMax(parameter, defaultParameter, minValue, maxValue);
1091        }
1092
1093    /**
1094     * Searches down through databases to find a given parameter, whose value
1095     * must be a float >= minValue and <= maxValue. If not, this method returns
1096     * minvalue-1, else it returns the parameter value. The parameter chosen is
1097     * marked "used" if it exists.
1098     */
1099
1100    float getFloat(Parameter parameter, double minValue, double maxValue)
1101        {
1102        if (_exists(parameter))
1103            {
1104            try
1105                {
1106                float i = Float.valueOf(get(parameter)).floatValue(); // what stupidity...
1107
1108                // For JDK 1.2 and later, this is more efficient...
1109                // float i = Float.parseFloat(get(parameter));
1110                // ...but we can't use it and still be compatible with JDK 1.1
1111
1112                if (i < minValue)
1113                    return (float) (minValue - 1);
1114                if (i > maxValue)
1115                    return (float) (minValue - 1);
1116                return i;
1117                }
1118            catch (NumberFormatException e)
1119                {
1120                return (float) (minValue - 1);
1121                }
1122            }
1123        else
1124            return (float) (minValue - 1);
1125        }
1126
1127    double getDouble(Parameter parameter) throws NumberFormatException
1128        {
1129        if (_exists(parameter))
1130            {
1131            try
1132                {
1133                // For JDK 1.2 and later, this is more efficient...
1134                // double i = Double.parseDouble(get(parameter));
1135                // ...but we can't use it and still be compatible with JDK 1.1
1136                return Double.valueOf(get(parameter)).doubleValue(); // what stupidity...
1137                }
1138            catch (NumberFormatException e)
1139                {
1140                throw new NumberFormatException("Bad double ("
1141                    + get(parameter) + " ) for parameter " + parameter);
1142                }
1143            }
1144        else
1145            throw new NumberFormatException(
1146                "Double does not exist for parameter " + parameter);
1147        }
1148
1149    /*
1150     * Searches down through databases to find a given parameter, whose value
1151     * must be an double. It returns the value, else throws a
1152     * NumberFormatException exception if there is an error in parsing the
1153     * parameter. The parameter chosen is marked "used" if it exists.
1154     */
1155    public double getDouble(Parameter parameter, Parameter defaultParameter)
1156        throws NumberFormatException
1157        {
1158        printGotten(parameter, defaultParameter, false);
1159        if (_exists(parameter))
1160            return getDouble(parameter);
1161        else if (_exists(defaultParameter))
1162            return getDouble(defaultParameter);
1163        else
1164            throw new NumberFormatException(
1165                "Double does not exist for either parameter " + parameter
1166                + "\nor\n" + defaultParameter);
1167        }
1168       
1169
1170    /**
1171     * Searches down through databases to find a given parameter, whose value
1172     * must be a double >= minValue. If not, this method returns minvalue-1,
1173     * else it returns the parameter value. The parameter chosen is marked
1174     * "used" if it exists.
1175     */
1176
1177    public double getDouble(Parameter parameter,
1178        Parameter defaultParameter, double minValue)
1179        {
1180        printGotten(parameter, defaultParameter, false);
1181        if (_exists(parameter))
1182            return getDouble(parameter, minValue);
1183        else
1184            return getDouble(defaultParameter, minValue);
1185        }
1186
1187    /**
1188     * Searches down through databases to find a given parameter, whose value
1189     * must be a double >= minValue. If not, this method returns minvalue-1,
1190     * else it returns the parameter value. The parameter chosen is marked
1191     * "used" if it exists.
1192     */
1193
1194    double getDouble(Parameter parameter, double minValue)
1195        {
1196        if (_exists(parameter))
1197            {
1198            try
1199                {
1200                double i = Double.valueOf(get(parameter)).doubleValue(); // what stupidity...
1201
1202                // For JDK 1.2 and later, this is more efficient...
1203                // double i = Double.parseDouble(get(parameter));
1204                // ...but we can't use it and still be compatible with JDK 1.1
1205
1206                if (i < minValue)
1207                    return (double) (minValue - 1);
1208                return i;
1209                }
1210            catch (NumberFormatException e)
1211                {
1212                return (double) (minValue - 1);
1213                }
1214            }
1215        else
1216            return (double) (minValue - 1);
1217        }
1218
1219    /**
1220     * Searches down through databases to find a given parameter, whose value
1221     * must be a double >= minValue and <= maxValue. If not, this method returns
1222     * minvalue-1, else it returns the parameter value. The parameter chosen is
1223     * marked "used" if it exists.
1224     */
1225
1226    public double getDoubleWithMax(Parameter parameter,
1227        Parameter defaultParameter, double minValue, double maxValue)
1228        {
1229        printGotten(parameter, defaultParameter, false);
1230        if (_exists(parameter))
1231            return getDouble(parameter, minValue, maxValue);
1232        else
1233            return getDouble(defaultParameter, minValue, maxValue);
1234        }
1235
1236    /**
1237     * Searches down through databases to find a given parameter, whose value
1238     * must be a double >= minValue and <= maxValue. If not, this method returns
1239     * minvalue-1, else it returns the parameter value. The parameter chosen is
1240     * marked "used" if it exists.
1241     *
1242     * @deprecated use getDoubleWithMax instead
1243     */
1244
1245    public double getDouble(Parameter parameter,
1246        Parameter defaultParameter, double minValue, double maxValue)
1247        {
1248        return getDoubleWithMax(parameter, defaultParameter, minValue, maxValue);
1249        }
1250
1251    /**
1252     * Searches down through databases to find a given parameter, whose value
1253     * must be a double >= minValue and <= maxValue. If not, this method returns
1254     * minvalue-1, else it returns the parameter value. The parameter chosen is
1255     * marked "used" if it exists.
1256     */
1257
1258    double getDouble(Parameter parameter, double minValue, double maxValue)
1259        {
1260        if (_exists(parameter))
1261            {
1262            try
1263                {
1264                double i = Double.valueOf(get(parameter)).doubleValue(); // what stupidity...
1265
1266                // For JDK 1.2 and later, this is more efficient...
1267                // double i = Double.parseDouble(get(parameter));
1268                // ...but we can't use it and still be compatible with JDK 1.1
1269
1270                if (i < minValue)
1271                    return (double) (minValue - 1);
1272                if (i > maxValue)
1273                    return (double) (minValue - 1);
1274                return i;
1275                }
1276            catch (NumberFormatException e)
1277                {
1278                return (double) (minValue - 1);
1279                }
1280            }
1281        else
1282            return (double) (minValue - 1);
1283        }
1284
1285    /**
1286     * Searches down through databases to find a given parameter, which must be
1287     * a float. If there is an error in parsing the parameter, then default is
1288     * returned. The parameter chosen is marked "used" if it exists.
1289     */
1290    public double getDoubleWithDefault(Parameter parameter,
1291        Parameter defaultParameter, double defaultValue)
1292        {
1293        printGotten(parameter, defaultParameter, false);
1294        if (_exists(parameter))
1295            return getDoubleWithDefault(parameter, defaultValue);
1296        else
1297            return getDoubleWithDefault(defaultParameter, defaultValue);
1298        }
1299
1300    /**
1301     * Searches down through databases to find a given parameter, which must be
1302     * a float. If there is an error in parsing the parameter, then default is
1303     * returned. The parameter chosen is marked "used" if it exists.
1304     */
1305    double getDoubleWithDefault(Parameter parameter, double defaultValue)
1306        {
1307        if (_exists(parameter))
1308            {
1309            try
1310                {
1311                // For JDK 1.2 and later, this is more efficient...
1312                // return Double.parseDouble(get(parameter));
1313                // ...but we can't use it and still be compatible with JDK 1.1
1314                return Double.valueOf(get(parameter)).doubleValue(); // what stupidity...
1315                }
1316            catch (NumberFormatException e)
1317                {
1318                return defaultValue;
1319                }
1320            }
1321        else
1322            return defaultValue;
1323        }
1324
1325    /**
1326     * Searches down through databases to find a given parameter, whose value
1327     * must be a long. It returns the value, else throws a NumberFormatException
1328     * exception if there is an error in parsing the parameter. The parameter
1329     * chosen is marked "used" if it exists. Longs may be in decimal or (if
1330     * preceded with an X or x) in hexadecimal.
1331     */
1332    /*protected*/ long getLong(Parameter parameter)
1333        throws NumberFormatException
1334        {
1335        if (_exists(parameter))
1336            {
1337            try
1338                {
1339                return parseLong(get(parameter));
1340                }
1341            catch (NumberFormatException e)
1342                {
1343                throw new NumberFormatException("Bad long (" + get(parameter)
1344                    + " ) for parameter " + parameter);
1345                }
1346            }
1347        else
1348            throw new NumberFormatException(
1349                "Long does not exist for parameter " + parameter);
1350        }
1351
1352    /**
1353     * Searches down through databases to find a given parameter, whose value
1354     * must be a long. It returns the value, else throws a NumberFormatException
1355     * exception if there is an error in parsing the parameter. The parameter
1356     * chosen is marked "used" if it exists. Longs may be in decimal or (if
1357     * preceded with an X or x) in hexadecimal.
1358     */
1359    public long getLong(Parameter parameter, Parameter defaultParameter)
1360        throws NumberFormatException
1361        {
1362        printGotten(parameter, defaultParameter, false);
1363        if (_exists(parameter))
1364            return getLong(parameter);
1365        else if (_exists(defaultParameter))
1366            return getLong(defaultParameter);
1367        else
1368            throw new NumberFormatException(
1369                "Long does not exist for either parameter " + parameter
1370                + "\nor\n" + defaultParameter);
1371        }
1372
1373    /**
1374     * Searches down through databases to find a given parameter, whose value
1375     * must be a long >= minValue. If not, this method returns errValue, else it
1376     * returns the parameter value. The parameter chosen is marked "used" if it
1377     * exists. Longs may be in decimal or (if preceded with an X or x) in
1378     * hexadecimal.
1379     */
1380
1381    public long getLong(Parameter parameter, Parameter defaultParameter,
1382        long minValue)
1383        {
1384        printGotten(parameter, defaultParameter, false);
1385        if (_exists(parameter))
1386            return getLong(parameter, minValue);
1387        else
1388            return getLong(defaultParameter, minValue);
1389        }
1390
1391    /**
1392     * Searches down through databases to find a given parameter, whose value
1393     * must be a long >= minValue. If not, this method returns errValue, else it
1394     * returns the parameter value. The parameter chosen is marked "used" if it
1395     * exists. Longs may be in decimal or (if preceded with an X or x) in
1396     * hexadecimal.
1397     */
1398    long getLong(Parameter parameter, long minValue)
1399        {
1400        if (_exists(parameter))
1401            {
1402            try
1403                {
1404                long i = parseLong(get(parameter));
1405                if (i < minValue)
1406                    return minValue - 1;
1407                return i;
1408                }
1409            catch (NumberFormatException e)
1410                {
1411                return minValue - 1;
1412                }
1413            }
1414        else
1415            return (minValue - 1);
1416        }
1417
1418    /**
1419     * Searches down through databases to find a given parameter, which must be
1420     * a long. If there is an error in parsing the parameter, then default is
1421     * returned. The parameter chosen is marked "used" if it exists. Longs may
1422     * be in decimal or (if preceded with an X or x) in hexadecimal.
1423     */
1424    public long getLongWithDefault(Parameter parameter,
1425        Parameter defaultParameter, long defaultValue)
1426        {
1427        printGotten(parameter, defaultParameter, false);
1428        if (_exists(parameter))
1429            return getLongWithDefault(parameter, defaultValue);
1430        else
1431            return getLongWithDefault(defaultParameter, defaultValue);
1432        }
1433
1434    /**
1435     * Searches down through databases to find a given parameter, which must be
1436     * a long. If there is an error in parsing the parameter, then default is
1437     * returned. The parameter chosen is marked "used" if it exists. Longs may
1438     * be in decimal or (if preceded with an X or x) in hexadecimal.
1439     */
1440    long getLongWithDefault(Parameter parameter, long defaultValue)
1441        {
1442        if (_exists(parameter))
1443            {
1444            try
1445                {
1446                return parseLong(get(parameter));
1447                }
1448            catch (NumberFormatException e)
1449                {
1450                return defaultValue;
1451                }
1452            }
1453        else
1454            return defaultValue;
1455        }
1456
1457    /**
1458     * Searches down through databases to find a given parameter, whose value
1459     * must be a long >= minValue and = < maxValue. If not, this method returns
1460     * errValue, else it returns the parameter value. The parameter chosen is
1461     * marked "used" if it exists. Longs may be in decimal or (if preceded with
1462     * an X or x) in hexadecimal.
1463     */
1464    public long getLongWithMax(Parameter parameter,
1465        Parameter defaultParameter, long minValue, long maxValue)
1466        {
1467        printGotten(parameter, defaultParameter, false);
1468        if (_exists(parameter))
1469            return getLong(parameter, minValue, maxValue);
1470        else
1471            return getLong(defaultParameter, minValue, maxValue);
1472        }
1473
1474    /**
1475     * Use getLongWithMax(...) instead. Searches down through databases to find
1476     * a given parameter, whose value must be a long >= minValue and = <
1477     * maxValue. If not, this method returns errValue, else it returns the
1478     * parameter value. The parameter chosen is marked "used" if it exists.
1479     * Longs may be in decimal or (if preceded with an X or x) in hexadecimal.
1480     */
1481    long getLongWithMax(Parameter parameter, long minValue, long maxValue)
1482        {
1483        if (_exists(parameter))
1484            {
1485            try
1486                {
1487                long i = parseLong(get(parameter));
1488                if (i < minValue)
1489                    return minValue - 1;
1490                if (i > maxValue)
1491                    return minValue - 1;
1492                return i;
1493                }
1494            catch (NumberFormatException e)
1495                {
1496                return minValue - 1;
1497                }
1498            }
1499        else
1500            return (minValue - 1);
1501        }
1502
1503    /**
1504     * Use getLongWithMax(...) instead. Searches down through databases to find
1505     * a given parameter, whose value must be a long >= minValue and = <
1506     * maxValue. If not, this method returns errValue, else it returns the
1507     * parameter value. The parameter chosen is marked "used" if it exists.
1508     * Longs may be in decimal or (if preceded with an X or x) in hexadecimal.
1509     *
1510     * @deprecated
1511     */
1512    public long getLong(Parameter parameter, Parameter defaultParameter,
1513        long minValue, long maxValue)
1514        {
1515        printGotten(parameter, defaultParameter, false);
1516        return getLongWithMax(parameter, defaultParameter, minValue, maxValue);
1517        }
1518
1519    /**
1520     * Use getLongWithMax(...) instead. Searches down through databases to find
1521     * a given parameter, whose value must be a long >= minValue and = <
1522     * maxValue. If not, this method returns errValue, else it returns the
1523     * parameter value. The parameter chosen is marked "used" if it exists.
1524     *
1525     * @deprecated
1526     */
1527    long getLong(Parameter parameter, long minValue, long maxValue)
1528        {
1529        return getLongWithMax(parameter, minValue, maxValue);
1530        }
1531
1532    /**
1533     * Searches down through the databases to find a given parameter, whose
1534     * value must be an absolute or relative path name. If it is absolute, a
1535     * File is made based on the path name. If it is relative, a file is made by
1536     * resolving the path name with respect to the directory in which the file
1537     * was which defined this ParameterDatabase in the ParameterDatabase
1538     * hierarchy. If the parameter is not found, this returns null. The File is
1539     * not checked for validity. The parameter chosen is marked "used" if it
1540     * exists.
1541     */
1542
1543    public File getFile(Parameter parameter, Parameter defaultParameter)
1544        {
1545        printGotten(parameter, defaultParameter, false);
1546        if (_exists(parameter))
1547            return getFile(parameter);
1548        else
1549            return getFile(defaultParameter);
1550        }
1551
1552    /**
1553     * Searches down through the databases to find a given parameter, whose
1554     * value must be an absolute or relative path name. If the parameter begins
1555     * with a "$", a file is made based on the relative path name and returned
1556     * directly. Otherwise, if it is absolute, a File is made based on the path
1557     * name, or if it is relative, a file is made by resolving the path name
1558     * with respect to the directory in which the file was which defined this
1559     * ParameterDatabase in the ParameterDatabase hierarchy. If the parameter is
1560     * not found, this returns null. The File is not checked for validity. The
1561     * parameter chosen is marked "used" if it exists.
1562     */
1563
1564    File getFile(Parameter parameter)
1565        {
1566        if (_exists(parameter))
1567            {
1568            String p = get(parameter);
1569            if (p == null)
1570                return null;
1571            if (p.startsWith(C_HERE))
1572                return new File(p.substring(C_HERE.length()));
1573            else {
1574                File f = new File(p);
1575                if (f.isAbsolute())
1576                    return f;
1577                else
1578                    return new File(directoryFor(parameter), p);
1579                }
1580            }
1581        else
1582            return null;
1583        }
1584
1585    /**
1586     * Searches down through databases to find a given parameter. Returns the
1587     * parameter's value (trimmed) or null if not found or if the trimmed result
1588     * is empty. The parameter chosen is marked "used" if it exists.
1589     */
1590
1591    public synchronized String getString(Parameter parameter,
1592        Parameter defaultParameter)
1593        {
1594        printGotten(parameter, defaultParameter, false);
1595        if (_exists(parameter))
1596            return getString(parameter);
1597        else
1598            return getString(defaultParameter);
1599        }
1600
1601    /**
1602     * Searches down through databases to find a given parameter. Returns the
1603     * parameter's value (trimmed) or null if not found or if the trimmed result
1604     * is empty. The parameter chosen is marked "used" if it exists.
1605     */
1606
1607    /*protected*/ synchronized String getString(Parameter parameter)
1608        {
1609        if (_exists(parameter))
1610            return get(parameter);
1611        else
1612            return null;
1613        }
1614
1615    /**
1616     * Searches down through databases to find a given parameter. Returns the
1617     * parameter's value trimmed of whitespace, or defaultValue.trim() if the
1618     * result is not found or the trimmed result is empty.
1619     */
1620    public String getStringWithDefault(Parameter parameter,
1621        Parameter defaultParameter, String defaultValue)
1622        {
1623        printGotten(parameter, defaultParameter, false);
1624        if (_exists(parameter))
1625            return getStringWithDefault(parameter, defaultValue);
1626        else
1627            return getStringWithDefault(defaultParameter, defaultValue);
1628        }
1629
1630    /**
1631     * Searches down through databases to find a given parameter. Returns the
1632     * parameter's value trimmed of whitespace, or defaultValue.trim() if the
1633     * result is not found or the trimmed result is empty.
1634     */
1635    /*protected*/ String getStringWithDefault(Parameter parameter,
1636        String defaultValue)
1637        {
1638        if (_exists(parameter))
1639            {
1640            String result = get(parameter);
1641            if (result == null)
1642                {
1643                if (defaultValue == null)
1644                    return null;
1645                else
1646                    result = defaultValue.trim();
1647                }
1648            else {
1649                result = result.trim();
1650                if (result.length() == 0)
1651                    {
1652                    if (defaultValue == null)
1653                        return null;
1654                    else
1655                        result = defaultValue.trim();
1656                    }
1657                }
1658            return result;
1659            }
1660        else {
1661            if (defaultValue == null)
1662                return null;
1663            else
1664                return defaultValue.trim();
1665            }
1666        }
1667
1668    /** Clears the checked flag */
1669    /*protected*/ synchronized void uncheck()
1670        {
1671        if (!checked)
1672            return; // we already unchecked this path -- this is dangerous if
1673                    // parents are used without children
1674        checked = false;
1675        int size = parents.size();
1676        for (int x = 0; x < size; x++)
1677            ((ParameterDatabase) (parents.elementAt(x))).uncheck();
1678        }
1679   
1680    /**
1681     * Sets a parameter in the topmost database to a given value, trimmed of
1682     * whitespace.
1683     */
1684    public synchronized void set(Parameter parameter, String value)
1685        {
1686        String tmp = value.trim();
1687        put(parameter.param, tmp);
1688        // fireParameterSet(parameter, tmp);
1689        }
1690
1691    /**
1692     * Prints out all the parameters marked as used, plus their values. If a
1693     * parameter was listed as "used" but not's actually in the database, the
1694     * value printed is UNKNOWN_VALUE (set to "?????")
1695     */
1696
1697    public synchronized void listGotten(PrintWriter p)
1698        {
1699        Vector vec = new Vector();
1700        Enumeration e = gotten.keys();
1701        while (e.hasMoreElements())
1702            vec.addElement(e.nextElement());
1703
1704        // sort the keys
1705        Object[] array = new Object[vec.size()];
1706        vec.copyInto(array);
1707
1708        java.util.Collections.sort(vec);
1709
1710        // Uncheck and print each item
1711        for (int x = 0; x < array.length; x++)
1712            {
1713            String s = (String) (array[x]);
1714            String v = null;
1715            if (s != null)
1716                {
1717                v = (String) (_get(s));
1718                uncheck();
1719                }
1720            if (v == null)
1721                v = UNKNOWN_VALUE;
1722            p.println(s + " = " + v);
1723            }
1724        p.flush();
1725        }
1726
1727    /** Prints out all the parameters NOT marked as used, plus their values. */
1728
1729    public synchronized void listNotGotten(PrintWriter p)
1730        {
1731        Vector vec = new Vector();
1732
1733        Hashtable all = new Hashtable();
1734        _list(null, false, null, all); // grab all the nonshadowed keys
1735        Enumeration e = gotten.keys();
1736        while (e.hasMoreElements())
1737            all.remove(e.nextElement());
1738        e = all.keys();
1739        while (e.hasMoreElements())
1740            vec.addElement(e.nextElement());
1741
1742        // sort the keys
1743        Object[] array = new Object[vec.size()];
1744        vec.copyInto(array);
1745
1746        java.util.Collections.sort(vec);
1747
1748        // Uncheck and print each item
1749        for (int x = 0; x < array.length; x++)
1750            {
1751            String s = (String) (array[x]);
1752            String v = null;
1753            if (s != null)
1754                {
1755                v = (String) (_get(s));
1756                uncheck();
1757                }
1758            if (v == null)
1759                v = UNKNOWN_VALUE;
1760            p.println(s + " = " + v);
1761            }
1762        p.flush();
1763        }
1764
1765    /** Prints out all the parameters NOT marked as used, plus their values. */
1766
1767    public synchronized void listNotAccessed(PrintWriter p)
1768        {
1769        Vector vec = new Vector();
1770
1771        Hashtable all = new Hashtable();
1772        _list(null, false, null, all); // grab all the nonshadowed keys
1773        Enumeration e = accessed.keys();
1774        while (e.hasMoreElements())
1775            all.remove(e.nextElement());
1776        e = all.keys();
1777        while (e.hasMoreElements())
1778            vec.addElement(e.nextElement());
1779
1780        // sort the keys
1781        Object[] array = new Object[vec.size()];
1782        vec.copyInto(array);
1783
1784        java.util.Collections.sort(vec);
1785
1786        // Uncheck and print each item
1787        for (int x = 0; x < array.length; x++)
1788            {
1789            String s = (String) (array[x]);
1790            String v = null;
1791            if (s != null)
1792                {
1793                v = (String) (_get(s));
1794                uncheck();
1795                }
1796            if (v == null)
1797                v = UNKNOWN_VALUE;
1798            p.println(s + " = " + v);
1799            }
1800        p.flush();
1801        }
1802
1803    /**
1804     * Prints out all the parameters marked as accessed ("gotten" by some
1805     * getFoo(...) method), plus their values. If this method ever prints
1806     * UNKNOWN_VALUE ("?????"), that's a bug.
1807     */
1808
1809    public synchronized void listAccessed(PrintWriter p)
1810        {
1811        Vector vec = new Vector();
1812        Enumeration e = accessed.keys();
1813        while (e.hasMoreElements())
1814            vec.addElement(e.nextElement());
1815
1816        // sort the keys
1817        Object[] array = new Object[vec.size()];
1818        vec.copyInto(array);
1819
1820        java.util.Collections.sort(vec);
1821
1822        // Uncheck and print each item
1823        for (int x = 0; x < array.length; x++)
1824            {
1825            String s = (String) (array[x]);
1826            String v = null;
1827            if (s != null)
1828                {
1829                v = (String) (_get(s));
1830                uncheck();
1831                }
1832            if (v == null)
1833                v = UNKNOWN_VALUE;
1834            p.println(s + " = " + v);
1835            }
1836        p.flush();
1837        }
1838
1839    /** Returns true if parameter exist in the database
1840        @ deprecated use exists(Parameter, null)
1841    */
1842    public synchronized boolean exists(Parameter parameter)
1843        {
1844        printGotten(parameter, null, true);
1845        return _exists(parameter);
1846        }
1847
1848
1849    /*protected*/ synchronized boolean _exists(Parameter parameter)
1850        {
1851        if (parameter == null) return false;
1852        String result = _get(parameter.param);
1853        uncheck();
1854       
1855        accessed.put(parameter.param, Boolean.TRUE);
1856        return (result != null);
1857        }
1858
1859    /**
1860     * Returns true if either parameter or defaultParameter exists in the
1861     * database
1862     */
1863    public synchronized boolean exists(Parameter parameter,
1864        Parameter defaultParameter)
1865        {
1866        printGotten(parameter, defaultParameter, true);
1867        if (exists(parameter))
1868            return true;
1869        if (exists(defaultParameter))
1870            return true;
1871        return false;
1872        }
1873
1874
1875/*
1876  P: Successfully retrieved parameter
1877  !P: Unsuccessfully retrieved parameter
1878  <P: Would have retrieved parameter
1879
1880  E: Successfully tested for existence of parameter
1881  !E: Unsuccessfully tested for existence of parameter
1882  <E: Would have tested for exidstence of parameter
1883*/
1884
1885    /*protected*/ void printGotten(Parameter parameter, Parameter defaultParameter, boolean exists)
1886        {
1887        if (printState == PS_UNKNOWN)
1888            {
1889            Parameter p = new Parameter(PRINT_PARAMS);
1890            String jp = get(p);
1891            // System.err.println(jp);
1892            if (jp == null || jp.equalsIgnoreCase("false"))
1893                printState = PS_NONE;
1894            else
1895                printState = PS_PRINT_PARAMS;
1896            // System.err.println(printState);
1897            uncheck();
1898            printGotten(p,null,false);
1899            }
1900
1901        if (printState == PS_PRINT_PARAMS)
1902            {
1903            String p = "P: ";
1904            if (exists) p = "E: ";
1905           
1906            if (parameter==null && defaultParameter == null)
1907                return;
1908               
1909            else if (parameter == null)
1910                {
1911                String result = _get(defaultParameter.param);
1912                uncheck();
1913                if (result == null)
1914                    // null parameter, didn't find defaultParameter
1915                    System.err.println("\t!" + p +defaultParameter.param);
1916                else
1917                    // null parameter, found defaultParameter
1918                    System.err.println("\t " + p +defaultParameter.param + " = " + result);
1919                }
1920           
1921            else if (defaultParameter == null)
1922                {
1923                String result = _get(parameter.param);
1924                uncheck();
1925                if (result == null)
1926                    // null defaultParameter, didn't find parameter
1927                    System.err.println("\t!" + p +parameter.param);
1928                else
1929                    // null defaultParameter, found parameter
1930                    System.err.println("\t " + p +parameter.param+ " = " + result);
1931                }
1932           
1933            else
1934                {
1935                String result = _get(parameter.param);
1936                uncheck();
1937                if (result == null)
1938                    {
1939                    // didn't find parameter
1940                    System.err.println("\t!" + p +parameter.param);
1941                    result = _get(defaultParameter.param);
1942                    uncheck();
1943                    if (result == null)
1944                        // didn't find defaultParameter
1945                        System.err.println("\t!" + p +defaultParameter.param);
1946                    else
1947                        // found defaultParameter
1948                        System.err.println("\t " + p +defaultParameter.param+ " = " + result);
1949                    }
1950                else
1951                    {
1952                    // found parameter
1953                    System.err.println("\t " + p +parameter.param+ " = " + result);
1954                    System.err.println("\t<" + p +defaultParameter.param);
1955                    }
1956                }
1957            }
1958        }
1959
1960    /*protected*/ synchronized String get(Parameter parameter)
1961        {
1962        String result = _get(parameter.param);
1963        uncheck();
1964
1965        // set hashtable appropriately
1966        if (parameter != null)
1967            accessed.put(parameter.param, Boolean.TRUE);
1968        if (parameter != null)
1969            gotten.put(parameter.param, Boolean.TRUE);
1970        return result;
1971        }
1972
1973    /** Private helper function */
1974    synchronized String _get(String parameter)
1975        {
1976        if (parameter == null)
1977            {
1978            return null;
1979            }
1980        if (checked)
1981            return null; // we already searched this path
1982        checked = true;
1983        String result = getProperty(parameter);
1984        if (result == null)
1985            {
1986            int size = parents.size();
1987            for (int x = 0; x < size; x++)
1988                {
1989                result = ((ParameterDatabase) (parents.elementAt(x)))._get(parameter);
1990                if (result != null)
1991                    {
1992                    return result;
1993                    }
1994                }
1995            }
1996        else  // preprocess
1997            {
1998            result = result.trim();
1999            if (result.length() == 0)
2000                result = null;
2001            }
2002        return result;
2003        }
2004
2005    /*protected*/ Set _getShadowedValues(Parameter parameter, Set vals)
2006        {
2007        if (parameter == null)
2008            {
2009            return vals;
2010            }
2011       
2012        if (checked)
2013            {
2014            return vals;
2015            }
2016       
2017        checked = true;
2018        String result = getProperty(parameter.param);
2019        if (result != null)
2020            {
2021            result = result.trim();
2022            if (result.length() != 0)
2023                vals.add(result);
2024            }
2025       
2026        int size = parents.size();
2027        for (int i = 0; i < size; ++i)
2028            {
2029            ((ParameterDatabase)parents.elementAt(i))._getShadowedValues(parameter,vals);
2030            }
2031
2032        return vals;
2033        }
2034
2035    public Set getShadowedValues(Parameter parameter)
2036        {
2037        Set vals = new HashSet();
2038        vals = _getShadowedValues(parameter, vals);
2039        uncheck();
2040        return vals;
2041        }
2042   
2043    /**
2044     * Searches down through databases to find the directory for the database
2045     * which holds a given parameter. Returns the directory name or null if not
2046     * found.
2047     */
2048
2049    public File directoryFor(Parameter parameter)
2050        {
2051        File result = _directoryFor(parameter);
2052        uncheck();
2053        return result;
2054        }
2055   
2056    /** Private helper function */
2057    synchronized File _directoryFor(Parameter parameter)
2058        {
2059        if (checked)
2060            return null; // we already searched this path
2061        checked = true;
2062        File result = null;
2063        String p = getProperty(parameter.param);
2064        if (p == null)
2065            {
2066            int size = parents.size();
2067            for (int x = 0; x < size; x++)
2068                {
2069                result = ((ParameterDatabase) (parents.elementAt(x)))
2070                    ._directoryFor(parameter);
2071                if (result != null)
2072                    return result;
2073                }
2074            return result;
2075            }
2076        else
2077            return directory;
2078        }
2079   
2080    /** Returns a String describing the location of the ParameterDatabase holding
2081        this parameter, or "" if there is none. */
2082    public String getLocation(Parameter parameter)
2083        {
2084        File file = fileFor(parameter);
2085        if (file == null) return "";
2086        try { return file.getCanonicalPath(); }
2087        catch (IOException e) { return ""; }
2088        }
2089       
2090    /**
2091     * Searches down through databases to find the parameter file
2092     * which holds a given parameter. Returns the filename or null if not
2093     * found.
2094     *
2095     * @deprecated You probably want to use getLocation
2096     */
2097
2098    public File fileFor(Parameter parameter)
2099        {
2100        File result = _fileFor(parameter);
2101        uncheck();
2102        return result;
2103        }
2104
2105    synchronized File _fileFor(Parameter parameter)
2106        {
2107        if (checked)
2108            return null;
2109       
2110        checked = true;
2111        File result = null;
2112        String p = getProperty(parameter.param);
2113        if (p==null)
2114            {
2115            int size = parents.size();
2116            for(int i = 0; i < size; ++i)
2117                {
2118                result = ((ParameterDatabase)parents.elementAt(i))._fileFor(parameter);
2119                if (result != null)
2120                    return result;
2121                }
2122            return result;
2123            }
2124        else
2125            return new File(directory,filename);
2126        }
2127
2128    /** Removes a parameter from the topmost database. */
2129    public synchronized void remove(Parameter parameter)
2130        {
2131        if (parameter.param.equals(PRINT_PARAMS)) printState = PS_UNKNOWN;
2132        remove(parameter.param);
2133        }
2134
2135    /** Removes a parameter from the database and all its parent databases. */
2136    public synchronized void removeDeeply(Parameter parameter)
2137        {
2138        _removeDeeply(parameter);
2139        uncheck();
2140        }
2141
2142    /** Private helper function */
2143    synchronized void _removeDeeply(Parameter parameter)
2144        {
2145        if (checked)
2146            return; // already removed from this path
2147        checked = true;
2148        remove(parameter);
2149        int size = parents.size();
2150        for (int x = 0; x < size; x++)
2151            ((ParameterDatabase) (parents.elementAt(x)))
2152                .removeDeeply(parameter);
2153        }
2154
2155    public void addParent(ParameterDatabase database)
2156        {
2157        parents.addElement(database);
2158        }
2159
2160    /** Creates an empty parameter database. */
2161    public ParameterDatabase()
2162        {
2163        super();
2164        accessed = new Hashtable();
2165        gotten = new Hashtable();
2166        directory = new File(new File("").getAbsolutePath()); // uses the user
2167                                                              // path
2168        filename = "";
2169        parents = new Vector();
2170        checked = false; // unnecessary
2171        listeners = new Vector();
2172        }
2173   
2174    /** Creates a new parameter database from the given Dictionary. 
2175        Both the keys and values will be run through toString() before adding to the dataase.   
2176        Keys are parameters.  Values are the values of the parameters. 
2177        Beware that a ParameterDatabase is itself a Dictionary; but if you pass one in here you
2178        will only get the lowest-level elements.  If parent.n are defined, parents will
2179        be attempted to be loaded -- that's the reason for the FileNotFoundException and IOException.  */
2180    public ParameterDatabase(java.util.Dictionary map) throws FileNotFoundException, IOException
2181        {
2182        this();
2183        java.util.Enumeration keys = map.keys();
2184        while(keys.hasMoreElements())
2185            {
2186            Object obj = keys.nextElement();
2187            set(new Parameter(""+obj),""+map.get(obj));
2188            }
2189
2190        // load parents
2191        for (int x = 0;; x++)
2192            {
2193            String s = getProperty("parent." + x);
2194            if (s == null)
2195                return; // we're done
2196
2197            if (new File(s).isAbsolute()) // it's an absolute file definition
2198                parents.addElement(new ParameterDatabase(new File(s)));
2199            else throw new FileNotFoundException("Attempt to load a relative file, but there's no parent file: " + s);
2200            }
2201        }
2202
2203    /** Creates a new parameter database loaded from the given string describing a file in a jar,
2204        in the context of a resource location (a class).
2205        This approach uses resourceLocation.getResourceAsStream() to load the parameter file.
2206        If parent.n are defined, parents will be attempted to be loaded -- that's
2207        the reason for the FileNotFoundException and IOException. */
2208
2209    public ParameterDatabase(String pathNameInJar, Class jarResourceLocation) throws FileNotFoundException, IOException
2210        {
2211        this();
2212        load(jarResourceLocation.getResourceAsStream(pathNameInJar));
2213
2214        listeners = new Vector();
2215
2216        // load parents
2217        for (int x = 0;; x++)
2218            {
2219            String s = getProperty("parent." + x);
2220            if (s == null)
2221                return; // we're done
2222
2223            String path = new File(new File(pathNameInJar).getParent(), s).toString();
2224
2225            parents.addElement(new ParameterDatabase(path, jarResourceLocation));
2226            }
2227        }
2228
2229
2230    /** Creates a new parameter database loaded from the given stream.  Non-relative parents are not permitted.
2231        If parent.n are defined, parents will be attempted to be loaded -- that's
2232        the reason for the FileNotFoundException and IOException. */
2233
2234    public ParameterDatabase(java.io.InputStream stream) throws FileNotFoundException, IOException
2235        {
2236        this();
2237        load(stream);
2238
2239        listeners = new Vector();
2240
2241        // load parents
2242        for (int x = 0;; x++)
2243            {
2244            String s = getProperty("parent." + x);
2245            if (s == null)
2246                return; // we're done
2247
2248            if (new File(s).isAbsolute()) // it's an absolute file definition
2249                parents.addElement(new ParameterDatabase(new File(s)));
2250            else throw new FileNotFoundException("Attempt to load a relative file, but there's no parent file: " + s);
2251            }
2252        }
2253
2254
2255    /**
2256     * Creates a new parameter database tree from a given database file and its
2257     * parent files.
2258     */
2259    public ParameterDatabase(File filename)
2260        throws FileNotFoundException, IOException
2261        {
2262        this();
2263        this.filename = filename.getName();
2264        directory = new File(filename.getParent()); // get the directory
2265                                                    // filename is in
2266        load(new FileInputStream(filename));
2267
2268        listeners = new Vector();
2269
2270        // load parents
2271        for (int x = 0;; x++)
2272            {
2273            String s = getProperty("parent." + x);
2274            if (s == null)
2275                return; // we're done
2276
2277            if (new File(s).isAbsolute()) // it's an absolute file definition
2278                parents.addElement(new ParameterDatabase(new File(s)));
2279            else
2280                // it's relative to my path
2281                parents.addElement(new ParameterDatabase(new File(filename
2282                            .getParent(), s)));
2283            }
2284        }
2285
2286    /**
2287     * Creates a new parameter database from a given database file and argv
2288     * list. The top-level database is completely empty, pointing to a second
2289     * database which contains the parameter entries stored in args, which
2290     * points to a tree of databases constructed using
2291     * ParameterDatabase(filename).
2292     */
2293
2294    public ParameterDatabase(File filename, String[] args)
2295        throws FileNotFoundException, IOException
2296        {
2297        this();
2298        this.filename = filename.getName();
2299        directory = new File(filename.getParent()); // get the directory
2300                                                    // filename is in
2301
2302        // Create the Parameter Database tree for the files
2303        ParameterDatabase files = new ParameterDatabase(filename);
2304
2305        // Create the Parameter Database for the arguments
2306        ParameterDatabase a = new ParameterDatabase();
2307        a.parents.addElement(files);
2308        for (int x = 0; x < args.length - 1; x++)
2309            {
2310            if (args[x].equals("-p"))
2311                {
2312                String s = args[x+1].trim();
2313                if (s.length() == 0) continue;  // failure
2314                int eq = s.indexOf('=');  // look for the '='
2315                if (eq <= 0) continue; // '=' isn't there, or it's the first char: failure                     
2316                put(s.substring(0,eq), s.substring(eq+1));  // add the parameter
2317                }
2318            }
2319
2320        // Set me up
2321        parents.addElement(a);
2322        listeners = new Vector();
2323        }
2324
2325    /**
2326     * Prints out all the parameters in the database. Useful for debugging. If
2327     * listShadowed is true, each parameter is printed with the parameter
2328     * database it's located in. If listShadowed is false, only active
2329     * parameters are listed, and they're all given in one big chunk.
2330     */
2331    //public void list(PrintStream p, boolean listShadowed)
2332    //    {
2333    //     list(new PrintWriter(p), listShadowed);
2334    //    }
2335
2336    /**
2337     * Prints out all the parameters in the database, but not shadowed
2338     * parameters.
2339     */
2340    // public void list(PrintStream p)
2341    //     {
2342    //     list(new PrintWriter(p), false);
2343    //     }
2344
2345    /**
2346     * Prints out all the parameters in the database, but not shadowed
2347     * parameters.
2348     */
2349    public void list(PrintWriter p)
2350        {
2351        list(p, false);
2352        }
2353
2354    /**
2355     * Prints out all the parameters in the database. Useful for debugging. If
2356     * listShadowed is true, each parameter is printed with the parameter
2357     * database it's located in. If listShadowed is false, only active
2358     * parameters are listed, and they're all given in one big chunk.
2359     */
2360    public void list(PrintWriter p, boolean listShadowed)
2361        {
2362        if (listShadowed)
2363            _list(p, listShadowed, "root", null);
2364        else {
2365            Hashtable gather = new Hashtable();
2366            _list(null, listShadowed, "root", gather);
2367
2368            Vector vec = new Vector();
2369            Enumeration e = gather.keys();
2370            while (e.hasMoreElements())
2371                vec.addElement(e.nextElement());
2372
2373            // sort the keys
2374//            Object[] array = new Object[vec.size()];
2375//            vec.copyInto(array);
2376//
2377            java.util.Collections.sort(vec);
2378
2379            // Uncheck and print each item
2380            for (int x = 0; x < /* array.length;*/ vec.size(); x++)
2381                {
2382                String s = (String) /* (array[x]); */ vec.get(x);
2383                String v = null;
2384                if (s != null)
2385                    v = (String) gather.get(s);
2386                if (v == null)
2387                    v = UNKNOWN_VALUE;
2388                if (p!=null) p.println(s + " = " + v);
2389                }
2390            }
2391        if (p!=null) p.flush();
2392        }
2393
2394    /** Private helper function. */
2395    void _list(PrintWriter p, boolean listShadowed,
2396        String prefix, Hashtable gather)
2397        {
2398        if (listShadowed)
2399            {
2400            // Print out my header
2401            if (p!=null) p.println("\n########" + prefix);
2402            super.list(p);
2403            int size = parents.size();
2404            for (int x = 0; x < size; x++)
2405                ((ParameterDatabase) (parents.elementAt(x)))._list(p,
2406                    listShadowed, prefix + "." + x, gather);
2407            }
2408        else {
2409            // load in reverse order so things get properly overwritten
2410            int size = parents.size();
2411            for (int x = size - 1; x >= 0; x--)
2412                ((ParameterDatabase) (parents.elementAt(x)))._list(p,
2413                    listShadowed, prefix, gather);
2414            Enumeration e = keys();
2415            while (e.hasMoreElements())
2416                {
2417                String key = (String) (e.nextElement());
2418                gather.put(key, get(key));
2419                }
2420            }
2421        if (p!=null) p.flush();
2422        }
2423
2424    public String toString()
2425        {
2426        String s = super.toString();
2427        if (parents.size() > 0)
2428            {
2429            s += " : (";
2430            for (int x = 0; x < parents.size(); x++)
2431                {
2432                if (x > 0)
2433                    s += ", ";
2434                s += parents.elementAt(x);
2435                }
2436            s += ")";
2437            }
2438        return s;
2439        }
2440
2441    /**
2442     * Builds a TreeModel from the available property keys.   
2443     * @return
2444     */
2445    public TreeModel buildTreeModel()
2446        {
2447        String sep = System.getProperty("file.separator");
2448        ParameterDatabaseTreeNode root = new ParameterDatabaseTreeNode(
2449            this.directory.getAbsolutePath() + sep + this.filename);
2450        ParameterDatabaseTreeModel model = new ParameterDatabaseTreeModel(root);
2451
2452        _buildTreeModel(model, root);
2453
2454        model.sort(root, new Comparator()
2455            {
2456            public int compare(Object o1, Object o2)
2457                {
2458                ParameterDatabaseTreeNode t1 = (ParameterDatabaseTreeNode)o1;
2459                ParameterDatabaseTreeNode t2 = (ParameterDatabaseTreeNode)o2;
2460               
2461                return ((Comparable)t1.getUserObject()).compareTo(t2.getUserObject());
2462                }
2463            });
2464
2465        // In order to add elements to the tree model, the leaves need to be
2466        // visible. This is because some properties have values *and* sub-
2467        // properties. Otherwise, if the nodes representing these properties did
2468        // not yet have children, then they would be invisible and the tree model
2469        // would be unable to add child nodes to them.
2470        model.setVisibleLeaves(false);
2471       
2472//        addListener(new ParameterDatabaseAdapter() {
2473//           public void parameterSet(ParameterDatabaseEvent evt) {
2474//               model.setVisibleLeaves(true);
2475//               _addNodeForParameter(model, root, evt.getParameter().param);
2476//               model.setVisibleLeaves(false);
2477//           }
2478//        });
2479
2480        return model;
2481        }
2482
2483    void _buildTreeModel(DefaultTreeModel model,
2484        DefaultMutableTreeNode root)
2485        {
2486        Enumeration e = keys();
2487        while (e.hasMoreElements())
2488            {
2489            _addNodeForParameter(model, root, (String)e.nextElement());
2490            }
2491
2492        int size = parents.size();
2493        for (int i = 0; i < size; ++i)
2494            {
2495            ParameterDatabase parentDB = (ParameterDatabase) parents
2496                .elementAt(i);
2497            parentDB._buildTreeModel(model, root);
2498            }
2499        }
2500
2501    /**
2502     * @param model
2503     * @param root
2504     * @param e
2505     */
2506    void _addNodeForParameter(DefaultTreeModel model, DefaultMutableTreeNode root, String key)
2507        {
2508        if (key.indexOf("parent.") == -1)
2509            {
2510            /*
2511             * TODO split is new to 1.4.  To maintain 1.2 compatability we need
2512             * to use a different approach.  Just use a string tokenizer.
2513             */
2514            StringTokenizer tok = new StringTokenizer(key,".");
2515            String[] path = new String[tok.countTokens()];
2516            int t = 0;
2517            while(tok.hasMoreTokens())
2518                {
2519                path[t++] = tok.nextToken();
2520                }
2521            DefaultMutableTreeNode parent = root;
2522
2523            for (int i = 0; i < path.length; ++i)
2524                {
2525                int children = model.getChildCount(parent);
2526                if (children > 0)
2527                    {
2528                    int c = 0;
2529                    for (; c < children; ++c)
2530                        {
2531                        DefaultMutableTreeNode child =
2532                            (DefaultMutableTreeNode) parent.getChildAt(c);
2533                        if (child.getUserObject().equals(path[i]))
2534                            {
2535                            parent = child;
2536                            break;
2537                            }
2538                        }
2539
2540                    if (c == children)
2541                        {
2542                        DefaultMutableTreeNode child =
2543                            new ParameterDatabaseTreeNode(path[i]);
2544                        model.insertNodeInto(child, parent,
2545                            parent.getChildCount());
2546                        parent = child;
2547                        }
2548                    }
2549                // If the parent has no children, just add the node.
2550                else {
2551                    DefaultMutableTreeNode child =
2552                        new ParameterDatabaseTreeNode(path[i]);
2553                    model.insertNodeInto(child, parent, 0);
2554                    parent = child;
2555                    }
2556                }
2557            }
2558        }
2559   
2560    /** Test the ParameterDatabase */
2561    public static void main(String[] args)
2562        throws FileNotFoundException, IOException
2563        {
2564        ParameterDatabase pd = new ParameterDatabase(new File(args[0]), args);
2565        pd.set(new Parameter("Hi there"), "Whatever");
2566        pd.set(new Parameter(new String[] { "1", "2", "3" }), " Whatever ");
2567        pd.set(new Parameter(new String[] { "a", "b", "c" }).pop().push("d"),
2568            "Whatever");
2569
2570        System.err.println("\n\n PRINTING ALL PARAMETERS \n\n");
2571        pd.list(new PrintWriter(System.err, true), true);
2572        System.err.println("\n\n PRINTING ONLY VALID PARAMETERS \n\n");
2573        pd.list(new PrintWriter(System.err, true), false);
2574        }
2575
2576    }
2577
Note: See TracBrowser for help on using the repository browser.