Source Code Cross Referenced for AbstractDateTimeDV.java in  » XML » xerces-2_9_1 » org » apache » xerces » impl » dv » xs » 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 » XML » xerces 2_9_1 » org.apache.xerces.impl.dv.xs 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        package org.apache.xerces.impl.dv.xs;
0019:
0020:        import javax.xml.datatype.DatatypeFactory;
0021:        import javax.xml.datatype.Duration;
0022:        import javax.xml.datatype.XMLGregorianCalendar;
0023:
0024:        import org.apache.xerces.impl.Constants;
0025:        import org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl;
0026:        import org.apache.xerces.xs.datatypes.XSDateTime;
0027:
0028:        /**
0029:         * This is the base class of all date/time datatype validators.
0030:         * It implements common code for parsing, validating and comparing datatypes.
0031:         * Classes that extend this class, must implement parse() method.
0032:         *
0033:         * REVISIT: There are many instance variables, which would cause problems
0034:         *          when we support grammar caching. A grammar is possibly used by
0035:         *          two parser instances at the same time, then the same simple type
0036:         *          decl object can be used to validate two strings at the same time.
0037:         *          -SG
0038:         *          
0039:         * @xerces.internal 
0040:         *
0041:         * @author Elena Litani
0042:         * @author Len Berman
0043:         * @author Gopal Sharma, SUN Microsystems Inc.
0044:         *
0045:         * @version $Id: AbstractDateTimeDV.java 572095 2007-09-02 18:32:43Z mrglavas $
0046:         */
0047:        public abstract class AbstractDateTimeDV extends TypeValidator {
0048:
0049:            //debugging
0050:            private static final boolean DEBUG = false;
0051:
0052:            //define shared variables for date/time
0053:
0054:            //define constants to be used in assigning default values for
0055:            //all date/time excluding duration
0056:            protected final static int YEAR = 2000;
0057:            protected final static int MONTH = 01;
0058:            protected final static int DAY = 01;
0059:
0060:            protected final DatatypeFactory factory = new DatatypeFactoryImpl();
0061:
0062:            public short getAllowedFacets() {
0063:                return (XSSimpleTypeDecl.FACET_PATTERN
0064:                        | XSSimpleTypeDecl.FACET_WHITESPACE
0065:                        | XSSimpleTypeDecl.FACET_ENUMERATION
0066:                        | XSSimpleTypeDecl.FACET_MAXINCLUSIVE
0067:                        | XSSimpleTypeDecl.FACET_MININCLUSIVE
0068:                        | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE);
0069:            }//getAllowedFacets()
0070:
0071:            // distinguishes between identity and equality for date/time values
0072:            // ie: two values representing the same "moment in time" but with different 
0073:            // remembered timezones are now equal but not identical.
0074:            public boolean isIdentical(Object value1, Object value2) {
0075:                if (!(value1 instanceof  DateTimeData)
0076:                        || !(value2 instanceof  DateTimeData)) {
0077:                    return false;
0078:                }
0079:
0080:                DateTimeData v1 = (DateTimeData) value1;
0081:                DateTimeData v2 = (DateTimeData) value2;
0082:
0083:                // original timezones must be the same in addition to date/time values
0084:                // being 'equal'
0085:                if ((v1.timezoneHr == v2.timezoneHr)
0086:                        && (v1.timezoneMin == v2.timezoneMin)) {
0087:                    return v1.equals(v2);
0088:                }
0089:
0090:                return false;
0091:            }//isIdentical()
0092:
0093:            // the parameters are in compiled form (from getActualValue)
0094:            public int compare(Object value1, Object value2) {
0095:                return compareDates(((DateTimeData) value1),
0096:                        ((DateTimeData) value2), true);
0097:            }//compare()
0098:
0099:            /**
0100:             * Compare algorithm described in dateDime (3.2.7).
0101:             * Duration datatype overwrites this method
0102:             *
0103:             * @param date1  normalized date representation of the first value
0104:             * @param date2  normalized date representation of the second value
0105:             * @param strict
0106:             * @return less, greater, less_equal, greater_equal, equal
0107:             */
0108:            protected short compareDates(DateTimeData date1,
0109:                    DateTimeData date2, boolean strict) {
0110:                if (date1.utc == date2.utc) {
0111:                    return compareOrder(date1, date2);
0112:                }
0113:                short c1, c2;
0114:
0115:                DateTimeData tempDate = new DateTimeData(null, this );
0116:
0117:                if (date1.utc == 'Z') {
0118:
0119:                    //compare date1<=date1<=(date2 with time zone -14)
0120:                    //
0121:                    cloneDate(date2, tempDate); //clones date1 value to global temporary storage: fTempDate
0122:                    tempDate.timezoneHr = 14;
0123:                    tempDate.timezoneMin = 0;
0124:                    tempDate.utc = '+';
0125:                    normalize(tempDate);
0126:                    c1 = compareOrder(date1, tempDate);
0127:                    if (c1 == LESS_THAN)
0128:                        return c1;
0129:
0130:                    //compare date1>=(date2 with time zone +14)
0131:                    //
0132:                    cloneDate(date2, tempDate); //clones date1 value to global temporary storage: tempDate
0133:                    tempDate.timezoneHr = -14;
0134:                    tempDate.timezoneMin = 0;
0135:                    tempDate.utc = '-';
0136:                    normalize(tempDate);
0137:                    c2 = compareOrder(date1, tempDate);
0138:                    if (c2 == GREATER_THAN)
0139:                        return c2;
0140:
0141:                    return INDETERMINATE;
0142:                } else if (date2.utc == 'Z') {
0143:
0144:                    //compare (date1 with time zone -14)<=date2
0145:                    //
0146:                    cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate
0147:                    tempDate.timezoneHr = -14;
0148:                    tempDate.timezoneMin = 0;
0149:                    tempDate.utc = '-';
0150:                    if (DEBUG) {
0151:                        System.out
0152:                                .println("tempDate=" + dateToString(tempDate));
0153:                    }
0154:                    normalize(tempDate);
0155:                    c1 = compareOrder(tempDate, date2);
0156:                    if (DEBUG) {
0157:                        System.out.println("date=" + dateToString(date2));
0158:                        System.out
0159:                                .println("tempDate=" + dateToString(tempDate));
0160:                    }
0161:                    if (c1 == LESS_THAN)
0162:                        return c1;
0163:
0164:                    //compare (date1 with time zone +14)<=date2
0165:                    //
0166:                    cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate
0167:                    tempDate.timezoneHr = 14;
0168:                    tempDate.timezoneMin = 0;
0169:                    tempDate.utc = '+';
0170:                    normalize(tempDate);
0171:                    c2 = compareOrder(tempDate, date2);
0172:                    if (DEBUG) {
0173:                        System.out
0174:                                .println("tempDate=" + dateToString(tempDate));
0175:                    }
0176:                    if (c2 == GREATER_THAN)
0177:                        return c2;
0178:
0179:                    return INDETERMINATE;
0180:                }
0181:                return INDETERMINATE;
0182:
0183:            }
0184:
0185:            /**
0186:             * Given normalized values, determines order-relation
0187:             * between give date/time objects.
0188:             *
0189:             * @param date1  date/time object
0190:             * @param date2  date/time object
0191:             * @return 0 if date1 and date2 are equal, a value less than 0 if date1 is less than date2, a value greater than 0 if date1 is greater than date2
0192:             */
0193:            protected short compareOrder(DateTimeData date1, DateTimeData date2) {
0194:                if (date1.position < 1) {
0195:                    if (date1.year < date2.year)
0196:                        return -1;
0197:                    if (date1.year > date2.year)
0198:                        return 1;
0199:                }
0200:                if (date1.position < 2) {
0201:                    if (date1.month < date2.month)
0202:                        return -1;
0203:                    if (date1.month > date2.month)
0204:                        return 1;
0205:                }
0206:                if (date1.day < date2.day)
0207:                    return -1;
0208:                if (date1.day > date2.day)
0209:                    return 1;
0210:                if (date1.hour < date2.hour)
0211:                    return -1;
0212:                if (date1.hour > date2.hour)
0213:                    return 1;
0214:                if (date1.minute < date2.minute)
0215:                    return -1;
0216:                if (date1.minute > date2.minute)
0217:                    return 1;
0218:                if (date1.second < date2.second)
0219:                    return -1;
0220:                if (date1.second > date2.second)
0221:                    return 1;
0222:                if (date1.utc < date2.utc)
0223:                    return -1;
0224:                if (date1.utc > date2.utc)
0225:                    return 1;
0226:                return 0;
0227:            }
0228:
0229:            /**
0230:             * Parses time hh:mm:ss.sss and time zone if any
0231:             *
0232:             * @param start
0233:             * @param end
0234:             * @param data
0235:             * @exception RuntimeException
0236:             */
0237:            protected void getTime(String buffer, int start, int end,
0238:                    DateTimeData data) throws RuntimeException {
0239:
0240:                int stop = start + 2;
0241:
0242:                //get hours (hh)
0243:                data.hour = parseInt(buffer, start, stop);
0244:
0245:                //get minutes (mm)
0246:
0247:                if (buffer.charAt(stop++) != ':') {
0248:                    throw new RuntimeException("Error in parsing time zone");
0249:                }
0250:                start = stop;
0251:                stop = stop + 2;
0252:                data.minute = parseInt(buffer, start, stop);
0253:
0254:                //get seconds (ss)
0255:                if (buffer.charAt(stop++) != ':') {
0256:                    throw new RuntimeException("Error in parsing time zone");
0257:                }
0258:
0259:                //find UTC sign if any
0260:                int sign = findUTCSign(buffer, start, end);
0261:
0262:                //get seconds (ms)
0263:                start = stop;
0264:                stop = sign < 0 ? end : sign;
0265:                data.second = parseSecond(buffer, start, stop);
0266:
0267:                //parse UTC time zone (hh:mm)
0268:                if (sign > 0) {
0269:                    getTimeZone(buffer, data, sign, end);
0270:                }
0271:            }
0272:
0273:            /**
0274:             * Parses date CCYY-MM-DD
0275:             *
0276:             * @param buffer
0277:             * @param start start position
0278:             * @param end end position
0279:             * @param date
0280:             * @exception RuntimeException
0281:             */
0282:            protected int getDate(String buffer, int start, int end,
0283:                    DateTimeData date) throws RuntimeException {
0284:
0285:                start = getYearMonth(buffer, start, end, date);
0286:
0287:                if (buffer.charAt(start++) != '-') {
0288:                    throw new RuntimeException(
0289:                            "CCYY-MM must be followed by '-' sign");
0290:                }
0291:                int stop = start + 2;
0292:                date.day = parseInt(buffer, start, stop);
0293:                return stop;
0294:            }
0295:
0296:            /**
0297:             * Parses date CCYY-MM
0298:             *
0299:             * @param buffer
0300:             * @param start start position
0301:             * @param end end position
0302:             * @param date
0303:             * @exception RuntimeException
0304:             */
0305:            protected int getYearMonth(String buffer, int start, int end,
0306:                    DateTimeData date) throws RuntimeException {
0307:
0308:                if (buffer.charAt(0) == '-') {
0309:                    // REVISIT: date starts with preceding '-' sign
0310:                    //          do we have to do anything with it?
0311:                    //
0312:                    start++;
0313:                }
0314:                int i = indexOf(buffer, start, end, '-');
0315:                if (i == -1)
0316:                    throw new RuntimeException(
0317:                            "Year separator is missing or misplaced");
0318:                int length = i - start;
0319:                if (length < 4) {
0320:                    throw new RuntimeException("Year must have 'CCYY' format");
0321:                } else if (length > 4 && buffer.charAt(start) == '0') {
0322:                    throw new RuntimeException(
0323:                            "Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden");
0324:                }
0325:                date.year = parseIntYear(buffer, i);
0326:                if (buffer.charAt(i) != '-') {
0327:                    throw new RuntimeException(
0328:                            "CCYY must be followed by '-' sign");
0329:                }
0330:                start = ++i;
0331:                i = start + 2;
0332:                date.month = parseInt(buffer, start, i);
0333:                return i; //fStart points right after the MONTH
0334:            }
0335:
0336:            /**
0337:             * Shared code from Date and YearMonth datatypes.
0338:             * Finds if time zone sign is present
0339:             *
0340:             * @param end
0341:             * @param date
0342:             * @exception RuntimeException
0343:             */
0344:            protected void parseTimeZone(String buffer, int start, int end,
0345:                    DateTimeData date) throws RuntimeException {
0346:
0347:                //fStart points right after the date
0348:
0349:                if (start < end) {
0350:                    if (!isNextCharUTCSign(buffer, start, end)) {
0351:                        throw new RuntimeException("Error in month parsing");
0352:                    } else {
0353:                        getTimeZone(buffer, date, start, end);
0354:                    }
0355:                }
0356:            }
0357:
0358:            /**
0359:             * Parses time zone: 'Z' or {+,-} followed by  hh:mm
0360:             *
0361:             * @param data
0362:             * @param sign
0363:             * @exception RuntimeException
0364:             */
0365:            protected void getTimeZone(String buffer, DateTimeData data,
0366:                    int sign, int end) throws RuntimeException {
0367:                data.utc = buffer.charAt(sign);
0368:
0369:                if (buffer.charAt(sign) == 'Z') {
0370:                    if (end > (++sign)) {
0371:                        throw new RuntimeException("Error in parsing time zone");
0372:                    }
0373:                    return;
0374:                }
0375:                if (sign <= (end - 6)) {
0376:
0377:                    int negate = buffer.charAt(sign) == '-' ? -1 : 1;
0378:                    //parse hr
0379:                    int stop = ++sign + 2;
0380:                    data.timezoneHr = negate * parseInt(buffer, sign, stop);
0381:                    if (buffer.charAt(stop++) != ':') {
0382:                        throw new RuntimeException("Error in parsing time zone");
0383:                    }
0384:
0385:                    //parse min
0386:                    data.timezoneMin = negate
0387:                            * parseInt(buffer, stop, stop + 2);
0388:
0389:                    if (stop + 2 != end) {
0390:                        throw new RuntimeException("Error in parsing time zone");
0391:                    }
0392:                    if (data.timezoneHr != 0 || data.timezoneMin != 0)
0393:                        data.normalized = false;
0394:                } else {
0395:                    throw new RuntimeException("Error in parsing time zone");
0396:                }
0397:                if (DEBUG) {
0398:                    System.out.println("time[hh]=" + data.timezoneHr
0399:                            + " time[mm]=" + data.timezoneMin);
0400:                }
0401:            }
0402:
0403:            /**
0404:             * Computes index of given char within StringBuffer
0405:             *
0406:             * @param start
0407:             * @param end
0408:             * @param ch     character to look for in StringBuffer
0409:             * @return index of ch within StringBuffer
0410:             */
0411:            protected int indexOf(String buffer, int start, int end, char ch) {
0412:                for (int i = start; i < end; i++) {
0413:                    if (buffer.charAt(i) == ch) {
0414:                        return i;
0415:                    }
0416:                }
0417:                return -1;
0418:            }
0419:
0420:            /**
0421:             * Validates given date/time object accoring to W3C PR Schema
0422:             * [D.1 ISO 8601 Conventions]
0423:             *
0424:             * @param data
0425:             */
0426:            protected void validateDateTime(DateTimeData data) {
0427:
0428:                //REVISIT: should we throw an exception for not valid dates
0429:                //          or reporting an error message should be sufficient?
0430:
0431:                /**
0432:                 * XML Schema 1.1 - RQ-123: Allow year 0000 in date related types.
0433:                 */
0434:                if (!Constants.SCHEMA_1_1_SUPPORT && data.year == 0) {
0435:                    throw new RuntimeException(
0436:                            "The year \"0000\" is an illegal year value");
0437:
0438:                }
0439:
0440:                if (data.month < 1 || data.month > 12) {
0441:                    throw new RuntimeException(
0442:                            "The month must have values 1 to 12");
0443:
0444:                }
0445:
0446:                //validate days
0447:                if (data.day > maxDayInMonthFor(data.year, data.month)
0448:                        || data.day < 1) {
0449:                    throw new RuntimeException(
0450:                            "The day must have values 1 to 31");
0451:                }
0452:
0453:                //validate hours
0454:                if (data.hour > 23 || data.hour < 0) {
0455:                    if (data.hour == 24 && data.minute == 0 && data.second == 0) {
0456:                        data.hour = 0;
0457:                        if (++data.day > maxDayInMonthFor(data.year, data.month)) {
0458:                            data.day = 1;
0459:                            if (++data.month > 12) {
0460:                                data.month = 1;
0461:                                if (Constants.SCHEMA_1_1_SUPPORT) {
0462:                                    ++data.year;
0463:                                } else if (++data.year == 0) {
0464:                                    data.year = 1;
0465:                                }
0466:                            }
0467:                        }
0468:                    } else {
0469:                        throw new RuntimeException(
0470:                                "Hour must have values 0-23, unless 24:00:00");
0471:                    }
0472:                }
0473:
0474:                //validate
0475:                if (data.minute > 59 || data.minute < 0) {
0476:                    throw new RuntimeException("Minute must have values 0-59");
0477:                }
0478:
0479:                //validate
0480:                if (data.second >= 60 || data.second < 0) {
0481:                    throw new RuntimeException("Second must have values 0-59");
0482:
0483:                }
0484:
0485:                //validate
0486:                if (data.timezoneHr > 14 || data.timezoneHr < -14) {
0487:                    throw new RuntimeException(
0488:                            "Time zone should have range -14:00 to +14:00");
0489:                } else {
0490:                    if ((data.timezoneHr == 14 || data.timezoneHr == -14)
0491:                            && data.timezoneMin != 0)
0492:                        throw new RuntimeException(
0493:                                "Time zone should have range -14:00 to +14:00");
0494:                    else if (data.timezoneMin > 59 || data.timezoneMin < -59)
0495:                        throw new RuntimeException(
0496:                                "Minute must have values 0-59");
0497:                }
0498:
0499:            }
0500:
0501:            /**
0502:             * Return index of UTC char: 'Z', '+', '-'
0503:             *
0504:             * @param start
0505:             * @param end
0506:             * @return index of the UTC character that was found
0507:             */
0508:            protected int findUTCSign(String buffer, int start, int end) {
0509:                int c;
0510:                for (int i = start; i < end; i++) {
0511:                    c = buffer.charAt(i);
0512:                    if (c == 'Z' || c == '+' || c == '-') {
0513:                        return i;
0514:                    }
0515:
0516:                }
0517:                return -1;
0518:            }
0519:
0520:            /**
0521:             * Returns <code>true</code> if the character at start is 'Z', '+' or '-'.
0522:             */
0523:            protected final boolean isNextCharUTCSign(String buffer, int start,
0524:                    int end) {
0525:                if (start < end) {
0526:                    char c = buffer.charAt(start);
0527:                    return (c == 'Z' || c == '+' || c == '-');
0528:                }
0529:                return false;
0530:            }
0531:
0532:            /**
0533:             * Given start and end position, parses string value
0534:             *
0535:             * @param buffer string to parse
0536:             * @param start  start position
0537:             * @param end    end position
0538:             * @return  return integer representation of characters
0539:             */
0540:            protected int parseInt(String buffer, int start, int end)
0541:                    throws NumberFormatException {
0542:                //REVISIT: more testing on this parsing needs to be done.
0543:                int radix = 10;
0544:                int result = 0;
0545:                int digit = 0;
0546:                int limit = -Integer.MAX_VALUE;
0547:                int multmin = limit / radix;
0548:                int i = start;
0549:                do {
0550:                    digit = getDigit(buffer.charAt(i));
0551:                    if (digit < 0)
0552:                        throw new NumberFormatException("'" + buffer
0553:                                + "' has wrong format");
0554:                    if (result < multmin)
0555:                        throw new NumberFormatException("'" + buffer
0556:                                + "' has wrong format");
0557:                    result *= radix;
0558:                    if (result < limit + digit)
0559:                        throw new NumberFormatException("'" + buffer
0560:                                + "' has wrong format");
0561:                    result -= digit;
0562:
0563:                } while (++i < end);
0564:                return -result;
0565:            }
0566:
0567:            // parse Year differently to support negative value.
0568:            protected int parseIntYear(String buffer, int end) {
0569:                int radix = 10;
0570:                int result = 0;
0571:                boolean negative = false;
0572:                int i = 0;
0573:                int limit;
0574:                int multmin;
0575:                int digit = 0;
0576:
0577:                if (buffer.charAt(0) == '-') {
0578:                    negative = true;
0579:                    limit = Integer.MIN_VALUE;
0580:                    i++;
0581:
0582:                } else {
0583:                    limit = -Integer.MAX_VALUE;
0584:                }
0585:                multmin = limit / radix;
0586:                while (i < end) {
0587:                    digit = getDigit(buffer.charAt(i++));
0588:                    if (digit < 0)
0589:                        throw new NumberFormatException("'" + buffer
0590:                                + "' has wrong format");
0591:                    if (result < multmin)
0592:                        throw new NumberFormatException("'" + buffer
0593:                                + "' has wrong format");
0594:                    result *= radix;
0595:                    if (result < limit + digit)
0596:                        throw new NumberFormatException("'" + buffer
0597:                                + "' has wrong format");
0598:                    result -= digit;
0599:                }
0600:
0601:                if (negative) {
0602:                    if (i > 1)
0603:                        return result;
0604:                    else
0605:                        throw new NumberFormatException("'" + buffer
0606:                                + "' has wrong format");
0607:                }
0608:                return -result;
0609:
0610:            }
0611:
0612:            /**
0613:             * If timezone present - normalize dateTime  [E Adding durations to dateTimes]
0614:             *
0615:             * @param date   CCYY-MM-DDThh:mm:ss+03
0616:             */
0617:            protected void normalize(DateTimeData date) {
0618:
0619:                // REVISIT: we have common code in addDuration() for durations
0620:                //          should consider reorganizing it.
0621:                //
0622:
0623:                //add minutes (from time zone)
0624:                int negate = -1;
0625:
0626:                if (DEBUG) {
0627:                    System.out.println("==>date.minute" + date.minute);
0628:                    System.out
0629:                            .println("==>date.timezoneMin" + date.timezoneMin);
0630:                }
0631:                int temp = date.minute + negate * date.timezoneMin;
0632:                int carry = fQuotient(temp, 60);
0633:                date.minute = mod(temp, 60, carry);
0634:
0635:                if (DEBUG) {
0636:                    System.out.println("==>carry: " + carry);
0637:                }
0638:                //add hours
0639:                temp = date.hour + negate * date.timezoneHr + carry;
0640:                carry = fQuotient(temp, 24);
0641:                date.hour = mod(temp, 24, carry);
0642:                if (DEBUG) {
0643:                    System.out.println("==>date.hour" + date.hour);
0644:                    System.out.println("==>carry: " + carry);
0645:                }
0646:
0647:                date.day = date.day + carry;
0648:
0649:                while (true) {
0650:                    temp = maxDayInMonthFor(date.year, date.month);
0651:                    if (date.day < 1) {
0652:                        date.day = date.day
0653:                                + maxDayInMonthFor(date.year, date.month - 1);
0654:                        carry = -1;
0655:                    } else if (date.day > temp) {
0656:                        date.day = date.day - temp;
0657:                        carry = 1;
0658:                    } else {
0659:                        break;
0660:                    }
0661:                    temp = date.month + carry;
0662:                    date.month = modulo(temp, 1, 13);
0663:                    date.year = date.year + fQuotient(temp, 1, 13);
0664:                    if (date.year == 0 && !Constants.SCHEMA_1_1_SUPPORT) {
0665:                        date.year = (date.timezoneHr < 0 || date.timezoneMin < 0) ? 1
0666:                                : -1;
0667:                    }
0668:                }
0669:                date.utc = 'Z';
0670:            }
0671:
0672:            /**
0673:             * @param date
0674:             */
0675:            protected void saveUnnormalized(DateTimeData date) {
0676:                date.unNormYear = date.year;
0677:                date.unNormMonth = date.month;
0678:                date.unNormDay = date.day;
0679:                date.unNormHour = date.hour;
0680:                date.unNormMinute = date.minute;
0681:                date.unNormSecond = date.second;
0682:            }
0683:
0684:            /**
0685:             * Resets object representation of date/time
0686:             *
0687:             * @param data   date/time object
0688:             */
0689:            protected void resetDateObj(DateTimeData data) {
0690:                data.year = 0;
0691:                data.month = 0;
0692:                data.day = 0;
0693:                data.hour = 0;
0694:                data.minute = 0;
0695:                data.second = 0;
0696:                data.utc = 0;
0697:                data.timezoneHr = 0;
0698:                data.timezoneMin = 0;
0699:            }
0700:
0701:            /**
0702:             * Given {year,month} computes maximum
0703:             * number of days for given month
0704:             *
0705:             * @param year
0706:             * @param month
0707:             * @return integer containg the number of days in a given month
0708:             */
0709:            protected int maxDayInMonthFor(int year, int month) {
0710:                //validate days
0711:                if (month == 4 || month == 6 || month == 9 || month == 11) {
0712:                    return 30;
0713:                } else if (month == 2) {
0714:                    if (isLeapYear(year)) {
0715:                        return 29;
0716:                    } else {
0717:                        return 28;
0718:                    }
0719:                } else {
0720:                    return 31;
0721:                }
0722:            }
0723:
0724:            private boolean isLeapYear(int year) {
0725:
0726:                //REVISIT: should we take care about Julian calendar?
0727:                return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)));
0728:            }
0729:
0730:            //
0731:            // help function described in W3C PR Schema [E Adding durations to dateTimes]
0732:            //
0733:            protected int mod(int a, int b, int quotient) {
0734:                //modulo(a, b) = a - fQuotient(a,b)*b
0735:                return (a - quotient * b);
0736:            }
0737:
0738:            //
0739:            // help function described in W3C PR Schema [E Adding durations to dateTimes]
0740:            //
0741:            protected int fQuotient(int a, int b) {
0742:
0743:                //fQuotient(a, b) = the greatest integer less than or equal to a/b
0744:                return (int) Math.floor((float) a / b);
0745:            }
0746:
0747:            //
0748:            // help function described in W3C PR Schema [E Adding durations to dateTimes]
0749:            //
0750:            protected int modulo(int temp, int low, int high) {
0751:                //modulo(a - low, high - low) + low
0752:                int a = temp - low;
0753:                int b = high - low;
0754:                return (mod(a, b, fQuotient(a, b)) + low);
0755:            }
0756:
0757:            //
0758:            // help function described in W3C PR Schema [E Adding durations to dateTimes]
0759:            //
0760:            protected int fQuotient(int temp, int low, int high) {
0761:                //fQuotient(a - low, high - low)
0762:
0763:                return fQuotient(temp - low, high - low);
0764:            }
0765:
0766:            protected String dateToString(DateTimeData date) {
0767:                StringBuffer message = new StringBuffer(25);
0768:                append(message, date.year, 4);
0769:                message.append('-');
0770:                append(message, date.month, 2);
0771:                message.append('-');
0772:                append(message, date.day, 2);
0773:                message.append('T');
0774:                append(message, date.hour, 2);
0775:                message.append(':');
0776:                append(message, date.minute, 2);
0777:                message.append(':');
0778:                append(message, date.second);
0779:                append(message, (char) date.utc, 0);
0780:                return message.toString();
0781:            }
0782:
0783:            protected final void append(StringBuffer message, int value, int nch) {
0784:                if (value == Integer.MIN_VALUE) {
0785:                    message.append(value);
0786:                    return;
0787:                }
0788:                if (value < 0) {
0789:                    message.append('-');
0790:                    value = -value;
0791:                }
0792:                if (nch == 4) {
0793:                    if (value < 10)
0794:                        message.append("000");
0795:                    else if (value < 100)
0796:                        message.append("00");
0797:                    else if (value < 1000)
0798:                        message.append("0");
0799:                    message.append(value);
0800:                } else if (nch == 2) {
0801:                    if (value < 10)
0802:                        message.append('0');
0803:                    message.append(value);
0804:                } else {
0805:                    if (value != 0)
0806:                        message.append((char) value);
0807:                }
0808:            }
0809:
0810:            protected final void append(StringBuffer message, double value) {
0811:                if (value < 0) {
0812:                    message.append('-');
0813:                    value = -value;
0814:                }
0815:                if (value < 10) {
0816:                    message.append('0');
0817:                }
0818:                append2(message, value);
0819:            }
0820:
0821:            protected final void append2(StringBuffer message, double value) {
0822:                final int intValue = (int) value;
0823:                if (value == intValue) {
0824:                    message.append(intValue);
0825:                } else {
0826:                    append3(message, value);
0827:                }
0828:            }
0829:
0830:            private void append3(StringBuffer message, double value) {
0831:                String d = String.valueOf(value);
0832:                int eIndex = d.indexOf('E');
0833:                if (eIndex == -1) {
0834:                    message.append(d);
0835:                    return;
0836:                }
0837:                int exp;
0838:                if (value < 1) {
0839:                    // Need to convert from scientific notation of the form 
0840:                    // n.nnn...E-N (N >= 4) to a normal decimal value.
0841:                    try {
0842:                        exp = parseInt(d, eIndex + 2, d.length());
0843:                    }
0844:                    // This should never happen. 
0845:                    // It's only possible if String.valueOf(double) is broken.
0846:                    catch (Exception e) {
0847:                        message.append(d);
0848:                        return;
0849:                    }
0850:                    message.append("0.");
0851:                    for (int i = 1; i < exp; ++i) {
0852:                        message.append('0');
0853:                    }
0854:                    // Remove trailing zeros.
0855:                    int end = eIndex - 1;
0856:                    while (end > 0) {
0857:                        char c = d.charAt(end);
0858:                        if (c != '0') {
0859:                            break;
0860:                        }
0861:                        --end;
0862:                    }
0863:                    // Now append the digits to the end. Skip over the decimal point.
0864:                    for (int i = 0; i <= end; ++i) {
0865:                        char c = d.charAt(i);
0866:                        if (c != '.') {
0867:                            message.append(c);
0868:                        }
0869:                    }
0870:                } else {
0871:                    // Need to convert from scientific notation of the form 
0872:                    // n.nnn...EN (N >= 7) to a normal decimal value.
0873:                    try {
0874:                        exp = parseInt(d, eIndex + 1, d.length());
0875:                    }
0876:                    // This should never happen. 
0877:                    // It's only possible if String.valueOf(double) is broken.
0878:                    catch (Exception e) {
0879:                        message.append(d);
0880:                        return;
0881:                    }
0882:                    final int integerEnd = exp + 2;
0883:                    for (int i = 0; i < eIndex; ++i) {
0884:                        char c = d.charAt(i);
0885:                        if (c != '.') {
0886:                            if (i == integerEnd) {
0887:                                message.append('.');
0888:                            }
0889:                            message.append(c);
0890:                        }
0891:                    }
0892:                    // Append trailing zeroes if necessary.
0893:                    for (int i = integerEnd - eIndex; i > 0; --i) {
0894:                        message.append('0');
0895:                    }
0896:                }
0897:            }
0898:
0899:            protected double parseSecond(String buffer, int start, int end)
0900:                    throws NumberFormatException {
0901:                int dot = -1;
0902:                for (int i = start; i < end; i++) {
0903:                    char ch = buffer.charAt(i);
0904:                    if (ch == '.')
0905:                        dot = i;
0906:                    else if (ch > '9' || ch < '0')
0907:                        throw new NumberFormatException("'" + buffer
0908:                                + "' has wrong format");
0909:                }
0910:                if (dot == -1) {
0911:                    if (start + 2 != end)
0912:                        throw new NumberFormatException("'" + buffer
0913:                                + "' has wrong format");
0914:                } else if (start + 2 != dot || dot + 1 == end) {
0915:                    throw new NumberFormatException("'" + buffer
0916:                            + "' has wrong format");
0917:                }
0918:                return Double.parseDouble(buffer.substring(start, end));
0919:            }
0920:
0921:            //
0922:            //Private help functions
0923:            //
0924:
0925:            private void cloneDate(DateTimeData finalValue,
0926:                    DateTimeData tempDate) {
0927:                tempDate.year = finalValue.year;
0928:                tempDate.month = finalValue.month;
0929:                tempDate.day = finalValue.day;
0930:                tempDate.hour = finalValue.hour;
0931:                tempDate.minute = finalValue.minute;
0932:                tempDate.second = finalValue.second;
0933:                tempDate.utc = finalValue.utc;
0934:                tempDate.timezoneHr = finalValue.timezoneHr;
0935:                tempDate.timezoneMin = finalValue.timezoneMin;
0936:            }
0937:
0938:            /**
0939:             * Represents date time data
0940:             */
0941:            static final class DateTimeData implements  XSDateTime {
0942:                int year, month, day, hour, minute, utc;
0943:                double second;
0944:                int timezoneHr, timezoneMin;
0945:                private String originalValue;
0946:                boolean normalized = true;
0947:
0948:                int unNormYear;
0949:                int unNormMonth;
0950:                int unNormDay;
0951:                int unNormHour;
0952:                int unNormMinute;
0953:                double unNormSecond;
0954:
0955:                // used for comparisons - to decide the 'interesting' portions of
0956:                // a date/time based data type.
0957:                int position;
0958:                // a pointer to the type that was used go generate this data
0959:                // note that this is not the actual simple type, but one of the
0960:                // statically created XXXDV objects, so this won't cause any GC problem.
0961:                final AbstractDateTimeDV type;
0962:                private String canonical;
0963:
0964:                public DateTimeData(String originalValue,
0965:                        AbstractDateTimeDV type) {
0966:                    this .originalValue = originalValue;
0967:                    this .type = type;
0968:                }
0969:
0970:                public DateTimeData(int year, int month, int day, int hour,
0971:                        int minute, double second, int utc,
0972:                        String originalValue, boolean normalized,
0973:                        AbstractDateTimeDV type) {
0974:                    this .year = year;
0975:                    this .month = month;
0976:                    this .day = day;
0977:                    this .hour = hour;
0978:                    this .minute = minute;
0979:                    this .second = second;
0980:                    this .utc = utc;
0981:                    this .type = type;
0982:                    this .originalValue = originalValue;
0983:                }
0984:
0985:                public boolean equals(Object obj) {
0986:                    if (!(obj instanceof  DateTimeData))
0987:                        return false;
0988:                    return type.compareDates(this , (DateTimeData) obj, true) == 0;
0989:                }
0990:
0991:                public synchronized String toString() {
0992:                    if (canonical == null) {
0993:                        canonical = type.dateToString(this );
0994:                    }
0995:                    return canonical;
0996:                }
0997:
0998:                /* (non-Javadoc)
0999:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getYear()
1000:                 */
1001:                public int getYears() {
1002:                    if (type instanceof  DurationDV)
1003:                        return 0;
1004:                    return normalized ? year : unNormYear;
1005:                }
1006:
1007:                /* (non-Javadoc)
1008:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getMonth()
1009:                 */
1010:                public int getMonths() {
1011:                    if (type instanceof  DurationDV) {
1012:                        return year * 12 + month;
1013:                    }
1014:                    return normalized ? month : unNormMonth;
1015:                }
1016:
1017:                /* (non-Javadoc)
1018:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getDay()
1019:                 */
1020:                public int getDays() {
1021:                    if (type instanceof  DurationDV)
1022:                        return 0;
1023:                    return normalized ? day : unNormDay;
1024:                }
1025:
1026:                /* (non-Javadoc)
1027:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getHour()
1028:                 */
1029:                public int getHours() {
1030:                    if (type instanceof  DurationDV)
1031:                        return 0;
1032:                    return normalized ? hour : unNormHour;
1033:                }
1034:
1035:                /* (non-Javadoc)
1036:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getMinutes()
1037:                 */
1038:                public int getMinutes() {
1039:                    if (type instanceof  DurationDV)
1040:                        return 0;
1041:                    return normalized ? minute : unNormMinute;
1042:                }
1043:
1044:                /* (non-Javadoc)
1045:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getSeconds()
1046:                 */
1047:                public double getSeconds() {
1048:                    if (type instanceof  DurationDV) {
1049:                        return day * 24 * 60 * 60 + hour * 60 * 60 + minute
1050:                                * 60 + second;
1051:                    }
1052:                    return normalized ? second : unNormSecond;
1053:                }
1054:
1055:                /* (non-Javadoc)
1056:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#hasTimeZone()
1057:                 */
1058:                public boolean hasTimeZone() {
1059:                    return utc != 0;
1060:                }
1061:
1062:                /* (non-Javadoc)
1063:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneHours()
1064:                 */
1065:                public int getTimeZoneHours() {
1066:                    return timezoneHr;
1067:                }
1068:
1069:                /* (non-Javadoc)
1070:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneMinutes()
1071:                 */
1072:                public int getTimeZoneMinutes() {
1073:                    return timezoneMin;
1074:                }
1075:
1076:                /* (non-Javadoc)
1077:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getLexicalValue()
1078:                 */
1079:                public String getLexicalValue() {
1080:                    return originalValue;
1081:                }
1082:
1083:                /* (non-Javadoc)
1084:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#normalize()
1085:                 */
1086:                public XSDateTime normalize() {
1087:                    if (!normalized) {
1088:                        DateTimeData dt = (DateTimeData) this .clone();
1089:                        dt.normalized = true;
1090:                        return dt;
1091:                    }
1092:                    return this ;
1093:                }
1094:
1095:                /* (non-Javadoc)
1096:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#isNormalized()
1097:                 */
1098:                public boolean isNormalized() {
1099:                    return normalized;
1100:                }
1101:
1102:                public Object clone() {
1103:                    DateTimeData dt = new DateTimeData(this .year, this .month,
1104:                            this .day, this .hour, this .minute, this .second,
1105:                            this .utc, this .originalValue, this .normalized,
1106:                            this .type);
1107:                    dt.canonical = this .canonical;
1108:                    dt.position = position;
1109:                    dt.timezoneHr = this .timezoneHr;
1110:                    dt.timezoneMin = this .timezoneMin;
1111:                    dt.unNormYear = this .unNormYear;
1112:                    dt.unNormMonth = this .unNormMonth;
1113:                    dt.unNormDay = this .unNormDay;
1114:                    dt.unNormHour = this .unNormHour;
1115:                    dt.unNormMinute = this .unNormMinute;
1116:                    dt.unNormSecond = this .unNormSecond;
1117:                    return dt;
1118:                }
1119:
1120:                /* (non-Javadoc)
1121:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getXMLGregorianCalendar()
1122:                 */
1123:                public XMLGregorianCalendar getXMLGregorianCalendar() {
1124:                    return type.getXMLGregorianCalendar(this );
1125:                }
1126:
1127:                /* (non-Javadoc)
1128:                 * @see org.apache.xerces.xs.datatypes.XSDateTime#getDuration()
1129:                 */
1130:                public Duration getDuration() {
1131:                    return type.getDuration(this );
1132:                }
1133:            }
1134:
1135:            protected XMLGregorianCalendar getXMLGregorianCalendar(
1136:                    DateTimeData data) {
1137:                return null;
1138:            }
1139:
1140:            protected Duration getDuration(DateTimeData data) {
1141:                return null;
1142:            }
1143:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.