001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.internal.xjc.model;
027:
028: /**
029: * represents a possible number of occurence.
030: *
031: * Usually, denoted by a pair of integers like (1,1) or (5,10).
032: * A special value "unbounded" is allowed as the upper bound.
033: *
034: * <p>
035: * For example, (0,unbounded) corresponds to the '*' occurence of DTD.
036: * (0,1) corresponds to the '?' occurence of DTD.
037: *
038: * @author
039: * <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
040: */
041: public final class Multiplicity {
042: public final int min;
043: public final Integer max; // null is used to represent "unbounded".
044:
045: public static Multiplicity create(int min, Integer max) {
046: if (min == 0 && max == null)
047: return STAR;
048: if (min == 1 && max == null)
049: return PLUS;
050: if (max != null) {
051: if (min == 0 && max == 0)
052: return ZERO;
053: if (min == 0 && max == 1)
054: return OPTIONAL;
055: if (min == 1 && max == 1)
056: return ONE;
057: }
058: return new Multiplicity(min, max);
059: }
060:
061: private Multiplicity(int min, Integer max) {
062: this .min = min;
063: this .max = max;
064: }
065:
066: public boolean equals(Object o) {
067: if (!(o instanceof Multiplicity))
068: return false;
069:
070: Multiplicity that = (Multiplicity) o;
071:
072: if (this .min != that.min)
073: return false;
074: if (this .max != null ? !this .max.equals(that.max)
075: : that.max != null)
076: return false;
077:
078: return true;
079: }
080:
081: public int hashCode() {
082: int result;
083: result = min;
084: result = 29 * result + (max != null ? max.hashCode() : 0);
085: return result;
086: }
087:
088: /** returns true if the multiplicity is (1,1). */
089: public boolean isUnique() {
090: if (max == null)
091: return false;
092: return min == 1 && max == 1;
093: }
094:
095: /** returns true if the multiplicity is (0,1) */
096: public boolean isOptional() {
097: if (max == null)
098: return false;
099: return min == 0 && max == 1;
100: }
101:
102: /** returns true if the multiplicity is (0,1) or (1,1). */
103: public boolean isAtMostOnce() {
104: if (max == null)
105: return false;
106: return max <= 1;
107: }
108:
109: /** returns true if the multiplicity is (0,0). */
110: public boolean isZero() {
111: if (max == null)
112: return false;
113: return max == 0;
114: }
115:
116: /**
117: * Returns true if the multiplicity represented by this object
118: * completely includes the multiplicity represented by the
119: * other object. For example, we say [1,3] includes [1,2] but
120: * [2,4] doesn't include [1,3].
121: */
122: public boolean includes(Multiplicity rhs) {
123: if (rhs.min < min)
124: return false;
125: if (max == null)
126: return true;
127: if (rhs.max == null)
128: return false;
129: return rhs.max <= max;
130: }
131:
132: /**
133: * Returns the string representation of the 'max' property.
134: * Either a number or a token "unbounded".
135: */
136: public String getMaxString() {
137: if (max == null)
138: return "unbounded";
139: else
140: return max.toString();
141: }
142:
143: /** gets the string representation.
144: * mainly debug purpose.
145: */
146: public String toString() {
147: return "(" + min + ',' + getMaxString() + ')';
148: }
149:
150: /** the constant representing the (0,0) multiplicity. */
151: public static final Multiplicity ZERO = new Multiplicity(0, 0);
152:
153: /** the constant representing the (1,1) multiplicity. */
154: public static final Multiplicity ONE = new Multiplicity(1, 1);
155:
156: /** the constant representing the (0,1) multiplicity. */
157: public static final Multiplicity OPTIONAL = new Multiplicity(0, 1);
158:
159: /** the constant representing the (0,unbounded) multiplicity. */
160: public static final Multiplicity STAR = new Multiplicity(0, null);
161:
162: /** the constant representing the (1,unbounded) multiplicity. */
163: public static final Multiplicity PLUS = new Multiplicity(1, null);
164:
165: // arithmetic methods
166: //============================
167: public static Multiplicity choice(Multiplicity lhs, Multiplicity rhs) {
168: return create(Math.min(lhs.min, rhs.min),
169: (lhs.max == null || rhs.max == null) ? null
170: : (Integer) Math.max(lhs.max, rhs.max));
171: }
172:
173: public static Multiplicity group(Multiplicity lhs, Multiplicity rhs) {
174: return create(lhs.min + rhs.min,
175: (lhs.max == null || rhs.max == null) ? null
176: : (Integer) (lhs.max + rhs.max));
177: }
178:
179: public static Multiplicity multiply(Multiplicity lhs,
180: Multiplicity rhs) {
181: int min = lhs.min * rhs.min;
182: Integer max;
183: if (isZero(lhs.max) || isZero(rhs.max))
184: max = 0;
185: else if (lhs.max == null || rhs.max == null)
186: max = null;
187: else
188: max = lhs.max * rhs.max;
189: return create(min, max);
190: }
191:
192: private static boolean isZero(Integer i) {
193: return i != null && i == 0;
194: }
195:
196: public static Multiplicity oneOrMore(Multiplicity c) {
197: if (c.max == null)
198: return c; // (x,*) => (x,*)
199: if (c.max == 0)
200: return c; // (0,0) => (0,0)
201: else
202: return create(c.min, null); // (x,y) => (x,*)
203: }
204:
205: public Multiplicity makeOptional() {
206: if (min == 0)
207: return this ;
208: return create(0, max);
209: }
210:
211: public Multiplicity makeRepeated() {
212: if (max == null || max == 0)
213: return this ; // (0,0)* = (0,0) and (n,unbounded)* = (n,unbounded)
214: return create(min, null);
215: }
216: }
|