Statistics
| Revision:

svn-gvsig-desktop / branches / gvSIG_WMSv2 / extensions / extWMS / src / com / iver / cit / gvsig / fmap / layers / TimeDimension.java @ 3537

History | View | Annotate | Download (12.8 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41

    
42
/* CVS MESSAGES:
43
*
44
* $Id: TimeDimension.java 3537 2006-01-05 23:15:59Z jaume $
45
* $Log$
46
* Revision 1.1.2.4  2006-01-05 23:15:53  jaume
47
* *** empty log message ***
48
*
49
* Revision 1.1.2.3  2006/01/04 18:09:02  jaume
50
* Time dimension
51
*
52
* Revision 1.1.2.2  2006/01/04 16:49:44  jaume
53
* Time dimensios
54
*
55
* Revision 1.1.2.1  2006/01/03 18:08:40  jaume
56
* *** empty log message ***
57
*
58
*
59
*/
60
/**
61
 * 
62
 */
63
package com.iver.cit.gvsig.fmap.layers;
64

    
65
import java.util.GregorianCalendar;
66

    
67
/**
68
 * @author jaume
69
 *
70
 */
71
public class TimeDimension implements IFMapWMSDimension {
72
    static private final long millisXsec    = 1000;
73
    static private final long millisXminute = 60 * millisXsec;
74
    static private final long millisXhora   = 60 * millisXminute;
75
    static private final long millisXdia    = 24 * millisXhora;
76
    static private final long millisXmes    = 30 * millisXdia;
77
    static private final long millisXanyo   = 365 * millisXdia;
78
    
79
    static private final String digit = "[0-9]";
80
    static private final String nonZeroDigit = "[1-9]";
81
    static private final String letter = "[a-zA-Z]";
82
    static private final String seconds = "([0-5]"+digit+"((\\.|,)"+digit+digit+")?)";
83
    static private final String minutes = "([0-5]"+digit+")";
84
    static private final String hours = "(0"+digit+"|1"+digit+"|2[0-3])";
85
    static private final String time = hours+":"+minutes+"(:"+seconds+")?";
86
    static private final String days = "(0"+nonZeroDigit+"|1"+digit+"|2"+digit+"|30|31)";
87
    static private final String months = "(0"+nonZeroDigit+"|10|11|12)";
88
    static private final String year = "("+digit+digit+")";
89
    static private final String century = "("+digit+digit+")";
90
    
91
    static private final String geologicDatasets = "(K|M|G)";
92
    static private final String floatingPointNumber = "("+digit+"+(\\."+digit+"+)?)";
93
    
94
    
95
    static private final String regexDateExtendedForBCE1 = "B?"+century+year;
96
    static private final String regexDateExtendedForBCE2 = "B?"+century+year+"-"+months;
97
    static private final String regexDateExtendedForBCE3 = "B?"+century+year+"-"+months+"-"+days;
98
    static private final String regexDateExtendedForBCE4 = "B?"+century+year+"-"+months+"-"+days+"(T| )"+time+"Z";
99
    // Note: in WMS 1.1.0 the suffix Z is optional
100
    // TODO truncated values not yet allowed
101
    
102
    static private final String regexDateExtendedForBCE = 
103
        "(" +  regexDateExtendedForBCE1  + "|"
104
            +  regexDateExtendedForBCE2  + "|"
105
            +  regexDateExtendedForBCE3  + "|"
106
            +  regexDateExtendedForBCE4  +      ")";
107
    
108
    static private final String regexDateForGeologicDatasets = geologicDatasets+floatingPointNumber;
109
    
110
    static private final String periodMagnitude = "(Y|M|D)";
111
    static private final String p1 = "(("+digit+")+"+periodMagnitude+")";
112
    
113
    static private final String timeMagnitude = "(H|M|S)";
114
    static private final String p2 = "("+floatingPointNumber+timeMagnitude+")";
115
    static private final String regexPeriod = "P(("+p1+"+"+"(T"+p2+")*)|("+p1+"*"+"(T"+p2+")+))"; 
116
    
117
    static private final String regexTimeDimension =
118
        "("+regexDateExtendedForBCE3+")/("+regexDateExtendedForBCE3+")/("+regexPeriod+")";
119
    
120
    private String name = "TIME";
121
    private String unit;
122
    private String unitSymbol;
123
    private String dimensionExpression;
124
    private Object minValue;
125
    private Object maxValue;
126
    private boolean isGeologic = false;
127
    private Integer valueCount;
128
    private String period;
129
    private long step; // Distance between two points in milliseconds.
130
    
131
    /**
132
     * Creates a new instance of TimeDimension.
133
     * @param units
134
     * @param unitSymbol
135
     * @param dimensionExpression
136
     */
137
    public TimeDimension(String _units, String _unitSymbol, String _dimensionExpression) {
138
        this.unit = _units;
139
        this.unitSymbol = _unitSymbol;
140
        this.dimensionExpression = _dimensionExpression;
141
    }
142

    
143
    public String getName() {
144
        return name;
145
    }
146
    
147
    public String getUnit() {
148
        return unit;
149
    }
150

    
151
    public String getUnitSymbol() {
152
        return unitSymbol;
153
    }
154

    
155

    
156
    public String getLowLimit() {
157
        return dimensionExpression.split("/")[0];
158
    }
159

    
160
    public String getHighLimit() {
161
        String[] s = dimensionExpression.split("/");
162
        return (s.length > 1) ? s[1] : s[0];
163
    }
164

    
165
    public String getResolution() {
166
        String[] s = dimensionExpression.split("/");
167
        return (s.length == 1) ? s[3] : null;
168
    }
169

    
170
    public boolean isValidValue(String value) {
171
        return (value.matches(regexDateForGeologicDatasets) || value.matches(regexDateExtendedForBCE));
172
    }
173

    
174
    public Object valueOf(String value) throws IllegalArgumentException {
175
//      TODO Missing geological dates
176
        String myValue = value.toUpperCase();
177
        if (isValidValue(myValue)) {
178
            Object val = null;
179
            if (myValue.matches(regexDateExtendedForBCE)){
180
                // This is a normal date
181
                int myYear;
182
                int myMonth;
183
                int myDay;
184
                int myHour;
185
                int myMinute;
186
                float mySecond;
187
                String[] s = myValue.split("-");
188
                myYear = (s[0].charAt(0)=='B')? -Integer.parseInt(s[0].substring(1, 5)) : Integer.parseInt(s[0].substring(0, 4));
189
                myMonth = (s.length>1) ? Integer.parseInt(s[1])-1 : 0; 
190
                if (myValue.matches(regexDateExtendedForBCE4)){
191
                    s = (s[2].indexOf('T')!=-1) ? s[2].split("T") : s[2].split(" ");
192
                    myDay = Integer.parseInt(s[0]);
193
                    
194
                    // Go with the time
195
                    s = s[1].split(":");
196
                    myHour = Integer.parseInt(s[0]);
197
                    myMinute = (s.length>1) ? Integer.parseInt(s[1]) : 0;
198
                    mySecond = (s.length>2) ? Float.parseFloat(s[2].substring(0, s[2].length()-2)) : 0;
199
                } else {
200
                    myDay = (s.length>2) ? Integer.parseInt(s[2]) : 1;
201
                    
202
                    myHour = 0;
203
                    myMinute = 0;
204
                    mySecond = 0;
205
                }
206
                GregorianCalendar cal = new GregorianCalendar(myYear, myMonth, myDay, myHour, myMinute, (int)mySecond);
207
                val = cal;
208
            } else{
209
                // this is a geological date >:-(
210
            }
211
            return val;    
212
        } else throw new IllegalArgumentException(myValue);
213
        
214
    }
215
 
216
    public String valueAt(int pos) throws ArrayIndexOutOfBoundsException {
217
        if (pos<0 || pos> valueCount())
218
            throw new ArrayIndexOutOfBoundsException(pos+"(must be >= 0 and <="+valueCount()+")");
219
        if (!isGeologic){
220
            long newTime = ((GregorianCalendar) minValue).getTimeInMillis();
221
            newTime += (step*pos);
222
            GregorianCalendar cal = new GregorianCalendar();
223
            cal.setTimeInMillis(newTime);
224
            if (cal.after(maxValue))
225
                return toString((GregorianCalendar) maxValue);
226
            else if (cal.before(minValue))
227
                return toString((GregorianCalendar) minValue);
228
            else
229
                return toString(cal);
230
        }
231
        return null;
232
    }
233

    
234
    /**
235
     * Prints a GregorianCalendar value in WMS1.1.1 format.
236
     * @param cal
237
     * @return
238
     */
239
    private String toString(GregorianCalendar cal) {
240
        int iYear   = cal.get(cal.YEAR);
241
        int iMonth  = cal.get(cal.MONTH) + 1;
242
        int iDay    = cal.get(cal.DAY_OF_MONTH);
243
        int iHour   = cal.get(cal.HOUR_OF_DAY);
244
        int iMinute = cal.get(cal.MINUTE);
245
        int iSecond = cal.get(cal.SECOND);
246
        String myYear;
247
        if (iYear<10)
248
            myYear = "200"+iYear;
249
        else if (iYear<100)
250
            myYear = "20"+iYear;
251
        else if (iYear<1000)
252
            myYear = "2"+iYear;
253
        else
254
            myYear = ""+iYear;
255
        String myMonth       = (iMonth<10) ? "0"+iMonth  : ""+iMonth;
256
        String myDay         = (iDay<10)   ? "0"+iDay    : ""+iDay;
257
        String myHour        = (iHour<10)  ? "0"+iHour   : ""+iHour;
258
        String myMinute      = (iMinute<10)? "0"+iMinute : ""+iMinute;
259
        String mySecond      = (iSecond<10)? "0"+iSecond : ""+iSecond;
260
        int myMilliSecond = cal.get(cal.MILLISECOND);
261
        
262
        
263
        String s = myYear+"-"+myMonth+"-"+myDay+"T"+myHour+":"+myMinute+":"+mySecond+"."+(myMilliSecond/10)+"Z";
264
        if (iYear<0)
265
            s = "B"+s;
266
        return s;
267
    }
268

    
269
    public int valueCount() {
270
        if (valueCount==null){
271
            if (period == null) return 0;
272
            if (!isGeologic){
273
                long x1 = ((GregorianCalendar) maxValue).getTimeInMillis();
274
                long x0 = ((GregorianCalendar) minValue).getTimeInMillis();
275
                long distance = x1-x0;
276
                step = 0;
277
                
278
                boolean isTimeField = false;
279
                String val = "";
280
                
281
                for (int i = 0; i < period.length(); i++) {
282
                    if (period.charAt(i) == 'P')
283
                        continue;
284
                    if (period.charAt(i) == 'T'){
285
                        isTimeField = true;
286
                        continue;
287
                    }
288
                    switch (period.charAt(i)){
289
                        case 'Y':
290
                            step += Integer.parseInt(val) * millisXanyo;
291
                            val = "";
292
                            break;
293
                        case 'M':
294
                            if (isTimeField)
295
                                step += Integer.parseInt(val) * millisXminute;
296
                            else
297
                                step += Integer.parseInt(val) * millisXmes;
298
                            val = "";
299
                            break;
300
                        case 'D':
301
                            step += Integer.parseInt(val) * millisXdia;
302
                            val = "";
303
                            break;
304
                        case 'H':
305
                            step += Integer.parseInt(val) * millisXhora;
306
                            val = "";
307
                            break;
308
                        case 'S':
309
                            step += Integer.parseInt(val) * 1000;
310
                            val = "";
311
                            break;
312
                        default:
313
                            val += period.charAt(i);
314
                            break;
315
                    }                       
316
                }
317
                valueCount = new Integer((int)(distance/step));
318
            }
319
        }
320
        return valueCount.intValue();
321
    }
322

    
323
//    public Object nextValueTo(String value) throws IllegalArgumentException {
324
//        if (isValidValue(value)){
325
//            
326
//            return null;
327
//        } else throw new IllegalArgumentException(value);
328
//    }
329
//
330
//    public Object previousValueTo(String value) throws IllegalArgumentException {
331
//        if (isValidValue(value)){
332
//            
333
//            return null;
334
//        } else throw new IllegalArgumentException(value);
335
//    }
336

    
337
    public void setExpression(String expr) throws IllegalArgumentException {
338
        dimensionExpression = expr.toUpperCase();
339
        
340
        if (dimensionExpression.matches(regexDateForGeologicDatasets)){
341
            isGeologic = true;
342
        } else if (dimensionExpression.matches(regexTimeDimension)){
343
            isGeologic = false;
344
        } else if (dimensionExpression.matches(regexDateExtendedForBCE)) {
345
            
346
        } else throw new IllegalArgumentException(dimensionExpression);
347
        String[] s = dimensionExpression.split("/");
348
        minValue = valueOf(s[0]);
349
        maxValue = (s.length>1) ? valueOf(s[1]) : valueOf(s[0]);
350
        period = (s.length>2 && s[2].matches(regexPeriod)) ? s[2] : null;
351
    }
352

    
353
        public String getExpression() {
354
                return dimensionExpression;
355
        }
356

    
357
}