/*
* 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.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
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.parameter.ParameterDescriptorGroup;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.util.GenericName;
/**
* A calculated attribut that define a MultiLineString geometry calculated
* from other attributs of the feature.
* For exemple : a boat that record trackes every hour.
* each record is available in a 0-N complex attribut.
* This class while extract each track and create a multiline as a new attribut.
* Any change applied to the tracks will be visible on the multiline.
*
* @author Johann Sorel (Geomatys)
*/
final class CalculateMultiLineStringOperation extends AbstractOperation {
private static final ParameterDescriptorGroup EMPTY_PARAMS = CalculateLineStringOperation.parameters("CalculateMultiLineString", 1);
private static final GeometryFactory GF = new GeometryFactory();
private static final AttributeType<MultiLineString> TYPE = new DefaultAttributeType<>(
Collections.singletonMap(NAME_KEY, NamesExt.create("MultiLineString")),MultiLineString.class,1,1,null);
private final GenericName[] path;
public CalculateMultiLineStringOperation(GenericName name, GenericName ... attributePath) {
this(Collections.singletonMap(DefaultAttributeType.NAME_KEY, name),attributePath);
}
public CalculateMultiLineStringOperation(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<LineString> lines = new ArrayList<>();
explore(feature,0,lines);
final MultiLineString geom = GF.createMultiLineString(lines.toArray(new LineString[lines.size()]));
final Attribute<MultiLineString> att = TYPE.newInstance();
att.setValue(geom);
return att;
}
private void explore(final Feature att, final int depth, final List<LineString> coords){
if(depth == path.length-1){
//we are on the field that hold the geometry
for (final Object propVal : asCollection(att, path[depth])) {
coords.add(((LineString)propVal));
}
}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);
}
}