/*
* Copyright (c) 2017 wetransform GmbH
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* wetransform GmbH <http://www.wetransform.to>
*/
package eu.esdihumboldt.hale.common.instance.index.spatial;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import com.vividsolutions.jts.geom.Geometry;
import de.fhg.igd.geom.BoundingBox;
import de.fhg.igd.geom.Localizable;
import eu.esdihumboldt.hale.common.core.service.ServiceProvider;
import eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder;
import eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser;
import eu.esdihumboldt.hale.common.instance.helper.InstanceTraverser;
import eu.esdihumboldt.hale.common.instance.index.LocalizableInstanceReference;
import eu.esdihumboldt.hale.common.instance.index.TypedInstanceReference;
import eu.esdihumboldt.hale.common.instance.model.Instance;
import eu.esdihumboldt.hale.common.instance.model.InstanceReference;
import eu.esdihumboldt.hale.common.instance.processing.AbstractInstanceProcessor;
import eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty;
/**
* Instance processor to populate the spatial index provided by the
* {@link SpatialIndexService}.
*
* @author Florian Esser
*/
public class SpatialIndexInstanceProcessor extends AbstractInstanceProcessor {
/**
* @see eu.esdihumboldt.hale.common.instance.processing.InstanceProcessor#process(eu.esdihumboldt.hale.common.instance.model.Instance,
* eu.esdihumboldt.hale.common.instance.model.InstanceReference)
*/
@Override
public void process(Instance instance, InstanceReference reference) {
SpatialIndexService<Localizable, Localizable> index = getSpatialIndexService();
final GeometryFinder finder = new GeometryFinder(null);
InstanceTraverser traverser = new DepthFirstInstanceTraverser(true);
traverser.traverse(instance, finder);
final List<Geometry> geometries = new ArrayList<>();
for (GeometryProperty<?> property : finder.getGeometries()) {
Geometry g = property.getGeometry();
for (int i = 0; i < g.getNumGeometries(); i++) {
geometries.add(g.getGeometryN(i));
}
}
final BoundingBox boundingBox = new BoundingBox();
for (Geometry geometry : geometries) {
boundingBox.add(BoundingBox.compute(geometry));
}
if (boundingBox.checkIntegrity()) {
TypedInstanceReference typedRef = new TypedInstanceReference(reference,
instance.getDefinition());
index.insert(new LocalizableInstanceReference(typedRef, boundingBox));
}
}
/**
* @see eu.esdihumboldt.hale.common.instance.processing.AbstractInstanceProcessor#close()
*/
@Override
public void close() throws IOException {
getSpatialIndexService().flush();
}
/**
* @return the spatial index service
* @throws IllegalStateException thrown if there is no
* {@link ServiceProvider} or no {@link SpatialIndexService}
* provided
*/
private SpatialIndexService<Localizable, Localizable> getSpatialIndexService() {
final ServiceProvider serviceProvider = Optional.ofNullable(this.getServiceProvider())
.orElseThrow(() -> new IllegalStateException("No service provider available"));
@SuppressWarnings("unchecked")
SpatialIndexService<Localizable, Localizable> index = Optional
.ofNullable(serviceProvider.getService(SpatialIndexService.class)).orElseThrow(
() -> new IllegalStateException("No SpatialIndexService was provided."));
return index;
}
}