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

History | View | Annotate | Download (20.7 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.dynobject.DynField;
57
import org.gvsig.tools.evaluator.Evaluator;
58

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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