KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > apache > xerces > validators > datatype > DurationDatatypeValidator


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999, 2000 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 org.enhydra.apache.xerces.validators.datatype;
59
60 import java.util.Hashtable JavaDoc;
61
62 /**
63  * Validator for <duration> datatype (W3C Schema Datatypes)
64  *
65  * @author Elena Litani
66  * @version $Id: DurationDatatypeValidator.java,v 1.1.1.1 2003/03/10 16:34:47 taweili Exp $
67  */

68
69 public class DurationDatatypeValidator extends DateTimeValidator {
70
71     // order-relation on duration is a partial order. The dates below are used to
72
// for comparison of 2 durations, based on the fact that
73
// duration x and y is x<=y iff s+x<=s+y
74
// see 3.2.6 duration W3C schema datatype specs
75
//
76
// the dates are in format: {CCYY,MM,DD, H, S, M, MS, timezone}
77
private final static int[][] DATETIMES= {
78         {1696, 9, 1, 0, 0, 0, 0, 'Z'},
79         {1697, 2, 1, 0, 0, 0, 0, 'Z'},
80         {1903, 3, 1, 0, 0, 0, 0, 'Z'},
81         {1903, 7, 1, 0, 0, 0, 0, 'Z'}};
82
83     private int[][] fDuration = null;
84
85
86     public DurationDatatypeValidator() throws InvalidDatatypeFacetException{
87         super();
88     }
89     public DurationDatatypeValidator ( DatatypeValidator base, Hashtable JavaDoc facets,
90                                         boolean derivedByList ) throws InvalidDatatypeFacetException {
91
92         super(base, facets, derivedByList);
93     }
94
95
96     /**
97      * Parses, validates and computes normalized version of duration object
98      *
99      * @param str The lexical representation of duration object PnYn MnDTnH nMnS
100      * @param date uninitialized date object
101      * @return normalized date representation
102      * @exception Exception Invalid lexical representation
103      */

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

174             end = indexOf (++fStart, fEnd, 'H');
175             if ( end!=-1 ) {
176                 //scan hours
177
date[h]=negate * parseInt(fStart,end);
178                 fStart=end+1;
179                 designator = true;
180             }
181
182             end = indexOf (fStart, fEnd, 'M');
183             if ( end!=-1 ) {
184                 //scan min
185
date[m]=negate * parseInt(fStart,end);
186                 fStart=end+1;
187                 designator = true;
188             }
189
190             end = indexOf (fStart, fEnd, 'S');
191             if ( end!=-1 ) {
192                 //scan seconds
193
int mlsec = indexOf (fStart, end, '.');
194                 if ( mlsec >0 ) {
195                     date[s] = negate * parseInt (fStart, mlsec);
196                     date[ms] = negate * parseInt (mlsec+1, end);
197                 }
198                 else {
199                     date[s]=negate * parseInt(fStart,end);
200                 }
201                 fStart=end+1;
202                 designator = true;
203             }
204             // no additional data shouls appear after last item
205
// P1Y1M1DT is illigal value as well
206
if ( fStart != fEnd || fBuffer.charAt(--fStart)=='T' ) {
207                 throw new SchemaDateTimeException();
208             }
209         }
210
211         if ( !designator ) {
212             throw new SchemaDateTimeException();
213         }
214
215         return date;
216     }
217
218
219     /**
220      * Compares 2 given durations. (refer to W3C Schema Datatypes "3.2.6 duration")
221      *
222      * @param date1 Unnormalized duration
223      * @param date2 Unnormalized duration
224      * @param strict (min/max)Exclusive strict == true ( LESS_THAN ) or ( GREATER_THAN )
225      * (min/max)Inclusive strict == false (LESS_EQUAL) or (GREATER_EQUAL)
226      * @return
227      */

228     protected short compareDates(int[] date1, int[] date2, boolean strict) {
229
230         //REVISIT: this is unoptimazed vs of comparing 2 durations
231
// Algorithm is described in 3.2.6.2 W3C Schema Datatype specs
232
//
233

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

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