1 74 package org.eclipse.emf.ecore.xml.type.internal; 75 76 import org.eclipse.emf.ecore.xml.type.InvalidDatatypeValueException; 77 import org.eclipse.emf.ecore.xml.type.internal.DataValue.TypeValidator; 78 79 80 88 public final class XMLDuration { 89 90 private final String ERROR_MESSAGE="The 'duration' value is invalid: "; 91 private final static int[][] DATETIMES= { 98 {1696, 9, 1, 0, 0, 0, 0, 'Z'}, 99 {1697, 2, 1, 0, 0, 0, 0, 'Z'}, 100 {1903, 3, 1, 0, 0, 0, 0, 'Z'}, 101 {1903, 7, 1, 0, 0, 0, 0, 'Z'}}; 102 103 private int hashCode = 0; 104 105 final int[] dateValue; 106 107 final String valueString; 108 109 public XMLDuration(String value) 110 { 111 this.dateValue = parse(value); 112 valueString = value; 113 } 114 115 public boolean equals(Object obj) 116 { 117 if (!(obj instanceof XMLDuration)) 118 return false; 119 int[] odata = ((XMLDuration)obj).dateValue; 120 return compareDates(dateValue, odata, true) == 0; 121 } 122 123 public int hashCode() 124 { 125 if (hashCode == 0) 126 { 127 int[] temp = addDuration(dateValue, DATETIMES[0], new int[XMLCalendar.TOTAL_SIZE]); 128 for (int i=0;i<XMLCalendar.TOTAL_SIZE;i++) 129 { 130 hashCode^=temp[i]; 131 } 132 } 133 return hashCode; 134 } 135 136 public static int compare(XMLDuration value1, XMLDuration value2) 138 { 139 return compareDates(value1.dateValue, value2.dateValue, true); 140 } 142 143 150 private int[] parse(String str) throws InvalidDatatypeValueException{ 151 int len = str.length(); 152 int[] date=new int[XMLCalendar.TOTAL_SIZE]; 153 154 int start = 0; 155 char c=str.charAt(start++); 156 if ( c!='P' && c!='-' ) { 157 throw new InvalidDatatypeValueException(ERROR_MESSAGE+str); 158 } 159 else { 160 date[XMLCalendar.utc]=(c=='-')?'-':0; 161 if ( c=='-' && str.charAt(start++)!='P' ) { 162 throw new InvalidDatatypeValueException(ERROR_MESSAGE+str); 163 } 164 } 165 166 int negate = 1; 167 if ( date[XMLCalendar.utc]=='-' ) { 169 negate = -1; 170 171 } 172 boolean designator = false; 174 175 int endDate = XMLCalendar.indexOf (str, start, len, 'T'); 176 if ( endDate == -1 ) { 177 endDate = len; 178 } 179 int end = XMLCalendar.indexOf (str, start, endDate, 'Y'); 181 if ( end!=-1 ) { 182 date[XMLCalendar.CY]=negate * XMLCalendar.parseInt(str,start,end); 184 start = end+1; 185 designator = true; 186 } 187 188 end = XMLCalendar.indexOf (str, start, endDate, 'M'); 189 if ( end!=-1 ) { 190 date[XMLCalendar.M]=negate * XMLCalendar.parseInt(str,start,end); 192 start = end+1; 193 designator = true; 194 } 195 196 end = XMLCalendar.indexOf (str, start, endDate, 'D'); 197 if ( end!=-1 ) { 198 date[XMLCalendar.D]=negate * XMLCalendar.parseInt(str,start,end); 200 start = end+1; 201 designator = true; 202 } 203 204 if ( len == endDate && start!=len ) { 205 throw new InvalidDatatypeValueException(ERROR_MESSAGE+str); 206 } 207 if ( len !=endDate ) { 208 209 end = XMLCalendar.indexOf (str, ++start, len, 'H'); 210 if ( end!=-1 ) { 211 date[XMLCalendar.h]=negate * XMLCalendar.parseInt(str,start,end); 213 start=end+1; 214 designator = true; 215 } 216 217 end = XMLCalendar.indexOf (str, start, len, 'M'); 218 if ( end!=-1 ) { 219 date[XMLCalendar.m]=negate * XMLCalendar.parseInt(str,start,end); 221 start=end+1; 222 designator = true; 223 } 224 225 end = XMLCalendar.indexOf (str, start, len, 'S'); 226 if ( end!=-1 ) { 227 int mlsec = XMLCalendar.indexOf (str, start, end, '.'); 229 if ( mlsec >0 ) { 230 date[XMLCalendar.s] = negate * XMLCalendar.parseInt (str, start, mlsec); 231 date[XMLCalendar.ms] = negate * XMLCalendar.parseInt (str, mlsec+1, end); 232 } 233 else { 234 date[XMLCalendar.s]=negate * XMLCalendar.parseInt(str, start,end); 235 } 236 start=end+1; 237 designator = true; 238 } 239 if ( start != len || str.charAt(--start)=='T' ) { 242 throw new InvalidDatatypeValueException(ERROR_MESSAGE+str); 243 } 244 } 245 246 if ( !designator ) { 247 throw new InvalidDatatypeValueException(ERROR_MESSAGE+str); 248 } 249 250 return date; 251 } 252 253 267 protected static short compareDates(int[] date1, int[] date2, boolean strict) { 268 269 273 short resultA, resultB= TypeValidator.INDETERMINATE; 275 276 resultA = XMLCalendar.compareOrder (date1, date2); 278 if ( resultA == 0 ) { 279 return 0; 280 } 281 282 int[][] result = new int[2][XMLCalendar.TOTAL_SIZE]; 283 284 int[] tempA = addDuration (date1, DATETIMES[0], result[0]); 286 int[] tempB = addDuration (date2, DATETIMES[0], result[1]); 287 resultA = XMLCalendar.compareOrder(tempA, tempB); 288 if ( resultA == TypeValidator.INDETERMINATE ) { 289 return TypeValidator.INDETERMINATE; 290 } 291 292 tempA = addDuration(date1, DATETIMES[1], result[0]); 293 tempB = addDuration(date2, DATETIMES[1], result[1]); 294 resultB = XMLCalendar.compareOrder(tempA, tempB); 295 resultA = compareResults(resultA, resultB, strict); 296 if (resultA == TypeValidator.INDETERMINATE) { 297 return TypeValidator.INDETERMINATE; 298 } 299 300 tempA = addDuration(date1, DATETIMES[2], result[0]); 301 tempB = addDuration(date2, DATETIMES[2], result[1]); 302 resultB = XMLCalendar.compareOrder(tempA, tempB); 303 resultA = compareResults(resultA, resultB, strict); 304 if (resultA == TypeValidator.INDETERMINATE) { 305 return TypeValidator.INDETERMINATE; 306 } 307 308 tempA = addDuration(date1, DATETIMES[3], result[0]); 309 tempB = addDuration(date2, DATETIMES[3], result[1]); 310 resultB = XMLCalendar.compareOrder(tempA, tempB); 311 resultA = compareResults(resultA, resultB, strict); 312 313 return resultA; 314 } 315 316 private static short compareResults(short resultA, short resultB, boolean strict){ 317 318 if ( resultB == TypeValidator.INDETERMINATE ) { 319 return TypeValidator.INDETERMINATE; 320 } 321 else if ( resultA!=resultB && strict ) { 322 return TypeValidator.INDETERMINATE; 323 } 324 else if ( resultA!=resultB && !strict ) { 325 if ( resultA!=0 && resultB!=0 ) { 326 return TypeValidator.INDETERMINATE; 327 } 328 else { 329 return (resultA!=0)?resultA:resultB; 330 } 331 } 332 return resultA; 333 } 334 335 private static int[] addDuration(int[] date, int[] addto, int[] duration) { 336 337 341 XMLCalendar.resetDateObj(duration); 342 int temp = addto[XMLCalendar.M] + date[XMLCalendar.M]; 344 duration[XMLCalendar.M] = XMLCalendar.modulo (temp, 1, 13); 345 int carry = XMLCalendar.fQuotient (temp, 1, 13); 346 347 duration[XMLCalendar.CY]=addto[XMLCalendar.CY] + date[XMLCalendar.CY] + carry; 349 350 temp = addto[XMLCalendar.s] + date[XMLCalendar.s]; 352 carry = XMLCalendar.fQuotient (temp, 60); 353 duration[XMLCalendar.s] = XMLCalendar.mod(temp, 60, carry); 354 355 temp = addto[XMLCalendar.m] +date[XMLCalendar.m] + carry; 357 carry = XMLCalendar.fQuotient (temp, 60); 358 duration[XMLCalendar.m]= XMLCalendar.mod(temp, 60, carry); 359 360 temp = addto[XMLCalendar.h] + date[XMLCalendar.h] + carry; 362 carry = XMLCalendar.fQuotient(temp, 24); 363 duration[XMLCalendar.h] = XMLCalendar.mod(temp, 24, carry); 364 365 366 duration[XMLCalendar.D]=addto[XMLCalendar.D] + date[XMLCalendar.D] + carry; 367 368 while ( true ) { 369 370 temp=XMLCalendar.maxDayInMonthFor(duration[XMLCalendar.CY], duration[XMLCalendar.M]); 371 if ( duration[XMLCalendar.D] < 1 ) { duration[XMLCalendar.D] = duration[XMLCalendar.D] + XMLCalendar.maxDayInMonthFor(duration[XMLCalendar.CY], duration[XMLCalendar.M]-1); 373 carry=-1; 374 } 375 else if ( duration[XMLCalendar.D] > temp ) { 376 duration[XMLCalendar.D] = duration[XMLCalendar.D] - temp; 377 carry=1; 378 } 379 else { 380 break; 381 } 382 temp = duration[XMLCalendar.M]+carry; 383 duration[XMLCalendar.M] = XMLCalendar.modulo(temp, 1, 13); 384 duration[XMLCalendar.CY] = duration[XMLCalendar.CY]+XMLCalendar.fQuotient(temp, 1, 13); 385 } 386 387 duration[XMLCalendar.utc]='Z'; 388 return duration; 389 } 390 391 public String toString() { 392 return valueString; 393 } 394 } 395 | Popular Tags |