/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.constellation.provider; import org.apache.sis.storage.DataStoreException; import org.constellation.api.DataType; import org.geotoolkit.data.AbstractFeatureStoreFactory; import org.geotoolkit.data.FeatureStore; import org.geotoolkit.data.memory.ExtendedFeatureStore; import org.geotoolkit.data.memory.MemoryFeatureStore; import org.geotoolkit.data.query.Query; import org.geotoolkit.data.query.QueryBuilder; import org.geotoolkit.parameter.Parameters; import org.opengis.parameter.ParameterNotFoundException; import org.opengis.parameter.ParameterValueGroup; import java.util.Collections; import java.util.Date; import java.util.LinkedHashSet; import java.util.Set; import java.util.logging.Level; import static org.constellation.provider.configuration.ProviderParameters.LAYER_DATE_END_FIELD_DESCRIPTOR; import static org.constellation.provider.configuration.ProviderParameters.LAYER_DATE_START_FIELD_DESCRIPTOR; import static org.constellation.provider.configuration.ProviderParameters.LAYER_ELEVATION_END_FIELD_DESCRIPTOR; import static org.constellation.provider.configuration.ProviderParameters.LAYER_ELEVATION_START_FIELD_DESCRIPTOR; import static org.constellation.provider.configuration.ProviderParameters.LAYER_NAME_DESCRIPTOR; import static org.constellation.provider.configuration.ProviderParameters.LAYER_QUERY_LANGUAGE; import static org.constellation.provider.configuration.ProviderParameters.LAYER_QUERY_STATEMENT; import static org.constellation.provider.configuration.ProviderParameters.containLayer; import static org.constellation.provider.configuration.ProviderParameters.getLayer; import static org.constellation.provider.configuration.ProviderParameters.getLayers; import static org.constellation.provider.configuration.ProviderParameters.getQueryLayers; import static org.constellation.provider.configuration.ProviderParameters.isLoadAll; import org.geotoolkit.util.NamesExt; import static org.geotoolkit.parameter.Parameters.value; import org.opengis.util.GenericName; /** * Abstract provider which handle a Datastore. * * @author Johann Sorel (Geomatys) */ public abstract class AbstractFeatureStoreProvider extends AbstractDataProvider{ private final Set<GenericName> index = new LinkedHashSet<>(); private ExtendedFeatureStore store; public AbstractFeatureStoreProvider(final String id, final ProviderFactory service, final ParameterValueGroup config) throws DataStoreException { super(id, service,config); visit(); } protected abstract FeatureStore createBaseFeatureStore(); /** * @return the datastore this provider encapsulate. */ @Override public ExtendedFeatureStore getMainStore(){ return store; } /** * {@inheritDoc } */ @Override public Set<GenericName> getKeys() { return Collections.unmodifiableSet(index); } /** * {@inheritDoc } */ @Override public Data get(final GenericName key) { return get(key, null); } /** * {@inheritDoc } */ @Override public Data get(final GenericName key, Date version) { GenericName goodKey; if (!index.contains(key)) { goodKey = containsOnlyLocalPart(index, key); if (goodKey == null) { goodKey = containsWithNamespaceError(index, key); if (goodKey == null) { return null; } } } else { goodKey = key; } final ParameterValueGroup layer = getLayer(getSource(), goodKey.tip().toString()); if (layer == null) { return new DefaultFeatureData(goodKey, store, null, null, null, null, null, version); } else { return new DefaultFeatureData( goodKey, store, null, value(LAYER_DATE_START_FIELD_DESCRIPTOR, layer), value(LAYER_DATE_END_FIELD_DESCRIPTOR, layer), value(LAYER_ELEVATION_START_FIELD_DESCRIPTOR, layer), value(LAYER_ELEVATION_END_FIELD_DESCRIPTOR, layer), version); } } /** * {@inheritDoc } */ @Override public synchronized void reload() { dispose(); visit(); fireUpdateEvent(); } /** * {@inheritDoc } */ @Override public synchronized void dispose() { if(store != null){ try { store.close(); } catch (DataStoreException ex) { LOGGER.log(Level.WARNING, null, ex); } } index.clear(); } @Override protected synchronized void visit() { final ParameterValueGroup source = getSource(); FeatureStore candidate = createBaseFeatureStore(); if (candidate == null) { //final StringBuilder sb = new StringBuilder("Could not create featurestore : "+this.getClass().getSimpleName()+" id="+getId()); //use an empty datastore candidate = new MemoryFeatureStore(); } String namespace; final ParameterValueGroup config = candidate.getConfiguration(); if (config != null) { try { namespace = Parameters.value(AbstractFeatureStoreFactory.NAMESPACE, config); } catch (ParameterNotFoundException ex) { LOGGER.log(Level.FINEST, "no parameter namespace found in provider configuration", ex); namespace = null; } } else { namespace = null; } if ("no namespace".equalsIgnoreCase(namespace)) { namespace = null; } store = new ExtendedFeatureStore(candidate); for(final ParameterValueGroup queryLayer : getQueryLayers(source)){ final String layerName = value(LAYER_NAME_DESCRIPTOR, queryLayer); final String language = value(LAYER_QUERY_LANGUAGE, queryLayer); final String statement = value(LAYER_QUERY_STATEMENT, queryLayer); final GenericName name = NamesExt.create(namespace, layerName); final Query query = QueryBuilder.language(language, statement, name); store.addQuery(query); index.add(name); } final boolean loadAll = isLoadAll(getSource()); // if we have only queryLayer we skip this part if (loadAll || !getLayers(source).isEmpty()) { try { for (final GenericName name : store.getNames()) { if ((loadAll || containLayer(getSource(), name.tip().toString())) && !index.contains(name)) { index.add(name); } } } catch (DataStoreException ex) { //Looks like we failed to retrieve the list of featuretypes, //the layers won't be indexed and the getCapability //won't be able to find thoses layers. getLogger().log(Level.SEVERE, "Failed to retrive list of available feature types.", ex); } } super.visit(); } @Override public void remove(GenericName key) { if (store == null) { reload(); } try { store.deleteFeatureType(key); reload(); } catch (DataStoreException ex) { getLogger().log(Level.INFO, "Unable to remove "+ key.toString() +" from provider.", ex); } } @Override public DataType getDataType() { return DataType.VECTOR; } }