KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > impl > dv > xs > DurationDV


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 2001, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package com.sun.org.apache.xerces.internal.impl.dv.xs;
59
60 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
61 import com.sun.org.apache.xerces.internal.impl.dv.ValidationContext;
62
63 /**
64  * Validator for <duration> datatype (W3C Schema Datatypes)
65  *
66  * @author Elena Litani
67  * @author Gopal Sharma, SUN Microsystem Inc.
68  * @version $Id: DurationDV.java,v 1.8 2003/12/11 15:08:25 sandygao Exp $
69  */

70 public class DurationDV extends AbstractDateTimeDV {
71
72     // order-relation on duration is a partial order. The dates below are used to
73
// for comparison of 2 durations, based on the fact that
74
// duration x and y is x<=y iff s+x<=s+y
75
// see 3.2.6 duration W3C schema datatype specs
76
//
77
// the dates are in format: {CCYY,MM,DD, H, S, M, MS, timezone}
78
private final static int[][] DATETIMES= {
79         {1696, 9, 1, 0, 0, 0, 0, 'Z'},
80         {1697, 2, 1, 0, 0, 0, 0, 'Z'},
81         {1903, 3, 1, 0, 0, 0, 0, 'Z'},
82         {1903, 7, 1, 0, 0, 0, 0, 'Z'}};
83
84     public Object JavaDoc getActualValue(String JavaDoc content, ValidationContext context) throws InvalidDatatypeValueException{
85         try{
86             return new DateTimeData(parse(content), this);
87         } catch (Exception JavaDoc ex) {
88             throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object JavaDoc[]{content, "duration"});
89         }
90     }
91
92     /**
93      * Parses, validates and computes normalized version of duration object
94      *
95      * @param str The lexical representation of duration object PnYn MnDTnH nMnS
96      * @param date uninitialized date object
97      * @return normalized date representation
98      * @exception SchemaDateTimeException Invalid lexical representation
99      */

100     protected int[] parse(String JavaDoc str) throws SchemaDateTimeException{
101         int len = str.length();
102         int[] date=new int[TOTAL_SIZE];
103
104         int start = 0;
105         char c=str.charAt(start++);
106         if ( c!='P' && c!='-' ) {
107             throw new SchemaDateTimeException();
108         }
109         else {
110             date[utc]=(c=='-')?'-':0;
111             if ( c=='-' && str.charAt(start++)!='P' ) {
112                 throw new SchemaDateTimeException();
113             }
114         }
115
116         int negate = 1;
117         //negative duration
118
if ( date[utc]=='-' ) {
119             negate = -1;
120
121         }
122         //at least one number and designator must be seen after P
123
boolean designator = false;
124
125         int endDate = indexOf (str, start, len, 'T');
126         if ( endDate == -1 ) {
127             endDate = len;
128         }
129         //find 'Y'
130
int end = indexOf (str, start, endDate, 'Y');
131         if ( end!=-1 ) {
132             //scan year
133
date[CY]=negate * parseInt(str,start,end);
134             start = end+1;
135             designator = true;
136         }
137
138         end = indexOf (str, start, endDate, 'M');
139         if ( end!=-1 ) {
140             //scan month
141
date[M]=negate * parseInt(str,start,end);
142             start = end+1;
143             designator = true;
144         }
145
146         end = indexOf (str, start, endDate, 'D');
147         if ( end!=-1 ) {
148             //scan day
149
date[D]=negate * parseInt(str,start,end);
150             start = end+1;
151             designator = true;
152         }
153
154         if ( len == endDate && start!=len ) {
155             throw new SchemaDateTimeException();
156         }
157         if ( len !=endDate ) {
158
159             //scan hours, minutes, seconds
160
//REVISIT: can any item include a decimal fraction or only seconds?
161
//
162

163             end = indexOf (str, ++start, len, 'H');
164             if ( end!=-1 ) {
165                 //scan hours
166
date[h]=negate * parseInt(str,start,end);
167                 start=end+1;
168                 designator = true;
169             }
170
171             end = indexOf (str, start, len, 'M');
172             if ( end!=-1 ) {
173                 //scan min
174
date[m]=negate * parseInt(str,start,end);
175                 start=end+1;
176                 designator = true;
177             }
178
179             end = indexOf (str, start, len, 'S');
180             if ( end!=-1 ) {
181                 //scan seconds
182
int mlsec = indexOf (str, start, end, '.');
183                 if ( mlsec >0 ) {
184                     date[s] = negate * parseInt (str, start, mlsec);
185                     date[ms] = negate * parseInt (str, mlsec+1, end);
186                 }
187                 else {
188                     date[s]=negate * parseInt(str, start,end);
189                 }
190                 start=end+1;
191                 designator = true;
192             }
193             // no additional data shouls appear after last item
194
// P1Y1M1DT is illigal value as well
195
if ( start != len || str.charAt(--start)=='T' ) {
196                 throw new SchemaDateTimeException();
197             }
198         }
199
200         if ( !designator ) {
201             throw new SchemaDateTimeException();
202         }
203
204         return date;
205     }
206
207     /**
208      * Compares 2 given durations. (refer to W3C Schema Datatypes "3.2.6 duration")
209      *
210      * @param date1 Unnormalized duration
211      * @param date2 Unnormalized duration
212      * @param strict (min/max)Exclusive strict == true ( LESS_THAN ) or ( GREATER_THAN )
213      * (min/max)Inclusive strict == false (LESS_EQUAL) or (GREATER_EQUAL)
214      * @return INDETERMINATE if the order relationship between date1 and date2 is indeterminate.
215      * EQUAL if the order relation between date1 and date2 is EQUAL.
216      * If the strict parameter is true, return LESS_THAN if date1 is less than date2 and
217      * return GREATER_THAN if date1 is greater than date2.
218      * If the strict parameter is false, return LESS_THAN if date1 is less than OR equal to date2 and
219      * return GREATER_THAN if date1 is greater than OR equal to date2
220      */

