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 / DefaultForeingKey.java @ 44363

History | View | Annotate | Download (16.3 KB)

1
package org.gvsig.fmap.dal.feature.impl;
2

    
3
import org.gvsig.fmap.dal.feature.EditableForeingKey;
4
import org.gvsig.fmap.dal.feature.ForeingKey;
5
import java.util.List;
6
import java.util.Objects;
7
import org.apache.commons.lang3.StringUtils;
8
import org.gvsig.expressionevaluator.Expression;
9
import org.gvsig.expressionevaluator.ExpressionBuilder;
10
import org.gvsig.expressionevaluator.ExpressionUtils;
11
import org.gvsig.expressionevaluator.SymbolTable;
12
import org.gvsig.fmap.dal.DALLocator;
13
import org.gvsig.fmap.dal.DataManager;
14
import org.gvsig.fmap.dal.StoresRepository;
15
import org.gvsig.fmap.dal.exception.DataException;
16
import org.gvsig.fmap.dal.expressionevaluator.FeatureSymbolTable;
17
import org.gvsig.fmap.dal.feature.Feature;
18
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
19
import org.gvsig.fmap.dal.feature.FeatureQuery;
20
import org.gvsig.fmap.dal.feature.FeatureStore;
21
import org.gvsig.fmap.dal.feature.FeatureType;
22
import org.gvsig.tools.ToolsLocator;
23
import org.gvsig.tools.dispose.DisposeUtils;
24
import org.gvsig.tools.dynobject.DynObjectValueItem;
25
import org.gvsig.tools.dynobject.DynStruct;
26
import org.gvsig.tools.persistence.PersistenceManager;
27
import org.gvsig.tools.persistence.Persistent;
28
import org.gvsig.tools.persistence.PersistentState;
29
import org.gvsig.tools.persistence.exception.PersistenceException;
30
import org.slf4j.Logger;
31
import org.slf4j.LoggerFactory;
32

    
33
/**
34
 *
35
 * @author jjdelcerro
36
 */
37
@SuppressWarnings("UseSpecificCatch")
38
public class DefaultForeingKey implements Persistent, ForeingKey, EditableForeingKey, org.gvsig.tools.lang.Cloneable {
39

    
40
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultForeingKey.class);
41

    
42
    private class DefaultContextForeingKey implements ContextForeingKey {
43

    
44
        private FeatureStore featureStore = null;
45
        private StoresRepository storesRepository = null;
46
        private Expression labelExpression;
47
        private SymbolTable symbolTable;
48
        private FeatureSymbolTable featureSymbolTable;
49
        private int refs;
50

    
51
        public DefaultContextForeingKey() {
52
            this.refs = 1;
53
        }
54
        
55
        public void addRef() {
56
            this.refs++;
57
        }
58

    
59
        public void relese() {
60
            this.refs--;
61
        }
62
        
63
        @Override
64
        public void dispose() {
65
            DisposeUtils.disposeQuietly(featureStore);
66
            this.featureStore = null;
67
            this.storesRepository = null;
68
            this.labelExpression = null;
69
            this.symbolTable = null;
70
            this.featureSymbolTable = null;
71
        }
72

    
73
        @Override
74
        public StoresRepository getStoresRepository() {
75
            if (this.storesRepository == null) {
76
                FeatureStore store = descriptor.getStore();
77
                if (store == null) {
78
                    this.storesRepository = DALLocator.getDataManager().getStoresRepository();
79

    
80
                } else {
81
                    this.storesRepository = store.getStoresRepository();
82
                }
83
            }
84
            return this.storesRepository;
85
        }
86

    
87
        @Override
88
        public FeatureStore getFeatureStore() {
89
            if (this.featureStore == null) {
90
                StoresRepository repository = this.getStoresRepository();
91
                this.featureStore = (FeatureStore) repository.getStore(tableName);
92
                if (this.featureStore == null) {
93
                    LOGGER.warn("Can't locate store '" + tableName + "' to get available values of field '" + descriptor.getName() + "'.");
94
                    return null;
95
                }
96
            }
97
            return this.featureStore;
98
        }
99

    
100
        @Override
101
        public Expression getLabelExpression() {
102
            if (this.labelExpression == null) {
103
                if (StringUtils.isBlank(labelFormula)) {
104
                    return null;
105
                }
106
                this.labelExpression = ExpressionUtils.createExpression(labelFormula);
107
            }
108
            return this.labelExpression;
109
        }
110

    
111
        @Override
112
        public FeatureSymbolTable getFeatureSymbolTable() {
113
            if (this.featureSymbolTable == null) {
114
                DataManager dataManager = DALLocator.getDataManager();
115
                this.featureSymbolTable = dataManager.createFeatureSymbolTable();
116
                this.symbolTable = this.featureSymbolTable.createParent();
117
            }
118
            return this.featureSymbolTable;
119
        }
120

    
121
        @Override
122
        public SymbolTable getSymbolTable() {
123
            if (this.symbolTable == null) {
124
                DataManager dataManager = DALLocator.getDataManager();
125
                this.featureSymbolTable = dataManager.createFeatureSymbolTable();
126
                this.symbolTable = this.featureSymbolTable.createParent();
127
            }
128
            return this.symbolTable;
129
        }
130
    }
