Revision 43215 trunk/org.gvsig.desktop/org.gvsig.desktop.plugin/org.gvsig.daltransform.app/org.gvsig.daltransform.app.join/src/main/java/org/gvsig/app/join/dal/feature/JoinTransform.java
JoinTransform.java | ||
---|---|---|
56 | 56 |
import org.slf4j.Logger; |
57 | 57 |
import org.slf4j.LoggerFactory; |
58 | 58 |
|
59 |
public class JoinTransform extends AbstractFeatureStoreTransform { |
|
59 |
public class JoinTransform |
|
60 |
extends AbstractFeatureStoreTransform { |
|
60 | 61 |
|
61 |
private static Logger logger = LoggerFactory.getLogger(JoinTransform.class);
|
|
62 |
|
|
62 |
private static final Logger logger = LoggerFactory.getLogger(JoinTransform.class);
|
|
63 |
|
|
63 | 64 |
public static final String PERSISTENCE_DEFINITION_NAME = "JoinTransform"; |
64 |
|
|
65 |
|
|
65 | 66 |
/** |
66 | 67 |
* Store from which the join transform will get the additional attributes |
67 | 68 |
*/ |
... | ... | |
85 | 86 |
private String[] attrs; |
86 | 87 |
|
87 | 88 |
/** |
88 |
* Attribute names may change after transformation a prefix is applied. |
|
89 |
* This map keeps correspondence between store1 original names
|
|
90 |
* and their transformed counterparts.
|
|
89 |
* Attribute names may change after transformation a prefix is applied. This
|
|
90 |
* map keeps correspondence between store1 original names and their
|
|
91 |
* transformed counterparts. |
|
91 | 92 |
*/ |
92 |
private Map<String,String> store1NamesMap;
|
|
93 |
private final Map<String, String> store1NamesMap;
|
|
93 | 94 |
|
94 | 95 |
/** |
95 | 96 |
* Attribute names may change after transformation if they are repeated in |
96 | 97 |
* both stores or if a prefix is applied. This map keeps correspondence |
97 | 98 |
* between store2 original names and their transformed counterparts. |
98 | 99 |
*/ |
99 |
private Map<String,String> store2NamesMap;
|
|
100 |
private final Map<String, String> store2NamesMap;
|
|
100 | 101 |
|
101 | 102 |
private JoinTransformEvaluator evaluator = null; |
102 | 103 |
|
... | ... | |
112 | 113 |
* A default constructor |
113 | 114 |
*/ |
114 | 115 |
public JoinTransform() { |
115 |
store1NamesMap = new HashMap<String,String>();
|
|
116 |
store2NamesMap = new HashMap<String,String>();
|
|
116 |
store1NamesMap = new HashMap<>(); |
|
117 |
store2NamesMap = new HashMap<>(); |
|
117 | 118 |
} |
118 | 119 |
|
119 | 120 |
/** |
120 | 121 |
* Initializes all the necessary data for this transform |
121 | 122 |
* |
122 |
* @param store1 |
|
123 |
* store whose default feature type is the target of this |
|
124 |
* transform |
|
123 |
* @param store1 store whose default feature type is the target of this |
|
124 |
* transform |
|
125 | 125 |
* |
126 |
* @param store2 |
|
127 |
* store whose default feature type will provide the new |
|
128 |
* attributes to join |
|
126 |
* @param store2 store whose default feature type will provide the new |
|
127 |
* attributes to join |
|
129 | 128 |
* |
130 |
* @param keyAttr1 |
|
131 |
* key attribute in store1 that matches keyAttr2 in store2 |
|
132 |
* (foreign key), used for joining both stores. |
|
129 |
* @param keyAttr1 key attribute in store1 that matches keyAttr2 in store2 |
|
130 |
* (foreign key), used for joining both stores. |
|
133 | 131 |
* |
134 |
* @param keyAttr2 |
|
135 |
* key attribute in store2 that matches keyAttr1 in store2 |
|
136 |
* (foreign key), used for joining both stores. |
|
132 |
* @param keyAttr2 key attribute in store2 that matches keyAttr1 in store2 |
|
133 |
* (foreign key), used for joining both stores. |
|
134 |
* @param prefix1 |
|
135 |
* @param prefix2 |
|
137 | 136 |
* |
138 |
* @param attrs |
|
139 |
* names of the attributes in store2 that will be joined to |
|
140 |
* store1. |
|
137 |
* @param attrs names of the attributes in store2 that will be joined to |
|
138 |
* store1. |
|
141 | 139 |
*/ |
142 |
public void initialize(FeatureStore store1, FeatureStore store2,
|
|
140 |
public void setValues(FeatureStore store1, FeatureStore store2,
|
|
143 | 141 |
String keyAttr1, String keyAttr2, String prefix1, String prefix2, |
144 |
String[] attrs) |
|
145 |
throws DataException { |
|
142 |
String[] attrs) { |
|
146 | 143 |
|
147 |
if (store1 == store2) {
|
|
144 |
if( store1 == store2 ) {
|
|
148 | 145 |
throw new IllegalArgumentException("store1 == store2"); |
149 | 146 |
} |
150 | 147 |
|
151 |
// Initialize needed data |
|
152 | 148 |
this.setFeatureStore(store1); |
153 | 149 |
this.store2 = store2; |
154 | 150 |
this.keyAttr1 = keyAttr1; |
... | ... | |
157 | 153 |
this.prefix2 = prefix2; // TODO |
158 | 154 |
this.attrs = attrs; |
159 | 155 |
|
156 |
} |
|
157 |
|
|
158 |
@Override |
|
159 |
public void setUp() throws Exception { |
|
160 |
|
|
160 | 161 |
// calculate this transform resulting feature type |
161 | 162 |
// by adding all specified attrs from store2 to store1's default |
162 | 163 |
// feature type |
163 | 164 |
// FIXME for more than one FTypes ?? |
164 |
this.originalFeatureType = this.getFeatureStore() |
|
165 |
.getDefaultFeatureType(); |
|
165 |
this.originalFeatureType = this.getFeatureStore().getDefaultFeatureType(); |
|
166 | 166 |
|
167 | 167 |
// keep index of geometry and att desc ============== |
168 |
int orig_geom_field_index =
|
|
169 |
this.originalFeatureType.getDefaultGeometryAttributeIndex(); |
|
170 |
FeatureAttributeDescriptor orig_geom_field_att =
|
|
171 |
this.originalFeatureType.getDefaultGeometryAttribute(); |
|
172 |
|
|
168 |
int orig_geom_field_index |
|
169 |
= this.originalFeatureType.getDefaultGeometryAttributeIndex();
|
|
170 |
FeatureAttributeDescriptor orig_geom_field_att |
|
171 |
= this.originalFeatureType.getDefaultGeometryAttribute();
|
|
172 |
|
|
173 | 173 |
// Create the feature type and copy the store 1 type |
174 | 174 |
EditableFeatureType editableFeatureType = this.getFeatureStore().getDefaultFeatureType().getEditable(); |
175 | 175 |
FeatureAttributeDescriptor[] featureAttributeDescriptors = editableFeatureType.getAttributeDescriptors(); |
176 |
for (int i=0 ; i<featureAttributeDescriptors.length ; i++){
|
|
177 |
editableFeatureType.remove(featureAttributeDescriptors[i].getName());
|
|
178 |
}
|
|
176 |
for( int i = 0; i < featureAttributeDescriptors.length; i++ ) {
|
|
177 |
editableFeatureType.remove(featureAttributeDescriptors[i].getName()); |
|
178 |
} |
|
179 | 179 |
addFeatureType(editableFeatureType, featureAttributeDescriptors, prefix1, store1NamesMap); |
180 | 180 |
|
181 | 181 |
// =========== set the new geom field name and restore geometry values |
182 |
if (orig_geom_field_index >= 0) {
|
|
182 |
if( orig_geom_field_index >= 0 ) {
|
|
183 | 183 |
EditableFeatureAttributeDescriptor ed_att = null; |
184 |
ed_att = (EditableFeatureAttributeDescriptor) |
|
185 |
editableFeatureType.getAttributeDescriptor(orig_geom_field_index); |
|
184 |
ed_att = (EditableFeatureAttributeDescriptor) editableFeatureType.getAttributeDescriptor(orig_geom_field_index); |
|
186 | 185 |
ed_att.setSRS(orig_geom_field_att.getSRS()); |
187 | 186 |
ed_att.setObjectClass(orig_geom_field_att.getObjectClass()); |
188 | 187 |
ed_att.setGeometryType(orig_geom_field_att.getGeomType()); |
... | ... | |
197 | 196 |
FeatureType featureType2 = store2.getDefaultFeatureType(); |
198 | 197 |
|
199 | 198 |
// Add the fields |
200 |
for (int i = 0; i < attrs.length; i++) {
|
|
201 |
addFeatureType(editableFeatureType, featureType2.getAttributeDescriptor(attrs[i]), prefix2, store2NamesMap);
|
|
199 |
for( int i = 0; i < attrs.length; i++ ) {
|
|
200 |
addFeatureType(editableFeatureType, featureType2.getAttributeDescriptor(attrs[i]), prefix2, store2NamesMap); |
|
202 | 201 |
} |
203 | 202 |
|
204 |
if (this.store2NamesMap.containsKey(keyAttr2)) {
|
|
203 |
if( this.store2NamesMap.containsKey(keyAttr2) ) {
|
|
205 | 204 |
this.attrsForQuery = this.attrs; |
206 | 205 |
} else { |
207 | 206 |
List<String> list = new ArrayList<String>(this.attrs.length + 1); |
208 | 207 |
list.addAll(Arrays.asList(this.attrs)); |
209 | 208 |
list.add(keyAttr2); |
210 |
this.attrsForQuery = (String[]) list.toArray(new String[] {});
|
|
209 |
this.attrsForQuery = (String[]) list.toArray(new String[]{}); |
|
211 | 210 |
} |
212 | 211 |
|
213 | 212 |
// assign calculated feature type as this transform's feature type |
214 |
FeatureType[] types = new FeatureType[] { editableFeatureType.getNotEditableCopy() }; |
|
213 |
FeatureType[] types = new FeatureType[]{ |
|
214 |
editableFeatureType.getNotEditableCopy()}; |
|
215 | 215 |
setFeatureTypes(Arrays.asList(types), types[0]); |
216 | 216 |
} |
217 | 217 |
|
218 | 218 |
private void addFeatureType(EditableFeatureType targetFeatureType, FeatureAttributeDescriptor[] featureAttributeDescriptors, |
219 |
String prefix, Map<String, String> storeMap) throws DataException{ |
|
219 |
String prefix, Map<String, String> storeMap) throws DataException {
|
|
220 | 220 |
|
221 |
for (int i=0 ; i<featureAttributeDescriptors.length ; i++){
|
|
221 |
for( int i = 0; i < featureAttributeDescriptors.length; i++ ) {
|
|
222 | 222 |
addFeatureType(targetFeatureType, featureAttributeDescriptors[i], prefix, storeMap); |
223 | 223 |
} |
224 | 224 |
} |
225 | 225 |
|
226 | 226 |
private void addFeatureType(EditableFeatureType targetFeatureType, FeatureAttributeDescriptor featureAttributeDescriptor, |
227 |
String prefix, Map<String, String> storeMap) throws DataException{ |
|
227 |
String prefix, Map<String, String> storeMap) throws DataException {
|
|
228 | 228 |
|
229 | 229 |
String attName = featureAttributeDescriptor.getName(); |
230 |
if ((prefix != null) && (!prefix.equals(""))){
|
|
230 |
if( (prefix != null) && (!prefix.equals("")) ) {
|
|
231 | 231 |
attName = prefix + "_" + attName; |
232 | 232 |
} |
233 | 233 |
|
234 | 234 |
// If an attribute already exists, calculate an alternate name and add it to our type |
235 | 235 |
int j = 0; |
236 |
while (targetFeatureType.getIndex(attName) >= 0) {
|
|
236 |
while( targetFeatureType.getIndex(attName) >= 0 ) {
|
|
237 | 237 |
attName = targetFeatureType.getAttributeDescriptor(attName).getName() + "_" + ++j; |
238 | 238 |
} |
239 | 239 |
|
240 |
EditableFeatureAttributeDescriptor editableFeatureAttributeDescriptor =
|
|
241 |
targetFeatureType.add(attName, featureAttributeDescriptor.getType(), |
|
240 |
EditableFeatureAttributeDescriptor editableFeatureAttributeDescriptor |
|
241 |
= targetFeatureType.add(attName, featureAttributeDescriptor.getType(),
|
|
242 | 242 |
featureAttributeDescriptor.getSize()); |
243 | 243 |
editableFeatureAttributeDescriptor.setPrecision(featureAttributeDescriptor.getPrecision()); |
244 | 244 |
|
245 | 245 |
// keep correspondence between original name and transformed name |
246 | 246 |
storeMap.put(featureAttributeDescriptor.getName(), attName); |
247 |
}
|
|
247 |
} |
|
248 | 248 |
|
249 | 249 |
/** |
250 | 250 |
* |
... | ... | |
255 | 255 |
* |
256 | 256 |
* @throws DataException |
257 | 257 |
*/ |
258 |
@Override |
|
258 | 259 |
public void applyTransform(Feature source, EditableFeature target) |
259 |
throws DataException { |
|
260 |
throws DataException {
|
|
260 | 261 |
|
261 | 262 |
// copy the data from store1 into the resulting feature |
262 | 263 |
this.copySourceToTarget(source, target); |
... | ... | |
281 | 282 |
|
282 | 283 |
Feature feat; |
283 | 284 |
|
284 |
|
|
285 | 285 |
itFeat = set.fastIterator(); |
286 |
if (itFeat.hasNext()) {
|
|
286 |
if( itFeat.hasNext() ) {
|
|
287 | 287 |
feat = (Feature) itFeat.next(); |
288 | 288 |
|
289 | 289 |
// copy all attributes from joined feature to target |
290 | 290 |
this.copyJoinToTarget(feat, target); |
291 | 291 |
} |
292 | 292 |
} finally { |
293 |
if (itFeat != null) {
|
|
293 |
if( itFeat != null ) {
|
|
294 | 294 |
itFeat.dispose(); |
295 | 295 |
} |
296 |
if (set != null) {
|
|
296 |
if( set != null ) {
|
|
297 | 297 |
set.dispose(); |
298 | 298 |
} |
299 | 299 |
} |
... | ... | |
305 | 305 |
*/ |
306 | 306 |
private void copyJoinToTarget(Feature join, EditableFeature target) { |
307 | 307 |
Iterator<Entry<String, String>> iter = store2NamesMap.entrySet() |
308 |
.iterator(); |
|
308 |
.iterator();
|
|
309 | 309 |
Entry<String, String> entry; |
310 | 310 |
FeatureType trgType = target.getType(); |
311 | 311 |
FeatureAttributeDescriptor attr; |
312 |
while (iter.hasNext()) {
|
|
312 |
while( iter.hasNext() ) {
|
|
313 | 313 |
entry = iter.next(); |
314 | 314 |
attr = trgType.getAttributeDescriptor((String) entry.getValue()); |
315 |
if (attr != null) {
|
|
315 |
if( attr != null ) {
|
|
316 | 316 |
target.set(attr.getIndex(), join.get((String) entry.getKey())); |
317 | 317 |
} |
318 | 318 |
} |
... | ... | |
327 | 327 |
FeatureType ftSrc = source.getType(); |
328 | 328 |
FeatureType ftTrg = target.getType(); |
329 | 329 |
|
330 |
|
|
331 |
for (int i = 0; i < source.getType().size(); i++) { |
|
330 |
for( int i = 0; i < source.getType().size(); i++ ) { |
|
332 | 331 |
attr = ftSrc.getAttributeDescriptor(i); |
333 | 332 |
attrTrg = ftTrg.getAttributeDescriptor(store1NamesMap.get(attr.getName())); |
334 |
if (attrTrg != null) {
|
|
333 |
if( attrTrg != null ) {
|
|
335 | 334 |
try { |
336 | 335 |
target.set(attrTrg.getIndex(), source.get(i)); |
337 |
} catch ( SetReadOnlyAttributeException e1) {
|
|
336 |
} catch (SetReadOnlyAttributeException e1) { |
|
338 | 337 |
// Ignore, do nothing |
339 |
|
|
338 |
|
|
340 | 339 |
} catch (IllegalArgumentException e) { |
341 | 340 |
attrTrg = ftTrg.getAttributeDescriptor(attr.getName()); |
342 | 341 |
target.set(attrTrg.getIndex(), attrTrg.getDefaultValue()); |
... | ... | |
348 | 347 |
} |
349 | 348 |
|
350 | 349 |
private JoinTransformEvaluator getEvaluator() { |
351 |
if (this.evaluator == null){ |
|
352 |
FeatureType ft2 = null; |
|
353 |
try { |
|
354 |
ft2 = this.store2.getDefaultFeatureType(); |
|
355 |
} catch (DataException e) { |
|
356 |
logger.error("While getting feat type.", e); |
|
357 |
} |
|
358 |
FeatureAttributeDescriptor att2 = ft2.getAttributeDescriptor(keyAttr2); |
|
359 |
boolean is_num = att2.getDataType().isNumeric(); |
|
350 |
if( this.evaluator == null ) { |
|
351 |
FeatureType ft2 = null; |
|
352 |
try { |
|
353 |
ft2 = this.store2.getDefaultFeatureType(); |
|
354 |
} catch (DataException e) { |
|
355 |
logger.warn("Can't access to the feature type to build the evaluator.", e); |
|
356 |
throw new RuntimeException("Can't access to the feature type to build the evaluator.", e); |
|
357 |
} |
|
358 |
FeatureAttributeDescriptor att2 = ft2.getAttributeDescriptor(keyAttr2); |
|
359 |
boolean is_num = att2.getDataType().isNumeric(); |
|
360 | 360 |
this.evaluator = new JoinTransformEvaluator(keyAttr2, is_num); |
361 | 361 |
} |
362 | 362 |
return evaluator; |
363 | 363 |
|
364 | 364 |
} |
365 | 365 |
|
366 |
private class JoinTransformEvaluator implements Evaluator { |
|
366 |
private class JoinTransformEvaluator |
|
367 |
implements Evaluator { |
|
367 | 368 |
|
368 | 369 |
private String attribute; |
369 | 370 |
private boolean isNumeric = false; |
... | ... | |
372 | 373 |
private EvaluatorFieldsInfo info = null; |
373 | 374 |
|
374 | 375 |
// private int attributeIndex; |
375 |
|
|
376 | 376 |
public JoinTransformEvaluator(String attribute, boolean is_numeric) { |
377 | 377 |
this.attribute = attribute; |
378 | 378 |
this.isNumeric = is_numeric; |
... | ... | |
390 | 390 |
this.info.addMatchFieldValue(this.attribute, value); |
391 | 391 |
} |
392 | 392 |
|
393 |
@Override |
|
393 | 394 |
public Object evaluate(EvaluatorData arg0) throws EvaluatorException { |
394 | 395 |
Object curValue = arg0.getDataValue(attribute); |
395 |
if (curValue == null) {
|
|
396 |
if( curValue == null ) {
|
|
396 | 397 |
return value == null; |
397 | 398 |
} |
398 | 399 |
return curValue.equals(value); |
399 | 400 |
} |
400 | 401 |
|
402 |
@Override |
|
401 | 403 |
public String getSQL() { |
402 | 404 |
return this.sql; |
403 | 405 |
} |
404 | 406 |
|
407 |
@Override |
|
405 | 408 |
public String getDescription() { |
406 | 409 |
return "Evaluates join transform match"; |
407 | 410 |
} |
408 | 411 |
|
412 |
@Override |
|
409 | 413 |
public String getName() { |
410 | 414 |
return "JoinTransformEvaluator"; |
411 | 415 |
} |
412 | 416 |
|
417 |
@Override |
|
413 | 418 |
public EvaluatorFieldsInfo getFieldsInfo() { |
414 | 419 |
return this.info; |
415 | 420 |
} |
416 | 421 |
|
417 |
}
|
|
422 |
} |
|
418 | 423 |
|
419 | 424 |
@SuppressWarnings("unchecked") |
425 |
@Override |
|
420 | 426 |
public FeatureType getSourceFeatureTypeFrom(FeatureType arg0) { |
421 | 427 |
return originalFeatureType; |
422 | 428 |
} |
423 | 429 |
|
424 |
public boolean isTransformsOriginalValues() { |
|
425 |
return false; |
|
426 |
} |
|
427 |
|
|
428 | 430 |
public static void registerPersistent() { |
429 | 431 |
PersistenceManager persistenceManager = ToolsLocator.getPersistenceManager(); |
430 | 432 |
|
... | ... | |
434 | 436 |
|
435 | 437 |
DynStruct definition = persistenceManager.getDefinition(PERSISTENCE_DEFINITION_NAME); |
436 | 438 |
|
437 |
if (definition == null){
|
|
439 |
if( definition == null ) {
|
|
438 | 440 |
definition = persistenceManager.addDefinition( |
439 | 441 |
JoinTransform.class, |
440 | 442 |
PERSISTENCE_DEFINITION_NAME, |
441 | 443 |
"JoinTransform Persistence definition", |
442 |
null,
|
|
444 |
null, |
|
443 | 445 |
null |
444 | 446 |
); |
445 | 447 |
definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE, |
... | ... | |
454 | 456 |
} |
455 | 457 |
} |
456 | 458 |
|
459 |
@Override |
|
457 | 460 |
public void saveToState(PersistentState state) throws PersistenceException { |
458 | 461 |
super.saveToState(state); |
459 | 462 |
state.set("store2", this.store2); |
460 | 463 |
state.set("keyAttr1", this.keyAttr1); |
461 | 464 |
state.set("keyAttr2", this.keyAttr2); |
462 | 465 |
state.set("prefix1", this.prefix1); |
463 |
state.set("prefix2", this.prefix2);
|
|
466 |
state.set("prefix2", this.prefix2); |
|
464 | 467 |
state.set("attrs", this.attrs); |
465 | 468 |
} |
466 | 469 |
|
470 |
@Override |
|
467 | 471 |
public void loadFromState(PersistentState state) throws PersistenceException { |
468 | 472 |
super.loadFromState(state); |
469 |
FeatureStore store2 = (FeatureStore) state.get("store2"); |
|
470 |
String keyAttr1 = state.getString("keyAttr1"); |
|
471 |
String keyAttr2 = state.getString("keyAttr2"); |
|
472 |
String prefix1 = state.getString("prefix1"); |
|
473 |
String prefix2 = state.getString("prefix2"); |
|
474 |
String[] attrs = (String[]) state.getArray("attrs", String.class); |
|
475 |
try { |
|
476 |
initialize(getFeatureStore(), store2, keyAttr1, keyAttr2, prefix1, prefix2, attrs); |
|
477 |
} catch (DataException e) { |
|
478 |
throw new PersistenceException("Impossible to create the transform", e); |
|
479 |
} |
|
473 |
store2 = (FeatureStore) state.get("store2"); |
|
474 |
keyAttr1 = state.getString("keyAttr1"); |
|
475 |
keyAttr2 = state.getString("keyAttr2"); |
|
476 |
prefix1 = state.getString("prefix1"); |
|
477 |
prefix2 = state.getString("prefix2"); |
|
478 |
attrs = (String[]) state.getArray("attrs", String.class); |
|
480 | 479 |
} |
481 | 480 |
|
482 | 481 |
} |
Also available in: Unified diff