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

History | View | Annotate | Download (14.8 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.get(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 selectable;
134
    private String labelFormula;
135
    private String tableName;
136
    private String codeName;
137

    
138
    private FeatureAttributeDescriptor descriptor;
139

    
140
    public DefaultForeingKey() {
141

    
142
    }
143

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

    
148
    @Override
149
    public boolean isSelectable() {
150
        return this.selectable;
151
    }
152

    
153
    @Override
154
    public void setSelectable(boolean selectable) {
155
        this.selectable = selectable;
156
    }
157

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
384
    @Override
385
    public DynObjectValueItem[] getAvailableValues(ContextForeingKey context) {
386
        if (!this.isSelectable()) {
387
            return null;
388
        }
389
        context = createLocalContextIfNull(context);
390
        try {
391
            Expression labelExpression = context.getLabelExpression();
392
            FeatureStore store = context.getFeatureStore();
393
            if (store == null) {
394
                return null;
395
            }
396

    
397
            int count = (int) store.getFeatureCount();
398
            DynObjectValueItem[] values = new DynObjectValueItem[Math.min(count, MAX_AVAILABLE_VALUES)];
399
            int n = 0;
400
            for (Feature feature : store.getFeatureSet()) {
401
                Object code = feature.get(codeName);
402
                Object value;
403
                if (labelExpression == null) {
404
                    value = code;
405
                } else {
406
                    context.getFeatureSymbolTable().setFeature(feature);
407
                    value = labelExpression.execute(context.getSymbolTable());
408
                }
409
                values[n++] = new DynObjectValueItem(code, Objects.toString(value, Objects.toString(code, "##ERROR##")));
410
                if( n>=MAX_AVAILABLE_VALUES ) {
411
                    break;
412
                }
413
            }
414
            return values;
415
        } catch (Exception ex) {
416
            LOGGER.warn("Can't get values from table '" + tableName + "' of field.", ex);
417
        } finally {
418
            disposeIfLocalContext(context);
419
        }
420
        return null;
421
    }
422

    
423
    @Override
424
    public void loadFromState(PersistentState state)
425
            throws PersistenceException {
426
        foreingKey = state.getBoolean("foreingKey");
427
        selectable = state.getBoolean("selectable");
428
        labelFormula = state.getString("labelFormula");
429
        codeName = state.getString("codeName");
430
        tableName = state.getString("tableName");
431
    }
432

    
433
    @Override
434
    public void saveToState(PersistentState state) throws PersistenceException {
435
        state.set("foreingKey", foreingKey);
436
        state.set("selectable", selectable);
437
        state.set("labelFormula", labelFormula);
438
        state.set("codeName", codeName);
439
        state.set("tableName", tableName);
440
    }
441

    
442
    private static final String FOREINGKEY_PERSISTENCE_DEFINITION_NAME = "ForeingKey";
443

    
444
    public static void registerPersistenceDefinition() {
445
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
446

    
447
        if (manager.getDefinition(FOREINGKEY_PERSISTENCE_DEFINITION_NAME)
448
                == null) {
449
            DynStruct definition = manager.addDefinition(DefaultForeingKey.class,
450
                    FOREINGKEY_PERSISTENCE_DEFINITION_NAME,
451
                    FOREINGKEY_PERSISTENCE_DEFINITION_NAME
452
                    + " persistent definition",
453
                    null,
454
                    null
455
            );
456
            definition.addDynFieldBoolean("foreingKey");
457
            definition.addDynFieldBoolean("selectable");
458
            definition.addDynFieldString("LabelFormula");
459
            definition.addDynFieldString("codeName");
460
            definition.addDynFieldString("tableName");
461
        }
462
    }
463

    
464
    @Override
465
    public ForeingKey clone() throws CloneNotSupportedException {
466
        DefaultForeingKey other = (DefaultForeingKey) super.clone();
467
        return other;
468
    }
469

    
470
}