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.content;
034:
035: import com.flexive.shared.FxContext;
036: import com.flexive.shared.XPathElement;
037: import com.flexive.shared.exceptions.FxInvalidParameterException;
038: import com.flexive.shared.exceptions.FxNoAccessException;
039: import com.flexive.shared.structure.FxMultiplicity;
040: import com.flexive.shared.structure.FxPropertyAssignment;
041: import com.flexive.shared.structure.GroupMode;
042: import com.flexive.shared.value.FxNoAccess;
043: import com.flexive.shared.value.FxValue;
044: import org.apache.commons.lang.ArrayUtils;
045:
046: import java.util.ArrayList;
047: import java.util.List;
048:
049: /**
050: * FxData extension for properties
051: *
052: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
053: */
054: public class FxPropertyData extends FxData {
055: private static final long serialVersionUID = -8738710689160073148L;
056: private FxValue value;
057: private long propertyId;
058:
059: public FxPropertyData(String xpPrefix, String alias, int index,
060: String xPath, String xPathFull, int[] indices,
061: long assignmentId, long propertyId,
062: FxMultiplicity assignmentMultiplicity, int pos,
063: FxGroupData parent, FxValue value, boolean systemInternal)
064: throws FxInvalidParameterException {
065: super (xpPrefix, alias, index, xPath, xPathFull, indices,
066: assignmentId, assignmentMultiplicity, pos, parent,
067: systemInternal);
068: this .value = value;
069: this .propertyId = propertyId;
070: if (this .value != null)
071: this .value.setXPath(xpPrefix + xPathFull);
072: }
073:
074: /**
075: * Get the assigned value
076: *
077: * @return value
078: */
079: public FxValue getValue() {
080: return value;
081: }
082:
083: /**
084: * {@inheritDoc}
085: */
086: @Override
087: public boolean isProperty() {
088: return true;
089: }
090:
091: /**
092: * {@inheritDoc}
093: */
094: @Override
095: public boolean isGroup() {
096: return false;
097: }
098:
099: /**
100: * Get the id of the property used by the assignment
101: *
102: * @return id of the property used by the assignment
103: */
104: public long getPropertyId() {
105: return propertyId;
106: }
107:
108: /**
109: * Set a new value for this property data
110: *
111: * @param value the value to set
112: * @throws FxInvalidParameterException if the passed value is of an invalid datatype or otherwise invalid
113: * @throws FxNoAccessException if the current value is readonly or not accessible
114: */
115: public void setValue(FxValue value)
116: throws FxInvalidParameterException, FxNoAccessException {
117: if (value == null)
118: return;
119: FxPropertyAssignment pa = (FxPropertyAssignment) this
120: .getAssignment();
121: if (value.isMultiLanguage() != pa.isMultiLang()) {
122: if (pa.isMultiLang())
123: throw new FxInvalidParameterException(
124: "value",
125: "ex.content.value.invalid.multilanguage.ass.multi",
126: this .getXPathFull());
127: else
128: throw new FxInvalidParameterException(
129: "value",
130: "ex.content.value.invalid.multilanguage.ass.single",
131: this .getXPathFull());
132: }
133: if (pa.getProperty().isSystemInternal())
134: throw new FxInvalidParameterException(pa.getAlias(),
135: "ex.content.value.systemInternal")
136: .setAffectedXPath(this .getXPathFull());
137: if (!pa.isValid(value))
138: throw new FxInvalidParameterException("value",
139: "ex.content.value.invalid", this .getXPathFull(),
140: ((FxPropertyAssignment) this .getAssignment())
141: .getProperty().getDataType(), value
142: .getValueClass().getCanonicalName())
143: .setAffectedXPath(this .getXPathFull());
144: if (pa.hasParentGroupAssignment()
145: && pa.getParentGroupAssignment().getMode() == GroupMode.OneOf) {
146: //check if parent group is a one-of and already some other data set
147: for (FxData check : this .getParent().getChildren()) {
148: if (!check.isEmpty()
149: && check.getAssignmentId() != this
150: .getAssignmentId())
151: throw new FxInvalidParameterException("value",
152: "ex.content.xpath.group.oneof", this
153: .getXPathFull(), this .getParent()
154: .getXPathFull());
155: }
156: }
157: if (this .value == null || FxContext.get().getRunAsSystem()) {
158: this .value = value;
159: this .value.setXPath(this .xpPrefix + this .getXPathFull());
160: return;
161: }
162: if (this .value instanceof FxNoAccess)
163: throw new FxNoAccessException("ex.content.value.noaccess")
164: .setAffectedXPath(this .getXPathFull());
165: if (this .value.isReadOnly())
166: throw new FxNoAccessException("ex.content.value.readOnly")
167: .setAffectedXPath(this .getXPathFull());
168: this .value = value;
169: this .value.setXPath(this .xpPrefix + this .getXPathFull());
170: }
171:
172: /**
173: * {@inheritDoc}
174: */
175: @Override
176: public boolean isEmpty() {
177: return this .value.isEmpty();
178: }
179:
180: /**
181: * Apply the multiplicity to XPath and children if its a group
182: */
183: @Override
184: protected void applyIndices() {
185: try {
186: List<XPathElement> elements = XPathElement.split(this
187: .getXPathFull());
188: if (elements.get(elements.size() - 1).getIndex() != this
189: .getIndex()) {
190: elements.get(elements.size() - 1).setIndex(
191: this .getIndex());
192: this .XPathFull = XPathElement.toXPath(elements);
193: this .indices = XPathElement.getIndices(this .XPathFull);
194: }
195: } catch (FxInvalidParameterException e) {
196: throw e.asRuntimeException();
197: }
198: }
199:
200: /**
201: * Check if this property is required and present in its minimal multiplicity
202: *
203: * @throws FxInvalidParameterException if required properties are empty
204: */
205: public void checkRequired() throws FxInvalidParameterException {
206: if (this .getAssignmentMultiplicity().isOptional())
207: return;
208: int valid = 0;
209: for (FxData curr : getParent().getChildren())
210: if (curr.getAssignmentId() == this .getAssignmentId()
211: && !curr.isEmpty())
212: valid++;
213: if (valid < this .getAssignmentMultiplicity().getMin())
214: throw new FxInvalidParameterException(this .getAlias(),
215: "ex.content.required.missing", this .getXPath(),
216: valid, this .getAssignmentMultiplicity().toString())
217: .setAffectedXPath(this .getXPathFull());
218: }
219:
220: /**
221: * {@inheritDoc}
222: */
223: @Override
224: public int getCreateableElements() {
225: if (this .value != null && this .value instanceof FxNoAccess)
226: return 0;
227: return super .getCreateableElements();
228: }
229:
230: /**
231: * {@inheritDoc}
232: */
233: @Override
234: public int getRemoveableElements() {
235: if (this .value != null
236: && (this .value instanceof FxNoAccess || this .value
237: .isReadOnly()))
238: return 0;
239: return super .getRemoveableElements();
240: }
241:
242: /**
243: * {@inheritDoc}
244: */
245: @Override
246: public boolean isRemoveable() {
247: if (!super .isRemoveable())
248: return false;
249: //only removeable if not null, system internal or not non accessible or readonly
250: return !this .isSystemInternal()
251: && (!(this .value != null && (this .value instanceof FxNoAccess || this .value
252: .isReadOnly())) || this .value == null);
253: }
254:
255: /**
256: * Return a list of all values of this assignment.
257: *
258: * @param includeEmpty true to include empty (i.e. newly initialized) values
259: * @return a list of all values of this assignment.
260: */
261: public List<FxValue> getValues(boolean includeEmpty) {
262: final List<FxValue> values = new ArrayList<FxValue>();
263: for (FxData data : getParent().getChildren()) {
264: if (data.getAssignmentId() == getAssignmentId()) {
265: final FxValue value = ((FxPropertyData) data)
266: .getValue();
267: if (includeEmpty || !value.isEmpty()) {
268: values.add(value);
269: }
270: }
271: }
272: return values;
273: }
274:
275: /**
276: * {@inheritDoc}
277: */
278: @Override
279: public boolean equals(Object obj) {
280: if (this == obj)
281: return true;
282: if (!(obj instanceof FxPropertyData))
283: return false;
284: if (!super .equals(obj))
285: return false;
286: FxPropertyData comp = (FxPropertyData) obj;
287: return this .value.equals(comp.value)
288: && this .propertyId == comp.propertyId;
289: }
290:
291: @Override
292: public int hashCode() {
293: int result;
294: result = value.hashCode();
295: result = 31 * result + (int) (propertyId ^ (propertyId >>> 32));
296: return result;
297: }
298:
299: /**
300: * {@inheritDoc}
301: */
302: @Override
303: FxPropertyData copy(FxGroupData parent) {
304: FxPropertyData clone;
305: try {
306: clone = new FxPropertyData(xpPrefix, getAlias(),
307: getIndex(), getXPath(), getXPathFull(), ArrayUtils
308: .clone(getIndices()), getAssignmentId(),
309: getPropertyId(), getAssignmentMultiplicity(),
310: getPos(), parent, value.copy(), isSystemInternal());
311: } catch (FxInvalidParameterException e) {
312: throw e.asRuntimeException();
313: }
314: return clone;
315: }
316: }
|