Source Code Cross Referenced for DateTimeValidator.java in  » Web-Server » Rimfaxe-Web-Server » org » apache » xerces » validators » datatype » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Rimfaxe Web Server » org.apache.xerces.validators.datatype 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:/*
0002: * The Apache Software License, Version 1.1
0003: *
0004: *
0005: * Copyright (c) 1999, 2001 The Apache Software Foundation.  All rights 
0006: * reserved.
0007: *
0008: * Redistribution and use in source and binary forms, with or without
0009: * modification, are permitted provided that the following conditions
0010: * are met:
0011: *
0012: * 1. Redistributions of source code must retain the above copyright
0013: *    notice, this  list of conditions and the following disclaimer. 
0014: *
0015: * 2. Redistributions in binary form must reproduce the above copyright
0016: *    notice, this  list of conditions and the following disclaimer in
0017: *    the documentation and/or other materials provided with the
0018: *    distribution.
0019: *
0020: * 3. The end-user documentation included with the redistribution,
0021: *    if any, must include the following acknowledgment:  
0022: *       "This product includes software developed by the
0023: *        Apache Software Foundation (http://www.apache.org/)."
0024: *    Alternately, this  acknowledgment may appear in the software itself,
0025: *    if and wherever such third-party acknowledgments normally appear.
0026: *
0027: * 4. The names "Xerces" and "Apache Software Foundation" must
0028: *    not be used to endorse or promote products derived from this 
0029: *    software without prior written permission. For written 
0030: *    permission, please contact apache@apache.org.
0031: *
0032: * 5. Products derived from this  software may not be called "Apache",
0033: *    nor may "Apache" appear in their name, without prior written
0034: *    permission of the Apache Software Foundation.
0035: *
0036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0039: * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0040: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0047: * SUCH DAMAGE.
0048: * ====================================================================
0049: *
0050: * This software consists of voluntary contributions made by many
0051: * individuals on behalf of the Apache Software Foundation and was
0052: * originally based on software copyright (c) 2001, International
0053: * Business Machines, Inc., http://www.apache.org.  For more
0054: * information on the Apache Software Foundation, please see
0055: * <http://www.apache.org/>.
0056: */
0057:
0058:package org.apache.xerces.validators.datatype;
0059:
0060:import java.util.Vector;
0061:import java.util.Enumeration;
0062:import java.util.Hashtable;
0063:import java.lang.Math;
0064:import org.apache.xerces.utils.regex.RegularExpression;
0065:import org.apache.xerces.validators.schema.SchemaSymbols;
0066:
0067:
0068:/**
0069: * This is the base class of all date/time datatype validators.
0070: * It implements common code for parsing, validating and comparing datatypes.
0071: * Classes that extend this class, must implement parse() method.
0072: * 
0073: * @author Elena Litani
0074: * @author Len Berman  
0075: *
0076: * @version $Id: DateTimeValidator.java,v 1.14.2.2 2001/11/05 13:10:19 elena Exp $
0077: */
0078:
0079:public abstract class DateTimeValidator extends AbstractNumericFacetValidator {
0080:
0081:    //debugging    
0082:    private static final boolean DEBUG=false;
0083:    
0084:    //define shared variables for date/time
0085:
0086:    //define constants
0087:    protected final static int CY = 0,  M = 1, D = 2, h = 3, 
0088:    m = 4, s = 5, ms = 6, utc=7, hh=0, mm=1;
0089:
0090:    //comparison
0091:    protected static final short LESS_THAN=-1;
0092:    protected static final short EQUAL=0;
0093:    protected static final short GREATER_THAN=1;
0094:
0095:    //size for all objects must have the same fields: 
0096:    //CCYY, MM, DD, h, m, s, ms + timeZone
0097:    protected final static int TOTAL_SIZE = 8;
0098:
0099:    //date obj size for gMonth datatype (without time zone): --09--
0100:    protected final static int MONTH_SIZE = 6; 
0101:
0102:    //date obj must have at least 6 chars after year (without time zone): "-MM-DD"
0103:    private final static int YEARMONTH_SIZE = 7;
0104:
0105:    //define constants to be used in assigning default values for 
0106:    //all date/time excluding duration
0107:    protected final static int YEAR=2000;
0108:    protected final static int MONTH=01;
0109:    protected final static int DAY = 15;
0110:
0111:    //obj to store timeZone for date/time object excluding duration
0112:    protected int[] timeZone;
0113:
0114:    //size of enumeration if any
0115:    protected int  fEnumSize;
0116:
0117:    //size of string buffer
0118:    protected int fEnd; 
0119:    protected int fStart;
0120:
0121:    //storage for string value of date/time object 
0122:    protected StringBuffer fBuffer;     
0123:
0124:    //obj to store all date/time objects with fields:
0125:    // {CY, M, D, h, m, s, ms, utc}
0126:    protected int[] fDateValue;
0127:    private int[] fTempDate;
0128:
0129:    //error message buffer
0130:    protected StringBuffer message;
0131:    //
0132:    //REVISIT:  more error checking, general debuging/common code clean up
0133:    //
0134:
0135:
0136:    //default constractor
0137:
0138:    public  DateTimeValidator () throws InvalidDatatypeFacetException {
0139:        super ( null, null, false ); // Native, No Facets defined, Restriction
0140:
0141:    }
0142:
0143:    public DateTimeValidator (DatatypeValidator base, Hashtable facets, boolean derivedByList ) 
0144:    throws InvalidDatatypeFacetException {
0145:        super  (base, facets, derivedByList);
0146:    }
0147:
0148:    protected void initializeValues(){
0149:        fDateValue = new int[TOTAL_SIZE];
0150:        fTempDate = new int[TOTAL_SIZE];
0151:        fEnd = 30; 
0152:        fStart = 0;
0153:        message = new StringBuffer(TOTAL_SIZE);
0154:        fBuffer = new StringBuffer(fEnd);
0155:        timeZone = new int[2];
0156:    }
0157:
0158:    protected void assignAdditionalFacets(String key,  Hashtable facets ) throws InvalidDatatypeFacetException{        
0159:        throw new InvalidDatatypeFacetException( getErrorString(DatatypeMessageProvider.ILLEGAL_DATETIME_FACET,
0160:                                                                DatatypeMessageProvider.MSG_NONE, new Object[] { key }));
0161:    }
0162:    
0163:    protected int compareValues (Object value1, Object value2) {
0164:            return compareDates((int[])value1, (int[])value2, true);
0165:    }
0166:
0167:    protected void setMaxInclusive (String value) {
0168:        fMaxInclusive = parse(value, null);
0169:    }
0170:    protected void setMinInclusive (String value) {
0171:        fMinInclusive = parse(value, null);
0172:    }
0173:    
0174:    protected void setMaxExclusive (String value) {
0175:        fMaxExclusive = parse(value, null);
0176:
0177:    }
0178:    protected void setMinExclusive (String value) {
0179:        fMinExclusive = parse(value, null);
0180:
0181:    }
0182:    protected void setEnumeration (Vector enumeration) throws InvalidDatatypeValueException{
0183:   
0184:    if ( enumeration != null ) {
0185:         
0186:        fEnumSize = enumeration.size();
0187:        fEnumeration = new int[fEnumSize][];
0188:        for ( int i=0; i<fEnumSize; i++ ) {
0189:            try {
0190:                fEnumeration[i] = parse((String)enumeration.elementAt(i), null);
0191:            }
0192:            catch ( RuntimeException e ) {
0193:                throw new InvalidDatatypeValueException(e.getMessage());
0194:            }
0195:        }
0196:    }
0197:}
0198:
0199:
0200:    protected String getMaxInclusive (boolean isBase) {
0201:        return (isBase)?(dateToString((int[]) ((DateTimeValidator)fBaseValidator).fMaxInclusive))
0202:        :dateToString((int[])fMaxInclusive);
0203:    }
0204:    protected String getMinInclusive (boolean isBase) {
0205:        return (isBase)?(dateToString((int[]) ((DateTimeValidator)fBaseValidator).fMinInclusive))
0206:        :dateToString((int[])fMinInclusive);
0207:    }
0208:    protected String getMaxExclusive (boolean isBase) {
0209:        return (isBase)?(dateToString((int[]) ((DateTimeValidator)fBaseValidator).fMaxExclusive))
0210:        :dateToString((int[])fMaxExclusive);
0211:    }
0212:    protected String getMinExclusive (boolean isBase) {
0213:        return (isBase)?(dateToString((int[]) ((DateTimeValidator)fBaseValidator).fMinExclusive))
0214:        :dateToString((int[])fMinExclusive);
0215:    }
0216:
0217:    protected void checkContent( String content, Object State, Vector enum, boolean asBase)
0218:                                    throws InvalidDatatypeValueException{
0219:    }
0220:
0221:    /**
0222:     * Implemented by each subtype, calling appropriate function to parse
0223:     * given date/time
0224:     * 
0225:     * @param content String value of the date/time
0226:     * @param date    Storage to represent date/time object.
0227:     *                If null - new object will be created, otherwise
0228:     *                date will be reset and reused
0229:     * @return updated date/time object
0230:     * @exception Exception
0231:     */
0232:    abstract protected int[] parse (String content, int[] date) throws SchemaDateTimeException;
0233:
0234:    /**
0235:     * Validate that a string is a W3C date/time type
0236:     * 
0237:     * @param content string value of date/time
0238:     * @param state
0239:     * @return  
0240:     * @exception InvalidDatatypeValueException
0241:     */
0242:    public Object validate(String content, Object state) throws InvalidDatatypeValueException{
0243:
0244:        try {
0245:            resetDateObj(fDateValue);
0246:            parse(content, fDateValue);
0247:        }
0248:        catch ( RuntimeException e ) {
0249:            throw new InvalidDatatypeValueException("Value '"+content+
0250:                                                    "' is not legal value for current datatype. " +e.getMessage() );
0251:        }
0252:        validateDate (fDateValue, content);
0253:        return null;
0254:    }
0255:
0256:    /**
0257:     * Validates date object against facet and base datatype
0258:     * 
0259:     * @param date    represents date/time obj
0260:     * @param content lexical representation of date/time obj
0261:     * @exception InvalidDatatypeValueException
0262:     */
0263:    protected void validateDate (int[] date, String content) throws InvalidDatatypeValueException{
0264:
0265:        if ( this .fBaseValidator != null ) {//validate against parent type if any
0266:            if ( (fFacetsDefined & DatatypeValidator.FACET_PATTERN ) != 0 ) {
0267:                if ( fRegex == null || fRegex.matches( content) == false )
0268:                    throw new InvalidDatatypeValueException("Value'"+content+
0269:                                                            "' does not match regular expression facet " + fRegex.getPattern() );
0270:            }
0271:            //validate against base type
0272:            ((DateTimeValidator)this .fBaseValidator).validateDate( date, content);
0273:            if ( (fFacetsDefined & DatatypeValidator.FACET_ENUMERATION ) != 0 ) {
0274:                int count=0;
0275:                boolean valid = false;
0276:                while ( count < fEnumSize ) {
0277:                    if ( compareDates(date, (int[])fEnumeration[count], false) == EQUAL ) {
0278:                        valid = true;
0279:                        break;
0280:                    }
0281:                    count++;
0282:                }
0283:                if ( !valid ) {
0284:                    throw new InvalidDatatypeValueException("Value'"+content+
0285:                                                            "' does not match enumeration values" );
0286:                }
0287:            }
0288:
0289:            // REVISIT: output values for facets in error message
0290:            short c;
0291:            if ( fMinInclusive != null ) {
0292:                
0293:                c = compareDates(date, (int[])fMinInclusive, false);
0294:                if ( c == LESS_THAN || c == INDETERMINATE ) {
0295:                    throw new InvalidDatatypeValueException("Value '"+content+
0296:                                                            "' is less than minInclusive: " +dateToString((int[])fMinInclusive) );
0297:                }
0298:            }
0299:            if ( fMinExclusive != null ) {
0300:
0301:                if ( compareDates(date, (int[])fMinExclusive, true) != GREATER_THAN ) {
0302:                    throw new InvalidDatatypeValueException("Value '"+content+
0303:                                                            "' is less than or equal to minExclusive: " +dateToString((int[])fMinExclusive));
0304:                }
0305:            }
0306:
0307:            if ( fMaxInclusive != null ) {
0308:
0309:                c = compareDates(date, (int[])fMaxInclusive, false );
0310:                if ( c  == GREATER_THAN  || c == INDETERMINATE ) {
0311:                    throw new InvalidDatatypeValueException("Value '"+content+
0312:                                                            "' is greater than maxInclusive: " +dateToString((int[])fMaxInclusive) );
0313:                }
0314:            }
0315:
0316:            if ( fMaxExclusive != null ) {
0317:
0318:                if ( compareDates(date, (int[])fMaxExclusive, true ) != LESS_THAN ) {
0319:                    throw new InvalidDatatypeValueException("Value '"+content+
0320:                                                            "' is greater than or equal to maxExlusive: " +dateToString((int[])fMaxExclusive) );
0321:                }
0322:            }
0323:        }
0324:        else {
0325:            return;
0326:        }
0327:
0328:    }
0329:    public int compare( String content1, String content2)  {
0330:        //implement compareDates using the compare() method
0331:        try{        
0332:            parse(content1, fDateValue);
0333:            parse(content2,fTempDate);
0334:            int result = compareDates(fDateValue, fTempDate, true);
0335:            return (result==INDETERMINATE)?-1:result;
0336:        }
0337:        catch ( RuntimeException e ) {
0338:            return -1;
0339:        
0340:        }
0341:    }
0342:
0343:
0344:    public Object clone() throws CloneNotSupportedException {
0345:        throw new CloneNotSupportedException("clone() is not supported in "+this .getClass().getName());
0346:    }
0347:
0348:
0349:
0350:    /**
0351:     * Compare algorithm described in dateDime (3.2.7).
0352:     * Duration datatype overwrites this method
0353:     * 
0354:     * @param date1  normalized date representation of the first value
0355:     * @param date2  normalized date representation of the second value
0356:     * @param strict
0357:     * @return less, greater, less_equal, greater_equal, equal
0358:     */
0359:    protected  short compareDates(int[] date1, int[] date2, boolean strict) {
0360:        if ( date1[utc]==date2[utc] ) {
0361:            return compareOrder(date1, date2);    
0362:        }
0363:        short c1, c2;
0364:
0365:        if ( date1[utc]=='Z' ) {
0366:
0367:            //compare date1<=date1<=(date2 with time zone -14)
0368:            //
0369:            cloneDate(date2); //clones date1 value to global temporary storage: fTempDate
0370:            timeZone[hh]=14;
0371:            timeZone[mm]=0;
0372:            fTempDate[utc]='+';
0373:            normalize(fTempDate);
0374:            c1 = compareOrder(date1, fTempDate);
0375:
0376:            //compare date1>=(date2 with time zone +14)
0377:            //
0378:            cloneDate(date2); //clones date1 value to global temporary storage: fTempDate
0379:            timeZone[hh]=14;
0380:            timeZone[mm]=0;
0381:            fTempDate[utc]='-';
0382:            normalize(fTempDate);
0383:            c2 = compareOrder(date1, fTempDate);
0384:
0385:            if ( (c1==LESS_THAN && c2==GREATER_THAN) ||
0386:                 (c1==GREATER_THAN && c2==LESS_THAN) ) {
0387:                return INDETERMINATE; 
0388:            }
0389:            //REVISIT: wait for clarification on this case from schema
0390:            return(c1!=INDETERMINATE)?c1:c2;
0391:        }
0392:        else if ( date2[utc]=='Z' ) {
0393:
0394:            //compare (date1 with time zone -14)<=date2 
0395:            //
0396:            cloneDate(date1); //clones date1 value to global temporary storage: fTempDate
0397:            timeZone[hh]=14;
0398:            timeZone[mm]=0;
0399:
0400:            fTempDate[utc]='-';
0401:            if (DEBUG) {
0402:               System.out.println("fTempDate=" + dateToString(fTempDate));
0403:            }
0404:            normalize(fTempDate);
0405:            c1 = compareOrder(fTempDate, date2);
0406:            if (DEBUG) {
0407:                System.out.println("date=" + dateToString(date2));
0408:                System.out.println("fTempDate=" + dateToString(fTempDate));
0409:            }
0410:            //compare (date1 with time zone +14)<=date2 
0411:            //
0412:            cloneDate(date1); //clones date1 value to global temporary storage: fTempDate
0413:            timeZone[hh]=14;
0414:            timeZone[mm]=0;
0415:            fTempDate[utc]='+';
0416:            normalize(fTempDate);
0417:            c2 = compareOrder(fTempDate, date2);
0418:            if (DEBUG) {
0419:               System.out.println("fTempDate=" + dateToString(fTempDate));
0420:            }
0421:            if ( (c1==LESS_THAN && c2==GREATER_THAN) ||
0422:                 (c1==GREATER_THAN && c2==LESS_THAN) ) {
0423:                return INDETERMINATE; 
0424:            }
0425:            //REVISIT: wait for clarification on this case from schema
0426:            return(c1!=INDETERMINATE)?c1:c2;
0427:        }
0428:        return INDETERMINATE;
0429:
0430:    }
0431:
0432:
0433:    /**
0434:     * Given normalized values, determines order-relation
0435:     * between give date/time objects.
0436:     * 
0437:     * @param date1  date/time object
0438:     * @param date2  date/time object
0439:     * @return 
0440:     */
0441:    protected short compareOrder (int[] date1, int[] date2) {
0442:        
0443:        for ( int i=0;i<TOTAL_SIZE;i++ ) {
0444:            if ( date1[i]<date2[i] ) {
0445:                return LESS_THAN;
0446:            }
0447:            else if ( date1[i]>date2[i] ) {
0448:                return GREATER_THAN;
0449:            }
0450:        }
0451:        return EQUAL;
0452:    }
0453:
0454:
0455:    /**
0456:     * Parses time hh:mm:ss.sss and time zone if any
0457:     * 
0458:     * @param start
0459:     * @param end
0460:     * @param data
0461:     * @return 
0462:     * @exception Exception
0463:     */
0464:    protected  void getTime (int start, int end, int[] data) throws RuntimeException{
0465:        
0466:        int stop = start+2;
0467:        
0468:        //get hours (hh)
0469:        data[h]=parseInt(start,stop);
0470:
0471:        //get minutes (mm)
0472:
0473:        if (fBuffer.charAt(stop++)!=':') {
0474:                throw new RuntimeException("Error in parsing time zone" );
0475:        }
0476:        start = stop;
0477:        stop = stop+2;
0478:        data[m]=parseInt(start,stop);
0479:
0480:        //get seconds (ss)
0481:        if (fBuffer.charAt(stop++)!=':') {
0482:                throw new RuntimeException("Error in parsing time zone" );
0483:        }
0484:        start = stop;
0485:        stop = stop+2;               
0486:        data[s]=parseInt(start,stop);
0487:
0488:        //get miliseconds (ms)
0489:        int milisec = indexOf(start, end, '.');
0490:
0491:        //find UTC sign if any
0492:        int sign = findUTCSign((milisec!=-1)?milisec:start, end);
0493:
0494:        //parse miliseconds 
0495:        if ( milisec != -1 ) {
0496:
0497:            if ( sign<0 ) {
0498:
0499:                //get all digits after "." 
0500:                data[ms]=parseInt(milisec+1,fEnd);
0501:            }
0502:            else {
0503:
0504:                //get ms before UTC sign
0505:                data[ms]=parseInt(milisec+1,sign);
0506:            }
0507:
0508:        }
0509:
0510:        //parse UTC time zone (hh:mm)        
0511:        if ( sign>0 ) {
0512:            getTimeZone(data,sign);
0513:        }
0514:    }
0515:
0516:
0517:    /**
0518:     * Parses date CCYY-MM-DD
0519:     * 
0520:     * @param start
0521:     * @param end
0522:     * @param data
0523:     * @return 
0524:     * @exception Exception
0525:     */
0526:    protected void getDate (int start, int end, int[] date) throws RuntimeException{
0527:
0528:        getYearMonth(start, end, date);
0529:
0530:        if (fBuffer.charAt(fStart++) !='-') {
0531:            throw new RuntimeException("CCYY-MM must be followed by '-' sign");
0532:        }
0533:        int stop = fStart + 2;
0534:        date[D]=parseInt(fStart, stop);
0535:        fStart = stop;  //fStart points right after the Day
0536:    }
0537:
0538:    /**
0539:     * Parses date CCYY-MM
0540:     * 
0541:     * @param start
0542:     * @param end
0543:     * @param data
0544:     * @return 
0545:     * @exception Exception
0546:     */
0547:    protected void getYearMonth (int start, int end, int[] date) throws RuntimeException{
0548:
0549:        if ( fBuffer.charAt(0)=='-' ) {
0550:            // REVISIT: date starts with preceding '-' sign
0551:            //          do we have to do anything with it?
0552:            //
0553:            start++;
0554:        }
0555:        int i = indexOf(start, end, '-');
0556:        if ( i==-1 ) throw new RuntimeException("Year separator is missing or misplaced");
0557:        date[CY]= parseIntYear(i);
0558:        if (fBuffer.charAt(i)!='-') {
0559:            throw new RuntimeException("CCYY must be followed by '-' sign");
0560:        }
0561:        start = ++i;
0562:        i = start +2;
0563:        date[M]=parseInt(start, i);
0564:        fStart = i; //fStart points right after the MONTH
0565:    }
0566:
0567:
0568:
0569:    /**
0570:     * Shared code from Date and YearMonth datatypes.
0571:     * Finds if time zone sign is present
0572:     * 
0573:     * @param end
0574:     * @param date
0575:     * @return 
0576:     * @exception Exception
0577:     */
0578:    protected void parseTimeZone (int end, int[] date) throws RuntimeException{
0579:
0580:        //fStart points right after the date
0581: 
0582:        if ( fStart<fEnd ) {
0583:            int sign = findUTCSign(fStart, fEnd);
0584:            if ( sign<0 ) {
0585:                throw new RuntimeException ("Error in month parsing");
0586:            }
0587:            else {
0588:                getTimeZone(date, sign);
0589:            }
0590:        }
0591:    }
0592:
0593:    /**
0594:     * Parses time zone: 'Z' or {+,-} followed by  hh:mm
0595:     * 
0596:     * @param data
0597:     * @param sign
0598:     * @return 
0599:     */
0600:    protected void getTimeZone (int[] data, int sign) throws RuntimeException{
0601:        data[utc]=fBuffer.charAt(sign);
0602:
0603:        if ( fBuffer.charAt(sign) == 'Z' ) {
0604:            if (fEnd>(++sign)) {
0605:                throw new RuntimeException("Error in parsing time zone");
0606:            }
0607:            return;
0608:        }
0609:        if ( sign<=(fEnd-6) ) {
0610:             
0611:            //parse [hh]
0612:            int stop = ++sign+2;
0613:            timeZone[hh]=parseInt(sign, stop);
0614:            if (fBuffer.charAt(stop++)!=':') {
0615:                throw new RuntimeException("Error in parsing time zone" );
0616:            }            
0617:            
0618:            //parse [ss]
0619:            timeZone[mm]=parseInt(stop, stop+2);
0620:            
0621:            if ( stop+2!=fEnd ) {
0622:                throw new RuntimeException("Error in parsing time zone");
0623:            }
0624:            
0625:        }
0626:        else {
0627:            throw new RuntimeException("Error in parsing time zone");
0628:        }
0629:        if ( DEBUG ) {
0630:            System.out.println("time[hh]="+timeZone[hh] + " time[mm]=" +timeZone[mm]);
0631:        }
0632:    }
0633:
0634:
0635:
0636:    /**
0637:     * Computes index of given char within StringBuffer
0638:     * 
0639:     * @param start
0640:     * @param end
0641:     * @param ch     character to look for in StringBuffer
0642:     * @return index of ch within StringBuffer
0643:     */
0644:    protected  int indexOf (int start, int end, char ch) {
0645:        for ( int i=start;i<end;i++ ) {
0646:            if ( fBuffer.charAt(i) == ch ) {
0647:                return i;
0648:            }
0649:        }
0650:        return -1;
0651:    }
0652:
0653:
0654:    /**
0655:     * Validates given date/time object accoring to W3C PR Schema 
0656:     * [D.1 ISO 8601 Conventions]
0657:     * 
0658:     * @param data
0659:     * @return 
0660:     */
0661:    protected void validateDateTime (int[]  data) {
0662:
0663:        //REVISIT: should we throw an exception for not valid dates
0664:        //          or reporting an error message should be sufficient?  
0665:        if ( data[CY]==0 ) {
0666:            throw new RuntimeException("The year \"0000\" is an illegal year value");
0667:
0668:        }
0669:
0670:        if ( data[M]<1 || data[M]>12 ) {
0671:            throw new RuntimeException("The month must have values 1 to 12");
0672:
0673:        }
0674:
0675:        //validate days
0676:        if ( data[D]>maxDayInMonthFor(data[CY], data[M]) || data[D]==0 ) {
0677:            throw new RuntimeException("The day must have values 1 to 31");
0678:        }
0679:
0680:        //validate hours
0681:        if ( data[h]>24 || data[h]<0 ||
0682:             (data[h] == 24 && (data[m]!=0 || data[s]!=0 || data[ms]!=0)) ) {
0683:            throw new RuntimeException("Hour must have values 0-24.  If hour is 24, minutes and seconds must both have the value 0.");
0684:        }
0685:
0686:        //validate minutes
0687:        if ( data[m]>59 || data[m]<0 ) {
0688:            throw new RuntimeException("Minute must have values 0-59");
0689:        }
0690:
0691:        //validate seconds
0692:        if ( data[s]>60 || data[s]<0 ) {
0693:            throw new RuntimeException("Second must have values 0-60");
0694:
0695:        }
0696:
0697:        //validate time-zone hours
0698:        if ( Math.abs(timeZone[hh])>14 ||
0699:             (Math.abs(timeZone[hh]) == 14 && timeZone[mm] != 0) ) {
0700:            throw new RuntimeException("Time zone should have range -14..+14");
0701:        }
0702:
0703:        //validate time-zone minutes
0704:        if ( Math.abs(timeZone[mm]) > 59 ) {
0705:            throw new RuntimeException("Minute must have values 0-59");
0706:        }
0707:    }
0708:
0709:
0710:    /**
0711:     * Return index of UTC char: 'Z', '+', '-'
0712:     * 
0713:     * @param start
0714:     * @param end
0715:     * @return 
0716:     */
0717:    protected int findUTCSign (int start, int end) {
0718:        int c;
0719:        for ( int i=start;i<end;i++ ) {
0720:            c=fBuffer.charAt(i);
0721:            if ( c == 'Z' || c=='+' || c=='-' ) {
0722:                return i;
0723:            }
0724:
0725:        }
0726:        return -1;
0727:    }
0728:
0729:
0730:    /**
0731:     * Given start and end position, parses string value
0732:     * 
0733:     * @param value  string to parse
0734:     * @param start  Start position
0735:     * @param end    end position
0736:     * @return  return integer representation of characters
0737:     */
0738:    protected  int parseInt (int start, int end) 
0739:    throws NumberFormatException{ 
0740:        //REVISIT: more testing on this parsing needs to be done.
0741:        int radix=10;
0742:        int result = 0;
0743:        int digit=0;
0744:        int limit = -Integer.MAX_VALUE;
0745:        int multmin = limit / radix;
0746:        int i = start;
0747:        do {
0748:            digit = Character.digit(fBuffer.charAt(i),radix);
0749:            if ( digit < 0 ) throw new NumberFormatException("'"+fBuffer.toString()+"' has wrong format");
0750:            if ( result < multmin ) throw new NumberFormatException("'"+fBuffer.toString()+"' has wrong format");
0751:            result *= radix;
0752:            if ( result < limit + digit ) throw new NumberFormatException("'"+fBuffer.toString()+"' has wrong format");
0753:            result -= digit;
0754:
0755:        }while ( ++i < end );
0756:        return -result;
0757:    }
0758:
0759:    // parse Year differently to support negative value.
0760:    protected int parseIntYear (int end){
0761:        int radix=10;
0762:        int result = 0;
0763:        boolean negative = false;
0764:        int i=0;
0765:        int limit;
0766:        int multmin;
0767:        int digit=0;
0768:
0769:        if (fBuffer.charAt(0) == '-'){
0770:            negative = true;
0771:            limit = Integer.MIN_VALUE;
0772:            i++;
0773:        } 
0774:        else{
0775:            limit = -Integer.MAX_VALUE;
0776:        }
0777:
0778:        int length = end-i;
0779:        if (length<4 ||
0780:            (length > 4 && fBuffer.charAt(i)=='0')) {
0781:            throw new RuntimeException("Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden.");
0782:        }
0783:
0784:        multmin = limit / radix;
0785:        while (i < end)
0786:        {
0787:            digit = Character.digit(fBuffer.charAt(i++),radix);
0788:            if (digit < 0) throw new NumberFormatException("'"+fBuffer.toString()+"' has wrong format");
0789:            if (result < multmin) throw new NumberFormatException("'"+fBuffer.toString()+"' has wrong format");
0790:            result *= radix;
0791:            if (result < limit + digit) throw new NumberFormatException("'"+fBuffer.toString()+"' has wrong format");
0792:            result -= digit;
0793:        }
0794:
0795:        if (negative)
0796:        {
0797:            if (i > 1) return result;
0798:            else throw new NumberFormatException("'"+fBuffer.toString()+"' has wrong format");
0799:        }
0800:        return -result;
0801:
0802:
0803:
0804:    }
0805:
0806:    /**
0807:     * normalize dateTime  [E Adding durations to dateTimes]
0808:     * If timezone present - normalize to UTC
0809:     * If hour is 24 - normalize to start of following day
0810:     * 
0811:     * @param date   CCYY-MM-DDThh:mm:ss+03
0812:     * @return CCYY-MM-DDThh:mm:ssZ
0813:     */
0814:    protected  void normalize (int[] date) {
0815:
0816:        // REVISIT: we have common code in addDuration() for durations
0817:        //          should consider reorganizing it.
0818:        //
0819:
0820:        //add minutes (from time zone)
0821:        int negate = 1;
0822:        if (date[utc]=='+') {
0823:            negate = -1;
0824:        }
0825:        if ( DEBUG ) {
0826:            System.out.println("==>date[m]"+date[m]);
0827:            System.out.println("==>timeZone[mm]" +timeZone[mm]);
0828:        }
0829:        int temp = date[m] + negate*timeZone[mm];
0830:        int carry = fQuotient (temp, 60);
0831:        date[m]= mod(temp, 60, carry);
0832:        
0833:        if ( DEBUG ) {
0834:            System.out.println("==>carry: " + carry);
0835:        }
0836:        //add hours
0837:        temp = date[h] + negate*timeZone[hh] + carry;
0838:        carry = fQuotient(temp, 24);
0839:        date[h]=mod(temp, 24, carry);
0840:        if ( DEBUG ) {
0841:            System.out.println("==>date[h]"+date[h]);
0842:            System.out.println("==>carry: " + carry);
0843:        }
0844:
0845:        date[D]=date[D]+carry;
0846:
0847:        while ( true ) {
0848:            temp=maxDayInMonthFor(date[CY], date[M]);
0849:            if (date[D]<1) {
0850:                date[D] = date[D] + maxDayInMonthFor(date[CY], date[M]-1);
0851:                carry=-1;
0852:            }
0853:            else if ( date[D]>temp ) {
0854:                date[D]=date[D]-temp;
0855:                carry=1;
0856:            }
0857:            else {
0858:                break;
0859:            }
0860:            temp=date[M]+carry;
0861:            date[M]=modulo(temp, 1, 13);
0862:            date[CY]=date[CY]+fQuotient(temp, 1, 13);
0863:        }
0864:
0865:        if (date[utc] != 0) {
0866:            date[utc]='Z';
0867:        }
0868:    }
0869:
0870:
0871:    /**
0872:     * Resets fBuffer to store string representation of 
0873:     * date/time
0874:     * 
0875:     * @param str    Lexical representation of date/time
0876:     */
0877:    protected void resetBuffer (String str) {
0878:        fBuffer.setLength(0);
0879:        fStart=fEnd=0;
0880:        timeZone[hh]=timeZone[mm]=0;
0881:        fBuffer.append(str);
0882:        fEnd = fBuffer.length();
0883:        
0884:    }
0885:
0886:
0887:    /**
0888:     * Resets object representation of date/time
0889:     * 
0890:     * @param data   date/time object
0891:     */
0892:    protected void resetDateObj (int[] data) {
0893:        for ( int i=0;i<TOTAL_SIZE;i++ ) {
0894:            data[i]=0;
0895:        }
0896:    }
0897:
0898:
0899:    /**
0900:     * Given {year,month} computes maximum 
0901:     * number of days for given month
0902:     * 
0903:     * @param year
0904:     * @param month
0905:     * @return 
0906:     */
0907:    protected int maxDayInMonthFor(int year, int month) {
0908:        //validate days
0909:        if ( month==4 || month==6 || month==9 || month==11 ) {
0910:            return 30;
0911:        }
0912:        else if ( month==2 ) {
0913:            if ( isLeapYear(year) ) {
0914:                return 29;
0915:            }
0916:            else {
0917:                return 28;
0918:            }
0919:        }
0920:        else {
0921:            return 31;
0922:        }
0923:    }
0924:
0925:
0926:    private boolean isLeapYear(int year) {
0927:        return((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))); 
0928:    }
0929:
0930:    //
0931:    // help function described in W3C PR Schema [E Adding durations to dateTimes]
0932:    //    
0933:    protected int mod (int a, int b, int quotient) {
0934:        //modulo(a, b) = a - fQuotient(a,b)*b 
0935:        return (a - quotient*b) ;
0936:    }
0937:    
0938:    //
0939:    // help function described in W3C PR Schema [E Adding durations to dateTimes]
0940:    //
0941:    protected int fQuotient (int a, int b) {
0942:        
0943:        //fQuotient(a, b) = the greatest integer less than or equal to a/b 
0944:        return (int)Math.floor((float)a/b);
0945:    }
0946:
0947:    //
0948:    // help function described in W3C PR Schema [E Adding durations to dateTimes]
0949:    //    
0950:    protected int modulo (int temp, int low, int high) {
0951:        //modulo(a - low, high - low) + low 
0952:        int a = temp - low;
0953:        int b = high - low;
0954:        return (mod (a, b, fQuotient(a, b)) + low) ;
0955:    }
0956:
0957:    //
0958:    // help function described in W3C PR Schema [E Adding durations to dateTimes]
0959:    //
0960:    protected int fQuotient (int temp, int low, int high) {
0961:        //fQuotient(a - low, high - low) 
0962:  
0963:        return fQuotient(temp - low, high - low);
0964:    }
0965:
0966:
0967:    protected String dateToString(int[] date) {
0968:        message.setLength(0);
0969:        message.append(date[CY]);
0970:        message.append('-');
0971:        message.append(date[M]);
0972:        message.append('-');
0973:        message.append(date[D]);
0974:        message.append('T');
0975:        message.append(date[h]);
0976:        message.append(':');
0977:        message.append(date[m]);
0978:        message.append(':');
0979:        message.append(date[s]);
0980:        message.append('.');
0981:        message.append(date[ms]);
0982:        message.append((char)date[utc]);
0983:        return message.toString();
0984:    }
0985:
0986:
0987:    /**
0988:     * Use this function to report errors in constructor
0989:     * 
0990:     * @param msg
0991:     * @param value
0992:     */
0993:    protected void reportError(String msg, String value) {
0994:        System.err.println("[Error]: " +msg+": Value  '"+value+"' is not legal for current datatype");
0995:    }
0996:
0997:
0998:    //
0999:    //Private help functions
1000:    //
1001:
1002:    private void cloneDate (int[] finalValue) {
1003:        resetDateObj(fTempDate);
1004:        for ( int i=0;i<TOTAL_SIZE;i++ ) {
1005:            fTempDate[i]=finalValue[i];
1006:        }
1007:    }
1008:
1009:}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.