Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / fmap / dal / feature / impl / DefaultEditableFeatureAttributeDescriptor.java @ 44673

History | View | Annotate | Download (19.8 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 3
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.fmap.dal.feature.impl;
25

    
26
import java.math.BigDecimal;
27
import java.text.DateFormat;
28
import java.util.HashMap;
29
import java.util.Locale;
30
import java.util.Objects;
31
import org.apache.commons.lang3.StringUtils;
32

    
33
import org.cresques.cts.IProjection;
34
import org.gvsig.expressionevaluator.Expression;
35
import org.gvsig.expressionevaluator.ExpressionUtils;
36
import org.gvsig.fmap.crs.CRSFactory;
37
import org.gvsig.fmap.dal.DALLocator;
38
import org.gvsig.fmap.dal.DataTypeUtils;
39
import org.gvsig.fmap.dal.DataTypes;
40
import org.gvsig.fmap.dal.expressionevaluator.FeatureAttributeEmulatorExpression;
41
import org.slf4j.Logger;
42
import org.slf4j.LoggerFactory;
43

    
44
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
45
import org.gvsig.fmap.dal.feature.EditableForeingKey;
46
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
47
import org.gvsig.fmap.dal.feature.FeatureType;
48
import org.gvsig.fmap.dal.feature.exception.AttributeFeatureTypeIntegrityException;
49
import org.gvsig.fmap.dal.feature.exception.AttributeFeatureTypeSizeException;
50
import org.gvsig.fmap.geom.Geometry;
51
import org.gvsig.fmap.geom.GeometryUtils;
52
import org.gvsig.fmap.geom.type.GeometryType;
53
import org.gvsig.timesupport.Interval;
54
import org.gvsig.tools.ToolsLocator;
55
import org.gvsig.tools.dataTypes.DataType;
56
import org.gvsig.tools.evaluator.Evaluator;
57

    
58
public class DefaultEditableFeatureAttributeDescriptor extends
59
    DefaultFeatureAttributeDescriptor implements
60
    EditableFeatureAttributeDescriptor {
61
    
62
    private static Logger logger = LoggerFactory.getLogger(
63
        DefaultEditableFeatureAttributeDescriptor.class);
64

    
65
    private final DefaultFeatureAttributeDescriptor source;
66
    private boolean hasStrongChanges;
67
    private String originalName = null;
68

    
69
    protected DefaultEditableFeatureAttributeDescriptor(
70
        DefaultFeatureAttributeDescriptor other) {
71
        super(other);
72
        if (other instanceof DefaultEditableFeatureAttributeDescriptor) {
73
            DefaultEditableFeatureAttributeDescriptor other_edi =
74
                (DefaultEditableFeatureAttributeDescriptor) other;
75
            originalName = other_edi.getOriginalName();
76
            this.source = other_edi.getSource();
77
        } else {
78
            this.source = other;
79
        }
80
        hasStrongChanges = false;
81
    }
82

    
83
    public DefaultEditableFeatureAttributeDescriptor(FeatureType type, boolean strongChanges) {
84
        super(type);
85
        this.source = null;
86
        hasStrongChanges = strongChanges;
87
    }
88

    
89
    public DefaultFeatureAttributeDescriptor getSource() {
90
        return this.source;
91
    }
92
    
93
    public void fixAll() {
94
        super.fixAll();
95
    }
96
    
97
    public void checkIntegrity() throws AttributeFeatureTypeIntegrityException {
98
        AttributeFeatureTypeIntegrityException ex =
99
            new AttributeFeatureTypeIntegrityException(getName());
100
        if (this.size < 0) {
101
            ex.add(new AttributeFeatureTypeSizeException(this.size));
102
        }
103

    
104
        if( this.dataType.isObject() && this.objectClass == null ) {
105
            logger.warn("Incorrect data type object, objectClass is null.");
106
            ex.add(new AttributeFeatureTypeIntegrityException(this.name));
107
        }
108
        
109
        // TODO: Add other integrity checks...
110

    
111
        if (ex.size() > 0) {
112
            throw ex;
113
        }
114
    }
115

    
116
    public EditableFeatureAttributeDescriptor setAllowNull(boolean allowNull) {
117
        updateStrongChanges(this.allowNull, allowNull);
118
        this.allowNull = allowNull;
119
        return this;
120
    }
121
    
122
    @Override
123
    public EditableForeingKey getForeingKey() {
124
        if( this.foreingKey==null ) {
125
            this.foreingKey = new DefaultForeingKey();
126
            this.foreingKey.setDescriptor(this);
127
        }
128
        return this.foreingKey;
129
    }
130

    
131
    public EditableFeatureAttributeDescriptor setDataType(DataType dataType) {
132
        updateStrongChanges(this.dataType, dataType);
133
        this.dataType = dataType;
134
        return this;
135
    }
136
    
137
    public EditableFeatureAttributeDescriptor setDataType(int type) {
138
        updateStrongChanges(this.dataType, type);
139
        this.dataType = ToolsLocator.getDataTypesManager().get(type);
140
        return this;
141
    }
142

    
143
    public EditableFeatureAttributeDescriptor setDefaultValue(
144
        Object defaultValue) {
145
        updateStrongChanges(this.defaultValue, defaultValue);
146
        this.defaultValue = defaultValue;
147
        return this;
148
    }
149

    
150
    public EditableFeatureAttributeDescriptor setEvaluator(Evaluator evaluator) {
151
        updateStrongChanges(this.evaluator, evaluator);
152
        this.evaluator = evaluator;
153
        return this;
154
    }
155

    
156
    @Override
157
    public EditableFeatureAttributeDescriptor setFeatureAttributeEmulator(FeatureAttributeEmulator featureAttributeEmulator) {
158
        this.featureAttributeEmulator = featureAttributeEmulator;
159
        return this;
160
    }
161
    
162
    @Override
163
    public EditableFeatureAttributeDescriptor setFeatureAttributeEmulator(Expression expression) {
164
        if( ExpressionUtils.isPhraseEmpty(expression) ) {
165
            this.setFeatureAttributeEmulator((FeatureAttributeEmulator)null);
166
            return this;
167
        } 
168
        FeatureAttributeEmulatorExpression emulator = DALLocator.getDataManager().createFeatureAttributeEmulatorExpression(
169
                this.getFeatureType(),
170
                expression
171
        );
172
        if( !emulator.isValid() ) {
173
            this.setFeatureAttributeEmulator(emulator);
174
            throw new IllegalArgumentException("Can't create calculated field '"+this.getName()+"', "+emulator.getErrorMessage());
175
        }
176
        return this.setFeatureAttributeEmulator(emulator);
177
    }
178

    
179
    @Override
180
    public EditableFeatureAttributeDescriptor setFeatureAttributeEmulator(String expression) {
181
        if( StringUtils.isBlank(expression) ) {
182
            this.setFeatureAttributeEmulator((FeatureAttributeEmulator)null);
183
            return this;
184
        } 
185
        return this.setFeatureAttributeEmulator(ExpressionUtils.createExpression(expression));
186
    }
187
        
188
    @Override
189
    public EditableFeatureAttributeDescriptor setGeometryType(int type) {
190
        this.geometryType = type;
191
        if( this.geometrySubType == Geometry.SUBTYPES.UNKNOWN ) {
192
            this.geometrySubType = Geometry.SUBTYPES.GEOM2D;
193
        }
194
        this.geomType = null;
195
        return this;
196
    }
197

    
198
    public EditableFeatureAttributeDescriptor setGeometrySubType(int subType) {
199
        this.geometrySubType = subType;
200
        this.geomType = null;
201
        return this;
202
    }
203

    
204
    public EditableFeatureAttributeDescriptor setGeometryType(
205
        GeometryType geometryType) {
206
        updateStrongChanges(this.geomType, geometryType);
207
        this.geomType = geometryType;
208
        this.geometryType = this.geomType.getType();
209
        this.geometrySubType = this.geomType.getSubType();
210
        return this;
211
    }
212

    
213
    @Override
214
    public EditableFeatureAttributeDescriptor setGeometryType(String geometryType) {
215
        if( StringUtils.isBlank(geometryType) ) {
216
            throw new IllegalArgumentException("Invalid geometry type (null)");
217
        }
218
        String separators = ":/-!;#@";
219
        Character sep = null;
220
        for (char ch : separators.toCharArray()) {
221
            if( geometryType.indexOf(ch)>=0 ) {
222
                sep = ch;
223
                break;
224
            }
225
        }
226
        if( sep == null ) {
227
            throw new IllegalArgumentException("Invalid geometry type ("+geometryType+") can't find separator, format can be GEOMETRYTYPE["+separators+"]GEOMETRYSUBTYPE");
228
        }
229
        String[] xx = geometryType.split("["+sep+"]");
230
        int theGeomType = GeometryUtils.getGeometryType(xx[0]);
231
        int theGeomSubtype = GeometryUtils.getGeometrySubtype(xx[1]);
232
        this.setGeometryType(theGeomType, theGeomSubtype);
233
        return this;
234
    }
235
            
236
    @Override
237
    public EditableFeatureAttributeDescriptor setGeometryType(int type, int subType) {
238
        this.geometryType = type;
239
        this.geometrySubType = subType;
240
        this.geomType = null;
241
        return this;
242
    }
243

    
244
    public EditableFeatureAttributeDescriptor setIsPrimaryKey(
245
        boolean isPrimaryKey) {
246
        updateStrongChanges(this.primaryKey, primaryKey);
247
        this.primaryKey = isPrimaryKey;
248
        return this;
249
    }
250

    
251
    public EditableFeatureAttributeDescriptor setIsReadOnly(boolean isReadOnly) {
252
        updateStrongChanges(this.readOnly, readOnly);
253
        this.readOnly = isReadOnly;
254
        return this;
255
    }
256

    
257
    public EditableFeatureAttributeDescriptor setMaximumOccurrences(
258
        int maximumOccurrences) {
259
        updateStrongChanges(this.maximumOccurrences, maximumOccurrences);
260
        this.maximumOccurrences = maximumOccurrences;
261
        return this;
262
    }
263

    
264
    public EditableFeatureAttributeDescriptor setMinimumOccurrences(
265
        int minimumOccurrences) {
266
        updateStrongChanges(this.minimumOccurrences, minimumOccurrences);
267
        this.minimumOccurrences = minimumOccurrences;
268
        return this;
269
    }
270

    
271
    @Override
272
    public EditableFeatureAttributeDescriptor setName(String name) {
273
        if( StringUtils.equalsIgnoreCase(this.name, name) ) {
274
            return this;
275
        }
276
        if (originalName == null) {
277
            originalName = this.name;
278
            if (!isComputed()) {
279
                hasStrongChanges = true;
280
            }
281
        }
282
        super.setName(name);
283
        if (!isComputed()) {
284
            hasStrongChanges = true;
285
        }
286
        return this;
287
    }
288
    
289
    public String getOriginalName() {
290
        return originalName;
291
    }
292

    
293
    public EditableFeatureAttributeDescriptor setObjectClass(Class theClass) {
294
        updateStrongChanges(this.objectClass, theClass);
295
        this.objectClass = theClass;
296
        return this;
297
    }
298

    
299
    @Override
300
    public EditableFeatureAttributeDescriptor setPrecision(int precision) {
301
        updateStrongChanges(this.precision, precision);
302
        this.precision = precision;
303
        return this;
304
    }
305

    
306
    @Override
307
    public EditableFeatureAttributeDescriptor setScale(int scale) {
308
        updateStrongChanges(this.scale, scale);
309
        this.scale = scale;
310
        this.coerceContext = null;
311
        this.mathContext = null;
312
        return this;
313
    }
314

    
315
    @Override
316
    public EditableFeatureAttributeDescriptor setSRS(IProjection SRS) {
317
        updateStrongChanges(this.SRS, SRS);
318
        this.SRS = SRS;
319
        return this;
320
    }
321

    
322
    @Override
323
    public EditableFeatureAttributeDescriptor setSRS(String SRS) {
324
        if( StringUtils.isBlank(SRS) ) {
325
            this.setSRS((IProjection)null);
326
            return this;
327
        }
328
        IProjection proj = CRSFactory.getCRS(SRS);
329
        this.setSRS(proj);
330
        return this;
331
    }
332
    
333
    public EditableFeatureAttributeDescriptor setInterval(Interval interval) {
334
        updateStrongChanges(this.getInterval(), interval);
335
        super.setInterval(interval);
336
        return this;
337
    }
338

    
339
    public EditableFeatureAttributeDescriptor setSize(int size) {
340
        updateStrongChanges(this.size, size);
341
        this.size = size;
342
        return this;
343
    }
344

    
345
    public boolean hasStrongChanges() {
346
        return hasStrongChanges;
347
    }
348

    
349
    public EditableFeatureAttributeDescriptor setAdditionalInfo(
350
        String infoName, Object value) {
351
        if (this.additionalInfo == null) {
352
            this.additionalInfo = new HashMap();
353
        }
354
        this.additionalInfo.put(infoName, value);
355
        return this;
356
    }
357

    
358
    public EditableFeatureAttributeDescriptor setIsAutomatic(boolean isAutomatic) {
359
        this.isAutomatic = isAutomatic;
360
        if( isAutomatic ) {
361
            this.setReadOnly(true);
362
        }
363
        return this;
364
    }
365
    
366
    public EditableFeatureAttributeDescriptor setIsTime(boolean isTime) {
367
        updateStrongChanges(this.isTime, isTime);
368
        this.isTime = isTime;
369
        return this;
370
    }
371

    
372
    public EditableFeatureAttributeDescriptor setDateFormat(DateFormat dateFormat) {
373
        this.dateFormat = dateFormat;
374
        return this;
375
    }
376

    
377
    public EditableFeatureAttributeDescriptor setIsIndexed(boolean isIndexed) {
378
        updateStrongChanges(this.indexed, isIndexed);
379
        this.indexed = isIndexed;
380
        return this;
381
    }
382
    
383
    public EditableFeatureAttributeDescriptor setAllowIndexDuplicateds(boolean allowDuplicateds) {
384
        updateStrongChanges(this.allowIndexDuplicateds, allowDuplicateds);
385
        this.allowIndexDuplicateds = allowDuplicateds;
386
        return this;
387
    }
388

    
389
    public EditableFeatureAttributeDescriptor setIsIndexAscending(boolean ascending) {
390
        updateStrongChanges(this.isIndexAscending, ascending);
391
        this.isIndexAscending = ascending;
392
        return this;
393
    }
394

    
395
    @Override
396
    public EditableFeatureAttributeDescriptor setDataProfileName(String dataProfile) {
397
        super.setDataProfileName(dataProfile);
398
        return this;
399
    }
400

    
401
    private void updateStrongChanges(int previous, int newvalue) {
402
        if( isComputed() ) {
403
            return;
404
        }
405
        if( previous == newvalue ) {
406
            return;
407
        }
408
        this.hasStrongChanges = true;
409
    }
410

    
411
    private void updateStrongChanges(DataType previous, int newvalue) {
412
        if( isComputed() ) {
413
            return;
414
        }
415
        if( previous!=null ) {
416
            if( previous.getType() == newvalue ) {
417
                return;
418
            }
419
        }
420
        this.hasStrongChanges = true;
421
    }
422

    
423
    private void updateStrongChanges(boolean previous, boolean newvalue) {
424
        if( isComputed() ) {
425
            return;
426
        }
427
        if( previous == newvalue ) {
428
            return;
429
        }
430
        this.hasStrongChanges = true;
431
    }
432

    
433
    private void updateStrongChanges(Object previous, Object newvalue) {
434
        if( isComputed() ) {
435
            return;
436
        }
437
        if( Objects.equals(newvalue, previous) ) {
438
            return;
439
        }
440
        this.hasStrongChanges = true;
441
    }
442

    
443
    @Override
444
    public EditableFeatureAttributeDescriptor setLocale(Locale locale) {
445
      if( locale == null ) {
446
        this.locale = Locale.ENGLISH;
447
      } else {
448
        this.locale = locale;
449
      }
450
      this.coerceContext = null;
451
      this.mathContext = null;
452
      return this;
453
    }
454

    
455
    public EditableFeatureAttributeDescriptor setLocale(String locale) {
456
      Locale l;
457
      try {
458
        String s = DataTypeUtils.toString(locale, null);
459
        if( StringUtils.isBlank(s) ) {
460
          return this.setLocale((Locale)null);
461
        }
462
        l = new Locale(s);
463
        return this.setLocale(l);
464
      } catch(Exception ex) {
465
          return this.setLocale((Locale)null);
466
      }
467
    }
468
    
469
    @Override
470
    public EditableFeatureAttributeDescriptor setRoundMode(int roundMode) {
471
      switch(roundMode) {
472
        case BigDecimal.ROUND_UP:
473
        case BigDecimal.ROUND_DOWN:
474
        case BigDecimal.ROUND_CEILING:
475
        case BigDecimal.ROUND_FLOOR:
476
        case BigDecimal.ROUND_HALF_UP:
477
        case BigDecimal.ROUND_HALF_DOWN:
478
        case BigDecimal.ROUND_HALF_EVEN:
479
        case BigDecimal.ROUND_UNNECESSARY:
480
          this.roundMode = roundMode;
481
          this.coerceContext = null;
482
          this.mathContext = null;
483
          break;
484
        default:
485
          throw new IllegalArgumentException("round mode '"+roundMode+"' not valid.");
486
      }
487
      return this;
488
    }
489

    
490
    @Override
491
    public EditableFeatureAttributeDescriptor set(String name, Object value) {
492
        if( StringUtils.isBlank(name)) {
493
            throw new IllegalArgumentException("Name can't be empty");
494
        }
495
        switch(name.toLowerCase()) {
496
            case "isreadonly":
497
            case "readonly":
498
                this.setIsReadOnly(DataTypeUtils.toBoolean(value, false));
499
                break;
500
            case "hidden":
501
                this.setHidden(DataTypeUtils.toBoolean(value, false));
502
                break;
503
            case "allownull":
504
                this.setAllowNull(DataTypeUtils.toBoolean(value, false));
505
                break;
506
            case "pk":
507
            case "ispk":
508
            case "primarykey":
509
            case "isprimarykey":
510
                this.setIsPrimaryKey(DataTypeUtils.toBoolean(value, false));
511
                break;
512
            case "isautomatic":
513
            case "automatic":
514
                this.setIsAutomatic(DataTypeUtils.toBoolean(value, false));
515
                break;
516
            case "time":
517
            case "istime":
518
                this.setIsTime(DataTypeUtils.toBoolean(value, false));
519
                break;
520
            case "profile":
521
                this.setDataProfileName(DataTypeUtils.toString(value, null));
522
                break;
523
            case "group":
524
                this.setGroup(DataTypeUtils.toString(value, null));
525
                break;
526
            case "description":
527
                this.setDescription(DataTypeUtils.toString(value, null));
528
                break;
529
            case "label":
530
                this.setLabel(DataTypeUtils.toString(value, null));
531
                break;
532
            case "shortlabel":
533
                this.setShortLabel(DataTypeUtils.toString(value, null));
534
                break;
535
            case "expression":
536
                this.setFeatureAttributeEmulator(DataTypeUtils.toString(value, null));
537
                break;
538
            case "size":
539
                this.setSize(DataTypeUtils.toInteger(value, 50));
540
                break;
541
            case "precision":
542
                this.setPrecision(DataTypeUtils.toInteger(value, 10));
543
                break;
544
            case "scale":
545
                this.setScale(DataTypeUtils.toInteger(value, 10));
546
                break;
547
            case "roundmode":
548
              this.setRoundMode(DataTypeUtils.toInteger(value, BigDecimal.ROUND_UNNECESSARY));
549
              break;
550
            case "locale":
551
              this.setLocale(DataTypeUtils.toString(value, null));
552
              break;
553
            case "order":
554
                this.setOrder(DataTypeUtils.toInteger(value, 0));
555
                break;
556
            case "foreingkey":
557
                this.getForeingKey().setForeingKey(DataTypeUtils.toBoolean(value, false));
558
                break;
559
            case "foreingkey.code":
560
                this.getForeingKey().setCodeName(DataTypeUtils.toString(value, ""));
561
                break;
562
            case "foreingkey.label":
563
                this.getForeingKey().setLabelFormula(DataTypeUtils.toString(value, ""));
564
                break;
565
            case "foreingkey.closedlist":
566
                this.getForeingKey().setClosedList(DataTypeUtils.toBoolean(value, false));
567
                break;
568
            case "foreingkey.table":
569
                this.getForeingKey().setTableName(DataTypeUtils.toString(value, null));
570
                break;
571
            case "interval":
572
                this.setInterval(DataTypeUtils.toInterval(value, null));
573
                break;
574
            case "geomtype":
575
            case "geometrytype":
576
                this.setGeometryType(DataTypeUtils.toString(value, null));
577
                break;
578
            case "srs":
579
                this.setSRS(DataTypeUtils.toProjection(value, null));
580
                break;
581
            default:
582
                throw new IllegalArgumentException("Name attribute '"+name+"' not valid.");
583
        }     
584
        return this;
585
    }
586
    
587
    
588
}