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

History | View | Annotate | Download (15.4 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

    
139
    private FeatureAttributeDescriptor descriptor;
140

    
141
    public DefaultForeingKey() {
142

    
143
    }
144

    
145
    public void setDescriptor(FeatureAttributeDescriptor descriptor) {
146
        this.descriptor = descriptor;
147
    }
148

    
149
    @Override
150
    public boolean isClosedList() {
151
        return this.closedList;
152
    }
153

    
154
    @Override
155
    public void setClosedList(boolean selectable) {
156
        this.closedList = selectable;
157
    }
158

    
159
    @Override
160
    public boolean isForeingKey() {
161
        return this.foreingKey;
162
    }
163

    
164
    @Override
165
    public void setForeingKey(boolean foreingKey) {
166
        this.foreingKey = foreingKey;
167
    }
168

    
169
    @Override
170
    public String getLabelFormula() {
171
        return this.labelFormula;
172
    }
173

    
174
    @Override
175
    public void setLabelFormula(String labelFormula) {
176
        this.labelFormula = labelFormula;
177
    }
178

    
179
    @Override
180
    public String getCodeName() {
181
        return this.codeName;
182
    }
183

    
184
    @Override
185
    public void setCodeName(String codeName) {
186
        this.codeName = codeName;
187
    }
188

    
189
    @Override
190
    public String getTableName() {
191
        return this.tableName;
192
    }
193

    
194
    @Override
195
    public void setTableName(String tableName) {
196
        this.tableName = tableName;
197
    }
198

    
199
    @Override
200
    public boolean isEmpty() {
201
        if (!this.foreingKey
202
                && !this.closedList
203
                && StringUtils.isBlank(this.tableName)
204
                && StringUtils.isBlank(this.codeName)
205
                && StringUtils.isBlank(this.labelFormula)) {
206
            return true;
207
        }
208
        return false;
209
    }
210

    
211
    @Override
212
    public void clean() {
213
        this.foreingKey = false;
214
        this.closedList = false;
215
        this.tableName = null;
216
        this.codeName = null;
217
        this.labelFormula = null;
218
    }
219

    
220
    private void disposeIfLocalContext(ContextForeingKey context) {
221
        DefaultContextForeingKey c = (DefaultContextForeingKey) context;
222
        c.relese();
223
        if( c.refs == 0 ) {
224
            context.dispose();
225
        }
226
    }
227

    
228
    private ContextForeingKey createLocalContextIfNull(ContextForeingKey context) {
229
        if (context == null) {
230
            return new DefaultContextForeingKey();
231
        }
232
        DefaultContextForeingKey c = (DefaultContextForeingKey) context;
233
        c.addRef();
234
        return c;
235
    }
236

    
237
    @Override
238
    public ContextForeingKey createContext() {
239
        return new DefaultContextForeingKey();
240
    }
241

    
242
    @Override
243
    public StoresRepository getStoresRepository(ContextForeingKey context) {
244
        context = createLocalContextIfNull(context);
245
        try {
246
            return context.getStoresRepository();
247
        } finally {
248
            disposeIfLocalContext(context);
249
        }
250
    }
251

    
252
    @Override
253
    public FeatureStore getFeatureStore(ContextForeingKey context) {
254
        context = createLocalContextIfNull(context);
255
        try {
256
            return context.getFeatureStore();
257
        } finally {
258
            disposeIfLocalContext(context);
259
        }
260
    }
261

    
262
    @Override
263
    public FeatureType getFeatureType(ContextForeingKey context) {
264
        context = createLocalContextIfNull(context);
265
        FeatureStore store = context.getFeatureStore();
266
        if (store == null) {
267
            return null;
268
        }
269
        try {
270
            return store.getDefaultFeatureType();
271
        } catch (DataException ex) {
272
            return null;
273
        } finally {
274
            disposeIfLocalContext(context);
275
        }
276
    }
277

    
278
    @Override
279
    public List<Feature> getFeatures(ContextForeingKey context) {
280
        context = createLocalContextIfNull(context);
281
        FeatureStore store = context.getFeatureStore();
282
        if (store == null) {
283
            return null;
284
        }
285
        try {
286
            return store.getFeatures();
287
        } finally {
288
            disposeIfLocalContext(context);
289
        }
290
    }
291

    
292
    @Override
293
    public Object getCode(ContextForeingKey context, Feature feature) {
294
//        context = createLocalContextIfNull(context);
295
        try {
296
            return feature.get(codeName);
297
        } finally {
298
//            disposeIfLocalContext(context);
299
        }
300
    }
301

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

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

    
339
    @Override
340
    public String getLabel(ContextForeingKey context, Object codeValue) {
341
        context = createLocalContextIfNull(context);
342
        try {
343
            Feature feature = this.getFeature(context, codeValue);
344
            if (feature == null) {
345
                return null;
346
            }
347
            return getLabel(context, feature);
348
        } finally {
349
            disposeIfLocalContext(context);
350
        }
351
    }
352

    
353
    @Override
354
    public Expression getLabelExpression(ContextForeingKey context) {
355
        context = createLocalContextIfNull(context);
356
        try {
357
            return context.getLabelExpression();
358
        } finally {
359
            disposeIfLocalContext(context);
360
        }
361
    }
362

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

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

    
437
    @Override
438
    public void loadFromState(PersistentState state)
439
            throws PersistenceException {
440
        foreingKey = state.getBoolean("foreingKey");
441
        closedList = state.getBoolean("selectable");
442
        labelFormula = state.getString("labelFormula");
443
        codeName = state.getString("codeName");
444
        tableName = state.getString("tableName");
445
    }
446

    
447
    @Override
448
    public void saveToState(PersistentState state) throws PersistenceException {
449
        state.set("foreingKey", foreingKey);
450
        state.set("selectable", closedList);
451
        state.set("labelFormula", labelFormula);
452
        state.set("codeName", codeName);
453
        state.set("tableName", tableName);
454
    }
455

    
456
    private static final String FOREINGKEY_PERSISTENCE_DEFINITION_NAME = "ForeingKey";
457

    
458
    public static void registerPersistenceDefinition() {
459
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
460

    
461
        if (manager.getDefinition(FOREINGKEY_PERSISTENCE_DEFINITION_NAME)
462
                == null) {
463
            DynStruct definition = manager.addDefinition(DefaultForeingKey.class,
464
                    FOREINGKEY_PERSISTENCE_DEFINITION_NAME,
465
                    FOREINGKEY_PERSISTENCE_DEFINITION_NAME
466
                    + " persistent definition",
467
                    null,
468
                    null
469
            );
470
            definition.addDynFieldBoolean("foreingKey");
471
            definition.addDynFieldBoolean("selectable");
472
            definition.addDynFieldString("LabelFormula");
473
            definition.addDynFieldString("codeName");
474
            definition.addDynFieldString("tableName");
475
        }
476
    }
477

    
478
    @Override
479
    public ForeingKey clone() throws CloneNotSupportedException {
480
        DefaultForeingKey other = (DefaultForeingKey) super.clone();
481
        return other;
482
    }
483

    
484
}