/*
* 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.internal.feature;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.opengis.feature.AttributeType;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureAssociationRole;
import org.opengis.feature.FeatureType;
import org.opengis.feature.Operation;
import org.opengis.feature.PropertyType;
/**
*
* @author Johann Sorel (Geomatys)
*/
public final class FeatureLoop {
private FeatureLoop(){}
public static void loop(Feature feature, Predicate<PropertyType> predicate, BiFunction<PropertyType,Object,Object> function){
final FeatureType type = feature.getType();
for(PropertyType pt : type.getProperties(true)){
if(predicate==null || predicate.test(pt)){
loop(feature, pt, function);
}
}
}
public static void loop(Feature feature, PropertyType pt, BiFunction<PropertyType,Object,Object> function){
final String attName = pt.getName().toString();
if(pt instanceof AttributeType){
final AttributeType at = (AttributeType) pt;
Object val = feature.getPropertyValue(attName);
if(at.getMaximumOccurs()>1){
//value is a collection
if(val instanceof List){
//use list iterator to avoid creating a new collection
final ListIterator ite = ((List)val).listIterator();
while(ite.hasNext()){
Object v = ite.next();
Object r = function.apply(pt, v);
if(v!=r) ite.set(r);
}
}else{
Collection c = (Collection) val;
//delay the creation of a new collection until it is really necessary
List cp = null;
int i=0;
for(Iterator ite = c.iterator();ite.hasNext();){
Object v = ite.next();
Object r = function.apply(pt, v);
if(v!=r){
cp = new ArrayList(c);
cp.set(i, r);
}
i++;
}
if(cp!=null){
feature.setPropertyValue(attName, val);
}
}
}else{
//single value
Object r = function.apply(pt, val);
if(r!=val){
//we do this test, since we know setting a null may
//cause the creation of a property is sis feature implementation
feature.setPropertyValue(attName, val);
}
}
}else if(pt instanceof FeatureAssociationRole){
//TODO
}else if(pt instanceof Operation){
//NOTE : value is a Property, the bifunction can call the set value when needed
Object val = feature.getPropertyValue(attName);
function.apply(pt, val);
}
}
}