Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.lib / src / main / java / org / gvsig / tools / dataTypes / impl / DefaultDataType.java @ 2088

History | View | Annotate | Download (12.2 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.tools.dataTypes.impl;
25

    
26
import java.text.MessageFormat;
27

    
28
import org.gvsig.tools.dataTypes.CoercionException;
29
import org.gvsig.tools.dataTypes.DataType;
30
import org.gvsig.tools.dataTypes.DataTypes;
31
import org.gvsig.tools.dataTypes.Coercion;
32
import org.slf4j.Logger;
33
import org.slf4j.LoggerFactory;
34
import org.gvsig.tools.dataTypes.CoercionContext;
35

    
36
public class DefaultDataType implements DataType {
37

    
38
  private static final Logger LOG = LoggerFactory.getLogger(DefaultDataTypesManager.class);
39

    
40
  private static class DefaultNumberPrecisionAndScale implements NumberPrecisionAndScale {
41

    
42
    private int precision;
43
    private int scale;
44

    
45
    public DefaultNumberPrecisionAndScale(int precision, int scale) {
46
      this.precision = precision;
47
      this.scale = scale;
48
    }
49

    
50
    @Override
51
    public int getPrecision() {
52
      return this.precision;
53
    }
54

    
55
    @Override
56
    public int getScale() {
57
      return this.scale;
58
    }
59

    
60
    public void setPrecision(int precision) {
61
      this.precision = precision;
62
    }
63

    
64
    public void setScale(int scale) {
65
      this.scale = scale;
66
    }
67
  }
68

    
69
  private static final NumberPrecisionAndScale EMPTY_PRECISION_AND_SCALE = new DefaultNumberPrecisionAndScale(PRECISION_NONE, SCALE_NONE);
70

    
71
  private Coercion coercion;
72
  private Class defaultClass;
73
  private String subtype;
74
  private int type;
75
  private String name;
76
  private String iconName;
77
  private int max_precision;
78
  private int default_precision;
79
  private int default_scale;
80
  private int flags;
81

    
82
  DefaultDataType(int type, String subtype, String name, Class defaultClass, Coercion coercion) {
83
    this(type, subtype, name, defaultClass, coercion, "datatype-any");
84
  }
85

    
86
  DefaultDataType(int type, String subtype, String name, Class defaultClass, Coercion coercion, String iconName) {
87
    this(type, subtype, name, defaultClass, coercion, "datatype-any", 0, PRECISION_NONE, PRECISION_NONE, SCALE_NONE);
88
  }
89

    
90
  DefaultDataType(int type, String subtype, String name, Class defaultClass, Coercion coercion, String iconName, int psflag, int max_precision, int default_precision) {
91
    this(type, subtype, name, defaultClass, coercion, "datatype-any", psflag, max_precision, default_precision, SCALE_NONE);
92
  }
93

    
94
  DefaultDataType(int type, String subtype, String name, Class defaultClass, Coercion coercion, String iconName, int flags, int max_precision, int default_precision, int default_scale) {
95

    
96
    if (name == null) {
97
      LOG.trace("Can't register null type name for type {}.", new Object[]{Integer.toHexString(type).toUpperCase()});
98
      throw new IllegalArgumentException();
99
    }
100
    this.type = type;
101
    this.subtype = subtype;
102
    this.name = name;
103
    this.defaultClass = defaultClass;
104
    this.coercion = coercion;
105
    this.iconName = iconName == null ? "datatype-any" : iconName;
106
    
107
    this.flags = flags;
108
    if( (this.flags&FLAG_FLOATING_POINT)==FLAG_FLOATING_POINT ) {
109
      this.flags |= FLAG_NUMBER;
110
    }
111
    if( (this.flags&FLAG_SUPPORT_PRECISION)==FLAG_SUPPORT_PRECISION ) {
112
      this.max_precision = max_precision;
113
      if( this.default_precision>max_precision ) {
114
        this.default_precision = max_precision;
115
      } else {
116
        this.default_precision = default_precision;
117
      }
118
      if( (this.flags&FLAG_SUPPORT_SCALE)==FLAG_SUPPORT_SCALE ) {
119
        if( this.default_scale>this.max_precision ) {
120
          this.default_scale = this.max_precision -1;
121
        } else {
122
          this.default_scale = default_scale;
123
        }
124
      } else {
125
        this.default_scale = SCALE_NONE;
126
      }
127
    } else {
128
      this.max_precision = PRECISION_NONE;
129
      this.default_precision = PRECISION_NONE;
130
      this.default_scale = SCALE_NONE;
131
    }
132
  }
133

    
134
  @Override
135
  public DataType clone() throws CloneNotSupportedException {
136
    DefaultDataType other = (DefaultDataType) super.clone();
137
    if (other.coercion instanceof Coercions) {
138
      this.coercion = ((Coercions) this.coercion).clone();
139
    }
140
    return other;
141
  }
142

    
143
  @Override
144
  public String getLabel() {
145
    return this.getName();
146
  }
147

    
148
  @Override
149
  public DataType getValue() {
150
    return this;
151
  }
152

    
153
  @Override
154
  public Object coerce(Object value) throws CoercionException {
155
    // http://en.wikipedia.org/wiki/Type_conversion#Implicit_type_conversion
156

    
157
    if (this.coercion != null) {
158
      return this.coercion.coerce(value);
159
    }
160
    if (defaultClass == null) {
161
      return value; // ??
162
    }
163
    if (defaultClass.isInstance(value)) {
164
      return value;
165
    }
166
    throw new CoercionException();
167
  }
168

    
169
  @Override
170
  public Object coerce(Object value, CoercionContext context) throws CoercionException {
171
    // http://en.wikipedia.org/wiki/Type_conversion#Implicit_type_conversion
172
    if (this.coercion != null) {
173
      return this.coercion.coerce(value, context);
174
    }
175
    if (defaultClass == null) {
176
      return value; // ??
177
    }
178
    if (defaultClass.isInstance(value)) {
179
      return value;
180
    }
181
    throw new CoercionException();
182
  }
183

    
184
  @Override
185
  public Coercion getCoercion() {
186
    return this.coercion;
187
  }
188

    
189
  @Override
190
  public Class getDefaultClass() {
191
    return this.defaultClass;
192
  }
193

    
194
  @Override
195
  public String getSubtype() {
196
    return this.subtype;
197
  }
198

    
199
  @Override
200
  public int getType() {
201
    return this.type;
202
  }
203

    
204
  @Override
205
  public String getName() {
206
    return this.name;
207
  }
208

    
209
  @Override
210
  public String getIconName() {
211
    return this.iconName;
212
  }
213

    
214
  @Override
215
  public boolean isContainer() {
216
    return (type & DataTypes.CONTAINER) == DataTypes.CONTAINER;
217
  }
218

    
219
  @Override
220
  public boolean isObject() {
221
    return (type & DataTypes.OBJECT) == DataTypes.OBJECT;
222
  }
223

    
224
  @Override
225
  public boolean isDynObject() {
226
    return type == DataTypes.DYNOBJECT;
227
  }
228

    
229
//  @Override
230
  public void setCoercion(Coercion coercion) {
231
    this.coercion = coercion;
232
    LOG.trace("Add coercion operation for data type {}.", new Object[]{name});
233
  }
234

    
235
  @Override
236
  public void addCoercion(Coercion coercion) {
237
    if (this.coercion == null) {
238
      this.coercion = coercion;
239
      return;
240
    }
241
    Coercions coercions;
242
    if (this.coercion instanceof Coercions) {
243
      coercions = (Coercions) this.coercion;
244
    } else {
245
      coercions = new Coercions();
246
      coercions.add(this.coercion);
247
      this.coercion = coercions;
248
    }
249
    coercions.add(coercion);
250
    LOG.trace("Add coercion operation for data type {}.", new Object[]{name});
251
  }
252

    
253
  @Override
254
  public String toString() {
255
    return MessageFormat.format(
256
            "type=0x{0};subtype={1};name={2};class={3};coercion={4}",
257
            new Object[]{
258
              Integer.toHexString(type).toUpperCase(),
259
              subtype,
260
              name,
261
              defaultClass == null ? null : defaultClass.getName(),
262
              coercion == null ? null : coercion.getClass().getName()
263
            }
264
    );
265
  }
266

    
267
  @Override
268
  public boolean isNumeric() {
269
    return (this.flags&FLAG_NUMBER) == FLAG_NUMBER;
270
  }
271

    
272
  @Override
273
  public boolean supportSize() {
274
    return (this.flags&FLAG_SUPPORT_SIZE) == FLAG_SUPPORT_SIZE;
275
  }
276

    
277
  @Override
278
  public boolean supportPrecision() {
279
    return (this.flags&FLAG_SUPPORT_PRECISION) == FLAG_SUPPORT_PRECISION;
280
  }
281

    
282
  @Override
283
  public boolean supportScale() {
284
    return (this.flags&FLAG_SUPPORT_SCALE) == FLAG_SUPPORT_SCALE;
285
  }
286

    
287
  @Override
288
  public boolean isPredefinedPrecision() {
289
    return (this.flags&FLAG_PREDEFINED_PRECISION) == FLAG_PREDEFINED_PRECISION ;
290
  }
291

    
292
  @Override
293
  public boolean isFloatingPoint() {
294
    return (this.flags&FLAG_FLOATING_POINT) == FLAG_FLOATING_POINT ;
295
  }
296
  
297
  @Override
298
  public int getFlags() {
299
    return this.flags;
300
  }
301

    
302
  @Override
303
  public NumberPrecisionAndScale fixPrecisionAndScale(int precision, int scale) {
304
    if( (this.flags&FLAG_SUPPORT_PRECISION) != FLAG_SUPPORT_PRECISION ) {
305
       return EMPTY_PRECISION_AND_SCALE;
306
    }
307
    DefaultNumberPrecisionAndScale r = new DefaultNumberPrecisionAndScale(
308
            precision, 
309
            scale
310
    );
311
    if( (this.flags&FLAG_PREDEFINED_PRECISION) == FLAG_PREDEFINED_PRECISION ) {
312
      r.precision = max_precision;
313
    }
314
    if( (this.flags&FLAG_SUPPORT_SCALE) != FLAG_SUPPORT_SCALE ) {
315
      // Soporta precision y no escala (byte, int, long... enteros)
316
      r.scale = 0;
317
      if( r.precision > max_precision ) {
318
        r.precision = max_precision;
319
      } else if( r.precision < 1 ) {
320
        r.precision = default_precision;
321
      }
322
    } else {
323
      if( r.scale == SCALE_NONE ) {
324
        r.scale = default_scale;
325
      }
326
      // Soporta precision y escala.
327
      if (r.precision < 1) {
328
        // Sin precision
329
        if (r.scale < 1) {
330
          // Sin precision y sin escala 
331
          // Asinamos los valores por defecto.
332
          r.precision = default_precision;
333
          r.scale = default_scale;
334
        } else {
335
          // Sin precision y con escala.
336
          if (r.scale <= max_precision) {
337
            // Sin precision y con escala < maxima precision.
338
            // Asignamos la precision a la maxima.
339
            r.precision = max_precision;
340
          } else {
341
            // Sin precision y con escala > maxima precision.
342
            // Esto es un error.
343
            // Asignamos la precision a la maxima y reducimos la escala
344
            // a la maxima precision.
345
            r.precision = max_precision;
346
            r.scale = max_precision;
347
          }
348
        }
349
      } else {
350
        // Con precicion
351
        if (r.scale < 1) {
352
          // Con precision y sin escala.
353
          // Esto no es del todo correto. 
354
          // Probablemente algunos proveedores lo convertirian a int. 
355
          // Vamos a forzar que siempre tenga 1 decimal.
356
          if (r.precision < max_precision) {
357
            // Con precision < maxima precision y sin escala.
358
            // Aumentamos la precision en 1 para a?adirle un decimal.
359
            r.precision += 1;
360
            r.scale = 1;
361
          } else {
362
            // Con precision >= maxima precision y sin escala.
363
            // No podemos aumentar la precision para a?adirle un decimal. 
364
            // Le a?adiremos 1 decimal, y dejaremos la precision a la maxima.
365
            // Perdemos precision.
366
            r.precision = max_precision;
367
            r.scale = 1;
368
          }
369
        } else {
370
          // Con precision y escala.     
371
          if (r.precision > max_precision) {
372
            // Con precision mayor que la maxima y con escala.
373
            // Reducimos la precision a la maxima.
374
            r.precision = max_precision;
375
          }
376
          if (r.precision >= r.scale) {
377
            // Con precision y escala menor que la precision.     
378
            // Es correcto, no hacemos nada.
379
          } else {
380
            // Con precision y escala mayor que la precision.
381
            if (r.scale <= max_precision) {
382
              // Con precision y escala mayor que la precision y menor que la maxima precision.
383
              // Aumentamos la precision para soportar la escala indicada.
384
              r.precision = r.scale;
385
            } else {
386
              // Con precision y escala mayor que la precision y mayor que la maxima precision.
387
              // Ponemos la maxima precision y reducimos la escala a esta.
388
              // Perdemos precision.
389
              r.precision = max_precision;
390
              r.scale = max_precision;
391
            }
392
          }
393
        }
394
      }
395
    }
396
    return r;
397
  }
398

    
399
  @Override
400
  public int getMaxPrecision() {
401
    return this.max_precision;
402
  }
403

    
404
  @Override
405
  public int getDefaultPrecision() {
406
    return this.default_precision;
407
  }
408

    
409
  @Override
410
  public int getDefaultScale() {
411
    return this.default_scale;
412
  }
413
}