Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.spi / src / main / java / org / gvsig / fmap / dal / feature / spi / AbstractFeatureSetProvider.java @ 47652

History | View | Annotate | Download (10.6 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.spi;
25

    
26
import java.util.Iterator;
27
import java.util.Objects;
28
import org.apache.commons.lang3.builder.ToStringBuilder;
29
import org.apache.commons.lang3.mutable.MutableObject;
30
import org.gvsig.expressionevaluator.Code;
31
import org.gvsig.expressionevaluator.Expression;
32
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
33
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
34
import org.gvsig.expressionevaluator.Interpreter;
35
import org.gvsig.expressionevaluator.MutableSymbolTable;
36
import org.gvsig.expressionevaluator.SymbolTable;
37

    
38
import org.gvsig.fmap.dal.exception.DataException;
39
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
40
import org.gvsig.fmap.dal.feature.FeatureQuery;
41
import org.gvsig.fmap.dal.feature.FeatureType;
42
import org.gvsig.fmap.geom.Geometry;
43
import org.gvsig.fmap.geom.SpatialIndex;
44
import org.gvsig.fmap.geom.primitive.Envelope;
45
import org.gvsig.tools.dispose.DisposableIterator;
46
import org.gvsig.tools.dispose.impl.AbstractDisposable;
47
import org.gvsig.tools.exception.BaseException;
48
import org.gvsig.tools.visitor.VisitCanceledException;
49
import org.gvsig.tools.visitor.Visitor;
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52

    
53
/**
54
 * Base implementation for {@link FeatureSetProvider}s, adding some utility
55
 * methods.
56
 * 
57
 * @author 2009- <a href="cordinyana@gvsig.org">C?sar Ordi?ana</a> - gvSIG team
58
 */
59
public abstract class AbstractFeatureSetProvider extends AbstractDisposable
60
                implements FeatureSetProvider {
61

    
62
        protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractFeatureSetProvider.class);
63
                
64
        private final AbstractFeatureStoreProvider store;
65
        private final FeatureQuery query;
66
        private final FeatureType providerFeatureType;
67
        private final FeatureType storeFeatureType;
68

    
69
        /**
70
         * Creates a new {@link FeatureSetProvider}.
71
         * 
72
         * @param store
73
         *            the underlying {@link FeatureStoreProvider} to get the data
74
         *            from
75
         * @param query
76
         *            used to create the {@link FeatureSetProvider}
77
         * @param providerFeatureType
78
         *            the type of feature to get
79
         */
80
        public AbstractFeatureSetProvider(AbstractFeatureStoreProvider store,
81
                        FeatureQuery query, FeatureType providerFeatureType, FeatureType storeFeatureType) {
82
                this.store = store;
83
                this.query = query;
84
                this.providerFeatureType = providerFeatureType;
85
                this.storeFeatureType = storeFeatureType;
86
        }
87
        public AbstractFeatureSetProvider(AbstractFeatureStoreProvider store,
88
                        FeatureQuery query, FeatureType providerFeatureType) {
89
            this(store, query, providerFeatureType, null);
90
        }
91
        /**
92
         * Return the {@link AbstractFeatureStoreProvider}.
93
         * 
94
         * @return the store
95
         */
96
        protected AbstractFeatureStoreProvider getStore() {
97
                return store;
98
        }
99

    
100
        /**
101
         * Returns the {@link FeatureQuery} used to create this set.
102
         * 
103
         * @return the query
104
         */
105
        protected FeatureQuery getQuery() {
106
                return query;
107
        }
108
    
109
        /**
110
         * Returns the type of features from provider to load.
111
         * 
112
         * @return the providerFeatureType
113
         */
114
        protected FeatureType getProviderFeatureType() {
115
                return providerFeatureType;
116
        }
117
    
118
        /**
119
         * Returns the type of features from store to load.
120
         * 
121
         * @return the storeFeatureType
122
         */
123
        protected FeatureType getStoreFeatureType() {
124
                return storeFeatureType;
125
        }
126

    
127
        /**
128
         * Returns the type of features from provider to load.
129
         * 
130
         * @return the providerFeatureType
131
         * @deprecated use getProviderFeatureType
132
         */        
133
        protected FeatureType getFeatureType() {
134
                return providerFeatureType;
135
        }
136
    
137
        @Override
138
        public final DisposableIterator fastIterator() throws DataException {
139
                return fastIterator(0);
140
        }
141

    
142
        public final DisposableIterator fastIterator(long index)
143
                        throws DataException {
144
                return createFastIterator(index);
145
        }
146

    
147
    @Override
148
    public final DisposableIterator fastIterator(long index, long elements) throws DataException {
149
                return createFastIterator(index, elements);
150
        }
151

    
152
    @Override
153
        public final DisposableIterator iterator() throws DataException {
154
                return iterator(0);
155
        }
156

    
157
        public final DisposableIterator iterator(long index) throws DataException {
158
                return createIterator(index);
159
        }
160

    
161
    @Override
162
        public final DisposableIterator iterator(long index, long elements) throws DataException {
163
                return createIterator(index, elements);
164
        }
165

    
166
        /**
167
         * Creates a new {@link Iterator}, begginning at the specified data index.
168
         * 
169
         * @param index
170
         *            the first element position to be returned by the
171
         *            {@link Iterator}
172
         * @return a new {@link Iterator}
173
         * @throws DataException
174
         *             if there is an error creating the {@link Iterator}
175
         */
176
        protected abstract AbstractFeatureProviderIterator createIterator(long index)
177
                        throws DataException;
178

    
179
        protected AbstractFeatureProviderIterator createIterator(long index, long elements)
180
                        throws DataException {
181
            return createIterator(index);
182
    }
183

    
184
    /**
185
         * Creates a new fast {@link Iterator}, begginning at the specified data
186
         * index. By fast this means the object instances of data (
187
         * {@link FeatureProvider}) may be reused between the
188
         * {@link Iterator#next()} method invocations.
189
         * 
190
         * @param index
191
         *            the first element position to be returned by the
192
         *            {@link Iterator}
193
         * @return a new {@link Iterator}
194
         * @throws DataException
195
         *             if there is an error creating the {@link Iterator}
196
         */
197
        protected abstract AbstractFeatureProviderIterator createFastIterator(
198
                        long index) throws DataException;
199
        
200
        protected AbstractFeatureProviderIterator createFastIterator(
201
                        long index, long elements) throws DataException {
202
            return createFastIterator(index);
203
        }
204

    
205
    @Override
206
    public String toString() {
207
        try {
208
            ToStringBuilder builder = new ToStringBuilder(this);
209
            builder.append("store", this.store, true);
210
            builder.append("query", this.query, true);
211
            return builder.toString();
212
        } catch (Exception e) {
213
            return super.toString();
214
        }
215
    }
216

    
217
    
218
    @SuppressWarnings("Convert2Lambda")
219
    protected Iterator createSpatialIterator(FeatureType featureType, FeatureQuery query, SpatialIndex spatialIndex) {
220
        if( featureType==null || spatialIndex == null || query == null || query.getFilter()==null) {
221
            return null;
222
        }
223
        FeatureAttributeDescriptor geomdesc = featureType.getDefaultGeometryAttribute();
224
        if( geomdesc == null ) {
225
            return null;
226
        }
227
        ExpressionEvaluatorManager expmanager = ExpressionEvaluatorLocator.getExpressionEvaluatorManager();
228
        Code filterCode = null;
229
        try {
230
            SymbolTable filterSymbolTable = null;
231
            Expression filterExp = query.getExpressionFilter();               
232
            if( filterExp == null ) {
233
                String sql = query.getFilter().getSQL();
234
                if( sql == null ) {
235
                    return null;
236
                }
237
                filterCode = expmanager.compile(sql);
238
            } else {
239
                filterCode = filterExp.getCode();
240
                filterSymbolTable = filterExp.getSymbolTable();
241
            }
242
            MutableObject<Code> spatialQuery = new MutableObject<>();
243
            try {
244
                filterCode.accept(new Visitor() {
245
                    @Override
246
                    public void visit(Object obj) throws VisitCanceledException, BaseException {
247
                        if (Code.isFunction((Code) obj, "ST_INTERSECTS")
248
                            || Code.isFunction((Code) obj, "ST_CONTAINS")
249
                            || Code.isFunction((Code) obj, "&&")) {
250
                            Code.Callable intersects = (Code.Callable) obj;
251
                            Code p1 = intersects.parameters().get(0);
252
                            Code p2 = intersects.parameters().get(1);
253
                            Code sq = null;
254
                            if (Code.isIdentifier(p1, geomdesc.getName())) {
255
                                sq = p2;
256
                            } else if (Code.isIdentifier(p2, geomdesc.getName())) {
257
                                sq = p1;
258
                            }
259
                            if (sq != null) {
260
                                spatialQuery.setValue(sq);
261
                                throw new VisitCanceledException();
262
                            }
263
                        }
264
                    }
265
                });
266
            } catch(VisitCanceledException ex) {
267

    
268
            }
269
            if( spatialQuery.getValue()!=null ) {
270
                Interpreter interpreter = expmanager.createInterpreter();
271
                MutableSymbolTable symbolTable;
272
                if( filterSymbolTable instanceof MutableSymbolTable ) {
273
                    interpreter.setSymbolTable(filterSymbolTable);
274
                } else {
275
                    symbolTable = expmanager.createSymbolTable();
276
                    if( filterSymbolTable != null ) {
277
                        symbolTable.addSymbolTable(filterSymbolTable);
278
                    }
279
                    interpreter.setSymbolTable(symbolTable);
280
                }
281
                Envelope envelope = null;
282
                Object value = interpreter.runCode(spatialQuery.getValue());
283
                if( value instanceof Geometry ) {
284
                    envelope = ((Geometry)value).getEnvelope();
285
                } else if( value instanceof Envelope ) {
286
                    envelope = (Envelope) value;
287
                }
288
                if( envelope!=null ) {
289
                    return spatialIndex.query(envelope, Long.MAX_VALUE);
290
                }
291
            }
292
        } catch (Exception ex) {
293
            LOGGER.warn("Can't use spatial index for query '"+Objects.toString(filterCode)+"'.",ex);
294
        }
295
        return null;
296
    }
297

    
298
}