221     protected short compareDates(int[] date1, int[] date2, boolean strict) {
222
223         //REVISIT: this is unoptimazed vs of comparing 2 durations
224
// Algorithm is described in 3.2.6.2 W3C Schema Datatype specs
225
//
226

227         //add constA to both durations
228
short resultA, resultB= INDETERMINATE;
229
230         //try and see if the objects are equal
231
resultA = compareOrder (date1, date2);
232         if ( resultA == 0 ) {
233             return 0;
234         }
235
236         int[][] result = new int[2][TOTAL_SIZE];
237
238         //long comparison algorithm is required
239
int[] tempA = addDuration (date1, DATETIMES[0], result[0]);
240         int[] tempB = addDuration (date2, DATETIMES[0], result[1]);
241         resultA = compareOrder(tempA, tempB);
242         if ( resultA == INDETERMINATE ) {
243             return INDETERMINATE;
244         }
245
246         tempA = addDuration(date1, DATETIMES[1], result[0]);
247         tempB = addDuration(date2, DATETIMES[1], result[1]);
248         resultB = compareOrder(tempA, tempB);
249         resultA = compareResults(resultA, resultB, strict);
250         if (resultA == INDETERMINATE) {
251             return INDETERMINATE;
252         }
253
254         tempA = addDuration(date1, DATETIMES[2], result[0]);
255         tempB = addDuration(date2, DATETIMES[2], result[1]);
256         resultB = compareOrder(tempA, tempB);
257         resultA = compareResults(resultA, resultB, strict);
258         if (resultA == INDETERMINATE) {
259             return INDETERMINATE;
260         }
261
262         tempA = addDuration(date1, DATETIMES[3], result[0]);
263         tempB = addDuration(date2, DATETIMES[3], result[1]);
264         resultB = compareOrder(tempA, tempB);
265         resultA = compareResults(resultA, resultB, strict);
266
267         return resultA;
268     }
269
270     private short compareResults(short resultA, short resultB, boolean strict){
271
272       if ( resultB == INDETERMINATE ) {
273             return INDETERMINATE;
274         }
275         else if ( resultA!=resultB && strict ) {
276             return INDETERMINATE;
277         }
278         else if ( resultA!=resultB && !strict ) {
279             if ( resultA!=0 && resultB!=0 ) {
280                 return INDETERMINATE;
281             }
282             else {
283                 return (resultA!=0)?resultA:resultB;
284             }
285         }
286         return resultA;
287     }
288
289     private int[] addDuration(int[] date, int[] addto, int[] duration) {
290
291         //REVISIT: some code could be shared between normalize() and this method,
292
// however is it worth moving it? The structures are different...
293
//
294

295         resetDateObj(duration);
296         //add months (may be modified additionaly below)
297
int temp = addto[M] + date[M];
298         duration[M] = modulo (temp, 1, 13);
299         int carry = fQuotient (temp, 1, 13);
300
301         //add years (may be modified additionaly below)
302
duration[CY]=addto[CY] + date[CY] + carry;
303         
304         //add seconds
305
temp = addto[s] + date[s];
306         carry = fQuotient (temp, 60);
307         duration[s] = mod(temp, 60, carry);
308
309         //add minutes
310
temp = addto[m] +date[m] + carry;
311         carry = fQuotient (temp, 60);
312         duration[m]= mod(temp, 60, carry);
313
314         //add hours
315
temp = addto[h] + date[h] + carry;
316         carry = fQuotient(temp, 24);
317         duration[h] = mod(temp, 24, carry);
318
319
320         duration[D]=addto[D] + date[D] + carry;
321
322         while ( true ) {
323
324             temp=maxDayInMonthFor(duration[CY], duration[M]);
325             if ( duration[D] < 1 ) { //original duration was negative
326
duration[D] = duration[D] + maxDayInMonthFor(duration[CY], duration[M]-1);
327                 carry=-1;
328             }
329             else if ( duration[D] > temp ) {
330                 duration[D] = duration[D] - temp;
331                 carry=1;
332             }
333             else {
334                 break;
335             }
336             temp = duration[M]+carry;
337             duration[M] = modulo(temp, 1, 13);
338             duration[CY] = duration[CY]+fQuotient(temp, 1, 13);
339         }
340
341         duration[utc]='Z';
342         return duration;
343     }
344
345     protected String JavaDoc dateToString(int[] date) {
346         StringBuffer JavaDoc message = new StringBuffer JavaDoc(30);
347         int negate = 1;
348         if ( date[CY]<0 ) {
349             message.append('-');
350             negate=-1;
351         }
352         message.append('P');
353         message.append(negate * date[CY]);
354         message.append('Y');
355         message.append(negate * date[M]);
356         message.append('M');
357         message.append(negate * date[D]);
358         message.append('D');
359         message.append('T');
360         message.append(negate * date[h]);
361         message.append('H');
362         message.append(negate * date[m]);
363         message.append('M');
364         message.append(negate * date[s]);
365         message.append('.');
366         message.append(negate * date[ms]);
367         message.append('S');
368
369         return message.toString();
370     }
371 }
372
Popular Tags