001: /*
002: * Project: AMODA - Abstract Modeled Application
003: * Class: de.gulden.framework.amoda.generic.option.GenericOptions
004: * Version: snapshot-beautyj-1.1
005: *
006: * Date: 2004-09-29
007: *
008: * This is a snapshot version of the AMODA 0.2 development branch,
009: * it is not released as a seperate version.
010: * For AMODA, see http://amoda.berlios.de/.
011: *
012: * This is licensed under the GNU Lesser General Public License (LGPL)
013: * and comes with NO WARRANTY.
014: *
015: * Author: Jens Gulden
016: * Email: amoda@jensgulden.de
017: */
018:
019: package de.gulden.framework.amoda.generic.option;
020:
021: import de.gulden.framework.amoda.generic.behaviour.*;
022: import de.gulden.framework.amoda.generic.core.*;
023: import de.gulden.framework.amoda.generic.core.GenericFeature;
024: import de.gulden.framework.amoda.generic.data.*;
025: import de.gulden.framework.amoda.model.data.*;
026: import de.gulden.framework.amoda.model.option.*;
027: import de.gulden.framework.amoda.model.option.Options;
028: import de.gulden.util.Toolbox;
029: import java.awt.*;
030: import java.io.*;
031: import java.lang.*;
032: import java.util.*;
033:
034: /**
035: * Class GenericOptions.
036: *
037: * @author Jens Gulden
038: * @version snapshot-beautyj-1.1
039: */
040: public class GenericOptions extends GenericFeature implements
041: Cloneable, Options {
042:
043: // ------------------------------------------------------------------------
044: // --- fields ---
045: // ------------------------------------------------------------------------
046:
047: public static String[] OPTION_ELEMENTS = { "option",
048: "options-group" };
049:
050: public static Object[][] XML_COLLECTION_ELEMENTS = { { "all",
051: OPTION_ELEMENTS } };
052:
053: protected GenericApplicationMemberAbstract parentMember;
054:
055: // ------------------------------------------------------------------------
056: // --- methods ---
057: // ------------------------------------------------------------------------
058:
059: public OptionEntry getOptionEntry(String id) {
060: try {
061: OptionEntry entry = (OptionEntry) get(id);
062: if (entry != null) {
063: return entry;
064: }
065: } catch (ClassCastException cce) {
066: // fallthrough
067: }
068: throw new IllegalOptionError(id);
069: }
070:
071: public OptionsGroup getOptionsGroup(String id) {
072: return (OptionsGroup) get(id);
073: }
074:
075: public String getString(String name) {
076: de.gulden.framework.amoda.model.option.OptionEntry e = getOptionEntry(name);
077: de.gulden.framework.amoda.model.data.Value v = e.getValue();
078: if (v != null) {
079: return v.getString();
080: } else {
081: return null;
082: }
083: }
084:
085: public int getInt(String name) {
086: de.gulden.framework.amoda.model.option.OptionEntry e = getOptionEntry(name);
087: de.gulden.framework.amoda.model.data.Value v = e.getValue();
088: if (v != null) {
089: return v.getInt();
090: } else {
091: return -1;
092: }
093: }
094:
095: public float getFloat(String name) {
096: de.gulden.framework.amoda.model.option.OptionEntry e = getOptionEntry(name);
097: de.gulden.framework.amoda.model.data.Value v = e.getValue();
098: if (v != null) {
099: return v.getFloat();
100: } else {
101: return -1.0f;
102: }
103: }
104:
105: public double getDouble(String name) {
106: de.gulden.framework.amoda.model.option.OptionEntry e = getOptionEntry(name);
107: de.gulden.framework.amoda.model.data.Value v = e.getValue();
108: if (v != null) {
109: return v.getDouble();
110: } else {
111: return -1.0;
112: }
113: }
114:
115: public boolean getBoolean(String name) {
116: de.gulden.framework.amoda.model.option.OptionEntry e = getOptionEntry(name);
117: de.gulden.framework.amoda.model.data.Value v = e.getValue();
118: if (v != null) {
119: return v.getBoolean();
120: } else {
121: return false;
122: }
123: }
124:
125: public Object getObject(String name) {
126: de.gulden.framework.amoda.model.option.OptionEntry e = getOptionEntry(name);
127: de.gulden.framework.amoda.model.data.Value v = e.getValue();
128: if (v != null) {
129: return v.get();
130: } else {
131: return null;
132: }
133: }
134:
135: public File getFile(String name) {
136: de.gulden.framework.amoda.model.option.OptionEntry e = getOptionEntry(name);
137: de.gulden.framework.amoda.model.data.Value v = e.getValue();
138: if (v != null) {
139: return v.getFile();
140: } else {
141: return null;
142: }
143: }
144:
145: public Color getColor(String name) {
146: de.gulden.framework.amoda.model.option.OptionEntry e = getOptionEntry(name);
147: de.gulden.framework.amoda.model.data.Value v = e.getValue();
148: if (v != null) {
149: return v.getColor();
150: } else {
151: return null;
152: }
153: }
154:
155: public void addAll(Options options) {
156: addAll(options, false);
157: }
158:
159: public void addAll(Options options, boolean addInFront) {
160: for (Iterator it = options.getEntries().values().iterator(); it
161: .hasNext();) {
162: de.gulden.framework.amoda.model.option.Option option = (de.gulden.framework.amoda.model.option.Option) it
163: .next();
164: add(option);
165: }
166: for (Iterator it = options.getGroups().values().iterator(); it
167: .hasNext();) {
168: de.gulden.framework.amoda.model.option.Option option = (de.gulden.framework.amoda.model.option.Option) it
169: .next();
170: add(option);
171: }
172: }
173:
174: public boolean isValid() {
175: // your code here
176: return true;
177: }
178:
179: public CompositeGroup getParent() {
180: GenericApplicationMemberAbstract parentMember = getParentMember();
181: if (parentMember instanceof CompositeGroup) {
182: return (CompositeGroup) parentMember;
183: } else {
184: if (parentMember != null) {
185: return parentMember.getParent();
186: } else {
187: return null;
188: }
189: }
190: }
191:
192: public Map getGroups() {
193: // this re-implements getGroups in order to simulate a recursive structure on options based on the structure of feature-groups
194: Map h = new de.gulden.util.OrderedHashMap();
195: GenericApplicationMemberAbstract parentMember = getParentMember();
196: if (parentMember instanceof de.gulden.framework.amoda.model.core.Feature) {
197: de.gulden.framework.amoda.model.core.Feature parentFeature = (de.gulden.framework.amoda.model.core.Feature) parentMember;
198: Map siblingMembers = parentFeature.getAll();
199: for (Iterator it = siblingMembers.values().iterator(); it
200: .hasNext();) {
201: Object o = it.next();
202: Class t = o.getClass();
203: // allow only feature-groups and features, NOT subclasses like commands, conditions etc.
204: // (to commands etc, inner options are local and are invisible here)
205: if ((t == de.gulden.framework.amoda.generic.core.GenericFeature.class)
206: || (t == de.gulden.framework.amoda.generic.core.GenericFeatureGroup.class)) {
207: de.gulden.framework.amoda.generic.core.GenericFeature feature = (de.gulden.framework.amoda.generic.core.GenericFeature) o;
208: GenericOptions options = (GenericOptions) feature
209: .getOptions();
210: if (options != null) {
211: options.setId(feature.getId()); // fake same id as feature-group, <options> don't have their own id anyway
212: h.put(options.getId(), options);
213: }
214: }
215: }
216: }
217: h.putAll(Toolbox.filterMapOnType(super .getAll(),
218: GenericOptions.class)); // for directly added options-groups
219: return h;
220: }
221:
222: public Map getAll() {
223: // needs to be re-implemented, too in order to incorporate groups
224: Map h = new de.gulden.util.OrderedHashMap();
225: h.putAll(getGroups());
226: h.putAll(getEntries());
227: // (make sure all members have a valid reference to a parent)
228: for (Iterator it = h.values().iterator(); it.hasNext();) {
229: Object o = it.next();
230: if (o instanceof CompositeMember) {
231: CompositeMember m = (CompositeMember) o;
232: if (m.getParent() == null) {
233: m.setParent(this );
234: }
235: }
236: }
237: return h;
238: }
239:
240: public GenericOptions flattenHierarchy(int maxDepth,
241: GenericCondition cond) {
242: // ************ UNTESTED ****************
243: if (countMaxDepth(cond) <= maxDepth) {
244: return this ;
245: } else {
246: GenericOptions opt = new GenericOptions();
247: opt.setParent(this .getParent());
248: for (Iterator it = getAll().values().iterator(); it
249: .hasNext();) {
250: Object o = it.next();
251: if (cond.test(o)) {
252: if (o instanceof GenericOptions) {
253: GenericOptions gOpt = ((GenericOptions) o)
254: .flattenHierarchy(maxDepth, cond);
255: gOpt = (GenericOptions) gOpt.clone(); // allow changing title
256: String optTitle = opt.findTitle();
257: ((de.gulden.framework.amoda.generic.metadata.GenericMetadata) gOpt
258: .getMetadata()).set("title", optTitle
259: + (optTitle.length() > 0 ? " / " : "")
260: + gOpt.findTitle());
261: opt.add(gOpt);
262: } else {
263: opt
264: .add((de.gulden.framework.amoda.model.data.CompositeMember) o);
265: }
266: }
267: }
268: return opt;
269: }
270: }
271:
272: public GenericApplicationMemberAbstract getParentMember() {
273: return parentMember;
274: }
275:
276: public void setParentMember(
277: GenericApplicationMemberAbstract _parentMember) {
278: parentMember = _parentMember;
279: }
280:
281: public Object clone() {
282: try {
283: return super .clone();
284: } catch (CloneNotSupportedException cnse) {
285: return null;
286: }
287: }
288:
289: public Map getEntries() {
290: return Toolbox.filterMapOnType(super .getAll(),
291: GenericOptionEntry.class);
292: }
293:
294: public String findTitle() {
295: String title = de.gulden.framework.amoda.generic.metadata.GenericMetadata
296: .findTitle(this );
297: if ((title == null)
298: || (title
299: .startsWith(Toolbox
300: .capitalize(GenericApplicationMemberAbstract.AUTO_ID_PREFIX)))) {
301: // no actual title: is <options> inside a member
302: GenericApplicationMemberAbstract parent = getParentMember();
303: if (parent != null) {
304: return parent.findTitle();
305: } else {
306: return "";
307: }
308: } else {
309: return title;
310: }
311: }
312:
313: public void setParent(CompositeGroup parent) {
314: // overwrites super.setParent
315: //super.setParent(parent); *** NOETIG?
316: // if a Feature is parent, then it is also the parent member (but not the other way round):
317: setParentMember((GenericApplicationMemberAbstract) parent);
318: }
319:
320: public void set(String id, Object value) {
321: GenericOptionEntry o = (GenericOptionEntry) getOptionEntry(id);
322: ((GenericValue) o.getValue(GenericOptionEntry.STATE_CURRENT))
323: .set(value);
324: }
325:
326: public void loadFromProperties(File file) {
327: // assumes that this is the main application options
328: try {
329: Properties props = new Properties();
330: java.io.FileInputStream f = new java.io.FileInputStream(
331: file);
332: props.load(f);
333: f.close();
334: for (Enumeration e = props.keys(); e.hasMoreElements();) {
335: String id = (String) e.nextElement();
336: String value = props.getProperty(id);
337: try {
338: GenericOptionEntry o = findOptionEntryByShortcut(id); // id might actually be shortcut-name, return null if not found
339: if (o == null) {
340: o = (GenericOptionEntry) getOptionEntry(id); // throws error if not found
341: }
342: ((de.gulden.framework.amoda.generic.data.GenericValue) o
343: .getValue(STATE_SAVED)).parseString(value);
344: } catch (IllegalOptionError ioe) {
345: getApplication().log(
346: "Unknown option name in properties file: "
347: + id + " (will be ignored)");
348: }
349: }
350: } catch (java.io.IOException ioe) {
351: getApplication().log(
352: "properties file '" + file.getAbsolutePath()
353: + "' not found - using defaults");
354: }
355: }
356:
357: public void saveToProperties(File file) {
358: // assumes that this is the main application options
359: try {
360: Properties props = new Properties();
361: java.io.FileOutputStream f = new java.io.FileOutputStream(
362: file);
363: for (Iterator it = this .getAll(GenericOptionEntry.class,
364: true).values().iterator(); it.hasNext();) {
365: GenericOptionEntry entry = (GenericOptionEntry) it
366: .next();
367: String id = entry.getQualifiedId();
368: de.gulden.framework.amoda.model.data.Value value = entry
369: .getValue(STATE_CURRENT);
370: if (value != null) {
371: String s = value.getString();
372: if (s != null) {
373: props.put(id, s);
374: entry.shiftValue(STATE_CURRENT, STATE_SAVED);
375: }
376: }
377: }
378: props.store(f, "AMODA application options");
379: f.close();
380: } catch (java.io.IOException ioe) {
381: getApplication().error("Cannot save properties file.", ioe);
382: }
383: }
384:
385: public void saveGlobalProperties() {
386: boolean persistentOptions = getApplication()
387: .getOptions()
388: .getBoolean(
389: GenericApplicationEnvironment.CONFIGURATION_PERSISTENT_OPTIONS);
390: if (persistentOptions) {
391: java.io.File file = getApplication().getOptions().getFile(
392: "properties");
393: if (file != null) {
394: saveToProperties(file);
395: } else {
396: getApplication()
397: .log(
398: "configuration properties not saved - no filename configured");
399: }
400: }
401: }
402:
403: public String getQualifiedId() {
404: // overwrites GenericApplicationMemberAbstract.getQualifiedId
405: de.gulden.framework.amoda.generic.core.GenericApplicationMemberAbstract parent = (de.gulden.framework.amoda.generic.core.GenericApplicationMemberAbstract) getParentMember();
406: if ((parent instanceof GenericOptions)
407: && (parent != getApplication().getOptions())) {
408: return parent.getQualifiedId() + "." + this .getId();
409: } else { // top-most option or option-group, parent feature names are not included
410: return this .getId();
411: }
412: }
413:
414: public void shiftAllValues(int from, int to) {
415: Map map = getAll(GenericOptionEntry.class, true);
416: for (Iterator it = map.values().iterator(); it.hasNext();) {
417: GenericOptionEntry entry = (GenericOptionEntry) it.next();
418: entry.shiftValue(from, to);
419: }
420: }
421:
422: public Class getClassType(String name) {
423: de.gulden.framework.amoda.model.option.OptionEntry e = getOptionEntry(name);
424: de.gulden.framework.amoda.model.data.Value v = e.getValue();
425: if (v != null) {
426: return v.getClassType();
427: } else {
428: return null;
429: }
430: }
431:
432: public Object getClassInstance(String name) {
433: de.gulden.framework.amoda.model.option.OptionEntry e = getOptionEntry(name);
434: de.gulden.framework.amoda.model.data.Value v = e.getValue();
435: if (v != null) {
436: return v.getClassInstance();
437: } else {
438: return null;
439: }
440: }
441:
442: public GenericOptionEntry findOptionEntryByShortcut(String shortcut) {
443: Map all = getAll();
444: for (Iterator it = all.values().iterator(); it.hasNext();) {
445: GenericFeature o = (GenericFeature) it.next();
446: String s = o.getShortcut();
447: if ((o instanceof GenericOptionEntry) && (s != null)
448: && (s.equals(shortcut))) {
449: return (GenericOptionEntry) o;
450: }
451: }
452: return null;
453: }
454:
455: } // end GenericOptions
|