/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2016, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.gce.imagemosaic.granulecollector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.geotools.gce.imagemosaic.MergeBehavior;
import org.geotools.gce.imagemosaic.RasterLayerRequest;
import org.geotools.gce.imagemosaic.RasterLayerResponse;
import org.geotools.gce.imagemosaic.RasterManager;
import org.geotools.resources.coverage.FeatureUtilities;
import org.opengis.filter.Filter;
/**
* Create SubmosaicProducer based on whether the request was for a stacked mosaic with additional
* domains requested
*/
public class DefaultSubmosaicProducerFactory implements SubmosaicProducerFactory {
@Override
public List<SubmosaicProducer> createProducers(RasterLayerRequest request,
RasterManager rasterManager, RasterLayerResponse response, boolean dryRun) {
// get merge behavior as per request
List<SubmosaicProducer> defaultSubmosaicProducers = new ArrayList<>();
MergeBehavior mergeBehavior = request.getMergeBehavior();
// prepare dimensions management if needed, that is in case we use stacking
if (mergeBehavior.equals(MergeBehavior.STACK)) {
// create filter to filter results
// === Custom Domains Management
final Map<String, List> requestedAdditionalDomains = request
.getRequestedAdditionalDomains();
if (!requestedAdditionalDomains.isEmpty()) {
Set<Map.Entry<String, List>> entries = requestedAdditionalDomains.entrySet();
// Preliminary check on additional domains specification
// we can't do stack in case there are multiple values selections for more than one domain
checkMultipleSelection(entries);
// Prepare filtering
Map.Entry<String, List> multipleSelectionEntry = null;
final List<Filter> filters = new ArrayList<Filter>(entries.size());
// Loop over the additional domains
for (Map.Entry<String, List> entry : entries) {
if (entry.getValue().size() > 1) {
// take note of the entry containing multiple values
multipleSelectionEntry = entry;
} else {
// create single value domain filter
String domainName = entry.getKey()
+ RasterManager.DomainDescriptor.DOMAIN_SUFFIX;
filters.add(rasterManager.getDomainsManager().createFilter(domainName,
Arrays.asList(entry.getValue())));
}
}
// Anding all filters together
Filter andFilter = filters.size() > 0
? FeatureUtilities.DEFAULT_FILTER_FACTORY.and(filters) : null;
if (multipleSelectionEntry == null) {
// Simpler case... no multiple selections. All filter have already been combined
defaultSubmosaicProducers
.add(new DefaultSubmosaicProducer(response, andFilter, dryRun));
} else {
final String domainName = multipleSelectionEntry.getKey()
+ RasterManager.DomainDescriptor.DOMAIN_SUFFIX;
// Need to loop over the multiple values of a custom domains
final List values = multipleSelectionEntry.getValue();
for (Object o : values) {
// create a filter for this value
Filter valueFilter = rasterManager.getDomainsManager()
.createFilter(domainName, Arrays.asList(o));
// combine that filter with the previously merged ones
Filter combinedFilter = andFilter == null ? valueFilter
: FeatureUtilities.DEFAULT_FILTER_FACTORY.and(andFilter,
valueFilter);
defaultSubmosaicProducers.add(
new DefaultSubmosaicProducer(response, combinedFilter, dryRun));
}
}
}
}
// we don't stack them, either because we are not asked to or because we don't need to although
// we were asked
// let's use a default marker
if (defaultSubmosaicProducers.isEmpty()) {
defaultSubmosaicProducers
.add(new DefaultSubmosaicProducer(response, Filter.INCLUDE, dryRun));
}
return defaultSubmosaicProducers;
}
/**
* Check whether the specified custom domains contain multiple selection. That case isn't supported so we will throw an exception
*
* @param entries
*/
private void checkMultipleSelection(Set<Map.Entry<String, List>> entries) {
int multipleDimensionsSelections = 0;
for (Map.Entry<String, List> entry : entries) {
if (entry.getValue().size() > 1) {
multipleDimensionsSelections++;
if (multipleDimensionsSelections > 1) {
throw new IllegalStateException(
"Unable to handle dimensions stacking for more than 1 dimension");
}
}
}
}
}