Revision 10663
trunk/extensions/extWMS/src/com/iver/cit/gvsig/fmap/layers/TimeDimension.java | ||
---|---|---|
43 | 43 |
* |
44 | 44 |
* $Id$ |
45 | 45 |
* $Log$ |
46 |
* Revision 1.7 2006-05-12 07:47:39 jaume |
|
46 |
* Revision 1.8 2007-03-08 12:04:32 jaume |
|
47 |
* fixed error parsing YYYY date formats |
|
48 |
* |
|
49 |
* Revision 1.7 2006/05/12 07:47:39 jaume |
|
47 | 50 |
* removed unnecessary imports |
48 | 51 |
* |
49 | 52 |
* Revision 1.6 2006/04/21 11:53:04 jaume |
... | ... | |
112 | 115 |
* |
113 | 116 |
*/ |
114 | 117 |
/** |
115 |
*
|
|
118 |
* |
|
116 | 119 |
*/ |
117 | 120 |
package com.iver.cit.gvsig.fmap.layers; |
118 | 121 |
|
... | ... | |
132 | 135 |
* As far as this class implements IFMapWMSDimension it uses the same interface |
133 | 136 |
* and documentation. |
134 | 137 |
* </p> |
135 |
*
|
|
138 |
* |
|
136 | 139 |
* @author jaume dominguez faus - jaume.dominguez@iver.es |
137 | 140 |
*/ |
138 | 141 |
public class TimeDimension implements IFMapWMSDimension { |
... | ... | |
140 | 143 |
static private final byte YEAR_TO_MONTH_FORMAT = 2; |
141 | 144 |
static private final byte YEAR_TO_DAY_FORMAT = 3; |
142 | 145 |
static private final byte FULL_FORMAT = 4; |
143 |
|
|
146 |
|
|
144 | 147 |
static private final long millisXsec = 1000; |
145 | 148 |
static private final long millisXminute = 60 * millisXsec; |
146 | 149 |
static private final long millisXhour = 60 * millisXminute; |
147 | 150 |
static private final long millisXday = 24 * millisXhour; |
148 | 151 |
static private final long millisXmonth = 30 * millisXday; |
149 | 152 |
// according on the Wikipedia (1 year = 365 days 6 hours 9 minutes 9,7 seconds) |
150 |
static private final long millisXyear = (365*millisXday) + (6*millisXhour) + (9*millisXminute) + 9700;
|
|
151 |
|
|
153 |
static private final long millisXyear = (365*millisXday) + (6*millisXhour) + (9*millisXminute) + 9700; |
|
154 |
|
|
152 | 155 |
static private final String digit = "[0-9]"; |
153 | 156 |
static private final String nonZeroDigit = "[1-9]"; |
154 | 157 |
static private final String seconds = "([0-5]"+digit+"((\\.|,)"+digit+digit+")?)"; |
... | ... | |
160 | 163 |
static private final String year = "("+digit+digit+")"; |
161 | 164 |
static private final String century = "("+digit+digit+")"; |
162 | 165 |
static private final String floatingPointNumber = "("+digit+"+(\\."+digit+"+)?)"; |
163 |
|
|
166 |
|
|
164 | 167 |
private String unit; |
165 | 168 |
private String unitSymbol; |
166 | 169 |
private ArrayList valueList; |
... | ... | |
170 | 173 |
private int type; |
171 | 174 |
private byte format = 0; |
172 | 175 |
|
173 |
static private final String regexDateExtendedForBCE1 = "B?"+century+year+"-";
|
|
176 |
static private final String regexDateExtendedForBCE1 = "B?"+century+year; |
|
174 | 177 |
static private final String regexDateExtendedForBCE2 = "B?"+century+year+"-"+months; |
175 | 178 |
static private final String regexDateExtendedForBCE3 = "B?"+century+year+"-"+months+"-"+days; |
176 | 179 |
static private final String regexDateExtendedForBCE4 = "B?"+century+year+"-"+months+"-"+days+"(T| )"+time+"Z"; |
177 | 180 |
// Note: in WMS 1.1.0 the suffix Z is optional |
178 |
|
|
179 |
static private final String regexDateExtendedForBCE =
|
|
181 |
|
|
182 |
static private final String regexDateExtendedForBCE = |
|
180 | 183 |
"(" + regexDateExtendedForBCE1 + "|" |
181 | 184 |
+ regexDateExtendedForBCE2 + "|" |
182 | 185 |
+ regexDateExtendedForBCE3 + "|" |
183 | 186 |
+ regexDateExtendedForBCE4 + ")"; |
184 |
|
|
187 |
|
|
185 | 188 |
static private final String periodMagnitude = "(Y|M|D)"; |
186 | 189 |
static private final String p1 = "(("+digit+")+"+periodMagnitude+")"; |
187 |
|
|
190 |
|
|
188 | 191 |
static private final String timeMagnitude = "(H|M|S)"; |
189 | 192 |
static private final String p2 = "("+floatingPointNumber+timeMagnitude+")"; |
190 |
static private final String regexPeriod = "P(("+p1+"+"+"(T"+p2+")*)|("+p1+"*"+"(T"+p2+")+))";
|
|
191 |
|
|
193 |
static private final String regexPeriod = "P(("+p1+"+"+"(T"+p2+")*)|("+p1+"*"+"(T"+p2+")+))"; |
|
194 |
|
|
192 | 195 |
static private final String regexIntervalTimeDimension = |
193 | 196 |
"("+regexDateExtendedForBCE+")/("+regexDateExtendedForBCE+")/("+regexPeriod+")"; |
194 |
|
|
197 |
|
|
195 | 198 |
static private final String geologicDatasets = "(K|M|G)"; |
196 | 199 |
static private final String regexDateForGeologicDatasets = geologicDatasets+floatingPointNumber; |
197 |
|
|
200 |
|
|
198 | 201 |
/** |
199 | 202 |
* Creates a new instance of TimeDimension. |
200 | 203 |
* @param units |
... | ... | |
206 | 209 |
this.unitSymbol = _unitSymbol; |
207 | 210 |
setExpression(_dimensionExpression); |
208 | 211 |
} |
209 |
|
|
212 |
|
|
210 | 213 |
public String getName() { |
211 | 214 |
return "TIME"; |
212 | 215 |
} |
213 |
|
|
216 |
|
|
214 | 217 |
public String getUnit() { |
215 | 218 |
return unit; |
216 | 219 |
} |
... | ... | |
227 | 230 |
return (String) valueList.get(valueList.size()-1); |
228 | 231 |
} |
229 | 232 |
|
230 |
|
|
233 |
|
|
231 | 234 |
public String getResolution() { |
232 | 235 |
return null; |
233 | 236 |
} |
... | ... | |
252 | 255 |
float mySecond; |
253 | 256 |
String[] s = myValue.split("-"); |
254 | 257 |
myYear = (s[0].charAt(0)=='B') ? -Integer.parseInt(s[0].substring(1, 5)) : Integer.parseInt(s[0].substring(0, 4)); |
255 |
myMonth = (s.length>1) ? Integer.parseInt(s[1])-1 : 0;
|
|
258 |
myMonth = (s.length>1) ? Integer.parseInt(s[1])-1 : 0; |
|
256 | 259 |
if (myValue.matches(regexDateExtendedForBCE4)){ |
257 | 260 |
if (s[2].endsWith("Z")) |
258 | 261 |
s[2] = s[2].substring(0,s[2].length()-1); |
259 | 262 |
s = (s[2].indexOf('T')!=-1) ? s[2].split("T") : s[2].split(" "); |
260 | 263 |
myDay = Integer.parseInt(s[0]); |
261 |
|
|
264 |
|
|
262 | 265 |
// Go with the time |
263 | 266 |
s = s[1].split(":"); |
264 | 267 |
myHour = Integer.parseInt(s[0]); |
... | ... | |
266 | 269 |
mySecond = (s.length>2) ? Float.parseFloat(s[2]) : 0; |
267 | 270 |
} else { |
268 | 271 |
myDay = (s.length>2) ? Integer.parseInt(s[2]) : 1; |
269 |
|
|
272 |
|
|
270 | 273 |
myHour = 0; |
271 | 274 |
myMinute = 0; |
272 | 275 |
mySecond = 0; |
... | ... | |
276 | 279 |
} else{ |
277 | 280 |
// this is a geological date >:-( |
278 | 281 |
} |
279 |
return val;
|
|
282 |
return val; |
|
280 | 283 |
} else throw new IllegalArgumentException(myValue); |
281 | 284 |
} |
282 | 285 |
return null; |
... | ... | |
319 | 322 |
} else if (items[i].matches(regexDateExtendedForBCE3)) { |
320 | 323 |
upgradeFormat(YEAR_TO_DAY_FORMAT); |
321 | 324 |
valueList.add(valueOf(items[i])); |
322 |
} else if (items[i].matches(regexDateExtendedForBCE4)) {
|
|
325 |
} else if (items[i].matches(regexDateExtendedForBCE4)) { |
|
323 | 326 |
upgradeFormat(FULL_FORMAT); |
324 | 327 |
valueList.add(valueOf(items[i])); |
325 | 328 |
} else if (items[i].matches(regexIntervalTimeDimension)) { |
326 | 329 |
// Analyze and transform this interval expression to a list |
327 | 330 |
// of values. |
328 |
|
|
331 |
|
|
329 | 332 |
// min value |
330 | 333 |
String[] s = items[i].split("/"); |
331 | 334 |
if (s[0].matches(regexDateExtendedForBCE1)) { |
... | ... | |
334 | 337 |
upgradeFormat(YEAR_TO_MONTH_FORMAT); |
335 | 338 |
} else if (s[0].matches(regexDateExtendedForBCE3)) { |
336 | 339 |
upgradeFormat(YEAR_TO_DAY_FORMAT); |
337 |
} else if (s[0].matches(regexDateExtendedForBCE4)) {
|
|
340 |
} else if (s[0].matches(regexDateExtendedForBCE4)) { |
|
338 | 341 |
upgradeFormat(FULL_FORMAT); |
339 | 342 |
} |
340 | 343 |
Object minValue = valueOf(s[0]); |
341 |
|
|
344 |
|
|
342 | 345 |
// max value |
343 | 346 |
if (s[0].matches(regexDateExtendedForBCE1)) { |
344 | 347 |
upgradeFormat(YEAR_FORMAT); |
... | ... | |
346 | 349 |
upgradeFormat(YEAR_TO_MONTH_FORMAT); |
347 | 350 |
} else if (s[1].matches(regexDateExtendedForBCE3)) { |
348 | 351 |
upgradeFormat(YEAR_TO_DAY_FORMAT); |
349 |
} else if (s[1].matches(regexDateExtendedForBCE4)) {
|
|
352 |
} else if (s[1].matches(regexDateExtendedForBCE4)) { |
|
350 | 353 |
upgradeFormat(FULL_FORMAT); |
351 | 354 |
} |
352 | 355 |
Object maxValue = valueOf(s[1]); |
353 |
|
|
356 |
|
|
354 | 357 |
String period = s[2]; |
355 |
|
|
358 |
|
|
356 | 359 |
if (period == null) { |
357 | 360 |
valueList.add(minValue); |
358 | 361 |
valueList.add(maxValue); |
359 | 362 |
continue; |
360 | 363 |
} |
361 |
|
|
364 |
|
|
362 | 365 |
long x1 = ((GregorianCalendar) maxValue).getTimeInMillis(); |
363 | 366 |
long x0 = ((GregorianCalendar) minValue).getTimeInMillis(); |
364 | 367 |
long distance = x1-x0; |
365 | 368 |
long step = 0; |
366 |
|
|
369 |
|
|
367 | 370 |
boolean isTimeField = false; |
368 | 371 |
String val = ""; |
369 |
|
|
372 |
|
|
370 | 373 |
for (int j = 0; j < period.length(); j++) { |
371 | 374 |
if (period.charAt(j) == 'P') |
372 | 375 |
continue; |
... | ... | |
401 | 404 |
default: |
402 | 405 |
val += period.charAt(j); |
403 | 406 |
break; |
404 |
}
|
|
407 |
} |
|
405 | 408 |
} |
406 | 409 |
// Now that we know the earliest and the latest date and the period |
407 | 410 |
// between two dates, I'm going to populate the list of values |
... | ... | |
425 | 428 |
} |
426 | 429 |
} |
427 | 430 |
} |
428 |
|
|
431 |
|
|
429 | 432 |
/** |
430 | 433 |
* Prints a GregorianCalendar value in WMS1.1.1 format. |
431 | 434 |
* @param cal |
... | ... | |
453 | 456 |
String myMinute = (iMinute<10)? "0"+iMinute : ""+iMinute; |
454 | 457 |
String mySecond = (iSecond<10)? "0"+iSecond : ""+iSecond; |
455 | 458 |
int myMilliSecond = cal.get(cal.MILLISECOND); |
456 |
|
|
457 |
|
|
459 |
|
|
460 |
|
|
458 | 461 |
String s = null; |
459 | 462 |
if (format == YEAR_FORMAT) |
460 | 463 |
s = myYear+""; |
... | ... | |
493 | 496 |
|
494 | 497 |
|
495 | 498 |
/* |
496 |
|
|
499 |
|
|
497 | 500 |
// an old (and good one) version. However, the new version is a bit better. |
498 |
|
|
501 |
|
|
499 | 502 |
public class TimeDimension implements IFMapWMSDimension { |
500 | 503 |
static private final long millisXsec = 1000; |
501 | 504 |
static private final long millisXminute = 60 * millisXsec; |
... | ... | |
503 | 506 |
static private final long millisXday = 24 * millisXhour; |
504 | 507 |
static private final long millisXmonth = 30 * millisXday; |
505 | 508 |
// according on the Wikipedia (1 year = 365 days 6 hours 9 minutes 9,7 seconds) |
506 |
static private final long millisXyear = (365*millisXday) + (6*millisXhour) + (9*millisXminute) + 9700;
|
|
507 |
|
|
509 |
static private final long millisXyear = (365*millisXday) + (6*millisXhour) + (9*millisXminute) + 9700; |
|
510 |
|
|
508 | 511 |
static private final String digit = "[0-9]"; |
509 | 512 |
static private final String nonZeroDigit = "[1-9]"; |
510 | 513 |
static private final String letter = "[a-zA-Z]"; |
... | ... | |
516 | 519 |
static private final String months = "(0?"+nonZeroDigit+"|10|11|12)"; |
517 | 520 |
static private final String year = "("+digit+digit+")"; |
518 | 521 |
static private final String century = "("+digit+digit+")"; |
519 |
|
|
522 |
|
|
520 | 523 |
static private final String geologicDatasets = "(K|M|G)"; |
521 | 524 |
static private final String floatingPointNumber = "("+digit+"+(\\."+digit+"+)?)"; |
522 |
|
|
523 |
|
|
525 |
|
|
526 |
|
|
524 | 527 |
static private final String regexDateExtendedForBCE1 = "B?"+century+year+"-"; |
525 | 528 |
static private final String regexDateExtendedForBCE2 = "B?"+century+year+"-"+months; |
526 | 529 |
static private final String regexDateExtendedForBCE3 = "B?"+century+year+"-"+months+"-"+days; |
527 | 530 |
static private final String regexDateExtendedForBCE4 = "B?"+century+year+"-"+months+"-"+days+"(T| )"+time+"Z"; |
528 | 531 |
// Note: in WMS 1.1.0 the suffix Z is optional |
529 | 532 |
// TODO truncated values not yet allowed |
530 |
|
|
531 |
static private final String regexDateExtendedForBCE =
|
|
533 |
|
|
534 |
static private final String regexDateExtendedForBCE = |
|
532 | 535 |
"(" + regexDateExtendedForBCE1 + "|" |
533 | 536 |
+ regexDateExtendedForBCE2 + "|" |
534 | 537 |
+ regexDateExtendedForBCE3 + "|" |
535 | 538 |
+ regexDateExtendedForBCE4 + ")"; |
536 |
|
|
537 |
|
|
539 |
|
|
540 |
|
|
538 | 541 |
static private final String regexDateForGeologicDatasets = geologicDatasets+floatingPointNumber; |
539 |
|
|
542 |
|
|
540 | 543 |
static private final String periodMagnitude = "(Y|M|D)"; |
541 | 544 |
static private final String p1 = "(("+digit+")+"+periodMagnitude+")"; |
542 |
|
|
545 |
|
|
543 | 546 |
static private final String timeMagnitude = "(H|M|S)"; |
544 | 547 |
static private final String p2 = "("+floatingPointNumber+timeMagnitude+")"; |
545 |
static private final String regexPeriod = "P(("+p1+"+"+"(T"+p2+")*)|("+p1+"*"+"(T"+p2+")+))";
|
|
546 |
|
|
548 |
static private final String regexPeriod = "P(("+p1+"+"+"(T"+p2+")*)|("+p1+"*"+"(T"+p2+")+))"; |
|
549 |
|
|
547 | 550 |
static private final String regexTimeDimension = |
548 | 551 |
"("+regexDateExtendedForBCE+"(,"+regexDateExtendedForBCE+")*|("+regexDateExtendedForBCE+")/("+regexDateExtendedForBCE+")/("+regexPeriod+"))"; |
549 |
|
|
552 |
|
|
550 | 553 |
private String name = "TIME"; |
551 | 554 |
private String unit; |
552 | 555 |
private String unitSymbol; |
... | ... | |
559 | 562 |
private long step; // Distance between two points in milliseconds. |
560 | 563 |
private int type; |
561 | 564 |
private boolean compiled = false; |
562 |
|
|
565 |
|
|
563 | 566 |
/** |
564 | 567 |
* Creates a new instance of TimeDimension. |
565 | 568 |
* @param units |
... | ... | |
575 | 578 |
public String getName() { |
576 | 579 |
return name; |
577 | 580 |
} |
578 |
|
|
581 |
|
|
579 | 582 |
public String getUnit() { |
580 | 583 |
return unit; |
581 | 584 |
} |
... | ... | |
600 | 603 |
} else { |
601 | 604 |
return expression; |
602 | 605 |
} |
603 |
|
|
606 |
|
|
604 | 607 |
} |
605 | 608 |
|
606 | 609 |
public String getResolution() { |
... | ... | |
613 | 616 |
public boolean isValidValue(String value) { |
614 | 617 |
return (value.matches(regexDateForGeologicDatasets) || value.matches(regexDateExtendedForBCE)); |
615 | 618 |
} |
616 |
|
|
619 |
|
|
617 | 620 |
public Object valueOf(String value) throws IllegalArgumentException { |
618 | 621 |
if (compiled) { |
619 | 622 |
// TODO Missing geological dates |
... | ... | |
630 | 633 |
float mySecond; |
631 | 634 |
String[] s = myValue.split("-"); |
632 | 635 |
myYear = (s[0].charAt(0)=='B')? -Integer.parseInt(s[0].substring(1, 5)) : Integer.parseInt(s[0].substring(0, 4)); |
633 |
myMonth = (s.length>1) ? Integer.parseInt(s[1])-1 : 0;
|
|
636 |
myMonth = (s.length>1) ? Integer.parseInt(s[1])-1 : 0; |
|
634 | 637 |
if (myValue.matches(regexDateExtendedForBCE4)){ |
635 | 638 |
if (s[2].endsWith("Z")) |
636 | 639 |
s[2] = s[2].substring(0,s[2].length()-1); |
637 | 640 |
s = (s[2].indexOf('T')!=-1) ? s[2].split("T") : s[2].split(" "); |
638 | 641 |
myDay = Integer.parseInt(s[0]); |
639 |
|
|
642 |
|
|
640 | 643 |
// Go with the time |
641 | 644 |
s = s[1].split(":"); |
642 | 645 |
myHour = Integer.parseInt(s[0]); |
... | ... | |
644 | 647 |
mySecond = (s.length>2) ? Float.parseFloat(s[2]) : 0; |
645 | 648 |
} else { |
646 | 649 |
myDay = (s.length>2) ? Integer.parseInt(s[2]) : 1; |
647 |
|
|
650 |
|
|
648 | 651 |
myHour = 0; |
649 | 652 |
myMinute = 0; |
650 | 653 |
mySecond = 0; |
... | ... | |
654 | 657 |
} else{ |
655 | 658 |
// this is a geological date >:-( |
656 | 659 |
} |
657 |
return val;
|
|
660 |
return val; |
|
658 | 661 |
} else throw new IllegalArgumentException(myValue); |
659 | 662 |
} |
660 | 663 |
return null; |
661 | 664 |
} |
662 |
|
|
665 |
|
|
663 | 666 |
public String valueAt(int pos) throws ArrayIndexOutOfBoundsException { |
664 |
if (compiled) {
|
|
667 |
if (compiled) { |
|
665 | 668 |
if (pos<0 || pos>valueCount()) |
666 | 669 |
throw new ArrayIndexOutOfBoundsException(pos+"(must be >= 0 and <="+valueCount()+")"); |
667 |
|
|
670 |
|
|
668 | 671 |
if (type == SINGLE_VALUE) |
669 | 672 |
return expression; |
670 |
|
|
673 |
|
|
671 | 674 |
if (type == MULTIPLE_VALUE) |
672 | 675 |
return expression.split(",")[pos]; |
673 |
|
|
676 |
|
|
674 | 677 |
if (!isGeologic){ |
675 | 678 |
long newTime = ((GregorianCalendar) minValue).getTimeInMillis(); |
676 | 679 |
newTime += (step*pos); |
... | ... | |
714 | 717 |
String myMinute = (iMinute<10)? "0"+iMinute : ""+iMinute; |
715 | 718 |
String mySecond = (iSecond<10)? "0"+iSecond : ""+iSecond; |
716 | 719 |
int myMilliSecond = cal.get(cal.MILLISECOND); |
717 |
|
|
718 |
|
|
720 |
|
|
721 |
|
|
719 | 722 |
String s = myYear+"-"+myMonth+"-"+myDay+"T"+myHour+":"+myMinute+":"+mySecond+"."+(myMilliSecond/10)+"Z"; |
720 | 723 |
if (iYear<0) |
721 | 724 |
s = "B"+s; |
... | ... | |
732 | 735 |
valueCount = new Integer(0); |
733 | 736 |
return valueCount.intValue(); |
734 | 737 |
} |
735 |
|
|
738 |
|
|
736 | 739 |
if (!isGeologic){ |
737 |
|
|
740 |
|
|
738 | 741 |
long x1 = ((GregorianCalendar) maxValue).getTimeInMillis(); |
739 | 742 |
long x0 = ((GregorianCalendar) minValue).getTimeInMillis(); |
740 | 743 |
long distance = x1-x0; |
741 | 744 |
step = 0; |
742 |
|
|
745 |
|
|
743 | 746 |
boolean isTimeField = false; |
744 | 747 |
String val = ""; |
745 |
|
|
748 |
|
|
746 | 749 |
for (int i = 0; i < period.length(); i++) { |
747 | 750 |
if (period.charAt(i) == 'P') |
748 | 751 |
continue; |
... | ... | |
777 | 780 |
default: |
778 | 781 |
val += period.charAt(i); |
779 | 782 |
break; |
780 |
}
|
|
783 |
} |
|
781 | 784 |
} |
782 | 785 |
valueCount = new Integer((int)(distance/step) + 1); // + 1 for the initial point |
783 | 786 |
} |
... | ... | |
787 | 790 |
return valueCount.intValue(); |
788 | 791 |
} |
789 | 792 |
} |
790 |
|
|
793 |
|
|
791 | 794 |
return valueCount.intValue(); |
792 | 795 |
} |
793 | 796 |
return -1; |
... | ... | |
815 | 818 |
} else { |
816 | 819 |
throw new IllegalArgumentException(); |
817 | 820 |
} |
818 |
String separator;
|
|
819 |
|
|
821 |
String separator; |
|
822 |
|
|
820 | 823 |
if (expression.indexOf("/")!=-1) { |
821 | 824 |
separator = "/"; |
822 | 825 |
type = INTERVAL; |
... | ... | |
827 | 830 |
separator = ","; |
828 | 831 |
type = SINGLE_VALUE; |
829 | 832 |
} |
830 |
|
|
833 |
|
|
831 | 834 |
compiled = true; |
832 | 835 |
String[] s = expression.split(separator); |
833 | 836 |
minValue = valueOf(s[0]); |
Also available in: Unified diff