/* * 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.constellation.configuration.ConfigurationException; import org.geotoolkit.factory.FactoryFinder; import org.geotoolkit.factory.Hints; import org.geotoolkit.style.MutableStyle; import org.geotoolkit.style.MutableStyleFactory; import org.geotoolkit.utility.parameter.ParametersExt; import org.opengis.filter.FilterFactory2; import org.opengis.parameter.GeneralParameterValue; import org.opengis.parameter.ParameterValueGroup; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map.Entry; import java.util.ServiceLoader; import java.util.Set; import java.util.logging.Level; import static org.constellation.provider.Provider.RELOAD_TIME_PROPERTY; /** * Main Data provider for styles objects. This class act as a proxy for * several SLD folder providers. * * @version $Id$ * @author Johann Sorel (Geomatys) */ @Deprecated public final class StyleProviders extends Providers implements PropertyChangeListener{ private final PropertyChangeSupport listeners = new PropertyChangeSupport(this); private long lastUpdateTime = System.currentTimeMillis(); protected final Class<String> keyClass = String.class; protected final Class<MutableStyle> valClass = MutableStyle.class; //all loaded providers private Collection<StyleProvider> PROVIDERS = null; /** * {@inheritDoc} */ public boolean contains(String key) { return getKeys().contains(key); } /** * Empty implementation. */ public void remove(String key) { } protected synchronized void fireUpdateEvent(){ final long oldTime = lastUpdateTime; lastUpdateTime = System.currentTimeMillis(); listeners.firePropertyChange(RELOAD_TIME_PROPERTY, oldTime, lastUpdateTime); } /** * {@inheritDoc} */ public void addPropertyListener(PropertyChangeListener listener) { listeners.addPropertyChangeListener(listener); } /** * {@inheritDoc} */ public void removePropertyListener(PropertyChangeListener listener) { listeners.removePropertyChangeListener(listener); } @Override public void propertyChange(final PropertyChangeEvent evt) { //a provider has been updated final Object source = evt.getSource(); if(source instanceof Provider){ //save changed configuration final Provider provider = (Provider) source; try { getConfigurator().updateProviderConfiguration(provider.getId(), provider.getSource()); } catch (ConfigurationException ex) { LOGGER.log(Level.SEVERE, ex.getMessage(), ex); } } //forward events fireUpdateEvent(); } public StyleProvider createProvider(final String providerId, final StyleProviderFactory factory, final ParameterValueGroup params) throws ConfigurationException{ getProviders(); final StyleProvider provider = factory.createProvider(providerId,params); //add in the list our provider provider.addPropertyListener(this); PROVIDERS.add(provider); //save the configuration getConfigurator().addProviderConfiguration(providerId,params,null); fireUpdateEvent(); return provider; } public StyleProvider removeProvider(final StyleProvider provider) throws ConfigurationException{ getConfigurator().removeProviderConfiguration(provider.getId()); final boolean b = PROVIDERS.remove(provider); if(b){ provider.removePropertyListener(this); fireUpdateEvent(); } return provider; } /** * {@inheritDoc } */ public Set<String> getKeys() { return getKeys(null); } /** * {@inheritDoc } */ public Set<String> getKeys(final String sourceId) { final Set<String> keys = new HashSet<>(); for(final Provider<String,MutableStyle> provider : getProviders()){ keys.addAll(provider.getKeys(sourceId)); } return keys; } /** * {@inheritDoc } * @deprecated use get(key, providerID) instead because two provider can have the same named layer */ @Deprecated public MutableStyle get(final String key) { final List<MutableStyle> candidates = new ArrayList<>(); for(final Provider<String,MutableStyle> provider : getProviders()){ final MutableStyle layer = provider.get(key); if(layer != null) candidates.add(layer); } if(candidates.size() >= 1){ return candidates.get(0); } return null; } public MutableStyle get(final String key, final String providerID) { final Provider<String,MutableStyle> provider = getProvider(providerID); if (provider == null) { return null; } return provider.get(key); } public List<MutableStyle> getAll() { final List<MutableStyle> values = new ArrayList<>(); for(Provider<String,MutableStyle> provider : getProviders()){ for(String key : provider.getKeys()){ values.add(provider.get(key)); } } return values; } public synchronized Collection<StyleProvider> getProviders(){ if(PROVIDERS != null){ return Collections.unmodifiableCollection(PROVIDERS); } final List<Entry<String,ParameterValueGroup>> configs; try { configs = getConfigurator().getProviderConfigurations(); } catch (ConfigurationException ex) { LOGGER.log(Level.SEVERE, ex.getMessage(), ex); return Collections.EMPTY_LIST; } final List<StyleProvider> cache = new ArrayList<>(); //rebuild providers for(Entry<String,ParameterValueGroup> entry : configs){ final String providerId = entry.getKey(); final ParameterValueGroup params = entry.getValue(); for(final ProviderFactory factory : getFactories()){ //check if config can be used by this factory final String paramName = factory.getStoreDescriptor().getName().getCode(); final GeneralParameterValue param = ParametersExt.getParameter(params, paramName); if(param!=null){ try{ final StyleProvider prov = (StyleProvider)factory.createProvider(providerId, params); if(prov != null){ prov.addPropertyListener(this); cache.add(prov); } }catch(Exception ex){ //we must not fail here in any case LOGGER.log(Level.SEVERE, "Factory "+factory.getName()+" failed to create a provider.",ex); } } } } PROVIDERS = cache; fireUpdateEvent(); return Collections.unmodifiableCollection(PROVIDERS); } public synchronized StyleProvider getProvider(final String id){ for (StyleProvider provider : getProviders()) { if (provider.getId().equals(id)) { return provider; } } return null; } /** * {@inheritDoc } */ public synchronized void reload() { dispose(); getProviders(); //will load providers fireUpdateEvent(); } /** * {@inheritDoc } */ public synchronized void dispose() { if(PROVIDERS == null){ //providers are not loaded return; } try{ //providers were loaded, dispose each of them for(final Provider<String,MutableStyle> provider : getProviders()){ try{ provider.removePropertyListener(this); provider.dispose(); }catch(Exception ex){ //we must not fail here in any case LOGGER.log(Level.SEVERE, "Failed to dispose provider : " + provider.toString(),ex); } } }finally{ //there should not be an error, but in worse case ensure this is correctly set to null. PROVIDERS = null; } } public static final MutableStyleFactory STYLE_FACTORY = (MutableStyleFactory) FactoryFinder.getStyleFactory(new Hints(Hints.STYLE_FACTORY, MutableStyleFactory.class)); public final FilterFactory2 FILTER_FACTORY = (FilterFactory2)FactoryFinder.getFilterFactory( new Hints(Hints.FILTER_FACTORY, FilterFactory2.class)); private static final Collection<StyleProviderFactory> FACTORIES; static { final List<StyleProviderFactory> cache = new ArrayList<>(); final ServiceLoader<StyleProviderFactory> loader = ServiceLoader.load(StyleProviderFactory.class); for(final StyleProviderFactory factory : loader){ cache.add(factory); } FACTORIES = Collections.unmodifiableCollection(cache); } private static final StyleProviders INSTANCE = new StyleProviders(); public Collection<StyleProviderFactory> getFactories() { return FACTORIES; } public StyleProviderFactory getFactory(final String factoryID) { for (StyleProviderFactory serv : FACTORIES) { if (serv.getName().equals(factoryID)) { return serv; } } return null; } /** * Returns the current instance of {@link StyleProviders}. */ public static StyleProviders getInstance(){ return INSTANCE; } }