/* * Copyright (c) 2012 Data Harmonisation Panel * * 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: * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.common.instance.geometry; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Queue; import javax.xml.namespace.QName; import com.vividsolutions.jts.geom.Geometry; import eu.esdihumboldt.hale.common.instance.model.Group; import eu.esdihumboldt.hale.common.instance.model.Instance; import eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty; /** * TODO Type description * * @author Simon Templer */ public class GeometryUtil { /** * Get all geometries of an instance. * * @param instance the instance * @return the geometries or an empty collection if there are none */ public static Collection<GeometryProperty<?>> getAllGeometries(Instance instance) { return getGeometries(instance, new ArrayList<QName>()); } /** * Get the default geometry of an instance. * * @param instance the instance * @param path the property path to start the search at, a <code>null</code> * will yield no geometries * @return the default geometries or an empty collection if there is none */ public static Collection<GeometryProperty<?>> getGeometries(Instance instance, List<QName> path) { Collection<GeometryProperty<?>> geometries = new ArrayList<GeometryProperty<?>>(); if (path == null) { return geometries; } // descend path and return the geometries found Queue<Group> parents = new LinkedList<Group>(); parents.add(instance); for (int i = 0; i < path.size(); i++) { QName name = path.get(i); Queue<Group> children = new LinkedList<Group>(); for (Group parent : parents) { Object[] values = parent.getProperty(name); if (values != null) { for (Object value : values) { if (value instanceof Group) { children.add((Group) value); } if (value instanceof Instance) { value = ((Instance) value).getValue(); } if (value != null && !(value instanceof Group) && i == path.size() - 1) { // detect geometry values at end of path // as they are not searched later on Collection<GeometryProperty<?>> geoms = getGeometryProperties(value); geometries.addAll(geoms); } } } } // prepare for next step parents = children; } // early exit #1 if (!geometries.isEmpty()) { // if there already are geometries, return them and don't search any // further // XXX is this OK in all cases? return geometries; } // now we have groups/instances at the end of the path collected in // parents // search in those groups/instances for additional geometries while (!parents.isEmpty()) { Group parent = parents.poll(); // add values contained in the instance Collection<GeometryProperty<?>> geoms = getGeometryProperties(parent); if (!geoms.isEmpty()) { geometries.addAll(geoms); // early exit #2 // don't check the children as they usually are only parts of // the geometry found here } else { // check children for geometries for (QName name : parent.getPropertyNames()) { Object[] values = parent.getProperty(name); if (values != null) { for (Object value : values) { if (value instanceof Group) { // check group later on parents.add((Group) value); } else { // add geometries for value geometries.addAll(getGeometryProperties(value)); } } } } } } return geometries; } /** * Try to get/create geometry properties from a property value. * * @param value the property value, e.g. a {@link Geometry}, * {@link GeometryProperty}, a {@link Collection} or * {@link Instance} * @return the geometry properties or an empty list if none could be created */ @SuppressWarnings({ "unchecked", "rawtypes" }) private static Collection<GeometryProperty<?>> getGeometryProperties(Object value) { if (value instanceof Instance) { value = ((Instance) value).getValue(); } if (value != null) { Collection<GeometryProperty<?>> result = new ArrayList<GeometryProperty<?>>(); if (value instanceof GeometryProperty) { // return the encountered GeometryProperty result.add((GeometryProperty) value); } if (value instanceof Geometry) { // create a GeometryProperty wrapping the geometry // XXX any way to determine a CRS? GeometryProperty prop = new DefaultGeometryProperty(null, (Geometry) value); result.add(prop); } if (value instanceof Collection<?>) { // add results from collection values for (Object subValue : ((Iterable<?>) value)) { result.addAll(getGeometryProperties(subValue)); } } return result; } return Collections.emptyList(); } }