Revision 10663 trunk/extensions/extWMS/src/com/iver/cit/gvsig/fmap/layers/TimeDimension.java

View differences:

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