1 22 23 package org.xquark.schema.datatypes; 24 25 import java.text.FieldPosition ; 26 import java.text.ParsePosition ; 27 import java.text.SimpleDateFormat ; 28 import java.util.Date ; 29 30 import org.apache.xerces.impl.xpath.regex.RegularExpression; 31 import org.xquark.schema.SchemaException; 32 import org.xquark.schema.validation.ValidationContextProvider; 33 34 35 abstract class AbstractDateTimeType extends ComparableType { 36 private static final String RCSRevision = "$Revision: 1.2 $"; 37 private static final String RCSName = "$Name: $"; 38 private static int[] POWERSOFTEN = { 1, 10, 100, 1000 }; 39 protected static final String TIMEZONE_PATTERN = "((((\\+)|(\\-))[0-9]{2}:[0-9]{2})|Z)?"; 40 41 private SimpleDateFormat timezoneFormat; 42 private FieldPosition emptyFieldPosition = new FieldPosition (0); 43 44 AbstractDateTimeType(String name, int nType) { 45 super(name, nType); 46 timezoneFormat = new SimpleDateFormat ("HH:mm"); 47 timezoneFormat.setLenient(false); 48 } 49 50 protected Object toValidType(Object data) { 51 return (Date ) data; 52 } 53 54 protected abstract SimpleDateFormat getDateTimeFormat(); 55 56 protected abstract RegularExpression getRegularExpression(); 57 58 protected abstract boolean isTimeFormat(); 59 60 protected abstract boolean isDateFormat(); 61 62 protected abstract DateTime createDateTime(long millis, long tz, boolean tzSpecified); 63 64 protected Comparable toComparable(String value) throws SchemaException { 65 RegularExpression regex = getRegularExpression(); 66 if (!regex.matches(value)) 67 super.invalidValue(value); 68 int len = value.length(); 69 SimpleDateFormat format = getDateTimeFormat(); 70 ParsePosition pos = new ParsePosition (0); 71 Date date = null; 72 if (len > 1 && value.charAt(0) == '-' && value.charAt(1) != '-') { 73 format.setLenient(false); 75 pos.setIndex(1); 76 date = format.parse(value, pos); 77 if (date == null) super.invalidValue(value); 78 format.setLenient(true); 80 pos.setIndex(0); 81 date = format.parse(value, pos); 82 } else { 83 format.setLenient(false); 84 date = format.parse(value, pos); 85 if (date == null) super.invalidValue(value); 86 } 87 long tz = 0; 88 long millis = 0; 89 boolean tzSpecified = false; 90 int index = pos.getIndex(); 91 if (isTimeFormat() && index < len && value.charAt(index) == '.') { 92 index++; 93 int count = 0; 94 while (index < len) { 95 char c = value.charAt(index++); 96 if (!Character.isDigit(c)) break; 97 millis *= 10; 98 millis += ((int) c - (int) '0'); 99 count++; 100 } 101 if (count > 3) { 102 millis = (long)(millis/Math.pow(10, count-3)); 104 } else { 105 millis *= POWERSOFTEN[3 - count]; 106 } 107 } 108 if (index < len) { 109 tzSpecified = true; 110 char c = value.charAt(index); 111 if (c == 'Z') { 113 tz = 0; 114 index++; 115 } else if (c == '+') { 116 pos.setIndex(index+1); 117 Date tzDate = timezoneFormat.parse(value, pos); 118 if (tzDate == null) super.invalidValue(value); 119 tz = tzDate.getTime(); 120 if (tz > DateTime.MAX_TIMEZONE_OFFSET) super.invalidValue(value); 121 index = pos.getIndex(); 122 } else if (c == '-') { 123 pos.setIndex(index+1); 124 Date tzDate = timezoneFormat.parse(value, pos); 125 if (tzDate == null) super.invalidValue(value); 126 tz = -tzDate.getTime(); 127 if (tz < -DateTime.MAX_TIMEZONE_OFFSET) super.invalidValue(value); 128 index = pos.getIndex(); 129 } else { 130 super.invalidValue(value); 131 } 132 } 133 if (index != len) 134 super.invalidValue(value); 135 return createDateTime(date.getTime()+millis, tz, tzSpecified); 136 } 137 138 public String toXMLString(Object data, ValidationContextProvider context) { 139 if (!isTimeFormat()) return stringValue(data); 140 if (data == null) return null; 141 Date date = (Date ) data; 142 StringBuffer result = new StringBuffer (20); 143 SimpleDateFormat format = getDateTimeFormat(); 144 format.format(date, result, emptyFieldPosition); 145 long millis = date.getTime() % 1000; 146 if (millis > 0) { 147 result.append('.'); 148 if (millis < 10) { 149 result.append("00"); 150 result.append(millis); 151 } else if (millis < 100) { 152 result.append("0"); 153 result.append(millis); 154 } else { 155 result.append(millis); 156 } 157 int len = result.length(); 158 while (result.charAt(len-1) == '0') { 159 result.setLength(len-1); 160 len--; 161 } 162 } 163 if (date instanceof DateTime && ((DateTime) date).hasTimeZone()) { 164 result.append('Z'); 165 } 166 return result.toString(); 167 } 168 169 protected String stringValue(Object data) { 170 if (data == null) return null; 171 Date date = (Date ) data; 172 StringBuffer result = new StringBuffer (20); 173 SimpleDateFormat format = getDateTimeFormat(); 174 long tz = 0; 175 boolean tzSpecified = false; 176 if (date instanceof DateTime && ((DateTime) date).hasTimeZone()) { 177 tz = ((DateTime) date).getTimeZone(); 178 tzSpecified = true; 179 } 180 long time = date.getTime(); 181 long millis = time % 1000; 182 format.format(new Date (time+tz), result, emptyFieldPosition); 183 if (millis > 0) { 184 result.append('.'); 185 if (millis < 10) { 186 result.append("00"); 187 result.append(millis); 188 } else if (millis < 100) { 189 result.append("0"); 190 result.append(millis); 191 } else { 192 result.append(millis); 193 } 194 int len = result.length(); 195 while (result.charAt(len-1) == '0') { 196 result.setLength(len-1); 197 len--; 198 } 199 } 200 if (tzSpecified) { 201 if (tz == 0) { 202 result.append('Z'); 203 } else if (tz > 0) { 204 result.append('+'); 205 timezoneFormat.format(new Date (tz), result, emptyFieldPosition); 206 } else { 207 result.append('-'); 208 timezoneFormat.format(new Date (-tz), result, emptyFieldPosition); 209 } 210 } 211 return result.toString(); 212 } 213 214 } 215 | Popular Tags |