131

    
132
    private boolean foreingKey;
133
    private boolean closedList;
134
    private String labelFormula;
135
    private String tableName;
136
    private String codeName;
137
    private DynObjectValueItem[] availableValues;
138
    private boolean ensureReferentialIntegrity;
139
    private FeatureAttributeDescriptor descriptor;
140

    
141
    public DefaultForeingKey() {
142
        this.foreingKey = false;
143
        this.closedList = false;
144
        this.tableName = null;
145
        this.codeName = null;
146
        this.labelFormula = null;
147
        this.ensureReferentialIntegrity = false;
148
    }
149

    
150
    public void setDescriptor(FeatureAttributeDescriptor descriptor) {
151
        this.descriptor = descriptor;
152
    }
153

    
154
    @Override
155
    public boolean isClosedList() {
156
        return this.closedList;
157
    }
158

    
159
    @Override
160
    public void setClosedList(boolean selectable) {
161
        this.closedList = selectable;
162
    }
163

    
164
    @Override
165
    public boolean isForeingKey() {
166
        return this.foreingKey;
167
    }
168

    
169
    @Override
170
    public void setForeingKey(boolean foreingKey) {
171
        this.foreingKey = foreingKey;
172
    }
173

    
174
    @Override
175
    public String getLabelFormula() {
176
        return this.labelFormula;
177
    }
178

    
179
    @Override
180
    public void setLabelFormula(String labelFormula) {
181
        this.labelFormula = labelFormula;
182
    }
183

    
184
    @Override
185
    public String getCodeName() {
186
        return this.codeName;
187
    }
188

    
189
    @Override
190
    public void setCodeName(String codeName) {
191
        this.codeName = codeName;
192
    }
193

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

    
199
    @Override
200
    public void setTableName(String tableName) {
201
        this.tableName = tableName;
202
    }
203

    
204
    @Override
205
    public boolean isEmpty() {
206
        if (!this.foreingKey
207
                && !this.closedList
208
                && StringUtils.isBlank(this.tableName)
209
                && StringUtils.isBlank(this.codeName)
210
                && StringUtils.isBlank(this.labelFormula)) {
211
            return true;
212
        }
213
        return false;
214
    }
215

    
216
    @Override
217
    public void clean() {
218
        this.foreingKey = false;
219
        this.closedList = false;
220
        this.tableName = null;
221
        this.codeName = null;
222
        this.labelFormula = null;
223
        this.ensureReferentialIntegrity = false;
224
    }
225

    
226
    private void disposeIfLocalContext(ContextForeingKey context) {
227
        DefaultContextForeingKey c = (DefaultContextForeingKey) context;
228
        c.relese();
229
        if( c.refs == 0 ) {
230
            context.dispose();
231
        }
232
    }
233

    
234
    private ContextForeingKey createLocalContextIfNull(ContextForeingKey context) {
235
        if (context == null) {
236
            return new DefaultContextForeingKey();
237
        }
238
        DefaultContextForeingKey c = (DefaultContextForeingKey) context;
239
        c.addRef();
240
        return c;
241
    }
242

    
243
    @Override
244
    public ContextForeingKey createContext() {
245
        return new DefaultContextForeingKey();
246
    }
247

    
248
    @Override
249
    public StoresRepository getStoresRepository(ContextForeingKey context) {
250
        context = createLocalContextIfNull(context);
251
        try {
252
            return context.getStoresRepository();
253
        } finally {
254
            disposeIfLocalContext(context);
255
        }
256
    }
