KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > datatypes > xsd > impl > XSDAbstractDateTimeType


1 /******************************************************************
2  * File: XSDAbstractDateTimeType.java
3  * Created by: Dave Reynolds
4  * Created on: 04-Dec-2003
5  *
6  * (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
7  * All rights reserved.
8  * [See end of file]
9  * $Id: XSDAbstractDateTimeType.java,v 1.3 2005/02/21 12:02:20 andy_seaborne Exp $
10  *****************************************************************/

11 package com.hp.hpl.jena.datatypes.xsd.impl;
12
13 import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
14 import com.hp.hpl.jena.graph.impl.LiteralLabel;
15
16 /**
17  * Base class for all date/time/duration type representations.
18  * Includes support functions for parsing and comparing dates.
19  *
20  * @author <a HREF="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
21  * @version $Revision: 1.3 $ on $Date: 2005/02/21 12:02:20 $
22  */

23 public class XSDAbstractDateTimeType extends XSDDatatype {
24
25     /**
26      * Constructor
27      */

28     public XSDAbstractDateTimeType(String JavaDoc typename) {
29         super(typename);
30     }
31      
32     /**
33      * Compares two instances of values of the given datatype.
34      * This ignores lang tags and just uses the java.lang.Number
35      * equality.
36      */

37     public boolean isEqual(LiteralLabel value1, LiteralLabel value2) {
38        return value1.getValue().equals(value2.getValue());
39     }
40     
41     /** Mask to indicate whether year is present */
42     public static final short YEAR_MASK = 0x1;
43     
44     /** Mask to indicate whether month is present */
45     public static final short MONTH_MASK = 0x2;
46     
47     /** Mask to indicate whether day is present */
48     public static final short DAY_MASK = 0x4;
49     
50     /** Mask to indicate whether time is present */
51     public static final short TIME_MASK = 0x8;
52     
53     /** Mask to indicate all date/time are present */
54     public static final short FULL_MASK = 0xf;
55     
56     
57 // --------------------------------------------------------------------
58
// This code is adapated from Xerces 2.6.0 AbstractDateTimeDV.
59
// Copyright (c) 1999-2003 The Apache Software Foundation. All rights
60
// reserved.
61
// --------------------------------------------------------------------
62

63      //define constants
64
protected final static int CY = 0, M = 1, D = 2, h = 3,
65      m = 4, s = 5, ms = 6, utc=7, hh=0, mm=1;
66         
67      //size for all objects must have the same fields:
68
//CCYY, MM, DD, h, m, s, ms + timeZone
69
protected final static int TOTAL_SIZE = 8;
70
71      //define constants to be used in assigning default values for
72
//all date/time excluding duration
73
protected final static int YEAR=2000;
74      protected final static int MONTH=01;
75      protected final static int DAY = 15;
76
77
78      /**
79       * Parses time hh:mm:ss.sss and time zone if any
80       *
81       * @param start
82       * @param end
83       * @param data
84       * @exception RuntimeException
85       */

86      protected void getTime (String JavaDoc buffer, int start, int end, int[] data, int[] timeZone) throws RuntimeException JavaDoc{
87
88          int stop = start+2;
89
90          //get hours (hh)
91
data[h]=parseInt(buffer, start,stop);
92
93          //get minutes (mm)
94

95          if (buffer.charAt(stop++)!=':') {
96                  throw new RuntimeException JavaDoc("Error in parsing time zone" );
97          }
98          start = stop;
99          stop = stop+2;
100          data[m]=parseInt(buffer, start,stop);
101
102          //get seconds (ss)
103
if (buffer.charAt(stop++)!=':') {
104                  throw new RuntimeException JavaDoc("Error in parsing time zone" );
105          }
106          start = stop;
107          stop = stop+2;
108          data[s]=parseInt(buffer, start,stop);
109
110          if (stop == end)
111              return;
112         
113          //get miliseconds (ms)
114
start = stop;
115          int milisec = buffer.charAt(start) == '.' ? start : -1;
116
117          //find UTC sign if any
118
int sign = findUTCSign(buffer, start, end);
119
120          //parse miliseconds
121
if ( milisec != -1 ) {
122              // The end of millisecond part is between . and
123
// either the end of the UTC sign
124
start = sign < 0 ? end : sign;
125              data[ms]=parseInt(buffer, milisec+1, start);
126          }
127
128          //parse UTC time zone (hh:mm)
129
if ( sign>0 ) {
130              if (start != sign)
131                  throw new RuntimeException JavaDoc("Error in parsing time zone" );
132              getTimeZone(buffer, data, sign, end, timeZone);
133          }
134          else if (start != end) {
135              throw new RuntimeException JavaDoc("Error in parsing time zone" );
136          }
137      }
138
139      /**
140       * Parses date CCYY-MM-DD
141       *
142       * @param start
143       * @param end
144       * @param data
145       * @exception RuntimeException
146       */

147      protected int getDate (String JavaDoc buffer, int start, int end, int[] date) throws RuntimeException JavaDoc{
148
149          start = getYearMonth(buffer, start, end, date);
150
151          if (buffer.charAt(start++) !='-') {
152              throw new RuntimeException JavaDoc("CCYY-MM must be followed by '-' sign");
153          }
154          int stop = start + 2;
155          date[D]=parseInt(buffer, start, stop);
156          return stop;
157      }
158
159      /**
160       * Parses date CCYY-MM
161       *
162       * @param start
163       * @param end
164       * @param data
165       * @exception RuntimeException
166       */

167      protected int getYearMonth (String JavaDoc buffer, int start, int end, int[] date) throws RuntimeException JavaDoc{
168
169          if ( buffer.charAt(0)=='-' ) {
170              // REVISIT: date starts with preceding '-' sign
171
// do we have to do anything with it?
172
//
173
start++;
174          }
175          int i = indexOf(buffer, start, end, '-');
176          if ( i==-1 ) throw new RuntimeException JavaDoc("Year separator is missing or misplaced");
177          int length = i-start;
178          if (length<4) {
179              throw new RuntimeException JavaDoc("Year must have 'CCYY' format");
180          }
181          else if (length > 4 && buffer.charAt(start)=='0'){
182              throw new RuntimeException JavaDoc("Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden");
183          }
184          date[CY]= parseIntYear(buffer, i);
185          if (buffer.charAt(i)!='-') {
186              throw new RuntimeException JavaDoc("CCYY must be followed by '-' sign");
187          }
188          start = ++i;
189          i = start +2;
190          date[M]=parseInt(buffer, start, i);
191          return i; //fStart points right after the MONTH
192
}
193
194      /**
195       * Shared code from Date and YearMonth datatypes.
196       * Finds if time zone sign is present
197       *
198       * @param end
199       * @param date
200       * @exception RuntimeException
201       */

202      protected void parseTimeZone (String JavaDoc buffer, int start, int end, int[] date, int[] timeZone) throws RuntimeException JavaDoc{
203
204          //fStart points right after the date
205

206          if ( start<end ) {
207              int sign = findUTCSign(buffer, start, end);
208              if ( sign<0 ) {
209                  throw new RuntimeException JavaDoc ("Error in month parsing");
210              }
211              else {
212                  getTimeZone(buffer, date, sign, end, timeZone);
213              }
214          }
215      }
216
217      /**
218       * Parses time zone: 'Z' or {+,-} followed by hh:mm
219       *
220       * @param data
221       * @param sign
222       * @exception RuntimeException
223       */

224      protected void getTimeZone (String JavaDoc buffer, int[] data, int sign, int end, int[] timeZone) throws RuntimeException JavaDoc{
225          data[utc]=buffer.charAt(sign);
226
227          if ( buffer.charAt(sign) == 'Z' ) {
228              if (end>(++sign)) {
229                  throw new RuntimeException JavaDoc("Error in parsing time zone");
230              }
231              return;
232          }
233          if ( sign<=(end-6) ) {
234
235              //parse [hh]
236
int stop = ++sign+2;
237              timeZone[hh]=parseInt(buffer, sign, stop);
238              if (buffer.charAt(stop++)!=':') {
239                  throw new RuntimeException JavaDoc("Error in parsing time zone" );
240              }
241
242              //parse [ss]
243
timeZone[mm]=parseInt(buffer, stop, stop+2);
244
245              if ( stop+2!=end ) {
246                  throw new RuntimeException JavaDoc("Error in parsing time zone");
247              }
248
249          }
250          else {
251              throw new RuntimeException JavaDoc("Error in parsing time zone");
252          }
253      }
254
255      /**
256       * Computes index of given char within StringBuffer
257       *
258       * @param start
259       * @param end
260       * @param ch character to look for in StringBuffer
261       * @return index of ch within StringBuffer
262       */

263      protected int indexOf (String JavaDoc buffer, int start, int end, char ch) {
264          for ( int i=start;i<end;i++ ) {
265              if ( buffer.charAt(i) == ch ) {
266                  return i;
267              }
268          }
269          return -1;
270      }
271
272      // check whether the character is in the range 0x30 ~ 0x39
273
public static final boolean isDigit(char ch) {
274          return ch >= '0' && ch <= '9';
275      }
276     
277      // if the character is in the range 0x30 ~ 0x39, return its int value (0~9),
278
// otherwise, return -1
279
public static final int getDigit(char ch) {
280          return isDigit(ch) ? ch - '0' : -1;
281      }
282
283
284      /**
285       * Return index of UTC char: 'Z', '+', '-'
286       *
287       * @param start
288       * @param end
289       * @return index of the UTC character that was found
290       */

291      protected int findUTCSign (String JavaDoc buffer, int start, int end) {
292          int c;
293          for ( int i=start;i<end;i++ ) {
294              c=buffer.charAt(i);
295              if ( c == 'Z' || c=='+' || c=='-' ) {
296                  return i;
297              }
298
299          }
300          return -1;
301      }
302
303      /**
304       * Given start and end position, parses string value
305       *
306       * @param value string to parse
307       * @param start Start position
308       * @param end end position
309       * @return return integer representation of characters
310       */

311      protected int parseInt (String JavaDoc buffer, int start, int end)
312      throws NumberFormatException JavaDoc{
313          //REVISIT: more testing on this parsing needs to be done.
314
int radix=10;
315          int result = 0;
316          int digit=0;
317          int limit = -Integer.MAX_VALUE;
318          int multmin = limit / radix;
319          int i = start;
320          do {
321              digit = getDigit(buffer.charAt(i));
322              if ( digit < 0 ) throw new NumberFormatException JavaDoc("'"+buffer.toString()+"' has wrong format");
323              if ( result < multmin ) throw new NumberFormatException JavaDoc("'"+buffer.toString()+"' has wrong format");
324              result *= radix;
325              if ( result < limit + digit ) throw new NumberFormatException JavaDoc("'"+buffer.toString()+"' has wrong format");
326              result -= digit;
327
328          }while ( ++i < end );
329          return -result;
330      }
331
332      // parse Year differently to support negative value.
333
protected int parseIntYear (String JavaDoc buffer, int end){
334          int radix=10;
335          int result = 0;
336          boolean negative = false;
337          int i=0;
338          int limit;
339          int multmin;
340          int digit=0;
341
342          if (buffer.charAt(0) == '-'){
343              negative = true;
344              limit = Integer.MIN_VALUE;
345              i++;
346
347          }
348          else{
349              limit = -Integer.MAX_VALUE;
350          }
351          multmin = limit / radix;
352          while (i < end)
353          {
354              digit = getDigit(buffer.charAt(i++));
355              if (digit < 0) throw new NumberFormatException JavaDoc("'"+buffer.toString()+"' has wrong format");
356              if (result < multmin) throw new NumberFormatException JavaDoc("'"+buffer.toString()+"' has wrong format");
357              result *= radix;
358              if (result < limit + digit) throw new NumberFormatException JavaDoc("'"+buffer.toString()+"' has wrong format");
359              result -= digit;
360          }
361
362          if (negative)
363          {
364              if (i > 1) return result;
365              else throw new NumberFormatException JavaDoc("'"+buffer.toString()+"' has wrong format");
366          }
367          return -result;
368
369      }
370
371      public String JavaDoc dateToString(int[] date) {
372          StringBuffer JavaDoc message = new StringBuffer JavaDoc(25);
373          append(message, date[CY], 4);
374          message.append('-');
375          append(message, date[M], 2);
376          message.append('-');
377          append(message, date[D], 2);
378          message.append('T');
379          append(message, date[h], 2);
380          message.append(':');
381          append(message, date[m], 2);
382          message.append(':');
383          append(message, date[s], 2);
384          message.append('.');
385          message.append(date[ms]);
386          append(message, (char)date[utc], 0);
387          return message.toString();
388      }
389     
390      protected void append(StringBuffer JavaDoc message, int value, int nch) {
391          if (value < 0) {
392              message.append('-');
393              value = -value;
394          }
395          if (nch == 4) {
396              if (value < 10)
397                  message.append("000");
398              else if (value < 100)
399                  message.append("00");
400              else if (value < 1000)
401                  message.append("0");
402              message.append(value);
403          }
404          else if (nch == 2) {
405              if (value < 10)
406                  message.append('0');
407              message.append(value);
408          }
409          else {
410              if (value != 0)
411                  message.append((char)value);
412          }
413      }
414
415     
416 // --------------------------------------------------------------------
417
// End of code is adapated from Xerces 2.6.0 AbstractDateTimeDV.
418
// --------------------------------------------------------------------
419

420 }
421
422
423
424 /*
425     (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
426     All rights reserved.
427
428     Redistribution and use in source and binary forms, with or without
429     modification, are permitted provided that the following conditions
430     are met:
431
432     1. Redistributions of source code must retain the above copyright
433        notice, this list of conditions and the following disclaimer.
434
435     2. Redistributions in binary form must reproduce the above copyright
436        notice, this list of conditions and the following disclaimer in the
437        documentation and/or other materials provided with the distribution.
438
439     3. The name of the author may not be used to endorse or promote products
440        derived from this software without specific prior written permission.
441
442     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
443     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
444     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
445     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
446     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
447     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
448     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
449     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
450     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
451     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
452 */

453
Popular Tags