001: package net.sf.saxon.value;
002:
003: import net.sf.saxon.expr.StaticProperty;
004: import net.sf.saxon.pattern.AnyNodeTest;
005: import net.sf.saxon.pattern.NoNodeTest;
006: import net.sf.saxon.type.AnyItemType;
007: import net.sf.saxon.type.ItemType;
008: import net.sf.saxon.type.Type;
009: import net.sf.saxon.type.BuiltInAtomicType;
010:
011: import java.io.Serializable;
012: import java.util.Collections;
013: import java.util.HashMap;
014: import java.util.Map;
015:
016: /**
017: * SequenceType: a sequence type consists of a primary type, which indicates the type of item,
018: * and a cardinality, which indicates the number of occurrences permitted. Where the primary type
019: * is element or attribute, there may also be a content type, indicating the required type
020: * annotation on the element or attribute content.
021: */
022:
023: public final class SequenceType implements Serializable {
024:
025: private ItemType primaryType; // the primary type of the item, e.g. "element", "comment", or "integer"
026: private int cardinality; // the required cardinality
027:
028: private static Map pool = Collections.synchronizedMap(new HashMap(
029: 50));
030:
031: /**
032: * A type that allows any sequence of items
033: */
034:
035: public static final SequenceType ANY_SEQUENCE = makeSequenceType(
036: AnyItemType.getInstance(),
037: StaticProperty.ALLOWS_ZERO_OR_MORE);
038:
039: /**
040: * A type that allows exactly one item, of any kind
041: */
042:
043: public static final SequenceType SINGLE_ITEM = makeSequenceType(
044: AnyItemType.getInstance(), StaticProperty.EXACTLY_ONE);
045:
046: /**
047: * A type that allows zero or one items, of any kind
048: */
049:
050: // public static final SequenceType OPTIONAL_ITEM =
051: // new SequenceType(Type.ITEM, Type.ITEM, StaticProperty.CARDINALITY_ALLOWS_ZERO_OR_ONE);
052: /**
053: * A type that allows exactly one atomic value
054: */
055:
056: public static final SequenceType SINGLE_ATOMIC = makeSequenceType(
057: Type.ANY_ATOMIC_TYPE, StaticProperty.EXACTLY_ONE);
058:
059: /**
060: * A type that allows zero or one atomic values
061: */
062:
063: public static final SequenceType OPTIONAL_ATOMIC = makeSequenceType(
064: Type.ANY_ATOMIC_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
065: /**
066: * A type that allows zero or more atomic values
067: */
068:
069: public static final SequenceType ATOMIC_SEQUENCE = makeSequenceType(
070: Type.ANY_ATOMIC_TYPE, StaticProperty.ALLOWS_ZERO_OR_MORE);
071:
072: /**
073: * A type that allows a single string
074: */
075:
076: public static final SequenceType SINGLE_STRING = makeSequenceType(
077: Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
078:
079: /**
080: * A type that allows a single integer
081: */
082:
083: public static final SequenceType SINGLE_INTEGER = makeSequenceType(
084: Type.INTEGER_TYPE, StaticProperty.EXACTLY_ONE);
085:
086: /**
087: * A type that allows a single integer
088: */
089:
090: public static final SequenceType OPTIONAL_INTEGER = makeSequenceType(
091: Type.INTEGER_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
092:
093: /**
094: * A type that allows zero or one nodes
095: */
096:
097: public static final SequenceType OPTIONAL_NODE = makeSequenceType(
098: AnyNodeTest.getInstance(),
099: StaticProperty.ALLOWS_ZERO_OR_ONE);
100:
101: /**
102: * A type that allows a single node
103: */
104:
105: public static final SequenceType SINGLE_NODE = makeSequenceType(
106: AnyNodeTest.getInstance(), StaticProperty.EXACTLY_ONE);
107:
108: /**
109: * A type that allows a sequence of zero or more nodes
110: */
111:
112: public static final SequenceType NODE_SEQUENCE = makeSequenceType(
113: AnyNodeTest.getInstance(),
114: StaticProperty.ALLOWS_ZERO_OR_MORE);
115:
116: /**
117: * A type that allows a sequence of zero or more numeric values
118: */
119:
120: public static final SequenceType NUMERIC_SEQUENCE = makeSequenceType(
121: Type.NUMBER_TYPE, StaticProperty.ALLOWS_ZERO_OR_MORE);
122:
123: /**
124: * Construct an instance of SequenceType. This is a private constructor: all external
125: * clients use the factory method makeSequenceType(), to allow object pooling.
126: *
127: * @param primaryType The item type
128: * @param cardinality The required cardinality
129: */
130: private SequenceType(ItemType primaryType, int cardinality) {
131: this .primaryType = primaryType;
132: if (primaryType instanceof NoNodeTest) {
133: this .cardinality = StaticProperty.EMPTY;
134: } else {
135: this .cardinality = cardinality;
136: }
137: }
138:
139: /**
140: * Construct an instance of SequenceType. This is a factory method: it maintains a
141: * pool of SequenceType objects to reduce the amount of object creation.
142: *
143: * @param primaryType The item type
144: * @param cardinality The required cardinality
145: */
146:
147: public static SequenceType makeSequenceType(ItemType primaryType,
148: int cardinality) {
149:
150: if (!(primaryType instanceof BuiltInAtomicType)) {
151: return new SequenceType(primaryType, cardinality);
152: }
153:
154: // For each ItemType, there is an array of 8 SequenceTypes, one for each possible
155: // cardinality (including impossible cardinalities, such as "0 or many"). The pool
156: // is a static HashMap that obtains this array, given an ItemType. The array contains null
157: // entries for cardinalities that have not been requested.
158:
159: SequenceType[] array = (SequenceType[]) pool.get(primaryType);
160: if (array == null) {
161: array = new SequenceType[8];
162: pool.put(primaryType, array);
163: }
164: int code = StaticProperty.getCardinalityCode(cardinality);
165: if (array[code] == null) {
166: SequenceType s = new SequenceType(primaryType, cardinality);
167: array[code] = s;
168: return s;
169: } else {
170: return array[code];
171: }
172: }
173:
174: /**
175: * Get the "primary" part of this required type. E.g. for type element(*, xs:date) the "primary type" is element()
176: *
177: * @return The item type code of the primary type
178: */
179: public ItemType getPrimaryType() {
180: return primaryType;
181: }
182:
183: /**
184: * Get the cardinality component of this SequenceType. This is one of the constants Cardinality.EXACTLY_ONE,
185: * Cardinality.ONE_OR_MORE, etc
186: *
187: * @return the required cardinality
188: * @see net.sf.saxon.value.Cardinality
189: */
190: public int getCardinality() {
191: return cardinality;
192: }
193:
194: /**
195: * Return a string representation of this SequenceType
196: * @return the string representation as an instance of the XPath
197: * SequenceType construct
198: */
199: public String toString() {
200: String s = primaryType.toString();
201: if (cardinality == StaticProperty.ALLOWS_ONE_OR_MORE) {
202: s = s + '+';
203: } else if (cardinality == StaticProperty.ALLOWS_ZERO_OR_MORE) {
204: s = s + '*';
205: } else if (cardinality == StaticProperty.ALLOWS_ZERO_OR_ONE) {
206: s = s + '?';
207: }
208: return s;
209: }
210:
211: /**
212: * Returns a hash code value for the object.
213: */
214: public int hashCode() {
215: return primaryType.hashCode() ^ cardinality;
216: }
217:
218: /**
219: * Indicates whether some other object is "equal to" this one.
220: */
221: public boolean equals(Object obj) {
222: if (obj instanceof SequenceType) {
223: return this .primaryType
224: .equals(((SequenceType) obj).primaryType)
225: && this .cardinality == ((SequenceType) obj).cardinality;
226: }
227: return false;
228: }
229:
230: }
231:
232: //
233: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
234: // you may not use this file except in compliance with the License. You may obtain a copy of the
235: // License at http://www.mozilla.org/MPL/
236: //
237: // Software distributed under the License is distributed on an "AS IS" basis,
238: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
239: // See the License for the specific language governing rights and limitations under the License.
240: //
241: // The Original Code is: all this file.
242: //
243: // The Initial Developer of the Original Code is Michael H. Kay
244: //
245: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
246: //
247: // Contributor(s): none.
248: //
|