/* * 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.coveragesgroup; import java.awt.*; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import org.apache.sis.measure.MeasurementRange; import org.apache.sis.storage.DataStoreException; import org.apache.sis.util.logging.Logging; import org.apache.sis.xml.MarshallerPool; import org.constellation.ServiceDef.Query; import org.constellation.business.IStyleBusiness; import org.constellation.provider.AbstractData; import org.constellation.provider.coveragesgroup.util.ConvertersJaxbToGeotk; import org.geotoolkit.coverage.grid.GridCoverage2D; import org.geotoolkit.data.query.QueryBuilder; import org.geotoolkit.display.PortrayalException; import org.geotoolkit.display2d.GO2Utilities; import org.geotoolkit.feature.type.PropertyDescriptor; import org.geotoolkit.filter.visitor.DefaultFilterVisitor; import org.geotoolkit.map.FeatureMapLayer; import org.geotoolkit.map.MapContext; import org.geotoolkit.map.MapItem; import org.geotoolkit.map.MapLayer; import org.geotoolkit.style.MutableStyle; import org.opengis.filter.And; import org.opengis.filter.Filter; import org.opengis.filter.PropertyIsEqualTo; import org.opengis.filter.expression.PropertyName; import org.opengis.geometry.Envelope; import org.opengis.util.GenericName; /** * * @author Cédric Briançon (Geomatys) * @author Quentin Boileau (Geomatys) */ public class CoveragesGroupLayerDetails extends AbstractData { private static final Logger LOGGER = Logging.getLogger("org.constellation.provider.coveragesgroup"); private MapContext ctxt; private MarshallerPool pool; private Unmarshaller unmarshaller; public CoveragesGroupLayerDetails(final GenericName name, final File file, final IStyleBusiness styleBusiness) { this(name, file, null, null, styleBusiness); } /** * hacked method to pass the login/pass to WebMapServer */ public CoveragesGroupLayerDetails(final GenericName name, final File file, final String login, final String password, final IStyleBusiness styleBusiness) { super(name, Collections.EMPTY_LIST); // Parsing ctxt : MapBuilder.createContext try { ctxt = createMapContextForFile(file, login, password, styleBusiness); } catch (JAXBException e) { LOGGER.log(Level.INFO, "Unable to convert map context file into a valid object", e); } } private MapContext createMapContextForFile(final File file, final String login, final String password, final IStyleBusiness styleBusiness) throws JAXBException { pool = new MarshallerPool(JAXBContext.newInstance(org.constellation.provider.coveragesgroup.xml.MapContext.class, org.apache.sis.internal.jaxb.geometry.ObjectFactory.class), null); unmarshaller = pool.acquireUnmarshaller(); final Object result = unmarshaller.unmarshal(file); if (!(result instanceof org.constellation.provider.coveragesgroup.xml.MapContext)) { throw new JAXBException("Wrong response for the unmarshalling"); } final org.constellation.provider.coveragesgroup.xml.MapContext mapContext = (org.constellation.provider.coveragesgroup.xml.MapContext)result; return ConvertersJaxbToGeotk.convertsMapContext(mapContext,login, password, styleBusiness); } @Override public SortedSet<Date> getAvailableTimes() throws DataStoreException { return new TreeSet<Date>(); } @Override public SortedSet<Number> getAvailableElevations() throws DataStoreException { return new TreeSet<Number>(); } @Override public GridCoverage2D getCoverage(Envelope envelope, Dimension dimension, Double elevation, Date time) throws DataStoreException, IOException { return null; } @Override public Envelope getEnvelope() throws DataStoreException { try { return ctxt.getBounds(); } catch (IOException ex) { throw new DataStoreException(ex); } } @Override public MapItem getMapLayer(MutableStyle style, Map<String, Object> params) throws PortrayalException { if (params != null) { final Map<String,?> extras = (Map<String, ?>) params.get(KEY_EXTRA_PARAMETERS); if (extras != null) { Filter filter = null; for (String key : extras.keySet()) { if (key.equalsIgnoreCase("cql_filter")) { final String cqlFilter = ((List) extras.get(key)).get(0).toString(); if (cqlFilter != null) { filter = buildCQLFilter(cqlFilter, filter); } } else if (key.startsWith("dim_") || key.startsWith("DIM_")) { final String dimValue = ((List) extras.get(key)).get(0).toString(); final String dimName = key.substring(4); filter = buildDimFilter(dimName, dimValue, filter); } } if (filter != null) { setFilter(ctxt, filter); } } } setSelectableAndVisible(ctxt); return ctxt; } /** * Set selectable and visible to {@code true} recursively for all map items. * * @param item A {@link MapItem} that could embed others, if it is a {@link MapContext} * for example. */ private static void setSelectableAndVisible(final MapItem item) { if (item instanceof MapLayer) { ((MapLayer) item).setSelectable(true); } item.setVisible(true); for (MapItem it : item.items()) { setSelectableAndVisible(it); } } /** * Apply filter for all {@link MapItem} recursively. * * @param item * @param filter */ private void setFilter(final MapItem item, final Filter filter) { if (item instanceof FeatureMapLayer) { final FeatureMapLayer fml = (FeatureMapLayer) item; final PropertyIsEqualToFilterVisitor myVisit = new PropertyIsEqualToFilterVisitor(); // load PropertyIsEqualTo filters filter.accept(myVisit, null); // Remove filters that can't apply to this layer. for (int i=myVisit.props.size() - 1; i>=0; i--) { final PropertyIsEqualTo tempProp = myVisit.props.get(i); final Collection<PropertyDescriptor> propsDesc = fml.getCollection().getFeatureType().getDescriptors(); final String propName = ((PropertyName)(tempProp).getExpression1()).getPropertyName(); boolean found = false; for (PropertyDescriptor prop : propsDesc) { if (prop.getName().tip().toString().equalsIgnoreCase(propName)) { found = true; break; } } if (!found) { myVisit.props.remove(tempProp); } } final Filter newFilter; if (myVisit.props.isEmpty()) { newFilter = Filter.INCLUDE; } else if (myVisit.props.size() == 1) { newFilter = myVisit.props.get(0); } else { newFilter = GO2Utilities.FILTER_FACTORY.and((List) myVisit.props); } final QueryBuilder qb = new QueryBuilder(fml.getQuery()); qb.setFilter(newFilter); fml.setQuery(qb.buildQuery()); return; } for (final MapItem m : item.items()) { setFilter(m, filter); } } @Override public MeasurementRange<?>[] getSampleValueRanges() { return new MeasurementRange<?>[0]; } @Override public boolean isQueryable(Query query) { return true; } @Override public TYPE getType() { return TYPE.COVERAGE; } /** * Visitor to find {@link PropertyIsEqualTo} filters in a {@link And} filter. */ private class PropertyIsEqualToFilterVisitor extends DefaultFilterVisitor { private final List<PropertyIsEqualTo> props = new ArrayList<PropertyIsEqualTo>(); @Override public Object visit(PropertyIsEqualTo filter, Object data) { props.add(filter); return super.visit(filter, data); } } }