/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2015, Geomatys * * 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.apache.sis.feature.op; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Point; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.sis.feature.AbstractOperation; import org.apache.sis.feature.DefaultAttributeType; import org.geotoolkit.util.NamesExt; import org.opengis.feature.Attribute; import org.opengis.feature.AttributeType; import org.opengis.feature.Feature; import org.opengis.feature.IdentifiedType; import org.opengis.feature.Property; import org.opengis.metadata.Identifier; import org.opengis.parameter.ParameterDescriptor; import org.opengis.parameter.ParameterDescriptorGroup; import org.opengis.parameter.ParameterValueGroup; import org.opengis.util.GenericName; import org.apache.sis.metadata.iso.citation.Citations; import org.apache.sis.parameter.DefaultParameterDescriptorGroup; /** * A calculated attribut that define a LineString geometry calculated * from other attributs of the feature. * For exemple : a boat that record it's position every hour. * each record is available in a 0-N complex attribut. * This class while extract each position and create a line as a new attribut. * Any change applied to the positions will be visible on the line. * * @author Johann Sorel (Geomatys) */ final class CalculateLineStringOperation extends AbstractOperation { /** * @todo this is a copy of {@code LinkOperation} package private method. */ static ParameterDescriptorGroup parameters(final String name, final int minimumOccurs, final ParameterDescriptor<?>... parameters) { final Map<String,Object> properties = new HashMap<>(4); properties.put(ParameterDescriptorGroup.NAME_KEY, name); properties.put(Identifier.AUTHORITY_KEY, Citations.SIS); return new DefaultParameterDescriptorGroup(properties, minimumOccurs, 1); } private static final ParameterDescriptorGroup EMPTY_PARAMS = parameters("CalculateLineString", 1); private static final GeometryFactory GF = new GeometryFactory(); private static final AttributeType<LineString> TYPE = new DefaultAttributeType<>( Collections.singletonMap(NAME_KEY, NamesExt.create("LineString")),LineString.class,1,1,null); private final GenericName[] path; public CalculateLineStringOperation(GenericName name, GenericName ... attributePath) { this(Collections.singletonMap(DefaultAttributeType.NAME_KEY, name),attributePath); } public CalculateLineStringOperation(Map<String, ?> identification, GenericName ... attributePath) { super(identification); this.path = attributePath; } @Override public ParameterDescriptorGroup getParameters() { return EMPTY_PARAMS; } @Override public IdentifiedType getResult() { return TYPE; } @Override public Property apply(Feature feature, ParameterValueGroup parameters) { final List<Coordinate> coords = new ArrayList<>(); explore(feature,0,coords); final LineString geom = GF.createLineString(coords.toArray(new Coordinate[coords.size()])); final Attribute<LineString> att = TYPE.newInstance(); att.setValue(geom); return att; } private void explore(final Feature att, final int depth, final List<Coordinate> coords){ if(depth == path.length-1){ //we are on the field that hold the geometry points for (final Object propVal : asCollection(att, path[depth])) { coords.add(((Point)propVal).getCoordinate()); } }else{ //explore childs int d = depth+1; for (final Object prop : asCollection(att,path[depth])) { final Feature child = (Feature) prop; explore(child, d, coords); } } } private static Collection asCollection(Feature att, GenericName property){ final Object value = att.getPropertyValue(property.toString()); if(value == null) return Collections.EMPTY_LIST; if(value instanceof Collection) return (Collection) value; return Collections.singletonList(value); } }