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

History | View | Annotate | Download (10.3 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
    @Override
128
        public final DisposableIterator fastIterator() throws DataException {
129
                return fastIterator(0);
130
        }
131

    
132
        public final DisposableIterator fastIterator(long index)
133
                        throws DataException {
134
                return createFastIterator(index);
135
        }
136

    
137
    @Override
138
    public final DisposableIterator fastIterator(long index, long elements) throws DataException {
139
                return createFastIterator(index, elements);
140
        }
141

    
142
    @Override
143
        public final DisposableIterator iterator() throws DataException {
144
                return iterator(0);
145
        }
146

    
147
        public final DisposableIterator iterator(long index) throws DataException {
148
                return createIterator(index);
149
        }
150

    
151
    @Override
152
        public final DisposableIterator iterator(long index, long elements) throws DataException {
153
                return createIterator(index, elements);
154
        }
155

    
156
        /**
157
         * Creates a new {@link Iterator}, begginning at the specified data index.
158
         * 
159
         * @param index
160
         *            the first element position to be returned by the
161
         *            {@link Iterator}
162
         * @return a new {@link Iterator}
163
         * @throws DataException
164
         *             if there is an error creating the {@link Iterator}
165
         */
166
        protected abstract AbstractFeatureProviderIterator createIterator(long index)
167
                        throws DataException;
168

    
169
        protected AbstractFeatureProviderIterator createIterator(long index, long elements)
170
                        throws DataException {
171
            return createIterator(index);
172
    }
173

    
174
    /**
175
         * Creates a new fast {@link Iterator}, begginning at the specified data
176
         * index. By fast this means the object instances of data (
177
         * {@link FeatureProvider}) may be reused between the
178
         * {@link Iterator#next()} method invocations.
179
         * 
180
         * @param index
181
         *            the first element position to be returned by the
182
         *            {@link Iterator}
183
         * @return a new {@link Iterator}
184
         * @throws DataException
185
         *             if there is an error creating the {@link Iterator}
186
         */
187
        protected abstract AbstractFeatureProviderIterator createFastIterator(
188
                        long index) throws DataException;
189
        
190
        protected AbstractFeatureProviderIterator createFastIterator(
191
                        long index, long elements) throws DataException {
192
            return createFastIterator(index);
193
        }
194

    
195
    @Override
196
    public String toString() {
197
        try {
198
            ToStringBuilder builder = new ToStringBuilder(this);
199
            builder.append("store", this.store, true);
200
            builder.append("query", this.query, true);
201
            return builder.toString();
202
        } catch (Exception e) {
203
            return super.toString();
204
        }
205
    }
206

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

    
256
            }
257
            if( spatialQuery.getValue()!=null ) {
258
                Interpreter interpreter = expmanager.createInterpreter();
259
                MutableSymbolTable symbolTable;
260
                if( filterSymbolTable instanceof MutableSymbolTable ) {
261
                    interpreter.setSymbolTable(filterSymbolTable);
262
                } else {
263
                    symbolTable = expmanager.createSymbolTable();
264
                    if( filterSymbolTable != null ) {
265
                        symbolTable.addSymbolTable(filterSymbolTable);
266
                    }
267
                    interpreter.setSymbolTable(symbolTable);
268
                }
269
                Envelope envelope = null;
270
                Object value = interpreter.runCode(spatialQuery.getValue());
271
                if( value instanceof Geometry ) {
272
                    envelope = ((Geometry)value).getEnvelope();
273
                } else if( value instanceof Envelope ) {
274
                    envelope = (Envelope) value;
275
                }
276
                if( envelope!=null ) {
277
                    return spatialIndex.query(envelope, Long.MAX_VALUE);
278
                }
279
            }
280
        } catch (Exception ex) {
281
            LOGGER.warn("Can't use spatial index for query '"+Objects.toString(filterCode)+"'.",ex);
282
        }
283
        return null;
284
    }
285

    
286
}