Revision 36235 branches/v2_0_0_prep/libraries/libFMap_dal/src/org/gvsig/fmap/dal/feature/impl/DefaultFeatureIndex.java
DefaultFeatureIndex.java | ||
---|---|---|
31 | 31 |
import java.util.ArrayList; |
32 | 32 |
import java.util.List; |
33 | 33 |
|
34 |
import org.slf4j.Logger; |
|
35 |
import org.slf4j.LoggerFactory; |
|
34 |
import org.cresques.Messages; |
|
36 | 35 |
|
36 |
import org.gvsig.fmap.dal.DataStoreNotification; |
|
37 | 37 |
import org.gvsig.fmap.dal.DataTypes; |
38 | 38 |
import org.gvsig.fmap.dal.exception.DataException; |
39 | 39 |
import org.gvsig.fmap.dal.exception.InitializeException; |
40 | 40 |
import org.gvsig.fmap.dal.feature.Feature; |
41 | 41 |
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
42 | 42 |
import org.gvsig.fmap.dal.feature.FeatureSet; |
43 |
import org.gvsig.fmap.dal.feature.FeatureStore; |
|
43 | 44 |
import org.gvsig.fmap.dal.feature.FeatureStoreNotification; |
44 | 45 |
import org.gvsig.fmap.dal.feature.FeatureType; |
45 | 46 |
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException; |
47 |
import org.gvsig.fmap.dal.feature.exception.FeatureIndexOperationException; |
|
46 | 48 |
import org.gvsig.fmap.dal.feature.exception.InvalidFeatureIndexException; |
47 | 49 |
import org.gvsig.fmap.dal.feature.spi.DefaultLongList; |
48 | 50 |
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices; |
49 | 51 |
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices; |
50 | 52 |
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProvider; |
51 | 53 |
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProviderServices; |
52 |
import org.gvsig.i18n.Messages; |
|
53 |
import org.gvsig.tools.ToolsLocator; |
|
54 | 54 |
import org.gvsig.tools.dispose.DisposableIterator; |
55 | 55 |
import org.gvsig.tools.dispose.DisposeUtils; |
56 |
import org.gvsig.tools.observer.impl.BaseWeakReferencingObservable; |
|
57 |
import org.gvsig.tools.task.SimpleTaskStatus; |
|
58 |
import org.gvsig.tools.task.TaskStatusManager; |
|
56 |
import org.gvsig.tools.observer.Observer; |
|
57 |
import org.gvsig.tools.observer.WeakReferencingObservable; |
|
58 |
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable; |
|
59 |
import org.gvsig.tools.task.AbstractMonitorableTask; |
|
60 |
import org.gvsig.tools.task.CancellableTask; |
|
61 |
import org.gvsig.tools.task.MonitorableTask; |
|
59 | 62 |
|
60 | 63 |
/** |
61 | 64 |
* Default feature index provider services. |
62 | 65 |
* |
63 |
* @author jyarza |
|
64 |
* |
|
66 |
* @author gvSIG team |
|
65 | 67 |
*/ |
66 |
public class DefaultFeatureIndex extends BaseWeakReferencingObservable
|
|
67 |
implements FeatureIndexProviderServices {
|
|
68 |
public class DefaultFeatureIndex implements FeatureIndexProviderServices,
|
|
69 |
WeakReferencingObservable {
|
|
68 | 70 |
|
69 |
private static final Logger LOG = LoggerFactory |
|
70 |
.getLogger(DefaultFeatureIndex.class); |
|
71 |
|
|
72 | 71 |
private final FeatureStoreProviderServices featureStore; |
73 | 72 |
private final FeatureType featureType; |
74 | 73 |
private final String attributeName; |
... | ... | |
77 | 76 |
private final FeatureIndexProvider indexProvider; |
78 | 77 |
private List attributeNames; |
79 | 78 |
|
80 |
private boolean filling = false; |
|
79 |
private Object featureOperationTaskLock = new Object(); |
|
80 |
private FeatureIndexOperationTask featureIndexTask; |
|
81 | 81 |
|
82 | 82 |
private boolean valid = true; |
83 | 83 |
|
84 |
private DelegateWeakReferencingObservable observable = |
|
85 |
new DelegateWeakReferencingObservable(this); |
|
86 |
|
|
84 | 87 |
public DefaultFeatureIndex(FeatureStoreProviderServices featureStore, |
85 | 88 |
FeatureType featureType, FeatureIndexProvider indexProvider, |
86 | 89 |
String attributeName, String indexName) { |
90 |
|
|
87 | 91 |
if (featureStore == null) { |
88 | 92 |
throw new IllegalArgumentException("featureStore cannot be null."); |
89 | 93 |
} |
... | ... | |
133 | 137 |
return featureType; |
134 | 138 |
} |
135 | 139 |
|
136 |
public final String getName() { |
|
137 |
return indexName; |
|
138 |
} |
|
139 |
|
|
140 | 140 |
public final String getAttributeName() { |
141 | 141 |
return attributeName; |
142 | 142 |
} |
... | ... | |
145 | 145 |
return dataType; |
146 | 146 |
} |
147 | 147 |
|
148 |
public final void fill() throws FeatureIndexException { |
|
149 |
fill(false); |
|
150 |
} |
|
148 |
/** |
|
149 |
* {@link MonitorableTask} and {@link CancellableTask} to perform long |
|
150 |
* operations on the index: filling and inserting or deleting a feature set. |
|
151 |
* |
|
152 |
* @author gvSIG Team |
|
153 |
* @version $Id$ |
|
154 |
*/ |
|
155 |
private static class FeatureIndexOperationTask extends |
|
156 |
AbstractMonitorableTask { |
|
151 | 157 |
|
152 |
public void fill(boolean background) |
|
153 |
throws FeatureIndexException { |
|
154 |
if (background) { |
|
155 |
filling = true; |
|
158 |
private final DefaultFeatureIndex index; |
|
156 | 159 |
|
157 |
Runnable task = new Runnable() { |
|
160 |
public static final int OP_FILL = 0; |
|
161 |
public static final int OP_INSERT_FSET = 1; |
|
162 |
public static final int OP_DELETE_FSET = 2; |
|
158 | 163 |
|
159 |
public void run() { |
|
160 |
try { |
|
161 |
clearAndFill(); |
|
162 |
} catch (DataException e) { |
|
163 |
LOG.error("Error filling index: " + this, e); |
|
164 |
private static final String[] OP_NAMES = { // |
|
165 |
Messages.getText("filling_index"), // OP_FILL |
|
166 |
Messages.getText("updating_index"), // OP_INSERT_FSET |
|
167 |
Messages.getText("updating_index"), // OP_DELETE_FSET |
|
168 |
}; |
|
169 |
|
|
170 |
private final int operation; |
|
171 |
|
|
172 |
private final FeatureSet data; |
|
173 |
|
|
174 |
private final Observer operationObserver; |
|
175 |
|
|
176 |
private final FeatureStore store; |
|
177 |
|
|
178 |
/** |
|
179 |
* Creates a new {@link FeatureIndexOperationTask} |
|
180 |
* |
|
181 |
* @param index |
|
182 |
* to operate on |
|
183 |
* @param store |
|
184 |
* to index data from |
|
185 |
* @param operation |
|
186 |
* to perform: {@link #OP_FILL}, {@link #OP_INSERT_FSET} or |
|
187 |
* {@link #OP_DELETE_FSET} |
|
188 |
* @param data |
|
189 |
* feature set to insert or delete in the insert or delete |
|
190 |
* operations |
|
191 |
* @param operationObserver |
|
192 |
* to be notified when the operation starts, finishes, is |
|
193 |
* cancelled or has finished with errors |
|
194 |
*/ |
|
195 |
protected FeatureIndexOperationTask(DefaultFeatureIndex index, |
|
196 |
FeatureStore store, int operation, FeatureSet data, |
|
197 |
Observer operationObserver) { |
|
198 |
super(OP_NAMES[operation]); |
|
199 |
this.index = index; |
|
200 |
this.store = store; |
|
201 |
this.operation = operation; |
|
202 |
this.data = data; |
|
203 |
this.operationObserver = operationObserver; |
|
204 |
setDaemon(true); |
|
205 |
setPriority(MIN_PRIORITY); |
|
206 |
} |
|
207 |
|
|
208 |
public void run() { |
|
209 |
try { |
|
210 |
switch (operation) { |
|
211 |
case OP_FILL: |
|
212 |
notify(FeatureStoreNotification.INDEX_FILLING_STARTED); |
|
213 |
clearAndFill(); |
|
214 |
break; |
|
215 |
|
|
216 |
case OP_INSERT_FSET: |
|
217 |
notify(FeatureStoreNotification.INDEX_FILLING_STARTED); |
|
218 |
insert(data); |
|
219 |
break; |
|
220 |
|
|
221 |
case OP_DELETE_FSET: |
|
222 |
notify(FeatureStoreNotification.INDEX_FILLING_STARTED); |
|
223 |
delete(data); |
|
224 |
break; |
|
225 |
} |
|
226 |
} catch (Exception e) { |
|
227 |
Exception fioex = |
|
228 |
new FeatureIndexOperationException(index, |
|
229 |
OP_NAMES[operation], e); |
|
230 |
notify(FeatureStoreNotification.INDEX_FILLING_ERROR, fioex); |
|
231 |
throw new RuntimeException(fioex); |
|
232 |
} finally { |
|
233 |
index.removeTask(this); |
|
234 |
} |
|
235 |
} |
|
236 |
|
|
237 |
/** |
|
238 |
* Clears the index data and fills it again. |
|
239 |
*/ |
|
240 |
private void clearAndFill() throws DataException { |
|
241 |
FeatureSet set = null; |
|
242 |
try { |
|
243 |
set = store.getFeatureSet(); |
|
244 |
synchronized (index) { |
|
245 |
if (isCancellationRequested()) { |
|
246 |
cancel(); |
|
247 |
return; |
|
164 | 248 |
} |
249 |
index.clear(); |
|
250 |
if (isCancellationRequested()) { |
|
251 |
cancel(); |
|
252 |
return; |
|
253 |
} |
|
254 |
insert(set); |
|
255 |
index.setValid(true); |
|
165 | 256 |
} |
166 |
}; |
|
257 |
} finally { |
|
258 |
DisposeUtils.dispose(set); |
|
259 |
} |
|
260 |
} |
|
167 | 261 |
|
168 |
Thread thread = new Thread(task, "Fill index data");
|
|
169 |
thread.setDaemon(true);
|
|
170 |
// thread.setPriority(-1);
|
|
171 |
thread.start();
|
|
172 |
} else {
|
|
262 |
private void insert(FeatureSet data) throws DataException {
|
|
263 |
DisposableIterator it = null;
|
|
264 |
taskStatus.setRangeOfValues(0, data.getSize());
|
|
265 |
taskStatus.add();
|
|
266 |
long counter = 0;
|
|
173 | 267 |
try { |
174 |
clearAndFill(); |
|
268 |
it = data.fastIterator(); |
|
269 |
synchronized (index) { |
|
270 |
while (it.hasNext()) { |
|
271 |
if (isCancellationRequested()) { |
|
272 |
index.clear(); |
|
273 |
cancel(); |
|
274 |
return; |
|
275 |
} |
|
276 |
Feature feat = (Feature) it.next(); |
|
277 |
index.insert(feat); |
|
278 |
taskStatus.setCurValue(counter++); |
|
279 |
} |
|
280 |
notify(FeatureStoreNotification.INDEX_FILLING_SUCCESS); |
|
281 |
} |
|
282 |
taskStatus.terminate(); |
|
283 |
} catch (RuntimeException e) { |
|
284 |
taskStatus.abort(); |
|
285 |
throw e; |
|
175 | 286 |
} catch (DataException e) { |
287 |
taskStatus.abort(); |
|
288 |
throw e; |
|
289 |
} finally { |
|
290 |
DisposeUtils.dispose(it); |
|
291 |
taskStatus.remove(); |
|
292 |
} |
|
293 |
} |
|
294 |
|
|
295 |
private void delete(FeatureSet data) throws FeatureIndexException { |
|
296 |
DisposableIterator it = null; |
|
297 |
try { |
|
298 |
it = data.fastIterator(); |
|
299 |
synchronized (index) { |
|
300 |
while (it.hasNext()) { |
|
301 |
if (isCancellationRequested()) { |
|
302 |
cancel(); |
|
303 |
return; |
|
304 |
} |
|
305 |
Feature feat = (Feature) it.next(); |
|
306 |
index.delete(feat); |
|
307 |
} |
|
308 |
notify(FeatureStoreNotification.INDEX_FILLING_SUCCESS); |
|
309 |
} |
|
310 |
} catch (DataException e) { |
|
176 | 311 |
throw new FeatureIndexException(e); |
312 |
} finally { |
|
313 |
DisposeUtils.dispose(it); |
|
177 | 314 |
} |
178 | 315 |
} |
179 |
} |
|
180 | 316 |
|
181 |
/** |
|
182 |
* Clears the index data and fills it again. |
|
183 |
*/ |
|
184 |
private synchronized void clearAndFill() throws DataException { |
|
185 |
FeatureSet set = null; |
|
186 |
try { |
|
187 |
filling = true; |
|
188 |
set = |
|
189 |
getFeatureStoreProviderServices().getFeatureStore() |
|
190 |
.getFeatureSet(); |
|
191 |
clear(); |
|
192 |
doInsert(set); |
|
193 |
filling = false; |
|
194 |
notify(this, new DefaultFeatureStoreNotification( |
|
195 |
getFeatureStoreProviderServices().getFeatureStore(), |
|
196 |
FeatureStoreNotification.INDEX_FILLED_SUCCESSFULLY, this)); |
|
197 |
} catch (DataException e) { |
|
198 |
filling = false; |
|
199 |
setValid(false); |
|
200 |
notify(this, new DefaultFeatureStoreNotification( |
|
201 |
getFeatureStoreProviderServices().getFeatureStore(), |
|
202 |
FeatureStoreNotification.INDEX_FILLING_ERROR, e)); |
|
203 |
throw new FeatureIndexException(e); |
|
204 |
} finally { |
|
205 |
DisposeUtils.dispose(set); |
|
317 |
private void cancel() { |
|
318 |
notify(FeatureStoreNotification.INDEX_FILLING_CANCELLED); |
|
319 |
taskStatus.cancel(); |
|
206 | 320 |
} |
207 |
} |
|
208 | 321 |
|
209 |
public synchronized final void insert(FeatureSet data) throws DataException { |
|
210 |
if (!isValid()) { |
|
211 |
throw new InvalidFeatureIndexException(); |
|
322 |
public void notifyOperationObserver(DataStoreNotification notification) { |
|
323 |
if (this.operationObserver != null) { |
|
324 |
this.operationObserver.update(index, notification); |
|
325 |
} |
|
212 | 326 |
} |
213 |
try { |
|
214 |
filling = true; |
|
215 |
doInsert(data); |
|
216 |
} finally { |
|
217 |
filling = false; |
|
327 |
|
|
328 |
private void notify(String notificationType) { |
|
329 |
DataStoreNotification notification = |
|
330 |
new DefaultFeatureStoreNotification(store, notificationType, |
|
331 |
index); |
|
332 |
notifyOperationObserver(notification); |
|
333 |
index.notifyObservers(notification); |
|
218 | 334 |
} |
335 |
|
|
336 |
private void notify(String notificationType, Exception exception) { |
|
337 |
DataStoreNotification notification = |
|
338 |
new DefaultFeatureStoreNotification(store, notificationType, |
|
339 |
exception); |
|
340 |
notifyOperationObserver(notification); |
|
341 |
index.notifyObservers(notification); |
|
342 |
} |
|
219 | 343 |
} |
220 | 344 |
|
221 |
private void doInsert(FeatureSet data) throws DataException { |
|
222 |
DisposableIterator it = null; |
|
223 |
TaskStatusManager statusManager = ToolsLocator.getTaskStatusManager(); |
|
224 |
SimpleTaskStatus status = |
|
225 |
statusManager.createDefaultSimpleTaskStatus(Messages |
|
226 |
.getText("filling_index")); |
|
227 |
status.setCancellable(false); |
|
228 |
status.setRangeOfValues(0, data.getSize()); |
|
229 |
status.add(); |
|
230 |
long counter = 0; |
|
231 |
try { |
|
232 |
it = data.fastIterator(); |
|
233 |
while (it.hasNext()) { |
|
234 |
Feature feat = (Feature) it.next(); |
|
235 |
doInsert(feat); |
|
236 |
status.setCurValue(counter++); |
|
345 |
private FeatureIndexOperationTask createIndexTask(int operation, |
|
346 |
FeatureSet data, Observer observer) { |
|
347 |
synchronized (featureOperationTaskLock) { |
|
348 |
if (featureIndexTask != null) { |
|
349 |
this.featureIndexTask.cancelRequest(); |
|
350 |
removeTask(this.featureIndexTask); |
|
237 | 351 |
} |
238 |
} catch (RuntimeException e) { |
|
239 |
status.abort(); |
|
240 |
throw e; |
|
241 |
} finally { |
|
242 |
DisposeUtils.dispose(it); |
|
243 |
status.remove(); |
|
352 |
FeatureIndexOperationTask fillingTask = |
|
353 |
new FeatureIndexOperationTask(this, |
|
354 |
featureStore.getFeatureStore(), operation, data, observer); |
|
355 |
this.featureIndexTask = fillingTask; |
|
356 |
return fillingTask; |
|
244 | 357 |
} |
245 | 358 |
} |
246 | 359 |
|
247 |
public synchronized final void insert(Feature feat) { |
|
248 |
if (!isValid()) { |
|
249 |
throw new RuntimeException(new InvalidFeatureIndexException()); |
|
360 |
private void removeTask(FeatureIndexOperationTask task) { |
|
361 |
synchronized (featureOperationTaskLock) { |
|
362 |
// Remove if it is not null and the same task |
|
363 |
if (this.featureIndexTask == task) { |
|
364 |
featureIndexTask = null; |
|
365 |
} |
|
250 | 366 |
} |
251 |
try { |
|
252 |
filling = true; |
|
253 |
doInsert(feat); |
|
254 |
} finally { |
|
255 |
filling = false; |
|
367 |
} |
|
368 |
|
|
369 |
public void fill() throws FeatureIndexException { |
|
370 |
fill(false, null); |
|
371 |
} |
|
372 |
|
|
373 |
public void fill(boolean background, Observer observer) |
|
374 |
throws FeatureIndexException { |
|
375 |
FeatureIndexOperationTask task = |
|
376 |
createIndexTask(FeatureIndexOperationTask.OP_FILL, null, observer); |
|
377 |
if (background) { |
|
378 |
task.start(); |
|
379 |
} else { |
|
380 |
task.run(); |
|
256 | 381 |
} |
257 | 382 |
} |
258 | 383 |
|
259 |
private void doInsert(Feature feat) { |
|
384 |
public final void insert(FeatureSet data) throws DataException { |
|
385 |
if (!isValid()) { |
|
386 |
throw new InvalidFeatureIndexException(); |
|
387 |
} |
|
388 |
FeatureIndexOperationTask task = |
|
389 |
createIndexTask(FeatureIndexOperationTask.OP_INSERT_FSET, data, |
|
390 |
null); |
|
391 |
task.run(); |
|
392 |
} |
|
393 |
|
|
394 |
public synchronized final void insert(Feature feat) throws DataException { |
|
260 | 395 |
try { |
261 |
indexProvider.insert(feat.get(attributeName),
|
|
396 |
getIndexProvider().insert(feat.get(getAttributeName()),
|
|
262 | 397 |
(FeatureReferenceProviderServices) feat.getReference()); |
263 | 398 |
} catch (NullPointerException e) { |
264 |
throw new IllegalArgumentException( |
|
265 |
"Feature does not contain a column with name " + attributeName); |
|
399 |
throw new IllegalArgumentException("Could not add Feature: " + feat |
|
400 |
+ " to index " + this |
|
401 |
+ ". It does not contain a column with name " |
|
402 |
+ getAttributeName(), e); |
|
266 | 403 |
} catch (ClassCastException e) { |
267 |
throw new IllegalArgumentException( |
|
268 |
"Attribute data type is not valid."); |
|
404 |
throw new IllegalArgumentException("Could not add Feature: " + feat |
|
405 |
+ " to index " + this + ". Attribute " + getAttributeName() |
|
406 |
+ " data type is not valid.", e); |
|
269 | 407 |
} |
270 | 408 |
} |
271 | 409 |
|
272 |
public FeatureSet getMatchFeatureSet(Object value) |
|
410 |
public final void delete(FeatureSet data) throws FeatureIndexException { |
|
411 |
if (!isValid()) { |
|
412 |
throw new InvalidFeatureIndexException(); |
|
413 |
} |
|
414 |
FeatureIndexOperationTask task = |
|
415 |
createIndexTask(FeatureIndexOperationTask.OP_DELETE_FSET, data, |
|
416 |
null); |
|
417 |
task.run(); |
|
418 |
} |
|
419 |
|
|
420 |
public synchronized final void delete(Feature feat) throws DataException { |
|
421 |
getIndexProvider().delete(feat.get(getAttributeName()), |
|
422 |
(FeatureReferenceProviderServices) feat.getReference()); |
|
423 |
} |
|
424 |
|
|
425 |
private synchronized void clear() throws DataException { |
|
426 |
getIndexProvider().clear(); |
|
427 |
} |
|
428 |
|
|
429 |
public synchronized FeatureSet getMatchFeatureSet(Object value) |
|
273 | 430 |
throws FeatureIndexException { |
274 | 431 |
if (!isValid()) { |
275 | 432 |
throw new InvalidFeatureIndexException(); |
... | ... | |
278 | 435 |
indexProvider.match(value))); |
279 | 436 |
} |
280 | 437 |
|
281 |
public FeatureSet getRangeFeatureSet(Object value1, Object value2)
|
|
282 |
throws FeatureIndexException { |
|
438 |
public synchronized FeatureSet getRangeFeatureSet(Object value1,
|
|
439 |
Object value2) throws FeatureIndexException {
|
|
283 | 440 |
if (!isValid()) { |
284 | 441 |
throw new InvalidFeatureIndexException(); |
285 | 442 |
} |
... | ... | |
287 | 444 |
indexProvider.range(value1, value2))); |
288 | 445 |
} |
289 | 446 |
|
290 |
public FeatureSet getNearestFeatureSet(int count, Object value) |
|
447 |
public synchronized FeatureSet getNearestFeatureSet(int count, Object value)
|
|
291 | 448 |
throws FeatureIndexException { |
292 | 449 |
if (!isValid()) { |
293 | 450 |
throw new InvalidFeatureIndexException(); |
... | ... | |
296 | 453 |
indexProvider.nearest(count, value))); |
297 | 454 |
} |
298 | 455 |
|
299 |
public FeatureSet getNearestFeatureSet(int count, Object value,
|
|
300 |
Object tolerance) throws FeatureIndexException { |
|
456 |
public synchronized FeatureSet getNearestFeatureSet(int count,
|
|
457 |
Object value, Object tolerance) throws FeatureIndexException {
|
|
301 | 458 |
if (!isValid()) { |
302 | 459 |
throw new InvalidFeatureIndexException(); |
303 | 460 |
} |
... | ... | |
310 | 467 |
indexProvider.initialize(); |
311 | 468 |
} |
312 | 469 |
|
313 |
public synchronized final void delete(Feature feat) { |
|
314 |
if (!isValid()) { |
|
315 |
throw new RuntimeException(new InvalidFeatureIndexException()); |
|
316 |
} |
|
317 |
try { |
|
318 |
filling = true; |
|
319 |
doDelete(feat); |
|
320 |
} finally { |
|
321 |
filling = false; |
|
322 |
} |
|
323 |
} |
|
324 |
|
|
325 |
private void doDelete(Feature feat) { |
|
326 |
indexProvider.delete(feat.get(this.attributeName), |
|
327 |
(FeatureReferenceProviderServices) feat.getReference()); |
|
328 |
} |
|
329 |
|
|
330 |
public synchronized final void delete(FeatureSet data) |
|
331 |
throws FeatureIndexException { |
|
332 |
if (!isValid()) { |
|
333 |
throw new InvalidFeatureIndexException(); |
|
334 |
} |
|
335 |
DisposableIterator it = null; |
|
336 |
try { |
|
337 |
filling = true; |
|
338 |
it = data.fastIterator(); |
|
339 |
while (it.hasNext()) { |
|
340 |
Feature feat = (Feature) it.next(); |
|
341 |
doDelete(feat); |
|
342 |
} |
|
343 |
} catch (DataException e) { |
|
344 |
throw new FeatureIndexException(e); |
|
345 |
} finally { |
|
346 |
filling = false; |
|
347 |
DisposeUtils.dispose(it); |
|
348 |
} |
|
349 |
} |
|
350 |
|
|
351 |
private void clear() throws DataException { |
|
352 |
indexProvider.clear(); |
|
353 |
} |
|
354 |
|
|
355 | 470 |
public List getAttributeNames() { |
356 | 471 |
return attributeNames; |
357 | 472 |
} |
... | ... | |
381 | 496 |
} |
382 | 497 |
|
383 | 498 |
public boolean isFilling() { |
384 |
return filling; |
|
499 |
synchronized (featureOperationTaskLock) { |
|
500 |
return featureIndexTask != null; |
|
501 |
} |
|
385 | 502 |
} |
386 | 503 |
|
387 | 504 |
public boolean isValid() { |
388 |
return !isFilling() && valid; |
|
505 |
synchronized (featureOperationTaskLock) { |
|
506 |
return !isFilling() && valid; |
|
507 |
} |
|
389 | 508 |
} |
390 | 509 |
|
391 | 510 |
public void setValid(boolean valid) { |
392 |
this.valid = valid; |
|
511 |
synchronized (featureOperationTaskLock) { |
|
512 |
this.valid = valid; |
|
513 |
} |
|
393 | 514 |
} |
394 | 515 |
|
395 | 516 |
public String toString() { |
... | ... | |
397 | 518 |
+ ", for the FeatureType: " + featureType + ", and the attribute: " |
398 | 519 |
+ attributeName; |
399 | 520 |
} |
521 |
|
|
522 |
public void notifyObservers(Object notification) { |
|
523 |
observable.notifyObservers(notification); |
|
524 |
} |
|
525 |
|
|
526 |
public String getName() { |
|
527 |
return indexName; |
|
528 |
} |
|
529 |
|
|
530 |
private FeatureIndexProvider getIndexProvider() { |
|
531 |
return indexProvider; |
|
532 |
} |
|
533 |
|
|
534 |
public void addObserver(Observer observer) { |
|
535 |
observable.addObserver(observer); |
|
536 |
} |
|
537 |
|
|
538 |
public void deleteObserver(Observer observer) { |
|
539 |
observable.deleteObserver(observer); |
|
540 |
} |
|
541 |
|
|
542 |
public void deleteObservers() { |
|
543 |
observable.deleteObservers(); |
|
544 |
} |
|
545 |
|
|
400 | 546 |
} |
Also available in: Unified diff