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.exceptions.FxInvalidParameterException;
036:
037: import java.io.Serializable;
038: import java.util.Random;
039:
040: /**
041: * Multiplicity of groups and properties
042: *
043: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
044: */
045: public class FxMultiplicity implements Serializable {
046: private static final long serialVersionUID = -7989666071224292389L;
047:
048: /**
049: * Unlimited occurances
050: */
051: public static final int N = Integer.MAX_VALUE;
052:
053: /**
054: * No more than 20 elements to be created in random creations
055: */
056: public static final int RANDOM_MAX = 20;
057:
058: public final static FxMultiplicity MULT_0_1 = new FxMultiplicity(0,
059: 1);
060: public final static FxMultiplicity MULT_1_1 = new FxMultiplicity(1,
061: 1);
062: public final static FxMultiplicity MULT_0_N = new FxMultiplicity(0,
063: N);
064: public final static FxMultiplicity MULT_1_N = new FxMultiplicity(1,
065: N);
066:
067: /**
068: * minimum multiplicity
069: */
070: private int min;
071:
072: /**
073: * maximum multiplicity, Integer.MAX_VALUE if unlimited
074: */
075: private int max;
076:
077: /**
078: * Symbol used to display unlimited
079: */
080: private static final String SYMBOL_UNLIMITED = "N";
081:
082: /**
083: * Constructor
084: *
085: * @param min minimum multiplicity
086: * @param max maximum multiplicity, Integer.MAX_VALUE if unlimited
087: */
088: public FxMultiplicity(int min, int max) {
089: if (min < 0)
090: throw new FxInvalidParameterException("min",
091: "ex.structure.multiplicity.minimum.invalid", min,
092: max).asRuntimeException();
093: if (max < 1)
094: throw new FxInvalidParameterException("max",
095: "ex.structure.multiplicity.maximum.invalid", max,
096: min).asRuntimeException();
097: if (min > max)
098: throw new FxInvalidParameterException("min",
099: "ex.structure.multiplicity.minimum.invalid", min,
100: max).asRuntimeException();
101:
102: this .min = min;
103: this .max = max;
104: }
105:
106: /**
107: * Copy Constructor
108: *
109: * @param m an FxMultiplicity object
110: */
111: public FxMultiplicity(FxMultiplicity m) {
112: this .min = m.min;
113: this .max = m.max;
114: }
115:
116: /**
117: * Is an occurance optional?
118: *
119: * @return if an occurance is optional
120: */
121: public boolean isOptional() {
122: return min == 0;
123: }
124:
125: /**
126: * Is at least one occurance required?
127: *
128: * @return if at least one occurance is required
129: */
130: public boolean isRequired() {
131: return min > 0;
132: }
133:
134: /**
135: * May occur unlimited?
136: *
137: * @return unlimited?
138: */
139: public boolean isUnlimited() {
140: return max == Integer.MAX_VALUE;
141: }
142:
143: /**
144: * More than one possible?
145: *
146: * @return if more than one are possible
147: */
148: public boolean isMultiple() {
149: return max > 1;
150: }
151:
152: /**
153: * Get the minimum multiplicity
154: *
155: * @return minimum multiplicity
156: */
157: public int getMin() {
158: return min;
159: }
160:
161: /**
162: * Get the maximum multiplicity
163: *
164: * @return maximum multiplicity
165: */
166: public int getMax() {
167: return max;
168: }
169:
170: /**
171: * String representation, uses SYMBOL_UNLIMITED for unlimited max occurances
172: *
173: * @return String representation, uses SYMBOL_UNLIMITED for unlimited max occurances
174: */
175: @Override
176: public String toString() {
177: return min + ".." + (isUnlimited() ? SYMBOL_UNLIMITED : max);
178: }
179:
180: /**
181: * {@inheritDoc}
182: */
183: @Override
184: public boolean equals(Object obj) {
185: if (obj instanceof FxMultiplicity) {
186: FxMultiplicity o = (FxMultiplicity) obj;
187: return o.getMin() == this .getMin()
188: && o.getMax() == this .getMax();
189: } else if (obj instanceof String) {
190: String o = (String) obj;
191: if (o.startsWith("[")) {
192: return o.equals("[" + this .toString() + "]");
193: } else
194: return o.equals(this .toString());
195: } else
196: return false;
197: }
198:
199: /**
200: * {@inheritDoc}
201: */
202: @Override
203: public int hashCode() {
204: return this .getMin() + this .getMax();
205: }
206:
207: /**
208: * Get the number of elements to create for this multiplicity if creating random test data
209: *
210: * @param rnd Random
211: * @param maxMultiplicity the maximum (random) multiplicity
212: * @return number of elements to create for this multiplicity if creating random test data
213: */
214: public int getRandomRange(Random rnd, int maxMultiplicity) {
215: int count;
216: if (isUnlimited())
217: count = maxMultiplicity;
218: else
219: count = getMax() - getMin() + 1;
220: if (count <= 0)
221: count = 1;
222: count = rnd.nextInt(count);
223: if (count <= 0)
224: count = 1;
225: if (count < getMin())
226: count = getMin();
227: if (count > getMax())
228: count = getMax();
229: // uncomment the following lines to return at least 2 elements if possible
230: // if( count == 1 && getMax() > 1 )
231: // count = 2;
232: return count;
233: }
234:
235: /**
236: * Check if the given index is valid for this multiplicity
237: *
238: * @param index the index to check
239: * @return valid
240: */
241: public boolean isValid(int index) {
242: return index >= getMin() && index <= getMax();
243: }
244:
245: /**
246: * Converts a String that represents a Number or "N" to int
247: *
248: * @param m representing a Number or "N"
249: * @return the number as int or Integer.MAX_VALUE
250: */
251: public static int getStringToInt(String m) {
252: int mul = -1;
253: if (SYMBOL_UNLIMITED.equals(m.toUpperCase())) {
254: mul = N;
255: } else {
256: mul = Integer.parseInt(m);
257: }
258: return mul;
259: }
260:
261: /**
262: * Converts a int into a String holding its number or SYMBOL_UNLIMITED
263: *
264: * @param m representing a Number
265: * @return the number as String
266: */
267: public static String getIntToString(int m) {
268: String mul = null;
269: if (m == FxMultiplicity.N) {
270: mul = FxMultiplicity.SYMBOL_UNLIMITED;
271: } else {
272: mul = String.valueOf(m);
273: }
274: return mul;
275: }
276: }
|