257

    
258
    @Override
259
    public FeatureStore getFeatureStore(ContextForeingKey context) {
260
        context = createLocalContextIfNull(context);
261
        try {
262
            return context.getFeatureStore();
263
        } finally {
264
            disposeIfLocalContext(context);
265
        }
266
    }
267

    
268
    @Override
269
    public FeatureType getFeatureType(ContextForeingKey context) {
270
        context = createLocalContextIfNull(context);
271
        FeatureStore store = context.getFeatureStore();
272
        if (store == null) {
273
            return null;
274
        }
275
        try {
276
            return store.getDefaultFeatureType();
277
        } catch (DataException ex) {
278
            return null;
279
        } finally {
280
            disposeIfLocalContext(context);
281
        }
282
    }
283

    
284
    @Override
285
    public List<Feature> getFeatures(ContextForeingKey context) {
286
        context = createLocalContextIfNull(context);
287
        FeatureStore store = context.getFeatureStore();
288
        if (store == null) {
289
            return null;
290
        }
291
        try {
292
            return store.getFeatures();
293
        } finally {
294
            disposeIfLocalContext(context);
295
        }
296
    }
297

    
298
    @Override
299
    public Object getCode(ContextForeingKey context, Feature feature) {
300
//        context = createLocalContextIfNull(context);
301
        try {
302
            return feature.get(codeName);
303
        } finally {
304
//            disposeIfLocalContext(context);
305
        }
306
    }
307

    
308
    @Override
309
    public FeatureQuery getQuery(ContextForeingKey context, Object codeValue) {
310
        context = createLocalContextIfNull(context);
311
        try {
312
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
313
            FeatureStore store = context.getFeatureStore();
314
            FeatureQuery query = store.createFeatureQuery();
315
            query.setFilter(builder.eq(
316
                    builder.variable(codeName),
317
                    builder.constant(codeValue)
318
            ).toString()
319
            );
320
            query.retrievesAllAttributes();
321
            return query;
322
        } finally {
323
            disposeIfLocalContext(context);
324
        }
325
    }
326

    
327
    @Override
328
    public Feature getFeature(ContextForeingKey context, Object codeValue) {
329
        context = createLocalContextIfNull(context);
330
        try {
331
            FeatureStore store = context.getFeatureStore();
332
            if (store == null) {
333
                return null;
334
            }
335
            FeatureQuery query = this.getQuery(context, codeValue);
336
            Feature feature = store.findFirst(query);
337
            return feature;
338
        } catch (DataException ex) {
339
            return null;
340
        } finally {
341
            disposeIfLocalContext(context);
342
        }
343
    }
344

    
345
    @Override
346
    public String getLabel(ContextForeingKey context, Object codeValue) {
347
        context = createLocalContextIfNull(context);
348
        try {
349
            Feature feature = this.getFeature(context, codeValue);
350
            if (feature == null) {
351
                return null;
352
            }
353
            return getLabel(context, feature);
354
        } finally {
355
            disposeIfLocalContext(context);
356
        }
357
    }
358

    
359
    @Override
360
    public Expression getLabelExpression(ContextForeingKey context) {
361
        context = createLocalContextIfNull(context);
362
        try {
363
            return context.getLabelExpression();
364
        } finally {
365
            disposeIfLocalContext(context);
366
        }
367
    }
368

    
369
    @Override
370
    public String getLabel(ContextForeingKey context, Feature feature) {
371
        if (feature == null) {
372
            return null;
373
        }
374
        context = createLocalContextIfNull(context);
375
        try {
376
            Expression labelExpression = context.getLabelExpression();
377
            if (labelExpression == null) {
378
                return feature.toString();
379
            }
380
            context.getFeatureSymbolTable().setFeature(feature);
381
            Object x = labelExpression.execute(context.getSymbolTable());
382
            if (x == null) {
383
                return null;
384
            }
385
            return x.toString();
386
        } finally {
387
            disposeIfLocalContext(context);
388
        }
389
    }
390

    
391
    @Override
