001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.tools.ant.util;
019:
020: import java.util.StringTokenizer;
021:
022: /**
023: * Utility class to contain version numbers in "Dewey Decimal"
024: * syntax. Numbers in the "Dewey Decimal" syntax consist of positive
025: * decimal integers separated by periods ".". For example, "2.0" or
026: * "1.2.3.4.5.6.7". This allows an extensible number to be used to
027: * represent major, minor, micro, etc versions. The version number
028: * must begin with a number.
029: *
030: */
031: public class DeweyDecimal {
032:
033: /** Array of components that make up DeweyDecimal */
034: private int[] components;
035:
036: /**
037: * Construct a DeweyDecimal from an array of integer components.
038: *
039: * @param components an array of integer components.
040: */
041: public DeweyDecimal(final int[] components) {
042: this .components = new int[components.length];
043:
044: for (int i = 0; i < components.length; i++) {
045: this .components[i] = components[i];
046: }
047: }
048:
049: /**
050: * Construct a DeweyDecimal from string in DeweyDecimal format.
051: *
052: * @param string the string in dewey decimal format
053: * @exception NumberFormatException if string is malformed
054: */
055: public DeweyDecimal(final String string)
056: throws NumberFormatException {
057: final StringTokenizer tokenizer = new StringTokenizer(string,
058: ".", true);
059: final int size = tokenizer.countTokens();
060:
061: components = new int[(size + 1) / 2];
062:
063: for (int i = 0; i < components.length; i++) {
064: final String component = tokenizer.nextToken();
065: if (component.equals("")) {
066: throw new NumberFormatException(
067: "Empty component in string");
068: }
069:
070: components[i] = Integer.parseInt(component);
071:
072: //Strip '.' token
073: if (tokenizer.hasMoreTokens()) {
074: tokenizer.nextToken();
075:
076: //If it ended in a dot, throw an exception
077: if (!tokenizer.hasMoreTokens()) {
078: throw new NumberFormatException(
079: "DeweyDecimal ended in a '.'");
080: }
081: }
082: }
083: }
084:
085: /**
086: * Return number of components in <code>DeweyDecimal</code>.
087: *
088: * @return the number of components in dewey decimal
089: */
090: public int getSize() {
091: return components.length;
092: }
093:
094: /**
095: * Return the component at specified index.
096: *
097: * @param index the index of components
098: * @return the value of component at index
099: */
100: public int get(final int index) {
101: return components[index];
102: }
103:
104: /**
105: * Return <code>true</code> if this <code>DeweyDecimal</code> is
106: * equal to the other <code>DeweyDecimal</code>.
107: *
108: * @param other the other DeweyDecimal
109: * @return true if equal to other DeweyDecimal, false otherwise
110: */
111: public boolean isEqual(final DeweyDecimal other) {
112: final int max = Math.max(other.components.length,
113: components.length);
114:
115: for (int i = 0; i < max; i++) {
116: final int component1 = (i < components.length) ? components[i]
117: : 0;
118: final int component2 = (i < other.components.length) ? other.components[i]
119: : 0;
120:
121: if (component2 != component1) {
122: return false;
123: }
124: }
125:
126: return true; // Exact match
127: }
128:
129: /**
130: * Return <code>true</code> if this <code>DeweyDecimal</code> is
131: * less than the other <code>DeweyDecimal</code>.
132: *
133: * @param other the other DeweyDecimal
134: * @return true if less than other DeweyDecimal, false otherwise
135: */
136: public boolean isLessThan(final DeweyDecimal other) {
137: return !isGreaterThanOrEqual(other);
138: }
139:
140: /**
141: * Return <code>true</code> if this <code>DeweyDecimal</code> is
142: * less than or equal to the other <code>DeweyDecimal</code>.
143: *
144: * @param other the other DeweyDecimal
145: * @return true if less than or equal to other DeweyDecimal, false otherwise
146: */
147: public boolean isLessThanOrEqual(final DeweyDecimal other) {
148: return !isGreaterThan(other);
149: }
150:
151: /**
152: * Return <code>true</code> if this <code>DeweyDecimal</code> is
153: * greater than the other <code>DeweyDecimal</code>.
154: *
155: * @param other the other DeweyDecimal
156: * @return true if greater than other DeweyDecimal, false otherwise
157: */
158: public boolean isGreaterThan(final DeweyDecimal other) {
159: final int max = Math.max(other.components.length,
160: components.length);
161:
162: for (int i = 0; i < max; i++) {
163: final int component1 = (i < components.length) ? components[i]
164: : 0;
165: final int component2 = (i < other.components.length) ? other.components[i]
166: : 0;
167:
168: if (component2 > component1) {
169: return false;
170: }
171: if (component2 < component1) {
172: return true;
173: }
174: }
175:
176: return false; // Exact match
177: }
178:
179: /**
180: * Return <code>true</code> if this <code>DeweyDecimal</code> is
181: * greater than or equal to the other <code>DeweyDecimal</code>.
182: *
183: * @param other the other DeweyDecimal
184: * @return true if greater than or equal to other DeweyDecimal, false otherwise
185: */
186: public boolean isGreaterThanOrEqual(final DeweyDecimal other) {
187: final int max = Math.max(other.components.length,
188: components.length);
189:
190: for (int i = 0; i < max; i++) {
191: final int component1 = (i < components.length) ? components[i]
192: : 0;
193: final int component2 = (i < other.components.length) ? other.components[i]
194: : 0;
195:
196: if (component2 > component1) {
197: return false;
198: }
199: if (component2 < component1) {
200: return true;
201: }
202: }
203:
204: return true; // Exact match
205: }
206:
207: /**
208: * Return string representation of <code>DeweyDecimal</code>.
209: *
210: * @return the string representation of DeweyDecimal.
211: */
212: public String toString() {
213: final StringBuffer sb = new StringBuffer();
214:
215: for (int i = 0; i < components.length; i++) {
216: if (i != 0) {
217: sb.append('.');
218: }
219: sb.append(components[i]);
220: }
221:
222: return sb.toString();
223: }
224: }
|