Source Code Cross Referenced for DateTimeParserBucket.java in  » Development » Joda-Time » org » joda » time » format » 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 » Development » Joda Time » org.joda.time.format 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  Copyright 2001-2006 Stephen Colebourne
003:         *
004:         *  Licensed under the Apache License, Version 2.0 (the "License");
005:         *  you may not use this file except in compliance with the License.
006:         *  You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         *  Unless required by applicable law or agreed to in writing, software
011:         *  distributed under the License is distributed on an "AS IS" BASIS,
012:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         *  See the License for the specific language governing permissions and
014:         *  limitations under the License.
015:         */
016:        package org.joda.time.format;
017:
018:        import java.util.Arrays;
019:        import java.util.Locale;
020:
021:        import org.joda.time.Chronology;
022:        import org.joda.time.DateTimeField;
023:        import org.joda.time.DateTimeFieldType;
024:        import org.joda.time.DateTimeUtils;
025:        import org.joda.time.DateTimeZone;
026:        import org.joda.time.DurationField;
027:        import org.joda.time.IllegalFieldValueException;
028:
029:        /**
030:         * DateTimeParserBucket is an advanced class, intended mainly for parser
031:         * implementations. It can also be used during normal parsing operations to
032:         * capture more information about the parse.
033:         * <p>
034:         * This class allows fields to be saved in any order, but be physically set in
035:         * a consistent order. This is useful for parsing against formats that allow
036:         * field values to contradict each other.
037:         * <p>
038:         * Field values are applied in an order where the "larger" fields are set
039:         * first, making their value less likely to stick.  A field is larger than
040:         * another when it's range duration is longer. If both ranges are the same,
041:         * then the larger field has the longer duration. If it cannot be determined
042:         * which field is larger, then the fields are set in the order they were saved.
043:         * <p>
044:         * For example, these fields were saved in this order: dayOfWeek, monthOfYear,
045:         * dayOfMonth, dayOfYear. When computeMillis is called, the fields are set in
046:         * this order: monthOfYear, dayOfYear, dayOfMonth, dayOfWeek.
047:         * <p>
048:         * DateTimeParserBucket is mutable and not thread-safe.
049:         *
050:         * @author Brian S O'Neill
051:         * @author Fredrik Borgh
052:         * @since 1.0
053:         */
054:        public class DateTimeParserBucket {
055:
056:            /** The chronology to use for parsing. */
057:            private final Chronology iChrono;
058:            private final long iMillis;
059:
060:            // TimeZone to switch to in computeMillis. If null, use offset.
061:            private DateTimeZone iZone;
062:            private int iOffset;
063:            /** The locale to use for parsing. */
064:            private Locale iLocale;
065:            /** Used for parsing two-digit years. */
066:            private Integer iPivotYear;
067:
068:            private SavedField[] iSavedFields = new SavedField[8];
069:            private int iSavedFieldsCount;
070:            private boolean iSavedFieldsShared;
071:
072:            private Object iSavedState;
073:
074:            /**
075:             * Constucts a bucket.
076:             * 
077:             * @param instantLocal  the initial millis from 1970-01-01T00:00:00, local time
078:             * @param chrono  the chronology to use
079:             * @param locale  the locale to use
080:             */
081:            public DateTimeParserBucket(long instantLocal, Chronology chrono,
082:                    Locale locale) {
083:                this (instantLocal, chrono, locale, null);
084:            }
085:
086:            /**
087:             * Constucts a bucket, with the option of specifying the pivot year for
088:             * two-digit year parsing.
089:             *
090:             * @param instantLocal  the initial millis from 1970-01-01T00:00:00, local time
091:             * @param chrono  the chronology to use
092:             * @param locale  the locale to use
093:             * @param pivotYear  the pivot year to use when parsing two-digit years
094:             * @since 1.1
095:             */
096:            public DateTimeParserBucket(long instantLocal, Chronology chrono,
097:                    Locale locale, Integer pivotYear) {
098:                super ();
099:                chrono = DateTimeUtils.getChronology(chrono);
100:                iMillis = instantLocal;
101:                iChrono = chrono.withUTC();
102:                iLocale = (locale == null ? Locale.getDefault() : locale);
103:                setZone(chrono.getZone());
104:                iPivotYear = pivotYear;
105:            }
106:
107:            //-----------------------------------------------------------------------
108:            /**
109:             * Gets the chronology of the bucket, which will be a local (UTC) chronology.
110:             */
111:            public Chronology getChronology() {
112:                return iChrono;
113:            }
114:
115:            //-----------------------------------------------------------------------
116:            /**
117:             * Returns the locale to be used during parsing.
118:             * 
119:             * @return the locale to use
120:             */
121:            public Locale getLocale() {
122:                return iLocale;
123:            }
124:
125:            //-----------------------------------------------------------------------
126:            /**
127:             * Returns the time zone used by computeMillis, or null if an offset is
128:             * used instead.
129:             */
130:            public DateTimeZone getZone() {
131:                return iZone;
132:            }
133:
134:            /**
135:             * Set a time zone to be used when computeMillis is called, which
136:             * overrides any set time zone offset.
137:             *
138:             * @param zone the date time zone to operate in, or null if UTC
139:             */
140:            public void setZone(DateTimeZone zone) {
141:                iSavedState = null;
142:                iZone = zone == DateTimeZone.UTC ? null : zone;
143:                iOffset = 0;
144:            }
145:
146:            //-----------------------------------------------------------------------
147:            /**
148:             * Returns the time zone offset in milliseconds used by computeMillis,
149:             * unless getZone doesn't return null.
150:             */
151:            public int getOffset() {
152:                return iOffset;
153:            }
154:
155:            /**
156:             * Set a time zone offset to be used when computeMillis is called, which
157:             * overrides the time zone.
158:             */
159:            public void setOffset(int offset) {
160:                iSavedState = null;
161:                iOffset = offset;
162:                iZone = null;
163:            }
164:
165:            //-----------------------------------------------------------------------
166:            /**
167:             * Returns the pivot year used for parsing two-digit years.
168:             * <p>
169:             * If null is returned, this indicates default behaviour
170:             *
171:             * @return Integer value of the pivot year, null if not set
172:             * @since 1.1
173:             */
174:            public Integer getPivotYear() {
175:                return iPivotYear;
176:            }
177:
178:            /**
179:             * Sets the pivot year to use when parsing two digit years.
180:             * <p>
181:             * If the value is set to null, this will indicate that default
182:             * behaviour should be used.
183:             *
184:             * @param pivotYear  the pivot year to use
185:             * @since 1.1
186:             */
187:            public void setPivotYear(Integer pivotYear) {
188:                iPivotYear = pivotYear;
189:            }
190:
191:            //-----------------------------------------------------------------------
192:            /**
193:             * Saves a datetime field value.
194:             * 
195:             * @param field  the field, whose chronology must match that of this bucket
196:             * @param value  the value
197:             */
198:            public void saveField(DateTimeField field, int value) {
199:                saveField(new SavedField(field, value));
200:            }
201:
202:            /**
203:             * Saves a datetime field value.
204:             * 
205:             * @param fieldType  the field type
206:             * @param value  the value
207:             */
208:            public void saveField(DateTimeFieldType fieldType, int value) {
209:                saveField(new SavedField(fieldType.getField(iChrono), value));
210:            }
211:
212:            /**
213:             * Saves a datetime field text value.
214:             * 
215:             * @param fieldType  the field type
216:             * @param text  the text value
217:             * @param locale  the locale to use
218:             */
219:            public void saveField(DateTimeFieldType fieldType, String text,
220:                    Locale locale) {
221:                saveField(new SavedField(fieldType.getField(iChrono), text,
222:                        locale));
223:            }
224:
225:            private void saveField(SavedField field) {
226:                SavedField[] savedFields = iSavedFields;
227:                int savedFieldsCount = iSavedFieldsCount;
228:
229:                if (savedFieldsCount == savedFields.length
230:                        || iSavedFieldsShared) {
231:                    // Expand capacity or merely copy if saved fields are shared.
232:                    SavedField[] newArray = new SavedField[savedFieldsCount == savedFields.length ? savedFieldsCount * 2
233:                            : savedFields.length];
234:                    System.arraycopy(savedFields, 0, newArray, 0,
235:                            savedFieldsCount);
236:                    iSavedFields = savedFields = newArray;
237:                    iSavedFieldsShared = false;
238:                }
239:
240:                iSavedState = null;
241:                savedFields[savedFieldsCount] = field;
242:                iSavedFieldsCount = savedFieldsCount + 1;
243:            }
244:
245:            /**
246:             * Saves the state of this bucket, returning it in an opaque object. Call
247:             * restoreState to undo any changes that were made since the state was
248:             * saved. Calls to saveState may be nested.
249:             *
250:             * @return opaque saved state, which may be passed to restoreState
251:             */
252:            public Object saveState() {
253:                if (iSavedState == null) {
254:                    iSavedState = new SavedState();
255:                }
256:                return iSavedState;
257:            }
258:
259:            /**
260:             * Restores the state of this bucket from a previously saved state. The
261:             * state object passed into this method is not consumed, and it can be used
262:             * later to restore to that state again.
263:             *
264:             * @param savedState opaque saved state, returned from saveState
265:             * @return true state object is valid and state restored
266:             */
267:            public boolean restoreState(Object savedState) {
268:                if (savedState instanceof  SavedState) {
269:                    if (((SavedState) savedState).restoreState(this )) {
270:                        iSavedState = savedState;
271:                        return true;
272:                    }
273:                }
274:                return false;
275:            }
276:
277:            /**
278:             * Computes the parsed datetime by setting the saved fields.
279:             * This method is idempotent, but it is not thread-safe.
280:             *
281:             * @return milliseconds since 1970-01-01T00:00:00Z
282:             * @throws IllegalArgumentException if any field is out of range
283:             */
284:            public long computeMillis() {
285:                return computeMillis(false, null);
286:            }
287:
288:            /**
289:             * Computes the parsed datetime by setting the saved fields.
290:             * This method is idempotent, but it is not thread-safe.
291:             *
292:             * @param resetFields false by default, but when true, unsaved field values are cleared
293:             * @return milliseconds since 1970-01-01T00:00:00Z
294:             * @throws IllegalArgumentException if any field is out of range
295:             */
296:            public long computeMillis(boolean resetFields) {
297:                return computeMillis(resetFields, null);
298:            }
299:
300:            /**
301:             * Computes the parsed datetime by setting the saved fields.
302:             * This method is idempotent, but it is not thread-safe.
303:             *
304:             * @param resetFields false by default, but when true, unsaved field values are cleared
305:             * @param text optional text being parsed, to be included in any error message
306:             * @return milliseconds since 1970-01-01T00:00:00Z
307:             * @throws IllegalArgumentException if any field is out of range
308:             * @since 1.3
309:             */
310:            public long computeMillis(boolean resetFields, String text) {
311:                SavedField[] savedFields = iSavedFields;
312:                int count = iSavedFieldsCount;
313:                if (iSavedFieldsShared) {
314:                    iSavedFields = savedFields = (SavedField[]) iSavedFields
315:                            .clone();
316:                    iSavedFieldsShared = false;
317:                }
318:                sort(savedFields, count);
319:
320:                long millis = iMillis;
321:                try {
322:                    for (int i = 0; i < count; i++) {
323:                        millis = savedFields[i].set(millis, resetFields);
324:                    }
325:                } catch (IllegalFieldValueException e) {
326:                    if (text != null) {
327:                        e.prependMessage("Cannot parse \"" + text + '"');
328:                    }
329:                    throw e;
330:                }
331:
332:                if (iZone == null) {
333:                    millis -= iOffset;
334:                } else {
335:                    int offset = iZone.getOffsetFromLocal(millis);
336:                    millis -= offset;
337:                    if (offset != iZone.getOffset(millis)) {
338:                        String message = "Illegal instant due to time zone offset transition ("
339:                                + iZone + ')';
340:                        if (text != null) {
341:                            message = "Cannot parse \"" + text + "\": "
342:                                    + message;
343:                        }
344:                        throw new IllegalArgumentException(message);
345:                    }
346:                }
347:
348:                return millis;
349:            }
350:
351:            /**
352:             * Sorts elements [0,high). Calling java.util.Arrays isn't always the right
353:             * choice since it always creates an internal copy of the array, even if it
354:             * doesn't need to. If the array slice is small enough, an insertion sort
355:             * is chosen instead, but it doesn't need a copy!
356:             * <p>
357:             * This method has a modified version of that insertion sort, except it
358:             * doesn't create an unnecessary array copy. If high is over 10, then
359:             * java.util.Arrays is called, which will perform a merge sort, which is
360:             * faster than insertion sort on large lists.
361:             * <p>
362:             * The end result is much greater performace when computeMillis is called.
363:             * Since the amount of saved fields is small, the insertion sort is a
364:             * better choice. Additional performance is gained since there is no extra
365:             * array allocation and copying. Also, the insertion sort here does not
366:             * perform any casting operations. The version in java.util.Arrays performs
367:             * casts within the insertion sort loop.
368:             */
369:            private static void sort(Comparable[] array, int high) {
370:                if (high > 10) {
371:                    Arrays.sort(array, 0, high);
372:                } else {
373:                    for (int i = 0; i < high; i++) {
374:                        for (int j = i; j > 0
375:                                && (array[j - 1]).compareTo(array[j]) > 0; j--) {
376:                            Comparable t = array[j];
377:                            array[j] = array[j - 1];
378:                            array[j - 1] = t;
379:                        }
380:                    }
381:                }
382:            }
383:
384:            class SavedState {
385:                final DateTimeZone iZone;
386:                final int iOffset;
387:                final SavedField[] iSavedFields;
388:                final int iSavedFieldsCount;
389:
390:                SavedState() {
391:                    this .iZone = DateTimeParserBucket.this .iZone;
392:                    this .iOffset = DateTimeParserBucket.this .iOffset;
393:                    this .iSavedFields = DateTimeParserBucket.this .iSavedFields;
394:                    this .iSavedFieldsCount = DateTimeParserBucket.this .iSavedFieldsCount;
395:                }
396:
397:                boolean restoreState(DateTimeParserBucket enclosing) {
398:                    if (enclosing != DateTimeParserBucket.this ) {
399:                        return false;
400:                    }
401:                    enclosing.iZone = this .iZone;
402:                    enclosing.iOffset = this .iOffset;
403:                    enclosing.iSavedFields = this .iSavedFields;
404:                    if (this .iSavedFieldsCount < enclosing.iSavedFieldsCount) {
405:                        // Since count is being restored to a lower count, the
406:                        // potential exists for new saved fields to destroy data being
407:                        // shared by another state. Set this flag such that the array
408:                        // of saved fields is cloned prior to modification.
409:                        enclosing.iSavedFieldsShared = true;
410:                    }
411:                    enclosing.iSavedFieldsCount = this .iSavedFieldsCount;
412:                    return true;
413:                }
414:            }
415:
416:            static class SavedField implements  Comparable {
417:                final DateTimeField iField;
418:                final int iValue;
419:                final String iText;
420:                final Locale iLocale;
421:
422:                SavedField(DateTimeField field, int value) {
423:                    iField = field;
424:                    iValue = value;
425:                    iText = null;
426:                    iLocale = null;
427:                }
428:
429:                SavedField(DateTimeField field, String text, Locale locale) {
430:                    iField = field;
431:                    iValue = 0;
432:                    iText = text;
433:                    iLocale = locale;
434:                }
435:
436:                long set(long millis, boolean reset) {
437:                    if (iText == null) {
438:                        millis = iField.set(millis, iValue);
439:                    } else {
440:                        millis = iField.set(millis, iText, iLocale);
441:                    }
442:                    if (reset) {
443:                        millis = iField.roundFloor(millis);
444:                    }
445:                    return millis;
446:                }
447:
448:                /**
449:                 * The field with the longer range duration is ordered first, where
450:                 * null is considered infinite. If the ranges match, then the field
451:                 * with the longer duration is ordered first.
452:                 */
453:                public int compareTo(Object obj) {
454:                    DateTimeField other = ((SavedField) obj).iField;
455:                    int result = compareReverse(iField.getRangeDurationField(),
456:                            other.getRangeDurationField());
457:                    if (result != 0) {
458:                        return result;
459:                    }
460:                    return compareReverse(iField.getDurationField(), other
461:                            .getDurationField());
462:                }
463:
464:                private int compareReverse(DurationField a, DurationField b) {
465:                    if (a == null || !a.isSupported()) {
466:                        if (b == null || !b.isSupported()) {
467:                            return 0;
468:                        }
469:                        return -1;
470:                    }
471:                    if (b == null || !b.isSupported()) {
472:                        return 1;
473:                    }
474:                    return -a.compareTo(b);
475:                }
476:            }
477:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.