Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / test / java / org / gvsig / fmap / dal / feature / impl / JoinTransform.java @ 40559

History | View | Annotate | Download (6.78 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.util.Arrays;
27
import java.util.HashMap;
28
import java.util.Iterator;
29
import java.util.Map;
30

    
31
import org.gvsig.fmap.dal.DALLocator;
32
import org.gvsig.fmap.dal.exception.DataException;
33
import org.gvsig.fmap.dal.feature.AbstractFeatureStoreTransform;
34
import org.gvsig.fmap.dal.feature.EditableFeature;
35
import org.gvsig.fmap.dal.feature.EditableFeatureType;
36
import org.gvsig.fmap.dal.feature.Feature;
37
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
38
import org.gvsig.fmap.dal.feature.FeatureQuery;
39
import org.gvsig.fmap.dal.feature.FeatureSet;
40
import org.gvsig.fmap.dal.feature.FeatureStore;
41
import org.gvsig.fmap.dal.feature.FeatureType;
42
import org.gvsig.tools.dispose.DisposableIterator;
43
import org.gvsig.tools.dispose.DisposeUtils;
44
import org.gvsig.tools.evaluator.Evaluator;
45
import org.gvsig.tools.persistence.PersistentState;
46
import org.gvsig.tools.persistence.exception.PersistenceException;
47

    
48
public class JoinTransform extends AbstractFeatureStoreTransform {
49

    
50
        /**
51
         * Store from which the join transform will get the additional attributes
52
         */
53
        private FeatureStore store2;
54

    
55
        /**
56
         * name of the key attr in store1 that will be used to match features in
57
         * store2
58
         */
59
        private String keyAttr1;
60

    
61
        /**
62
         * name of the key attr in store2 that will be used to match features in
63
         * store1
64
         */
65
        private String keyAttr2;
66

    
67
        /**
68
         * names of the attributes to join from store2 to store1
69
         */
70
        private String[] attrs;
71

    
72
        /**
73
         * Attribute names may change after transformation if they are repeated in
74
         * both stores. This map keeps correspondence between store2 original names
75
         * and their transformed counterparts.
76
         */
77
        private Map targetNamesMap;
78

    
79
        private FeatureType originalFeatureType;
80

    
81
        /**
82
         * A default constructor
83
         */
84
        public JoinTransform() {
85
                targetNamesMap = new HashMap();
86
        }
87

    
88
        /**
89
         * Initializes all the necessary data for this transform
90
         *
91
         * @param store1
92
         *            store whose default feature type is the target of this
93
         *            transform
94
         *
95
         * @param store2
96
         *            store whose default feature type will provide the new
97
         *            attributes to join
98
         *
99
         * @param keyAttr1
100
         *            key attribute in store1 that matches keyAttr2 in store2
101
         *            (foreign key), used for joining both stores.
102
         *
103
         * @param keyAttr2
104
         *            key attribute in store2 that matches keyAttr1 in store2
105
         *            (foreign key), used for joining both stores.
106
         *
107
         * @param attrs
108
         *            names of the attributes in store2 that will be joined to
109
         *            store1.
110
         */
111
        public void initialize(FeatureStore store1, FeatureStore store2,
112
                        String keyAttr1, String keyAttr2, String[] attrs)
113
                        throws DataException {
114

    
115
                // Initialize needed data
116
                this.setFeatureStore(store1);
117

    
118
                this.store2 = store2;
119
                this.keyAttr1 = keyAttr1;
120
                this.keyAttr2 = keyAttr2;
121
                this.attrs = attrs;
122
                this.originalFeatureType = this.getFeatureStore()
123
                                .getDefaultFeatureType();
124

    
125
                // calculate this transform resulting feature type
126
                // by adding all specified attrs from store2 to store1's default
127
                // feature type
128
                EditableFeatureType type = this.getFeatureStore().getDefaultFeatureType().getEditable();
129

    
130
                for (int i = 0; i < attrs.length; i++) {
131
                        String name = attrs[i];
132

    
133
                        // If an attribute already exists with the same name in store1's
134
                        // default feature type,
135
                        // calculate an alternate name and add it to our type
136
                        int j = 0;
137
                        while (type.getIndex(name) >= 0) {
138
                                name = attrs[i] + "_" + ++j;
139
                        }
140
                        type.add(name, store2.getDefaultFeatureType()
141
                                        .getAttributeDescriptor(attrs[i]).getType());
142

    
143
                        // keep correspondence between original name and transformed name
144
                        this.targetNamesMap.put(attrs[i], name);
145
                }
146

    
147
                // assign calculated feature type as this transform's feature type
148
                FeatureType[] types = new FeatureType[] { type.getNotEditableCopy() };
149
                setFeatureTypes(Arrays.asList(types), types[0]);
150
        }
151

    
152
        /**
153
         *
154
         *
155
         * @param source
156
         *
157
         * @param target
158
         *
159
         * @throws DataException
160
         */
161
        public void applyTransform(Feature source, EditableFeature target)
162
                        throws DataException {
163

    
164
                // copy the data from store1 into the resulting feature
165
                target.copyFrom(source);
166

    
167
                // ask store2 for the specified attributes, filtering by the key
168
                // attribute value
169
                // from the source feature
170
                Evaluator eval = DALLocator.getDataManager().createExpresion(
171
                                keyAttr2 + "=" + source.get(keyAttr1));
172
                FeatureQuery query = this.getFeatureStore().createFeatureQuery();
173
                query.setAttributeNames(attrs);
174
                query.setFilter(eval);
175

    
176
                FeatureSet set = null;
177
                DisposableIterator it = null;
178

    
179
                try {
180
                        set = store2.getFeatureSet(query);
181

    
182
                        // In this join implementation, we will take only the first matching
183
                        // feature found in store2
184
                        it = set.iterator();
185
                        if (it.hasNext()) {
186
                                Feature feat = (Feature) it.next();
187

    
188
                                // copy all attributes from joined feature to target
189
                                Iterator it2 = feat.getType().iterator();
190
                                while (it2.hasNext()) {
191
                                        FeatureAttributeDescriptor attr =
192
                                                        (FeatureAttributeDescriptor) it2.next();
193
                                        // find original attribute name
194
                                        String targetName =
195
                                                        (String) this.targetNamesMap.get(attr.getName());
196
                                        // copy its value to target feature attribute
197
                                        target.set(targetName, feat.get(attr.getName()));
198
                                }
199
                        }
200
                } finally {
201
                        DisposeUtils.dispose(set);
202
                        DisposeUtils.dispose(it);
203
                }
204
        }
205

    
206
        public void saveToState(PersistentState state) throws PersistenceException {
207
                // TODO Auto-generated method stub
208

    
209
        }
210

    
211
        public void loadFromState(PersistentState state) throws PersistenceException {
212
                // TODO Auto-generated method stub
213

    
214
        }
215

    
216
        /*
217
         * (non-Javadoc)
218
         *
219
         * @see
220
         * org.gvsig.fmap.dal.feature.FeatureStoreTransform#getSourceFeatureTypeFrom
221
         * (org.gvsig.fmap.dal.feature.FeatureType)
222
         */
223
        public FeatureType getSourceFeatureTypeFrom(FeatureType targetFeatureType) {
224
                return this.originalFeatureType;
225
        }
226

    
227
        public boolean isTransformsOriginalValues() {
228
                return false;
229
        }
230

    
231
}