001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
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.shared.structure;
034:
035: import com.flexive.shared.CacheAdmin;
036: import com.flexive.shared.FxLanguage;
037: import com.flexive.shared.XPathElement;
038: import com.flexive.shared.exceptions.FxApplicationException;
039: import com.flexive.shared.exceptions.FxInvalidParameterException;
040: import com.flexive.shared.exceptions.FxNotFoundException;
041: import com.flexive.shared.security.ACL;
042: import com.flexive.shared.value.FxString;
043: import com.flexive.shared.value.FxValue;
044: import org.apache.commons.lang.StringUtils;
045:
046: import java.util.ArrayList;
047: import java.util.List;
048:
049: /**
050: * FxPropertyAssignment for editing
051: *
052: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
053: */
054: public class FxPropertyAssignmentEdit extends FxPropertyAssignment {
055:
056: private static final long serialVersionUID = -4124525757694024524L;
057: private boolean isNew;
058:
059: /**
060: * Create an editable instance from an existing FxPropertyAssignment
061: *
062: * @param pa existing FxPropertyAssignment
063: */
064: public FxPropertyAssignmentEdit(FxPropertyAssignment pa) {
065: super (pa.getId(), pa.isEnabled(), pa.getAssignedType(), pa
066: .getAlias(), pa.getXPath(), pa.getPosition(),
067: new FxMultiplicity(pa.getMultiplicity()), pa
068: .getDefaultMultiplicity(), pa
069: .getParentGroupAssignment(), pa
070: .getBaseAssignmentId(),
071: pa.getLabel() == null ? null : pa.getLabel().copy(),
072: pa.getHint() == null ? null : pa.getHint().copy(), pa
073: .getDefaultValue() == null ? null : pa
074: .getDefaultValue().copy(), pa.getProperty()
075: .asEditable(), new ACL(pa.getACL()), pa
076: .getDefaultLanguage(), FxStructureOption
077: .cloneOptions(pa.options));
078: if (pa.isSystemInternal())
079: _setSystemInternal();
080: this .isNew = false;
081: }
082:
083: /**
084: * Ctor to create a new FxPropertyAssignmentEdit from an existing FxPropertyAssignment as a new one for a given type with a
085: * new alias and a given parentXPath (not validated)
086: *
087: * @param pa original property assignment
088: * @param type type to assign it
089: * @param alias new alias
090: * @param parentXPath parent XPath within the type to assign
091: * @param parent optional parent assignment if already known (prevents lookup of parentXPath if valid)
092: * @throws FxNotFoundException if parentXPath is invalid
093: * @throws FxInvalidParameterException if parentXPath is invalid
094: */
095: private FxPropertyAssignmentEdit(FxPropertyAssignment pa,
096: FxType type, String alias, String parentXPath,
097: FxAssignment parent) throws FxNotFoundException,
098: FxInvalidParameterException {
099: super (-1, pa.isEnabled(), type, alias, XPathElement.buildXPath(
100: false, parentXPath, alias), pa.getPosition(),
101: new FxMultiplicity(pa.getMultiplicity()), pa
102: .getDefaultMultiplicity(), pa
103: .getParentGroupAssignment(), pa.getId(), pa
104: .getLabel().copy(), pa.getHint().copy(), pa
105: .getDefaultValue().copy(), pa.getProperty()
106: .asEditable(), new ACL(pa.getACL()), pa
107: .getDefaultLanguage(), FxStructureOption
108: .cloneOptions(pa.options));
109: if (pa.isSystemInternal())
110: _setSystemInternal();
111: if (parent == null) {
112: //check parentXPath
113: parent = type.getAssignment(parentXPath);
114: if (parent != null
115: && parent instanceof FxPropertyAssignment)
116: throw new FxInvalidParameterException("parentXPath",
117: "ex.structure.assignment.noGroup", parentXPath);
118: }
119: //check parentXPath
120: if (parent == null)
121: parentGroupAssignment = null;
122: else
123: parentGroupAssignment = (FxGroupAssignment) parent;
124: isNew = true;
125: }
126:
127: public boolean isNew() {
128: return isNew;
129: }
130:
131: public FxPropertyAssignmentEdit setACL(ACL ACL)
132: throws FxInvalidParameterException {
133: if (!getProperty().mayOverrideACL())
134: throw new FxInvalidParameterException("ACL",
135: "ex.structure.override.property.forbidden", "ACL",
136: getProperty().getName());
137: this .ACL = ACL;
138: return this ;
139: }
140:
141: /**
142: * Set the default value for this property assignment
143: *
144: * @param defaultValue default value
145: * @return this
146: */
147: public FxPropertyAssignmentEdit setDefaultValue(FxValue defaultValue) {
148: this .defaultValue = defaultValue;
149: return this ;
150: }
151:
152: /**
153: * Set an option
154: *
155: * @param key option key
156: * @param value value of the option
157: * @return the assignment itself, useful for chained calls
158: * @throws FxInvalidParameterException if the property does not allow overriding
159: */
160: public FxPropertyAssignmentEdit setOption(String key, String value)
161: throws FxInvalidParameterException {
162:
163: FxStructureOption pOpt = getProperty().getOption(key);
164: if (pOpt.isSet() && !pOpt.isOverrideable())
165: throw new FxInvalidParameterException(key,
166: "ex.structure.override.forbidden", key,
167: getProperty().getName());
168:
169: FxStructureOption.setOption(options, key, true, value);
170: return this ;
171: }
172:
173: /**
174: * Set a boolean option
175: *
176: * @param key option key
177: * @param value value of the option
178: * @return the assignemnt itself, useful for chained calls
179: * @throws FxInvalidParameterException if the property does not allow overriding
180: */
181: public FxPropertyAssignmentEdit setOption(String key, boolean value)
182: throws FxInvalidParameterException {
183:
184: FxStructureOption pOpt = getProperty().getOption(key);
185: if (pOpt.isSet() && !pOpt.isOverrideable())
186: throw new FxInvalidParameterException(key,
187: "ex.structure.override.forbidden", key,
188: getProperty().getName());
189:
190: FxStructureOption.setOption(options, key, true, value);
191: return this ;
192: }
193:
194: /**
195: * Clear an option entry
196: *
197: * @param key option name
198: */
199: public void clearOption(String key) {
200: FxStructureOption.clearOption(options, key);
201: }
202:
203: /**
204: * Should this assignment support multilingual data?
205: *
206: * @param multiLang multi lingual data supported?
207: * @return this
208: * @throws FxInvalidParameterException on errors
209: */
210: public FxPropertyAssignmentEdit setMultiLang(boolean multiLang)
211: throws FxInvalidParameterException {
212: return setOption(FxStructureOption.OPTION_MULTILANG, multiLang);
213: }
214:
215: /**
216: * Set a default language. Multilingual FxPropertyData instances will be initialized with this language
217: *
218: * @param language the default language
219: * @return this
220: */
221: public FxPropertyAssignmentEdit setDefaultLanguage(long language) {
222: if (this .isMultiLang())
223: this .defaultLang = language;
224: return this ;
225: }
226:
227: /**
228: * Reset the default language to the system language
229: *
230: * @return this
231: */
232: public FxPropertyAssignmentEdit clearDefaultLanguage() {
233: if (this .isMultiLang())
234: this .defaultLang = FxLanguage.SYSTEM_ID;
235: return this ;
236: }
237:
238: /**
239: * Set if this property be used in the visual query editor (UI hint)
240: *
241: * @param searchable property can be used in the visual query editor
242: * @return the property itself, useful for chained calls
243: * @throws FxInvalidParameterException if overriding is not allowed
244: */
245: public FxPropertyAssignmentEdit setSearchable(boolean searchable)
246: throws FxInvalidParameterException {
247: return setOption(FxStructureOption.OPTION_SEARCHABLE,
248: searchable);
249: }
250:
251: /**
252: * Set overview appearance setting
253: *
254: * @param inOverview overview appearance setting
255: * @return the property itself, useful for chained calls
256: * @throws FxInvalidParameterException if not allowed to override
257: */
258: public FxPropertyAssignmentEdit setInOverview(boolean inOverview)
259: throws FxInvalidParameterException {
260: return setOption(FxStructureOption.OPTION_SHOW_OVERVIEW,
261: inOverview);
262: }
263:
264: /**
265: * Set if to use an HTML editor to edit values of this property?
266: *
267: * @param useHTMLEditor use HTML editor to edit values of this property?
268: * @return the property itself, useful for chained calls
269: * @throws FxInvalidParameterException if not allowed to override
270: */
271: public FxPropertyAssignmentEdit setUseHTMLEditor(
272: boolean useHTMLEditor) throws FxInvalidParameterException {
273: return setOption(FxStructureOption.OPTION_HTML_EDITOR,
274: useHTMLEditor);
275: }
276:
277: /**
278: * Set multiline display ability
279: *
280: * @param multiLine render property in multiple lines?
281: * @return the property itself, useful for chained calls
282: * @throws FxInvalidParameterException on errors
283: */
284: public FxPropertyAssignmentEdit setMultiLine(boolean multiLine)
285: throws FxInvalidParameterException {
286: return setOption(FxStructureOption.OPTION_MULTILINE, multiLine);
287: }
288:
289: /**
290: * Set this property assignment as (temporary) disabled - it will not be initialized when creating new instances, etc.
291: *
292: * @param enabled enabled flag
293: * @return this
294: */
295: public FxPropertyAssignmentEdit setEnabled(boolean enabled) {
296: this .enabled = enabled;
297: return this ;
298: }
299:
300: /**
301: * Set the multiplicity of this assignment
302: *
303: * @param multiplicity new multiplicity
304: * @return this
305: * @throws FxInvalidParameterException on errors
306: */
307: public FxPropertyAssignmentEdit setMultiplicity(
308: FxMultiplicity multiplicity)
309: throws FxInvalidParameterException {
310: if (!getProperty().mayOverrideBaseMultiplicity())
311: throw new FxInvalidParameterException("MULTIPLICITY",
312: "ex.structure.override.property.forbidden",
313: "Multiplicity", getProperty().getName());
314: this .multiplicity = multiplicity;
315: return this ;
316: }
317:
318: /**
319: * Set the default multiplicity (used i.e. in user interfaces editors and determines the amount of values that will
320: * be initialized when creating an empty element).
321: *
322: *
323: *
324: * @param defaultMultiplicity the default multiplicity
325: * @return this
326: * @throws com.flexive.shared.exceptions.FxInvalidParameterException if the defaultMultiplicity is not within the range of min and max
327: */
328: public FxPropertyAssignmentEdit setDefaultMultiplicity(
329: int defaultMultiplicity) throws FxInvalidParameterException {
330: if (this .getMultiplicity().isValid(defaultMultiplicity)) {
331: this .defaultMultiplicity = defaultMultiplicity;
332: return this ;
333: } else
334: throw new FxInvalidParameterException(
335: "default multiplicity",
336: "ex.structure.modificaiton.defaultMultiplicity.invalid");
337: /*
338: *If the set value is < min or > max multiplicity of this assignment it will
339: * be auto adjusted to the next valid value without throwing an exception
340:
341: if (defaultMultiplicity < this.getMultiplicity().getMin())
342: this.defaultMultiplicity = this.getMultiplicity().getMin();
343: if (defaultMultiplicity > this.getMultiplicity().getMax())
344: this.defaultMultiplicity = this.getMultiplicity().getMax();
345: */
346: }
347:
348: /**
349: * Set the position of this assignment (within the same parent group).
350: * Changing an assignments position will be upate all affected other assignments within the same
351: * group. Invalid values will be adjusted (to 0 or the max. possible position)
352: *
353: * @param position position within the parent group
354: * @return this
355: */
356: public FxPropertyAssignmentEdit setPosition(int position) {
357: this .position = position;
358: return this ;
359: }
360:
361: /**
362: * Set the alias of this property assignment.
363: * Property assignments may define an alias to allow multiple use of the same property but
364: * using a different name. The alias is the rightmost part of the XPath used to address an assignment.
365: *
366: * @param alias the alias of this assignment
367: * @return this
368: * @throws FxInvalidParameterException on errors
369: */
370: public FxPropertyAssignmentEdit setAlias(String alias)
371: throws FxInvalidParameterException {
372: if (StringUtils.isEmpty(alias))
373: throw new FxInvalidParameterException("ALIAS",
374: "ex.structure.assignment.noAlias");
375: this .alias = alias;
376: return this ;
377: }
378:
379: /**
380: * Set the XPath of this assignment - this is used mainly internally and affects new assignments only
381: *
382: * @param XPath the XPath to set
383: * @return this
384: * @throws FxInvalidParameterException on errors
385: */
386: public FxPropertyAssignmentEdit setXPath(String XPath)
387: throws FxInvalidParameterException {
388: if (StringUtils.isEmpty(alias))
389: throw new FxInvalidParameterException("XPATH",
390: "ex.structure.assignment.noXPath");
391: try {
392: this .getAssignedType().getAssignment(XPath);
393: throw new FxInvalidParameterException("XPATH",
394: "ex.structure.assignment.exists", XPath,
395: getAssignedType().getName());
396: } catch (FxNotFoundException e) {
397: //ok, it really is new
398: }
399: this .XPath = XPath;
400: return this ;
401: }
402:
403: /**
404: * Setter for the label
405: *
406: * @param label label to set
407: * @return this
408: */
409: public FxPropertyAssignmentEdit setLabel(FxString label) {
410: this .label = label;
411: return this ;
412: }
413:
414: /**
415: * Set the hint message
416: *
417: * @param hint hint message
418: * @return the property itself, useful for chained calls
419: */
420: public FxPropertyAssignmentEdit setHint(FxString hint) {
421: this .hint = hint;
422: return this ;
423: }
424:
425: /**
426: * Create a new FxPropertyAssignmentEdit from an existing FxPropertyAssignment as a new one for a given type with a
427: * new alias and a given parentXPath
428: *
429: * @param pa original property assignment
430: * @param type type to assign it
431: * @param alias new alias
432: * @param parentXPath parent XPath within the type to assign
433: * @param parent optional parent assignment if already known (prevents lookup of parentXPath if valid)
434: * @return new FxPropertyAssignmentEdit
435: * @throws FxNotFoundException if parentXPath is invalid
436: * @throws FxInvalidParameterException if parentXPath is invalid
437: */
438: public static FxPropertyAssignmentEdit createNew(
439: FxPropertyAssignment pa, FxType type, String alias,
440: String parentXPath, FxAssignment parent)
441: throws FxNotFoundException, FxInvalidParameterException {
442: return new FxPropertyAssignmentEdit(pa, type, alias,
443: parentXPath, parent);
444: }
445:
446: /**
447: * Create a new FxPropertyAssignmentEdit from an existing FxPropertyAssignment as a new one for a given type with a
448: * new alias and a given parentXPath
449: *
450: * @param pa original property assignment
451: * @param type type to assign it
452: * @param alias new alias
453: * @param parentXPath parent XPath within the type to assign
454: * @return new FxPropertyAssignmentEdit
455: * @throws FxNotFoundException if parentXPath is invalid
456: * @throws FxInvalidParameterException if parentXPath is invalid
457: */
458: public static FxPropertyAssignmentEdit createNew(
459: FxPropertyAssignment pa, FxType type, String alias,
460: String parentXPath) throws FxNotFoundException,
461: FxInvalidParameterException {
462: return new FxPropertyAssignmentEdit(pa, type, alias,
463: parentXPath, null);
464: }
465:
466: /**
467: * Convenience method to create a new FxPropertyAssignmentEdit from an existing FxPropertyAssignment as a new one for a given type with a
468: * new alias and a given parentXPath
469: *
470: * @param originalProperty the original properties XPath (like ROOT/CAPTION)
471: * @param type name of the type to assign it
472: * @param parentXPath parent XPath within the type to assign
473: * @param alias new alias
474: * @return new FxPropertyAssignmentEdit
475: * @throws FxNotFoundException if parentXPath is invalid
476: * @throws FxInvalidParameterException if parentXPath is invalid
477: */
478: public static FxPropertyAssignmentEdit reuse(
479: String originalProperty, String type, String parentXPath,
480: String alias) throws FxNotFoundException,
481: FxInvalidParameterException {
482: return createNew(
483: (FxPropertyAssignment) CacheAdmin.getEnvironment()
484: .getAssignment(originalProperty),
485: CacheAdmin.getEnvironment().getType(type), alias,
486: parentXPath).setEnabled(true);
487: }
488:
489: /**
490: * Convenience method to create a new FxPropertyAssignmentEdit from an existing FxPropertyAssignment as a new one for a given type with a
491: * new alias and a given parentXPath
492: *
493: * @param originalProperty the original properties XPath (like ROOT/CAPTION)
494: * @param type name of the type to assign it
495: * @param parentXPath parent XPath within the type to assign
496: * @return new FxPropertyAssignmentEdit
497: * @throws FxNotFoundException if parentXPath is invalid
498: * @throws FxInvalidParameterException if parentXPath is invalid
499: */
500: public static FxPropertyAssignmentEdit reuse(
501: String originalProperty, String type, String parentXPath)
502: throws FxNotFoundException, FxInvalidParameterException {
503: FxPropertyAssignment propertyAssignment = (FxPropertyAssignment) CacheAdmin
504: .getEnvironment().getAssignment(originalProperty);
505: return createNew(propertyAssignment,
506: CacheAdmin.getEnvironment().getType(type),
507: propertyAssignment.getAlias(), parentXPath).setEnabled(
508: true);
509: }
510:
511: /**
512: * Get a (unmodifiable) list of all options set for this property assignment
513: *
514: * @return (unmodifiable) list of all options set for this property assignment
515: */
516: public List<FxStructureOption> getOptions() {
517: return FxStructureOption.getUnmodifieableOptions(options);
518: }
519:
520: /**
521: * Sets the parent group assignment.
522: *
523: * @param parent the parent group assignment.
524: */
525: public void setParentGroupAssignment(FxGroupAssignment parent) {
526: this .parentGroupAssignment = parent;
527: }
528:
529: /**
530: * Returns the property of this assignment as editable.
531: *
532: * @return the editable property object.
533: */
534: public FxPropertyEdit getPropertyEdit() {
535: if (!(property instanceof FxPropertyEdit))
536: throw new FxApplicationException(
537: "ex.structure.noEditableProperty")
538: .asRuntimeException();
539: else
540: return (FxPropertyEdit) property;
541: }
542:
543: /**
544: * Returns a new List of all available options.
545: * The options include those of the class itsself and of its assigned FxProperty
546: * To eliminate duplicate keys and determine the correct overriding oder,
547: * the <code>FxPropertyAssignment.getOption(key)</code> method
548: * is used. If an option is contained in the returned List then <code>hasOption(key)
549: * ==true</code>, otherwise <code>false</code>.
550: *
551: * @return new List containing all availiable options.
552: */
553: protected List<FxStructureOption> getAllAvailableOptions() {
554: List<FxStructureOption> allOptions = new ArrayList<FxStructureOption>(
555: options);
556: List<String> setOptions = new ArrayList<String>(2);
557: List<FxStructureOption> result = new ArrayList<FxStructureOption>();
558:
559: allOptions.addAll(super .getProperty().options);
560: allOptions.addAll(options);
561: //iterate over all options and eliminate duplicate keys
562: for (FxStructureOption o : allOptions) {
563: if (hasOption(o.getKey())) {
564: if (!setOptions.contains(o.getKey())) {
565: setOptions.add(o.getKey());
566: result.add(getOption(o.getKey()));
567: }
568: }
569: }
570: return result;
571: }
572:
573: }
|