001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2007
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.war.beans.admin.structure;
034:
035: import com.flexive.faces.messages.FxFacesMsgErr;
036: import com.flexive.shared.FxSharedUtils;
037: import com.flexive.shared.exceptions.FxInvalidParameterException;
038: import com.flexive.shared.structure.FxStructureOption;
039:
040: import java.util.ArrayList;
041: import java.util.List;
042: import java.util.Map;
043:
044: /**
045: * Conveniently wraps FxStructureOptions to simplify GUI Manipulaiton.
046: * The OptionWrapper wraps the options of a structure element (group or property) and
047: * its assignment. Options of the structure element override those of the assignment.
048: * Provides Maps to verify if an option is valid or may be overwritten to enhance GUI
049: * presentaiton.
050: *
051: * @author Gerhard Glos (gerhard.glos@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
052: */
053:
054: public class OptionWrapper {
055: private static String[] standardOptionKeys = {
056: FxStructureOption.OPTION_HTML_EDITOR,
057: FxStructureOption.OPTION_MULTILANG,
058: FxStructureOption.OPTION_MULTILINE,
059: FxStructureOption.OPTION_SEARCHABLE,
060: FxStructureOption.OPTION_SHOW_OVERVIEW };
061:
062: private List<WrappedOption> structureOptions = null;
063: private List<WrappedOption> assignmentOptions = null;
064: private Map<String, Boolean> assignmentOptionValidMap = null;
065: private Map<String, Boolean> assignmentOptionOverridableMap = null;
066: private Map<String, Boolean> structureOptionValidMap = null;
067:
068: /**
069: * Creates the OptionWrapper
070: *
071: * @param structureOptions optionlist of the structure element (e.g. group or property)
072: * @param assignmentOptions optionlist of the according assignment (e.g. groupassignment or propertyassignment)
073: * @param addStandardOptions if the standard options (FxStructureOption.OPTION_...) should be added to the
074: * structureOptions, if not alaready present
075: */
076: public OptionWrapper(List<FxStructureOption> structureOptions,
077: List<FxStructureOption> assignmentOptions,
078: boolean addStandardOptions) {
079: this .structureOptions = new ArrayList<WrappedOption>();
080: this .assignmentOptions = new ArrayList<WrappedOption>();
081:
082: if (structureOptions != null)
083: for (FxStructureOption o : structureOptions) {
084: this .structureOptions.add(new WrappedOption(o));
085: }
086: if (assignmentOptions != null)
087: for (FxStructureOption o : assignmentOptions) {
088: this .assignmentOptions.add(new WrappedOption(o));
089: }
090:
091: if (addStandardOptions) {
092: List<WrappedOption> standardOptions = new ArrayList<WrappedOption>();
093: for (int i = 0; i < standardOptionKeys.length; i++) {
094: standardOptions.add(new WrappedOption(
095: standardOptionKeys[i],
096: FxStructureOption.VALUE_FALSE, true, true));
097: }
098: for (WrappedOption o : standardOptions) {
099: if (!this .structureOptions.contains(o))
100: this .structureOptions.add(o);
101: }
102: }
103: }
104:
105: /**
106: * Creates the OptionWrapper
107: *
108: * @param structureOptions optionlist of the structure element (e.g. group or property)
109: * @param assignmentOptions optionlist of the according assignment (e.g. groupassignment or propertyassignment)
110: * @param standardOptionKeyList a List of option keys from which new options will be created and added,
111: * if not alaready present
112: */
113: public OptionWrapper(List<FxStructureOption> structureOptions,
114: List<FxStructureOption> assignmentOptions,
115: List<String> standardOptionKeyList) {
116: new OptionWrapper(structureOptions, assignmentOptions, false);
117: List<WrappedOption> standardOptions = new ArrayList<WrappedOption>();
118: for (String key : standardOptionKeyList) {
119: standardOptions.add(new WrappedOption(key,
120: FxStructureOption.VALUE_FALSE, false, true));
121: }
122: for (WrappedOption o : standardOptions) {
123: if (!this .structureOptions.contains(o))
124: this .structureOptions.add(o);
125: }
126: }
127:
128: /**
129: * Sets an option with Key key to Value value. If isStructure==true, the option will be set
130: * in the structureOptions list, else in the assignmentOptions list.
131: * If the option is not present a new option will be created and set accordingly.
132: *
133: * @param isStructureOption if the option should be set/created in the structureOptions or assignmentOptions list
134: * @param key the Key
135: * @param value the Value as String
136: */
137: public void setOption(boolean isStructureOption, String key,
138: String value) {
139: WrappedOption o = new WrappedOption(key, value, false, true);
140: if (isStructureOption) {
141: if (!structureOptions.contains(o))
142: structureOptions.add(new WrappedOption(key, value,
143: false, true));
144: else {
145: List<WrappedOption> options = getAll(structureOptions,
146: key);
147: for (WrappedOption wo : options)
148: wo.setValue(value);
149: }
150: } else {
151: if (!assignmentOptions.contains(o))
152: assignmentOptions.add(new WrappedOption(key, value,
153: false, true));
154: else {
155: List<WrappedOption> options = getAll(assignmentOptions,
156: key);
157: for (WrappedOption wo : options)
158: wo.setValue(value);
159: }
160: }
161: }
162:
163: /**
164: * Sets an option with Key key to Value value. If isStructure==true, the option will be set
165: * in the structureOptions list, else in the assignmentOptions list.
166: * If the option is not present a new option will be created and set accordingly
167: *
168: * @param isStructureOption if the option should be set/created in the structureOptions or assignmentOptions list
169: * @param key the Key
170: * @param value the Value as boolean
171: */
172: public void setOption(boolean isStructureOption, String key,
173: boolean value) {
174: WrappedOption o = new WrappedOption(key, value, false, true);
175: if (isStructureOption) {
176: if (!structureOptions.contains(o))
177: structureOptions.add(new WrappedOption(key, value,
178: false, true));
179: else {
180: List<WrappedOption> options = getAll(structureOptions,
181: key);
182: for (WrappedOption wo : options)
183: wo.setValue(value);
184: }
185: } else {
186: if (!assignmentOptions.contains(o))
187: assignmentOptions.add(new WrappedOption(key, value,
188: false, true));
189: else {
190: List<WrappedOption> options = getAll(assignmentOptions,
191: key);
192: for (WrappedOption wo : options)
193: wo.setValue(value);
194: }
195: }
196: }
197:
198: /**
199: * Gets an option with Key key. If isStructure==true, the option will be from the
200: * structureOptions list, else from the assignmentOptions list.
201: * If the option is not present a new option will be created and set with default values.
202: *
203: * @param isStructureOption if the option should be set/created in the structureOptions or assignmentOptions list
204: * @param key the Key
205: *
206: * @return the option with the matching key.
207: */
208: public WrappedOption getOption(boolean isStructureOption, String key) {
209: WrappedOption o = new WrappedOption(key,
210: FxStructureOption.VALUE_FALSE, false, true);
211: if (isStructureOption) {
212: if (!structureOptions.contains(o)) {
213: WrappedOption newOption = new WrappedOption(key,
214: FxStructureOption.VALUE_FALSE, false, true);
215: structureOptions.add(newOption);
216: return newOption;
217: } else
218: return getFirst(structureOptions, key);
219: } else {
220: if (!assignmentOptions.contains(o)) {
221: WrappedOption newOption = new WrappedOption(key,
222: FxStructureOption.VALUE_FALSE, false, true);
223: assignmentOptions.add(newOption);
224: return newOption;
225: } else
226: return getFirst(assignmentOptions, key);
227: }
228: }
229:
230: /**
231: * Gets an option with Key key. If isStructure==true, the option will be from the
232: * structureOptions list, else from the assignmentOptions list.
233: * If the option is not present, null will be returned.
234: *
235: * @param isStructureOption if the option should be set/created in the structureOptions or assignmentOptions list
236: * @param key the Key
237: *
238: * @return the option with the matching key or null if the option is not present.
239: */
240: public WrappedOption getOptionNoCreate(boolean isStructureOption,
241: String key) {
242: WrappedOption o = new WrappedOption(key,
243: FxStructureOption.VALUE_FALSE, false, true);
244: if (isStructureOption) {
245: if (!structureOptions.contains(o)) {
246: return null;
247: } else
248: return getFirst(structureOptions, key);
249: } else {
250: if (!assignmentOptions.contains(o)) {
251: return null;
252: } else
253: return getFirst(assignmentOptions, key);
254: }
255: }
256:
257: /**
258: * Add create a new option to the specified options list.
259: *
260: * @param options the option list to add the new option to
261: * @param key the option key
262: * @param value the option value
263: * @param overridable the option overridable flag
264: * @throws FxInvalidParameterException on errors (empty key or empty value)
265: */
266: public void addOption(List<WrappedOption> options, String key,
267: String value, boolean overridable)
268: throws FxInvalidParameterException {
269: if (key != null && !"".equals(key.trim())) {
270: if (value != null && !"".equals(value.trim())) {
271: options.add(new WrappedOption(key, value, overridable,
272: true));
273: } else
274: throw new FxInvalidParameterException("value",
275: "ex.optionWrapper.noValue");
276: } else
277: throw new FxInvalidParameterException("key",
278: "ex.optionWrapper.noKey");
279: }
280:
281: public void deleteOption(List<WrappedOption> options,
282: WrappedOption o) {
283: int deleteIndex = -1;
284: for (int i = 0; i < options.size(); i++) {
285: if (options.get(i).equalsCompletely(o)) {
286: deleteIndex = i;
287: break;
288: }
289: }
290: if (deleteIndex != -1)
291: options.remove(deleteIndex);
292: else
293: options.remove(o);
294: }
295:
296: public List<WrappedOption> getStructureOptions() {
297: return structureOptions;
298: }
299:
300: public List<WrappedOption> getAssignmentOptions() {
301: return assignmentOptions;
302: }
303:
304: public List<FxStructureOption> asFxStructureOptionList(
305: List<WrappedOption> options) {
306: List<FxStructureOption> converted = new ArrayList<FxStructureOption>(
307: options.size());
308: for (WrappedOption o : options) {
309: converted.add(o.asFxStructureOption());
310: }
311: return converted;
312: }
313:
314: private boolean mayOverrideOption(String key) {
315: for (WrappedOption o : structureOptions) {
316: if (o.key.equals(key) && !o.isOverridable())
317: return false;
318: }
319: return true;
320: }
321:
322: private boolean isRedundant(String key) {
323: WrappedOption o = getFirst(structureOptions, key);
324: return o != null
325: && o
326: .equalsKeyAndValue(getFirst(assignmentOptions,
327: key));
328: }
329:
330: private WrappedOption getFirst(List<WrappedOption> options,
331: String key) {
332: WrappedOption result = null;
333: for (WrappedOption o : options) {
334: if (o.key.equals(key))
335: return o;
336: }
337: return result;
338: }
339:
340: /**
341: * @param options the options list
342: * @param key the key
343: * @return all options with Key key
344: */
345: private List<WrappedOption> getAll(List<WrappedOption> options,
346: String key) {
347: List<WrappedOption> result = new ArrayList<WrappedOption>();
348: for (WrappedOption o : options) {
349: if (o.key.equals(key))
350: result.add(o);
351: }
352: return result;
353: }
354:
355: public boolean hasOption(List<WrappedOption> options, String key) {
356: return countKeyOccurence(options, key) > 0;
357: }
358:
359: private int countKeyOccurence(List<WrappedOption> options,
360: String key) {
361: int c = 0;
362: for (WrappedOption o : options) {
363: if (o.getKey().toUpperCase().equals(key.toUpperCase()))
364: c++;
365: }
366: return c;
367: }
368:
369: /**
370: * A Map to indicate if an assignment option for a given key is valid.
371: *
372: * @return a Map for JSF pages which indicates if an assignment option for a given key is valid.
373: */
374: public Map<String, Boolean> getIsAssignmentOptionValidMap() {
375: if (assignmentOptionValidMap == null) {
376: assignmentOptionValidMap = FxSharedUtils
377: .getMappedFunction(new FxSharedUtils.ParameterMapper<String, Boolean>() {
378: public Boolean get(Object key) {
379: return !(key == null
380: || "".equals(key)
381: || countKeyOccurence(
382: assignmentOptions,
383: (String) key) > 1 || isRedundant((String) key));
384: }
385: });
386: }
387: return assignmentOptionValidMap;
388: }
389:
390: /**
391: * A Map to indicate if an assignment option for a given key may be overrwritten.
392: *
393: * @return a Map for JSF pages which indicates if an assignment option for a given key may be overwritten.
394: */
395: public Map<String, Boolean> getIsAssignmentOptionOverridableMap() {
396: if (assignmentOptionOverridableMap == null) {
397: assignmentOptionOverridableMap = FxSharedUtils
398: .getMappedFunction(new FxSharedUtils.ParameterMapper<String, Boolean>() {
399: public Boolean get(Object key) {
400: return mayOverrideOption((String) key);
401: }
402: });
403: }
404: return assignmentOptionOverridableMap;
405: }
406:
407: /**
408: * A Map to indicate if a structure option for a given key is valid.
409: *
410: * @return a Map for JSF pages which indicates if a structure option for a given key is valid.
411: */
412: public Map<String, Boolean> getIsStructureOptionValidMap() {
413: if (structureOptionValidMap == null) {
414: structureOptionValidMap = FxSharedUtils
415: .getMappedFunction(new FxSharedUtils.ParameterMapper<String, Boolean>() {
416: public Boolean get(Object key) {
417: return !(key == null || "".equals(key) || countKeyOccurence(
418: structureOptions, (String) key) > 1);
419: }
420: });
421: }
422: return structureOptionValidMap;
423: }
424:
425: /**
426: * Wraps the GUI relevant information of FxStructureOption Objects and provides convenient setters and getters
427: */
428: public class WrappedOption {
429:
430: private String key;
431: private String value;
432: private boolean overridable;
433: private boolean set;
434:
435: public WrappedOption(String key, String value,
436: boolean overridable, boolean set) {
437: setKey(key);
438: this .value = value;
439: this .overridable = overridable;
440: this .set = set;
441: }
442:
443: public WrappedOption(String key, boolean value,
444: boolean overridable, boolean set) {
445: setKey(key);
446: this .value = asStringValue(value);
447: this .overridable = overridable;
448: this .set = set;
449: }
450:
451: public WrappedOption(FxStructureOption option) {
452: this .key = option.getKey().toUpperCase();
453: this .value = option.getValue();
454: this .overridable = option.isOverrideable();
455: this .set = option.isSet();
456: }
457:
458: private String asStringValue(boolean value) {
459: if (value)
460: return FxStructureOption.VALUE_TRUE;
461: else
462: return FxStructureOption.VALUE_FALSE;
463: }
464:
465: public FxStructureOption asFxStructureOption() {
466: return new FxStructureOption(this .key, this .overridable,
467: this .set, this .value);
468: }
469:
470: public void setValue(String value) {
471: this .value = value;
472: }
473:
474: public void setValue(boolean value) {
475: this .value = asStringValue(value);
476: }
477:
478: public void setKey(String k) {
479: if (k == null)
480: k = "";
481: this .key = k.toUpperCase();
482: }
483:
484: public String getKey() {
485: return key;
486: }
487:
488: /**
489: * Hack used for commandButtons to concatenate id's and gain "unique" id's for buttons in
490: * <ui:repeat> tags
491: */
492: public String getId() {
493: int result;
494: result = (key != null ? key.hashCode() : 0);
495: result = 31 * result + (overridable ? 1 : 0);
496: result = 31 * result
497: + (value != null ? value.hashCode() : 0);
498: result = 31 * result + (set ? 1 : 0);
499: if (result < 0)
500: result = result * -1;
501: return String.valueOf(result);
502: }
503:
504: public String getValue() {
505: return value;
506: }
507:
508: public boolean getBooleanValue() {
509: return FxStructureOption.VALUE_TRUE.equals(value);
510: }
511:
512: public boolean isOverridable() {
513: return overridable;
514: }
515:
516: public void setOverridable(boolean b) {
517: this .overridable = b;
518: }
519:
520: public boolean isSet() {
521: return set;
522: }
523:
524: @Override
525: public boolean equals(Object o) {
526: if (o == null || !(o instanceof WrappedOption))
527: return false;
528: return this .key.equals(((WrappedOption) o).getKey()
529: .toUpperCase());
530: }
531:
532: @Override
533: public int hashCode() {
534: return key.hashCode();
535: }
536:
537: public boolean equalsCompletely(WrappedOption o) {
538: if (o == null)
539: return false;
540: if (this .key.equals(o.key) && this .set == o.set
541: && this .overridable == o.overridable)
542: if (this .value != null && this .value.equals(o.value)
543: || this .value == null && o.value == null)
544: return true;
545: return false;
546: }
547:
548: public boolean equalsKeyAndValue(WrappedOption o) {
549: if (o == null)
550: return false;
551: if (this .key.equals(o.key))
552: if (this .value != null && this .value.equals(o.value)
553: || this .value == null && o.value == null)
554: return true;
555: return false;
556: }
557: }
558: }
|