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 @ 44745

History | View | Annotate | Download (20.6 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 static org.gvsig.tools.dataTypes.DataTypeUtils.coerce;
57
import org.gvsig.tools.dynobject.DynField;
58
import org.gvsig.tools.evaluator.Evaluator;
59

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

    
67
    private final DefaultFeatureAttributeDescriptor source;
68
    private boolean hasStrongChanges;
69
    private String originalName = null;
70

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

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

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

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

    
113
        if (ex.size() > 0) {
114
            throw ex;
115
        }
116
    }
117

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

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

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

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

    
158
    @Override
159
    public EditableFeatureAttributeDescriptor setFeatureAttributeEmulator(FeatureAttributeEmulator featureAttributeEmulator) {
160
        this.featureAttributeEmulator = featureAttributeEmulator;
161
        return this;
162
    }
163
    
164
    @Override
165
    public EditableFeatureAttributeDescriptor setFeatureAttributeEmulator(Expression expression) {
166
        if( ExpressionUtils.isPhraseEmpty(expression) ) {
167
            this.setFeatureAttributeEmulator((FeatureAttributeEmulator)null);
168
            return this;
169
        } 
170
        FeatureAttributeEmulatorExpression emulator = DALLocator.getDataManager().createFeatureAttributeEmulatorExpression(
171
                this.getFeatureType(),
172
                expression
173
        );
174
        return this.setFeatureAttributeEmulator(emulator);
175
    }
176

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
343
    public boolean hasStrongChanges() {
344
        return hasStrongChanges;
345
    }
346

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

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

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

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

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

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

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

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

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

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

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

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

    
488
    @Override
489
    public EditableFeatureAttributeDescriptor set(String name, Object value) {
490
        if( StringUtils.isBlank(name)) {
491
            throw new IllegalArgumentException("Name can't be empty");
492
        }
493
        switch(name.toLowerCase()) {
494
            case "isreadonly":
495
            case "readonly":
496
                this.setIsReadOnly(DataTypeUtils.toBoolean(value, false));
497
                break;
498
            case "hidden":
499
                this.setHidden(DataTypeUtils.toBoolean(value, false));
500
                break;
501
            case "allownull":
502
                this.setAllowNull(DataTypeUtils.toBoolean(value, false));
503
                break;
504
            case "pk":
505
            case "ispk":
506
            case "primarykey":
507
            case "isprimarykey":
508
                this.setIsPrimaryKey(DataTypeUtils.toBoolean(value, false));
509
                break;
510
            case "isautomatic":
511
            case "automatic":
512
                this.setIsAutomatic(DataTypeUtils.toBoolean(value, false));
513
                break;
514
            case "time":
515
            case "istime":
516
                this.setIsTime(DataTypeUtils.toBoolean(value, false));
517
                break;
518
            case "profile":
519
                this.setDataProfileName(DataTypeUtils.toString(value, null));
520
                break;
521
            case "group":
522
                this.setGroup(DataTypeUtils.toString(value, null));
523
                break;
524
            case "description":
525
                this.setDescription(DataTypeUtils.toString(value, null));
526
                break;
527
            case "label":
528
                this.setLabel(DataTypeUtils.toString(value, null));
529
                break;
530
            case "shortlabel":
531
                this.setShortLabel(DataTypeUtils.toString(value, null));
532
                break;
533
            case "expression":
534
                this.setFeatureAttributeEmulator(DataTypeUtils.toString(value, null));
535
                break;
536
            case "size":
537
                this.setSize(DataTypeUtils.toInteger(value, 50));
538
                break;
539
            case "precision":
540
                this.setPrecision(DataTypeUtils.toInteger(value, 10));
541
                break;
542
            case "scale":
543
                this.setScale(DataTypeUtils.toInteger(value, 10));
544
                break;
545
            case "roundmode":
546
              this.setRoundMode(DataTypeUtils.toInteger(value, BigDecimal.ROUND_UNNECESSARY));
547
              break;
548
            case "locale":
549
              this.setLocale(DataTypeUtils.toString(value, null));
550
              break;
551
            case "order":
552
                this.setOrder(DataTypeUtils.toInteger(value, 0));
553
                break;
554
            case "foreingkey":
555
                this.getForeingKey().setForeingKey(DataTypeUtils.toBoolean(value, false));
556
                break;
557
            case "foreingkey.code":
558
                this.getForeingKey().setCodeName(DataTypeUtils.toString(value, ""));
559
                break;
560
            case "foreingkey.label":
561
                this.getForeingKey().setLabelFormula(DataTypeUtils.toString(value, ""));
562
                break;
563
            case "foreingkey.closedlist":
564
                this.getForeingKey().setClosedList(DataTypeUtils.toBoolean(value, false));
565
                break;
566
            case "foreingkey.table":
567
                this.getForeingKey().setTableName(DataTypeUtils.toString(value, null));
568
                break;
569
            case "interval":
570
                this.setInterval(DataTypeUtils.toInterval(value, null));
571
                break;
572
            case "geomtype":
573
            case "geometrytype":
574
                this.setGeometryType(DataTypeUtils.toString(value, null));
575
                break;
576
            case "srs":
577
                this.setSRS(DataTypeUtils.toProjection(value, null));
578
                break;
579
            case "relation":
580
                this.setRelationType(toRelation(value));
581
                break;
582
            default:
583
                throw new IllegalArgumentException("Name attribute '"+name+"' not valid.");
584
        }     
585
        return this;
586
    }
587
    
588
    private int toRelation(Object value) {
589
      if (value == null) {
590
        return DynField.RELATION_TYPE_NONE;
591
      }
592
      Integer x = (Integer) DataTypeUtils.coerce(DataTypes.INT,value, null);
593
      if (x != null) {
594
        return x;
595
      }
596
      try {
597
        String s = value.toString().toUpperCase();
598
        switch (s) {
599
          case "NONE":
600
          default:
601
            return DynField.RELATION_TYPE_NONE;
602
          case "IDENTITY":
603
            return DynField.RELATION_TYPE_IDENTITY;
604
          case "COLLABORATION":
605
            return DynField.RELATION_TYPE_COLLABORATION;
606
          case "COMPOSITION":
607
            return DynField.RELATION_TYPE_COMPOSITION;
608
          case "AGGREGATE":
609
            return DynField.RELATION_TYPE_AGGREGATE;
610
        }
611
      } catch(Exception ex) {
612
        return DynField.RELATION_TYPE_NONE;
613
      }
614
    }
615
}