Statistics
| Revision:

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

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 3592 2006-01-11 12:20:50Z jaume $
45
* $Log$
46
* Revision 1.1.2.7  2006-01-11 12:20:30  jaume
47
* *** empty log message ***
48
*
49
* Revision 1.1.2.6  2006/01/10 11:33:31  jaume
50
* Time dimension working against Jet Propulsion Laboratory's WMS server
51
*
52
* Revision 1.1.2.5  2006/01/09 18:10:38  jaume
53
* casi con el time dimension
54
*
55
* Revision 1.1.2.4  2006/01/05 23:15:53  jaume
56
* *** empty log message ***
57
*
58
* Revision 1.1.2.3  2006/01/04 18:09:02  jaume
59
* Time dimension
60
*
61
* Revision 1.1.2.2  2006/01/04 16:49:44  jaume
62
* Time dimensios
63
*
64
* Revision 1.1.2.1  2006/01/03 18:08:40  jaume
65
* *** empty log message ***
66
*
67
*
68
*/
69
/**
70
 * 
71
 */
72
package com.iver.cit.gvsig.fmap.layers;
73

    
74
import java.util.GregorianCalendar;
75

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

    
152
    public String getName() {
153
        return name;
154
    }
155
    
156
    public String getUnit() {
157
        return unit;
158
    }
159

    
160
    public String getUnitSymbol() {
161
        return unitSymbol;
162
    }
163

    
164

    
165
    public String getLowLimit() {
166
        return dimensionExpression.split("/")[0];
167
    }
168

    
169
    public String getHighLimit() {
170
        String[] s = dimensionExpression.split("/");
171
        return (s.length > 1) ? s[1] : s[0];
172
    }
173

    
174
    public String getResolution() {
175
        String[] s = dimensionExpression.split("/");
176
        return (s.length == 1) ? s[3] : null;
177
    }
178

    
179
    public boolean isValidValue(String value) {
180
        return (value.matches(regexDateForGeologicDatasets) || value.matches(regexDateExtendedForBCE));
181
    }
182

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

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

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

    
332
    public void setExpression(String expr) throws IllegalArgumentException {
333
        dimensionExpression = expr.toUpperCase();
334
        
335
        if (dimensionExpression.matches(regexDateForGeologicDatasets)){
336
            isGeologic = true;
337
        } else if (dimensionExpression.matches(regexTimeDimension)){
338
            isGeologic = false;
339
        } else if (dimensionExpression.matches(regexDateExtendedForBCE)) {
340
            
341
        } else {
342
            System.err.println("Invalid dimension expression: "+expr+" (for "+this.getName()+")");
343
            //throw new IllegalArgumentException(dimensionExpression);
344
        }
345
        String[] s = dimensionExpression.split("/");
346
        minValue = valueOf(s[0]);
347
        maxValue = (s.length>1) ? valueOf(s[1]) : valueOf(s[0]);
348
        period = (s.length>2 && s[2].matches(regexPeriod)) ? s[2] : null;
349
    }
350

    
351
        public String getExpression() {
352
                return dimensionExpression;
353
        }
354

    
355
}