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.exceptions.FxInvalidParameterException;
036: import com.flexive.shared.structure.FxSelectListItem;
037: import com.flexive.shared.structure.TypeStorageMode;
038: import com.flexive.shared.value.FxReference;
039: import org.apache.commons.lang.StringUtils;
040: import org.apache.commons.logging.Log;
041: import org.apache.commons.logging.LogFactory;
042:
043: import java.io.Serializable;
044:
045: /**
046: * Primary key for FxContents
047: *
048: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
049: */
050: public class FxPK implements Serializable, Comparable<FxPK> {
051: private static final Log LOG = LogFactory.getLog(FxPK.class);
052: private static final long serialVersionUID = 8452775369399900087L;
053:
054: /**
055: * Id to use for new instances (flags them as new)
056: */
057: public static final int NEW_ID = -1;
058:
059: /**
060: * Constant to select the maximum available version
061: */
062: public static final int MAX = -1;
063:
064: /**
065: * Constant to select the version whose workflow step is flagged as live
066: *
067: * @see com.flexive.shared.workflow.Step#isLiveStep()
068: */
069: public static final int LIVE = -2;
070:
071: protected long id;
072: protected int version;
073:
074: /**
075: * Ctor
076: *
077: * @param id id
078: * @param version version
079: */
080: public FxPK(long id, int version) {
081: this .id = id;
082: this .version = version;
083: if (this .version < LIVE)
084: throw new FxInvalidParameterException("version", LOG,
085: "ex.content.pk.invalid.version", id, version)
086: .asRuntimeException();
087: }
088:
089: /**
090: * Ctor, version is initialized with <code>MAX</code>
091: *
092: * @param id id
093: * @see #MAX
094: */
095: public FxPK(long id) {
096: this .id = id;
097: this .version = MAX;
098: }
099:
100: /**
101: * Constructor for new FxContents
102: */
103: public FxPK() {
104: this .id = NEW_ID;
105: this .version = 1;
106: }
107:
108: /**
109: * Is this primary key for a new FxContent?
110: *
111: * @return if this primary key is for a new FxContent
112: */
113: public boolean isNew() {
114: return this .id == NEW_ID;
115: }
116:
117: /**
118: * Getter for the id
119: *
120: * @return id
121: */
122: public long getId() {
123: return id;
124: }
125:
126: /**
127: * Getter for the version.
128: * Can be an arbitrary number or a constant for maximum or live version
129: *
130: * @return version
131: * @see #MAX
132: * @see #LIVE
133: */
134: public int getVersion() {
135: return version;
136: }
137:
138: /**
139: * Get the storage mode for this primary key.
140: * This method is reserved for future uses when different storage modes will be implemented!
141: *
142: * @return storage mode
143: */
144: public TypeStorageMode getStorageMode() {
145: return TypeStorageMode.Hierarchical;
146: }
147:
148: /**
149: * Create a new primary key
150: *
151: * @return a new primary key
152: */
153: public static FxPK createNewPK() {
154: return new FxPK(-1);
155: }
156:
157: /**
158: * Does this primary key point to a distinct version or is it something like maximum or live version?
159: *
160: * @return distinct version
161: */
162: public boolean isDistinctVersion() {
163: return this .version >= 0;
164: }
165:
166: /**
167: * {@inheritDoc}
168: */
169: @Override
170: public String toString() {
171: String ver = "" + this .getVersion();
172: if (getVersion() == LIVE)
173: ver = "LIVE";
174: else if (getVersion() == MAX)
175: ver = "MAX";
176: return (isNew() ? "NEW" : getId() + "." + ver);
177: }
178:
179: /**
180: * Construct a primary key from a String
181: *
182: * @param value string value
183: * @return primary key
184: * @throws IllegalArgumentException if the string does not represent a valid PK value
185: * @see #toString()
186: */
187: public static FxPK fromString(String value) {
188: if (StringUtils.isNumeric(value)) {
189: return new FxPK(Long.parseLong(value));
190: } else if (value == null || "NEW".equals(value)
191: || value.indexOf('.') <= 0) {
192: return new FxPK();
193: }
194: String[] pk = value.split("\\.");
195: if (pk == null || pk.length != 2)
196: throw new IllegalArgumentException();
197: long _id, _ver;
198: try {
199: _id = Long.parseLong(pk[0]);
200: } catch (NumberFormatException e) {
201: throw new IllegalArgumentException();
202: }
203: try {
204: _ver = Integer.parseInt(pk[1]);
205: } catch (NumberFormatException e) {
206: if ("MAX".equals(pk[1]))
207: _ver = MAX;
208: else if ("LIVE".equals(pk[1]))
209: _ver = LIVE;
210: else
211: throw new IllegalArgumentException();
212: }
213: return new FxPK(_id, (int) _ver);
214: }
215:
216: /**
217: * {@inheritDoc}
218: */
219: @Override
220: public int hashCode() {
221: final int PRIME = 31;
222: int result = 1;
223: result = PRIME * result + (int) (id ^ (id >>> 32));
224: result = PRIME * result + version;
225: return result;
226: }
227:
228: /**
229: * {@inheritDoc}
230: */
231: @Override
232: public boolean equals(Object obj) {
233: if (obj == null || !(obj instanceof FxPK))
234: return false;
235: final FxPK other = (FxPK) obj;
236: return id == other.id && version == other.version;
237: }
238:
239: /**
240: * <p>Extract a PK from the given object. Useful for scripting or JSF-related
241: * calls where the actual value type may vary.</p>
242: * <p>Current, following types for <code>value</code> are supported:
243: * <ul>
244: * <li>{@link com.flexive.shared.content.FxPK FxPK} - trivial</li>
245: * <li>{@link com.flexive.shared.value.FxReference FxReference} - return the PK contained in the "best translation" for the current user</li>
246: * <li>{@link com.flexive.shared.structure.FxSelectListItem FxSelectListItem} - use the item's ID as an object ID and return the PK</li>
247: * <li>{@link Long} - return a new PK for the given object ID</li>
248: * <li>{@link String} - return a new PK based on the given PK string representation</li>
249: * </ul>
250: * </p>
251: *
252: * @param value the value to be interpreted as an FxPK obejct
253: * @return the primary key
254: */
255: public static FxPK fromObject(Object value) {
256: if (value instanceof FxPK) {
257: return (FxPK) value;
258: } else if (value instanceof FxReference) {
259: return ((FxReference) value).getBestTranslation();
260: } else if (value instanceof FxSelectListItem) {
261: return new FxPK(((FxSelectListItem) value).getId());
262: } else if (value instanceof Long) {
263: return new FxPK((Long) value);
264: } else if (value instanceof String) {
265: return fromString((String) value);
266: }
267: throw new FxInvalidParameterException("VALUE", LOG,
268: "ex.content.pk.fromObject.invalid", value, value
269: .getClass()).asRuntimeException();
270: }
271:
272: public int compareTo(FxPK o) {
273: return id > o.id ? 1 : id < o.id ? -1 : 0;
274: }
275: }
|