392
    public DynObjectValueItem[] getAvailableValues(ContextForeingKey context) {
393
        if (!this.isClosedList()) {
394
            return null;
395
        }
396
        if( this.availableValues == null ) {
397
            context = createLocalContextIfNull(context);
398
            try {
399
                Expression labelExpression = context.getLabelExpression();
400
                FeatureStore store = context.getFeatureStore();
401
                if (store == null) {
402
                    return null;
403
                }
404
                int count = (int) store.getFeatureCount();
405
                DynObjectValueItem[] values = new DynObjectValueItem[Math.min(count, MAX_AVAILABLE_VALUES)];
406
                int n = 0;
407
                for (Feature feature : store.getFeatureSet()) {
408
                    Object code = feature.get(codeName);
409
                    Object value;
410
                    if (labelExpression == null) {
411
                        value = code;
412
                    } else {
413
                        context.getFeatureSymbolTable().setFeature(feature);
414
                        value = labelExpression.execute(context.getSymbolTable());
415
                    }
416
                    values[n++] = new DynObjectValueItem(code, Objects.toString(value, Objects.toString(code, "##ERROR##")));
417
                    if( n>=MAX_AVAILABLE_VALUES ) {
418
                        break;
419
                    }
420
                }
421
                this.availableValues = values;
422
            } catch (Exception ex) {
423
                LOGGER.warn("Can't get values from table '" + tableName + "' of field.", ex);
424
            } finally {
425
                disposeIfLocalContext(context);
426
            }
427
        }
428
        return this.availableValues;
429
    }
430
    
431
    @Override
432
    public String getLabelForValue(Object value) {
433
        DynObjectValueItem[] values = this.getAvailableValues(null);
434
        if( values != null ) {
435
            for (DynObjectValueItem value1 : values) {
436
                if( Objects.equals(value, value1.getValue()) ) {
437
                    return value1.getLabel();
438
                }
439
            }
440
        }
441
        return Objects.toString(value, "##ERROR##");
442
    }
443

    
444
    @Override
445
    public void loadFromState(PersistentState state)
446
            throws PersistenceException {
447
        foreingKey = state.getBoolean("foreingKey");
448
        closedList = state.getBoolean("selectable");
449
        labelFormula = state.getString("labelFormula");
450
        codeName = state.getString("codeName");
451
        tableName = state.getString("tableName");
452
        ensureReferentialIntegrity = state.getBoolean("ensureReferentialIntegrity");
453
    }
454

    
455
    @Override
456
    public void saveToState(PersistentState state) throws PersistenceException {
457
        state.set("foreingKey", foreingKey);
458
        state.set("selectable", closedList);
459
        state.set("labelFormula", labelFormula);
460
        state.set("codeName", codeName);
461
        state.set("tableName", tableName);
462
        state.set("ensureReferentialIntegrity", ensureReferentialIntegrity);
463
    }
464

    
465
    private static final String FOREINGKEY_PERSISTENCE_DEFINITION_NAME = "ForeingKey";
466

    
467
    public static void registerPersistenceDefinition() {
468
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
469

    
470
        if (manager.getDefinition(FOREINGKEY_PERSISTENCE_DEFINITION_NAME)
471
                == null) {
472
            DynStruct definition = manager.addDefinition(DefaultForeingKey.class,
473
                    FOREINGKEY_PERSISTENCE_DEFINITION_NAME,
474
                    FOREINGKEY_PERSISTENCE_DEFINITION_NAME
475
                    + " persistent definition",
476
                    null,
477
                    null
478
            );
479
            definition.addDynFieldBoolean("foreingKey");
480
            definition.addDynFieldBoolean("selectable");
481
            definition.addDynFieldString("LabelFormula");
482
            definition.addDynFieldString("codeName");
483
            definition.addDynFieldString("tableName");
484
            definition.addDynFieldBoolean("ensureReferentialIntegrity");
485
        }
486
    }
487

    
488
    @Override
489
    public ForeingKey clone() throws CloneNotSupportedException {
490
        DefaultForeingKey other = (DefaultForeingKey) super.clone();
491
        return other;
492
    }
493

    
494
    @Override
495
    public boolean getEnsureReferentialIntegrity() {
496
        return this.ensureReferentialIntegrity;
497
    }
498

    
499
    @Override
500
    public void setEnsureReferentialIntegrity(boolean ensureReferentialIntegrity) {
501
        this.ensureReferentialIntegrity = ensureReferentialIntegrity;
502
    }
503
    
504
    
505

    
506
}