001: /***
002: * Retrotranslator: a Java bytecode transformer that translates Java classes
003: * compiled with JDK 5.0 into classes that can be run on JVM 1.4.
004: *
005: * Copyright (c) 2005 - 2008 Taras Puchko
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * 3. Neither the name of the copyright holders nor the names of its
017: * contributors may be used to endorse or promote products derived from
018: * this software without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
022: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
023: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
024: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
025: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
026: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
027: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
028: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
029: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
030: * THE POSSIBILITY OF SUCH DAMAGE.
031: */package net.sf.retrotranslator.runtime.format;
032:
033: import java.text.SimpleDateFormat;
034: import java.util.*;
035:
036: /**
037: * @author Taras Puchko
038: */
039: abstract class DateTimeConversion extends Conversion {
040:
041: public static Map<Character, DateTimeConversion> getConversions() {
042: HashMap<Character, DateTimeConversion> map = new HashMap<Character, DateTimeConversion>();
043: map.put('H', new PatternConversion("HH"));
044: map.put('I', new PatternConversion("hh"));
045: map.put('k', new PatternConversion("H"));
046: map.put('l', new PatternConversion("h"));
047: map.put('M', new PatternConversion("mm"));
048: map.put('S', new PatternConversion("ss"));
049: map.put('L', new PatternConversion("SSS"));
050: map.put('N', new PatternConversion("SSS000000"));
051: map.put('p', new PatternConversion("a", true));
052: map.put('z', new TimeZoneOffsetConversion());
053: map.put('Z', new PatternConversion("z"));
054: map.put('s', new MillisConversion(1000));
055: map.put('Q', new MillisConversion(1));
056: map.put('B', new PatternConversion("MMMM"));
057: map.put('b', new PatternConversion("MMM"));
058: map.put('h', new PatternConversion("MMM"));
059: map.put('A', new PatternConversion("EEEE"));
060: map.put('a', new PatternConversion("EEE"));
061: map.put('C', new CenturyConversion());
062: map.put('Y', new PatternConversion("yyyy"));
063: map.put('y', new PatternConversion("yy"));
064: map.put('j', new PatternConversion("DDD"));
065: map.put('m', new PatternConversion("MM"));
066: map.put('d', new PatternConversion("dd"));
067: map.put('e', new PatternConversion("d"));
068: map.put('R', new PatternConversion("HH:mm"));
069: map.put('T', new PatternConversion("HH:mm:ss"));
070: map.put('r', new PatternConversion("hh:mm:ss a"));
071: map.put('D', new PatternConversion("MM/dd/yy"));
072: map.put('F', new PatternConversion("yyyy-MM-dd"));
073: map.put('c',
074: new PatternConversion("EEE MMM dd HH:mm:ss z yyyy"));
075: return map;
076: }
077:
078: public void format(FormatContext context) {
079: context.assertNoPrecision();
080: context.assertNoFlag('#');
081: context.checkWidth();
082: Object argument = context.getArgument();
083: if (argument == null) {
084: context.writePadded(String.valueOf(argument));
085: } else {
086: printf(context);
087: }
088: }
089:
090: protected abstract void printf(FormatContext context);
091:
092: protected static Calendar getCalendar(FormatContext context) {
093: Object argument = context.getArgument();
094: Calendar calendar;
095: if (argument instanceof Date) {
096: calendar = new GregorianCalendar();
097: calendar.setTime((Date) argument);
098: } else if (argument instanceof Calendar) {
099: calendar = (Calendar) argument;
100: } else if (argument instanceof Long) {
101: calendar = new GregorianCalendar();
102: calendar.setTimeInMillis((Long) argument);
103: } else {
104: throw context.getConversionException();
105: }
106: return calendar;
107: }
108:
109: private static class PatternConversion extends DateTimeConversion {
110:
111: private String pattern;
112: private boolean toLowerCase;
113:
114: public PatternConversion(String pattern) {
115: this .pattern = pattern;
116: }
117:
118: public PatternConversion(String pattern, boolean toLowerCase) {
119: this .pattern = pattern;
120: this .toLowerCase = toLowerCase;
121: }
122:
123: protected void printf(FormatContext context) {
124: Locale locale = context.getLocale();
125: if (locale == null) {
126: locale = Locale.US;
127: }
128: SimpleDateFormat format = new SimpleDateFormat(pattern,
129: locale);
130: Object argument = context.getArgument();
131: Date date;
132: if (argument instanceof Date) {
133: date = (Date) argument;
134: } else if (argument instanceof Calendar) {
135: Calendar calendar = (Calendar) argument;
136: format.setTimeZone(calendar.getTimeZone());
137: date = calendar.getTime();
138: } else if (argument instanceof Long) {
139: date = new Date((Long) argument);
140: } else {
141: throw context.getConversionException();
142: }
143: String result = format.format(date);
144: if (toLowerCase) {
145: result = result.toLowerCase(locale);
146: }
147: context.writePadded(result);
148: }
149: }
150:
151: private static class MillisConversion extends DateTimeConversion {
152:
153: private long divisor;
154:
155: public MillisConversion(long divisor) {
156: this .divisor = divisor;
157: }
158:
159: protected void printf(FormatContext context) {
160: Object argument = context.getArgument();
161: long millis;
162: if (argument instanceof Date) {
163: millis = ((Date) argument).getTime();
164: } else if (argument instanceof Calendar) {
165: millis = ((Calendar) argument).getTimeInMillis();
166: } else if (argument instanceof Long) {
167: millis = (Long) argument;
168: } else {
169: throw context.getConversionException();
170: }
171: context.writePadded(String.valueOf(millis / divisor));
172: }
173: }
174:
175: private static class TimeZoneOffsetConversion extends
176: DateTimeConversion {
177:
178: protected void printf(FormatContext context) {
179: int offset = getCalendar(context).get(Calendar.ZONE_OFFSET) / 60000;
180: StringBuilder builder = new StringBuilder(5)
181: .append(offset < 0 ? '-' : '+');
182: int value = offset < 0 ? -offset : offset;
183: String s = Integer.toString(value / 60 * 100 + value % 60);
184: for (int i = 4 - s.length(); i > 0; i--) {
185: builder.append('0');
186: }
187: context.writePadded(builder.append(s).toString());
188: }
189: }
190:
191: private static class CenturyConversion extends DateTimeConversion {
192:
193: protected void printf(FormatContext context) {
194: int century = getCalendar(context).get(Calendar.YEAR) / 100;
195: if (century < 10) {
196: char[] chars = Integer.toString(century + 10)
197: .toCharArray();
198: chars[0] = '0';
199: context.writePadded(new String(chars));
200: } else {
201: context.writePadded(Integer.toString(century));
202: }
203: }
204: }
205:
206: }
|