001: package net.sf.saxon.value;
002:
003: import net.sf.saxon.expr.StaticProperty;
004:
005: /**
006: * This class contains static methods to manipulate the cardinality
007: * property of a type.
008: * Cardinality of expressions is denoted by one of the values ONE_OR_MORE, ZERO_OR_MORE,
009: * ZERO_OR_ONE, EXACTLY_ONE, or EMPTY. These are combinations of the three bit-significant
010: * values ALLOWS_ZERO, ALLOWS_ONE, and ALLOWS_MANY.
011: */
012:
013: public final class Cardinality {
014:
015: /**
016: * Private constructor: no instances allowed
017: */
018:
019: private Cardinality() {
020: }
021:
022: /**
023: * Determine whether multiple occurrences are allowed
024: */
025:
026: public static final boolean allowsMany(int cardinality) {
027: return (cardinality & StaticProperty.ALLOWS_MANY) != 0;
028: }
029:
030: /**
031: * Determine whether empty sequence is allowed
032: */
033:
034: public static final boolean allowsZero(int cardinality) {
035: return (cardinality & StaticProperty.ALLOWS_ZERO) != 0;
036: }
037:
038: /**
039: * Form the union of two cardinalities. The cardinality of the expression "if (c) then e1 else e2"
040: * is the union of the cardinalities of e1 and e2.
041: * @param c1 a cardinality
042: * @param c2 another cardinality
043: * @return the cardinality that allows both c1 and c2
044: */
045:
046: public static final int union(int c1, int c2) {
047: int r = c1 | c2;
048: // eliminate disallowed options
049: if (r == (StaticProperty.ALLOWS_MANY | StaticProperty.ALLOWS_ZERO))
050: r = StaticProperty.ALLOWS_ZERO_OR_MORE;
051: return r;
052: }
053:
054: /**
055: * Form the sum of two cardinalities
056: */
057:
058: public static final int sum(int c1, int c2) {
059: if (allowsMany(c1) || allowsMany(c2)) {
060: return c1 | c2;
061: }
062: if (!allowsZero(c1) && !allowsZero(c2)) {
063: return StaticProperty.ALLOWS_ONE_OR_MORE;
064: } else {
065: return StaticProperty.ALLOWS_ZERO_OR_MORE;
066: }
067: }
068:
069: /**
070: * Test if one cardinality subsumes another. Cardinality c1 subsumes c2 if every option permitted
071: * by c2 is also permitted by c1.
072: * @param c1 a cardinality
073: * @param c2 another cardinality
074: * @return true if if every option permitted
075: * by c2 is also permitted by c1.
076: */
077:
078: public static final boolean subsumes(int c1, int c2) {
079: return (c1 | c2) == c1;
080: }
081:
082: /**
083: * Add two cardinalities
084: */
085:
086: public static final int add(int c1, int c2) {
087: if (c1 == StaticProperty.EMPTY) {
088: return c2;
089: }
090: if (c2 == StaticProperty.EMPTY) {
091: return c1;
092: }
093: boolean allowsZero = Cardinality.allowsZero(c1)
094: && Cardinality.allowsZero(c2);
095: return StaticProperty.ALLOWS_ONE_OR_MORE
096: | (allowsZero ? StaticProperty.ALLOWS_ZERO : 0);
097: }
098:
099: /**
100: * Multiply two cardinalities
101: */
102:
103: public static final int multiply(int c1, int c2) {
104: if (c1 == StaticProperty.EMPTY || c2 == StaticProperty.EMPTY) {
105: return StaticProperty.EMPTY;
106: }
107: if (c2 == StaticProperty.EXACTLY_ONE) {
108: return c1;
109: }
110: if (c1 == StaticProperty.EXACTLY_ONE) {
111: return c2;
112: }
113: if (c1 == StaticProperty.ALLOWS_ZERO_OR_ONE
114: && c2 == StaticProperty.ALLOWS_ZERO_OR_ONE) {
115: return StaticProperty.ALLOWS_ZERO_OR_ONE;
116: }
117: if (c1 == StaticProperty.ALLOWS_ONE_OR_MORE
118: && c2 == StaticProperty.ALLOWS_ONE_OR_MORE) {
119: return StaticProperty.ALLOWS_ONE_OR_MORE;
120: }
121: return StaticProperty.ALLOWS_ZERO_OR_MORE;
122: }
123:
124: /**
125: * Display the cardinality
126: */
127:
128: public static String toString(int cardinality) {
129: switch (cardinality) {
130: case StaticProperty.ALLOWS_ZERO_OR_ONE:
131: return "zero or one";
132: case StaticProperty.EXACTLY_ONE:
133: return "exactly one";
134: case StaticProperty.ALLOWS_ZERO_OR_MORE:
135: return "zero or more";
136: case StaticProperty.ALLOWS_ONE_OR_MORE:
137: return "one or more";
138: case StaticProperty.EMPTY:
139: return "exactly zero";
140: case StaticProperty.ALLOWS_MANY:
141: return "more than one";
142: default:
143: return "code " + cardinality;
144: }
145: }
146:
147: /**
148: * Get the occurence indicator representing the cardinality
149: */
150:
151: public static String getOccurrenceIndicator(int cardinality) {
152: switch (cardinality) {
153: case StaticProperty.ALLOWS_ZERO_OR_ONE:
154: return "?";
155: case StaticProperty.EXACTLY_ONE:
156: return "";
157: case StaticProperty.ALLOWS_ZERO_OR_MORE:
158: return "*";
159: case StaticProperty.ALLOWS_ONE_OR_MORE:
160: return "+";
161: default:
162: throw new AssertionError("unknown cardinality value");
163: }
164: }
165: }
166:
167: //
168: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
169: // you may not use this file except in compliance with the License. You may obtain a copy of the
170: // License at http://www.mozilla.org/MPL/
171: //
172: // Software distributed under the License is distributed on an "AS IS" basis,
173: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
174: // See the License for the specific language governing rights and limitations under the License.
175: //
176: // The Original Code is: all this file.
177: //
178: // The Initial Developer of the Original Code is Michael H. Kay
179: //
180: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
181: //
182: // Contributor(s): none.
183: //
|