forwad for Malte as I accidently delted his message from the pending request list

Dear OpenJump Enthusiast,

I've tried to make a copy of a FeatureCollection containing Features with null values. I used the cloneFeatureCollection-Method of the FeatureCollectionTools Class from the Pirol Project (now implemented in the OJ beta, too) and got a NPE.

I think a Feature should have Attributes containing null values, so I fixed this.
The fixed class is attached.

Greetings from cloudy Hanover,
Malte




/*
 * Created on 12.01.2005
 *
 * SVN header information:
 *  $Author: mentaer $
 *  $Rev: 2509 $
 *  $Date: 2007/02/03 14:19:04 $
 *  $Id: FeatureCollectionTools.java,v 1.2 2007/02/03 14:19:04 mentaer Exp $s
 */
package de.fho.jump.pirol.utilities.apiTools;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jump.feature.AttributeType;
import com.vividsolutions.jump.feature.BasicFeature;
import com.vividsolutions.jump.feature.Feature;
import com.vividsolutions.jump.feature.FeatureCollection;
import com.vividsolutions.jump.feature.FeatureDataset;
import com.vividsolutions.jump.feature.FeatureSchema;
import com.vividsolutions.jump.workbench.model.Layer;
import com.vividsolutions.jump.workbench.plugin.PlugInContext;
import com.vividsolutions.jump.workbench.ui.EditTransaction;

import de.fho.jump.pirol.utilities.FeatureCollection.PirolFeatureCollection;
import de.fho.jump.pirol.utilities.FormulaParsing.FormulaValue;
import de.fho.jump.pirol.utilities.attributes.AttributeInfo;
import de.fho.jump.pirol.utilities.comparisonAndSorting.ObjectComparator;
import de.fho.jump.pirol.utilities.debugOutput.DebugUserIds;
import de.fho.jump.pirol.utilities.debugOutput.PersonalLogger;
import de.fho.jump.pirol.utilities.metaData.MetaInformationHandler;

/**
 * Class to speed up handling of FeatureCollections (or lists of features) 
during progamming by implementing
 * a set of common tasks.
 * Most functions can be used in a static way, but on the other hand for each 
FeatureCollection a instance of this class can be invoked.
 * This might be more convenient, if there is more than one thing to do with 
the same feature collection. 
 * 
 * @author Ole Rahn
 * <br>
 * <br>FH Osnabr&uuml;ck - University of Applied Sciences Osnabr&uuml;ck,
 * <br>Project: PIROL (2005),
 * <br>Subproject: Daten- und Wissensmanagement
 * 
 * @version $Rev: 2509 $
 */

public class FeatureCollectionTools extends ToolToMakeYourLifeEasier {
    
    protected FeatureCollection fc = null;
    protected List<Feature> featureList;
    private HashMap<Integer, Feature> fid2Object = new HashMap<Integer, 
Feature>();
    
    protected static PersonalLogger logger = new 
PersonalLogger(DebugUserIds.ALL); 
    
    public FeatureCollectionTools( FeatureCollection fc ){
        super(); 
        this.fc = fc;
        this.featureList = this.fc.getFeatures();
    }
    
    public FeatureCollectionTools( List<Feature> fcl ){
        super();
        this.featureList = fcl;
    }

    /**
     * gets the Feature with the given FID.
     [EMAIL PROTECTED] fid FID to look for
     [EMAIL PROTECTED] the feature
     */
    public Feature getFeature( int fid ){
        Integer FID = new Integer(fid);
                if (!this.fid2Object.containsKey(FID)){
                    
this.fid2Object.put(FID,FeatureCollectionTools.getFeatureFromCollection(this.featureList,
 fid));
                }
                
                return (Feature)this.fid2Object.get(FID);
        }

    
    /**
     * Get the feature with the specified ID from the List 
     [EMAIL PROTECTED] features array with Feature objects
     [EMAIL PROTECTED] fid the feature ID we are looking for
     [EMAIL PROTECTED] feature with specified FID if exists, else null
     */
    public static Feature getFeatureFromCollection( List<Feature> features, int 
fid ){
                return 
FeatureCollectionTools.getFeatureFromCollection((Feature[])features.toArray(new 
Feature[0]), fid);               
        }
    
    /**
     * Get the feature with the specified ID from the array 
     [EMAIL PROTECTED] features array with Feature objects
     [EMAIL PROTECTED] fid the feature ID we are looking for
     [EMAIL PROTECTED] feature with specified FID if exists, else null
     */
    public static Feature getFeatureFromCollection( Feature[] features, int fid 
){
                Feature feat;
                
                for ( int i=0; i < features.length; i++ ){
                        feat = features[i];
                        
                        if (feat.getID() == fid){
                                return feat;
                        }
                }
                return null;            
        }
    
    /**
     * deep copies a the FeatureSchema, the Features and their Geometries
     * @param fc the FeatureCollection to copy
     * @return the new copied FeatureCollection
     */
    public final static PirolFeatureCollection 
cloneFeatureCollection(FeatureCollection fc){
        FeatureSchema clonedSchema = 
(FeatureSchema)fc.getFeatureSchema().clone();
        FeatureDataset newFc = new FeatureDataset(clonedSchema);
        
        Feature[] featuresToCopy = FeatureCollection2FeatureArray(fc);
        Feature newFeat = null;
        AttributeType attrType = null;
        
        for (int i=0; i<featuresToCopy.length; i++){
                newFeat = new BasicFeature(clonedSchema);
                
                for (int attr=0; attr<clonedSchema.getAttributeCount(); attr++){
                        attrType = clonedSchema.getAttributeType(attr);
                        /**
                             * FIX for Null Values.
                             * Added by mweller 24.07.2007
                             */
                      if(featuresToCopy[i].getAttribute(attr) != null){
                        if (attrType.equals(AttributeType.DOUBLE)){
                                newFeat.setAttribute(attr, new 
Double(((Double)featuresToCopy[i].getAttribute(attr)).doubleValue()) );
                        } else if (attrType.equals(AttributeType.INTEGER)){
                                newFeat.setAttribute(attr, new 
Integer(((Integer)featuresToCopy[i].getAttribute(attr)).intValue()) );
                        } else if (attrType.equals(AttributeType.STRING)){
                                newFeat.setAttribute(attr, 
((String)featuresToCopy[i].getAttribute(attr)).trim() );
                        } else if (attrType.equals(AttributeType.GEOMETRY)){
                                newFeat.setAttribute(attr, 
((Geometry)featuresToCopy[i].getAttribute(attr)).clone() );
                        } else if (attrType.equals(AttributeType.DATE)){
                                newFeat.setAttribute(attr, 
((Date)featuresToCopy[i].getAttribute(attr)).clone() );
                        } else if (attrType.equals(AttributeType.OBJECT)){
                                logger.printError("not implemented!");
                                newFeat.setAttribute(attr, 
(featuresToCopy[i].getAttribute(attr)) );
                        }
                }
                else{
                  newFeat.setAttribute(attr, null );
          }
                }
                
                newFc.add(newFeat);
        }
        return MetaInformationHandler.createPirolFeatureCollection(newFc);
    }
    
    /**
     * Get the feature with the specified ID from the FeatureCollection 
     [EMAIL PROTECTED] features array with Feature objects
     [EMAIL PROTECTED] fid the feature ID we are looking for
     [EMAIL PROTECTED] feature with specified FID if exists, else null
     */
    public static Feature getFeatureFromCollection( FeatureCollection features, 
int fid ){
        return 
FeatureCollectionTools.getFeatureFromCollection(features.getFeatures(), fid);   
         
        }
    
    /**
     [EMAIL PROTECTED] features list of features to calculate the mean for
     [EMAIL PROTECTED] attr name of attribute to calculate the mean for
     [EMAIL PROTECTED] the mean (double because a mean of integers will very 
likely be a double) 
     */
    public static double getAritmeticMiddleForAttribute( Feature[] features, 
String attr ){
        
        if (features == null || features.length==0) return Double.NaN;
        
        Feature f = features[0];
        FeatureSchema fs = f.getSchema();
        int attrInd = fs.getAttributeIndex(attr);
        return FeatureCollectionTools.getAritmeticMiddleForAttribute( features, 
attrInd );
    }
    
    /**
     * Method to calculate means (or modes) for the attributes given. If means 
or modes 
     * are calulated depends on the attribute type of each given given 
attribute.
     * This method is hopefully faster, than calculation each mean (mode) in an 
extra loop,
     * if there are more means (modes) to calculate than one...
     [EMAIL PROTECTED] features list of features to calculate mean/modes for
     [EMAIL PROTECTED] attrs array of attribute names to calculate mean/modes 
for
     [EMAIL PROTECTED] array of objects, representing means (or modes) --> e.g. 
Double, Integer or String objects.
     */
    public static Object[] getMeanOrModeForAttributes( Feature[] features, 
String[] attrs ){
        if (features==null || features.length==0) return null;

        int numVals = features.length;
        int numAttrs = attrs.length;
        
        FeatureSchema fs = features[0].getSchema();
        Object[] meansOrModes = new Object[numAttrs];
        AttributeType[] ats = new AttributeType[numAttrs];

        Object[] sumsOrMaps = new Object[numAttrs];
        boolean[] atIsNumeric = new boolean[numAttrs];
        
        for (int i=0; i<numAttrs; i++){
            ats[i] = fs.getAttributeType(attrs[i]);
            atIsNumeric[i] = 
FeatureCollectionTools.isAttributeTypeNumeric(ats[i]);
            if (atIsNumeric[i]){
                sumsOrMaps[i] = new Double(0);
            } else {
                // Map; no. of max. occurances; modus value
                sumsOrMaps[i] = new Object[]{ new HashMap(), new Integer(0), 
null };
            }
        }
        
        Feature currFeat;
        Double sum;
        Object value, modus;
        Map<Object,Object> map;
        
        Feature[] featArray = features;
        
        Integer maxOcc;
        int occ = 0;
        
        for (int i=0; i<featArray.length; i++){
            currFeat = featArray[i];
            for (int j=0; j<numAttrs; j++){
                if (atIsNumeric[j]){
                    sum = ((Double)sumsOrMaps[j]);
                    if (currFeat.getAttribute(attrs[j]) != null){
                        sumsOrMaps[j] = new Double(sum.doubleValue() + 
ObjectComparator.getDoubleValue(currFeat.getAttribute(attrs[j])));
                    } else {
                        // value is skipped
                        FeatureCollectionTools.logger.printMinorError("skipped 
a value (NULL), when calculating mean for " + attrs[j]);
                    }
                } else {
                    value = currFeat.getAttribute(attrs[j]);
                    
                    if (value.getClass().equals(String.class)){
                        ((String)value).trim();
                    }
                    
                    map = (Map)((Object[])sumsOrMaps[j])[0];
                    maxOcc = (Integer)((Object[])sumsOrMaps[j])[1];
                    modus = ((Object[])sumsOrMaps[j])[2];
                    
                    if ( map.containsKey(value) ){
                        occ = ((Integer)map.get(value)).intValue();
                        occ += 1;
                        map.remove(value);
                    } else {
                        occ = 1;
                    }
                    map.put(value,new Integer(occ));
                    
                    if (occ > maxOcc.intValue()){
                        maxOcc = new Integer(occ);
                        modus = value;
                    }
                    
                    sumsOrMaps[j] = new Object[]{map,maxOcc,modus};
                    
                }
            }
        }
        
        for ( int i=0; i<meansOrModes.length; i++ ){
            if (atIsNumeric[i]){
                meansOrModes[i] = new Double( 
((Double)sumsOrMaps[i]).doubleValue()/((double)numVals) );
            } else {
                meansOrModes[i] = ((Object[])sumsOrMaps[i])[2];
            }
        }
        
        return meansOrModes;
    }
    
    /**
     * Creates an envelope object for the features in the given array. This is 
an easy way
     * to get an envelope for a subset of a layer's features.
     [EMAIL PROTECTED] features array of Feature object to create an envelope 
for
     [EMAIL PROTECTED] the envelope containing the given features
     */
    public static Envelope getEnvelopeForFeatures(Feature[] features){
        Envelope env = null;
        Feature feat;
        
        for (int i=0; i<features.length; i++){
            feat = features[i];
            if (env==null){
                env = new Envelope(feat.getGeometry().getCoordinate());
            } else {
                env.expandToInclude(feat.getGeometry().getCoordinate());
            }
        }
        
        return env;
    }

    /**
     [EMAIL PROTECTED] features list of features to calculate the mean for
     [EMAIL PROTECTED] attr index of attribute to calculate the mean for
     [EMAIL PROTECTED] the mean (double because a mean of integers will very 
likely be a double) 
     */
    public static double getAritmeticMiddleForAttribute( List<Feature> 
features, int attr ){
        return 
FeatureCollectionTools.getAritmeticMiddleForAttribute((Feature[])features.toArray(new
 Feature[0]), attr);
    }
    
    /**
     [EMAIL PROTECTED] featArray array of features to calculate the mean for
     [EMAIL PROTECTED] attr index of attribute to calculate the mean for
     [EMAIL PROTECTED] the mean (double because a mean of integers will very 
likely be a double) 
     */
    public static double getAritmeticMiddleForAttribute( Feature[] featArray, 
int attr ){
        double sumVals = 0;
        int numVals = 0;
        
        if (featArray.length==0) {
            logger.printWarning("no features in list - return value will be 
NAN!");
            return Double.NaN;
        }
        
        Feature f = featArray[0];
        FeatureSchema fs = f.getSchema();
        
        if ( 
FeatureCollectionTools.isAttributeTypeNumeric(fs.getAttributeType(attr)) ){
           
            //Iterator iter = features.iterator();
            Feature feat;
            double value;
            
            for (int i=0; i<featArray.length; i++){
                feat = featArray[i];
                value = 
ObjectComparator.getDoubleValue(feat.getAttribute(attr));
                
                sumVals += value;
                numVals ++;
            }
        }
        
        return (sumVals/(double)numVals);
    }
    
    /**
     * Calculates the center of mass for the gives features' geometries.
     * It's like getCentroid(), but puts out one center of mass for N features 
instead of N centers for N features.
     [EMAIL PROTECTED] features the features
     [EMAIL PROTECTED] the point, representing the center of mass
     */
    public static Geometry getCenterOfMass( Feature[] features ){
        double sumX = 0, sumY = 0;
        GeometryFactory gf = new GeometryFactory();  
        
        if (features==null || features.length==0) return null;
        
        Feature feat;
        
        for (int i=0; i<features.length; i++){
            feat = features[i];
            sumX += feat.getGeometry().getCoordinate().x;
            sumY += feat.getGeometry().getCoordinate().y;
        }
        
        double newX = sumX / (double)features.length;
        double newY = sumY / (double)features.length;
        
        return gf.createPoint(new Coordinate(newX, newY));
    }
    
    /**
     [EMAIL PROTECTED] features list of features
     [EMAIL PROTECTED] attr name of attribute
     [EMAIL PROTECTED] number of differnt values in the given features 
attributes or -1 if an error occurs
     */
    public static Set getSetOfDifferentAttributeValues( Feature[] features, 
String attr ){
        Feature f = features[0];
        FeatureSchema fs = f.getSchema();
        int attrInd = fs.getAttributeIndex(attr);
        return FeatureCollectionTools.getSetOfDifferentAttributeValues( 
features, attrInd );
    }
    
    /**
     [EMAIL PROTECTED] features list of features
     [EMAIL PROTECTED] attr index of attribute
     [EMAIL PROTECTED] number of differnt values in the given features 
attributes or -1 if an error occurs
     */
    public static Set<Object> getSetOfDifferentAttributeValues( Feature[] 
features, int attr ){
        Feature[] featArray = features;
        int numFeats = featArray.length;
        
        HashSet<Object> differentValues = new HashSet<Object>();
        Object val;
        
        for (int i=numFeats-1; i>=0; i--){
            
            val = featArray[i].getAttribute(attr);
            //if (!differentValues.contains(val))
                differentValues.add(val);
        }
        
        return differentValues;
    }
    
    /**
     [EMAIL PROTECTED] features list of features
     [EMAIL PROTECTED] attr name of attribute
     [EMAIL PROTECTED] number of differnt values in the given features 
attributes or -1 if an error occurs
     */
    public static int getNumOfDifferentAttributeValues( Feature[] features, 
String attr ){
        Feature f = features[0];
        FeatureSchema fs = f.getSchema();
        int attrInd = fs.getAttributeIndex(attr);
        return FeatureCollectionTools.getNumOfDifferentAttributeValues( 
features, attrInd );
    }
    
    /**
     [EMAIL PROTECTED] features list of features
     [EMAIL PROTECTED] attr index of attribute
     [EMAIL PROTECTED] number of differnt values in the given features 
attributes or -1 if an error occurs
     */
    public static int getNumOfDifferentAttributeValues( Feature[] features, int 
attr ){
        return 
FeatureCollectionTools.getSetOfDifferentAttributeValues(features,attr).size();
    }

    /**
     [EMAIL PROTECTED] features list of features to calculate the mode for
     [EMAIL PROTECTED] attr name of attribute to calculate the mode for
     [EMAIL PROTECTED] the mode 
     */
    public static Object getModusForAttribute( Feature[] features, String attr 
){
        Feature f = features[0];
        FeatureSchema fs = f.getSchema();
        int attrInd = fs.getAttributeIndex(attr);
        return FeatureCollectionTools.getModusForAttribute( features, attrInd );
    }
    

    /**
     * Counts the number of appearances of each value of the given attributes 
within the given features.
     * (Somewhat like a histogram for each given attribute, but each histogram 
class is just a single value.)
     * @param features array of Features to count value appearances for 
     * @param attrs array of attribute indices of attributes to count value 
appearances for
     * @return Array of mappings of values to number of appearances 
     */
    public final static HashMap<Object,Integer>[] getValueAppearancesCount( 
Feature[] features, int[] attrs ){
        HashMap<Object,Integer>[] value2NumAppearanceMaps = new 
HashMap[attrs.length];
        
        for (int i=0; i<attrs.length; i++){
                value2NumAppearanceMaps[i] = new HashMap<Object,Integer>();
        }
        
        Feature feat;
        Object value;
        
        for (int i=0; i<features.length; i++){
            feat = features[i];
            
            for (int attInd=0; attInd<attrs.length; attInd++){
                value = feat.getAttribute(attrs[attInd]);
                
                if (!value2NumAppearanceMaps[attInd].containsKey(value)){
                        value2NumAppearanceMaps[attInd].put(value, 1);
                } else {
                        value2NumAppearanceMaps[attInd].put(value, 
value2NumAppearanceMaps[attInd].get(value).intValue()+1);
                }
                
            }

        }
        
        return value2NumAppearanceMaps;
    }
    
    /**
     [EMAIL PROTECTED] features list of features to calculate the mode for
     [EMAIL PROTECTED] attr index of attribute to calculate the mode for
     [EMAIL PROTECTED] the mode 
     */
    public static Object getModusForAttribute( Feature[] features, int attr ){
        HashMap<Object,Integer> map = new HashMap<Object,Integer>();
        Object modus = null;
        int maxNr = 0;
        
        if (features==null || features.length==0) return null;
        
        Feature[] featArray = features;
        Feature feat;
        Object value;
        int occ, numFeats = featArray.length;
        
        for (int i=0; i<numFeats; i++){
            feat = featArray[i];

            value = feat.getAttribute(attr);
            
            if (value.getClass().getName().equals(String.class.getName())){
                ((String)value).trim();
            }
            
            if ( map.containsKey(value) ){
                occ = ((Integer)map.get(value)).intValue();
                occ += 1;
                map.remove(value);
            } else {
                occ = 1;
            }
            map.put(value,new Integer(occ));
            
            if (occ > maxNr){
                maxNr = occ;
                modus = value;
            }
        }
        
        return modus;
    }
    
    /**
     * deletes the given features from the map. It thereby creates an 
EditTransaction that
     * enables the user to undo the deletion.
     [EMAIL PROTECTED] features features to be deleted
     [EMAIL PROTECTED] context curr. PlugIn context
     */
    public static void deleteFeatures( List<Feature> features, PlugInContext 
context ){
        Map layer2FeatList = LayerTools.getLayer2FeatureMap(features, context);
        
        Layer[] layersWithFeatures = 
(Layer[])layer2FeatList.keySet().toArray(new Layer[0]);
        Feature[] selFeatsOfLayer;
        
        for ( int i=0; i<layersWithFeatures.length; i++ ){
            EditTransaction edtr = new EditTransaction(new ArrayList(), "delete 
features", layersWithFeatures[i], true, true, context.getLayerViewPanel());
            
            selFeatsOfLayer = 
(Feature[])((List)layer2FeatList.get(layersWithFeatures[i])).toArray(new 
Feature[0]);
            
            for (int j=0; j<selFeatsOfLayer.length; j++){
                edtr.deleteFeature(selFeatsOfLayer[j]);
            }
            
            edtr.commit();
            edtr.clearEnvelopeCaches();
        }
    }
    
    /**
     * "deep copys" the given Feature
     [EMAIL PROTECTED] feat the feature to be copied
     [EMAIL PROTECTED] copy of the feature
     */
    public static Feature copyFeature( Feature feat ){
        Feature newFeat = new BasicFeature(feat.getSchema());
        
        int numAttr = feat.getSchema().getAttributeCount();
        
        for ( int i=0; i<numAttr; i++ ){
            newFeat.setAttribute( feat.getSchema().getAttributeName(i), 
feat.getAttribute(i) );
        }
        
        newFeat.setGeometry((Geometry)feat.getGeometry());
        
        return newFeat;
    }
    
    /**
     * "deep copys" the given Feature and thereby sets the given feature schema
     [EMAIL PROTECTED] feat the feature to be copied
     [EMAIL PROTECTED] newFs the new feature schema
     [EMAIL PROTECTED] copy of the feature
     */
    public static Feature copyFeatureAndSetFeatureSchema( Feature feat, 
FeatureSchema newFs ){
        feat = feat.clone(true);
        FeatureSchema fs = feat.getSchema();
        
        Feature newFeat = new BasicFeature(newFs);
        int numAttr = feat.getSchema().getAttributeCount();
        
        for ( int i=0; i<numAttr; i++ ){
            newFeat.setAttribute( fs.getAttributeName(i), 
feat.getAttribute(fs.getAttributeName(i)) );
        }
        
        newFeat.setGeometry((Geometry)feat.getGeometry());
        
        return newFeat;
    }
    
    public String getUniqueAttributeName(String attr){
        return FeatureCollectionTools.getUniqueAttributeName( this.fc, attr );
    }
    
    public static String getUniqueAttributeName(FeatureCollection fc, String 
attr){
        FeatureSchema fs = fc.getFeatureSchema();
        String newName = new String(attr);
        String suffix = "";
        
        for ( int i=2; FeatureCollectionTools.attributeExistsInSchema(fs, 
newName+suffix); i++ ){
            suffix = " ("+i+")";
        }
        
        return newName+suffix;
    }
    
    protected static boolean attributeExistsInSchema(FeatureSchema fs, String 
attr){
        try {
            int index = fs.getAttributeIndex(attr);
            return (index>=0);
        } catch (RuntimeException e) {
            return false;
        }
    }
    
    public PirolFeatureCollection addAttributeToFeatureCollection( String attr, 
AttributeType at, Object defaultVal ){
        if (this.fc != null)
            return FeatureCollectionTools.addAttributeToFeatureCollection( 
this.fc, attr, at, defaultVal, true );
        return null;
    }
    
    public static boolean isAttributeTypeNumeric( AttributeType at ){
        return ( at.equals(AttributeType.DOUBLE) || 
at.equals(AttributeType.INTEGER) );
    }
    
    /**
     * Method to apply a given formula to the given, new attribute of the given 
featureCollection
     [EMAIL PROTECTED] oldFc old FeatureCollection that will be replaced by the 
new one
     [EMAIL PROTECTED] attrInfo information for the new attribute
     [EMAIL PROTECTED] formula the parsed formula
     [EMAIL PROTECTED] FeatureCollection containing the new attribute
     */
    public static PirolFeatureCollection applyFormulaToFeatureCollection( 
FeatureCollection oldFc, AttributeInfo attrInfo, FormulaValue formula, boolean 
clearOldFeatureCollection ){
        
        PirolFeatureCollection newFc = 
FeatureCollectionTools.addAttributeToFeatureCollection( oldFc, attrInfo, 
clearOldFeatureCollection );
        
        Feature[] features = (Feature[])newFc.getFeatures().toArray(new 
Feature[0]);
        Feature feat;
        int numFeats = features.length, attrInd = 
newFc.getFeatureSchema().getAttributeIndex(attrInfo.getUniqueAttributeName());
        
        for (int i=0; i<numFeats; i++){
            feat = features[i];
            feat.setAttribute(attrInd, new Double(formula.getValue(feat)));
            
            if (i%500 == 0)
                logger.printDebug("done: " + i);
        }
        return newFc;
    }
    
    public static PirolFeatureCollection addAttributeToFeatureCollection( 
FeatureCollection fc, AttributeInfo attrInfo ){
        return FeatureCollectionTools.addAttributeToFeatureCollection(fc, 
attrInfo.getUniqueAttributeName(), attrInfo.getAttributeType(), 
attrInfo.getNullValue(), true);
    }
    
    public static PirolFeatureCollection addAttributeToFeatureCollection( 
FeatureCollection fc, AttributeInfo attrInfo, boolean clearOldFeatureCollection 
){
        return FeatureCollectionTools.addAttributeToFeatureCollection(fc, 
attrInfo.getUniqueAttributeName(), attrInfo.getAttributeType(), 
attrInfo.getNullValue(), clearOldFeatureCollection);
    }
    
    /**
     * Method to add a new attribute to an existing FeatureCollection. Since 
there is no "legal" way to
     * add an attribute to a FeatureCollection, this method creates (and 
returns) a new FeatureCollection with a new
     * FeatureSchema to do this operation. If a layer is to be manipulated the 
new FeatureCollection has to be set
     * as THE FeatureCollection for the layer...
     [EMAIL PROTECTED] fc the old feature collection
     [EMAIL PROTECTED] attr name of the new attribute
     [EMAIL PROTECTED] at type of the new attribute
     [EMAIL PROTECTED] defaultVal the initial value for the attribute, since we 
do not want NULL values in the attribute table
     [EMAIL PROTECTED] clearOldFeatureCollection if true the old feature 
collection will be erased to save RAM
     [EMAIL PROTECTED] new FeatureCollection with a new FeatureSchema including 
the new attribute
     */
    public static PirolFeatureCollection addAttributeToFeatureCollection( 
FeatureCollection fc, String attr, AttributeType at, Object defaultVal, boolean 
clearOldFeatureCollection ){
        FeatureSchema fs = (FeatureSchema)fc.getFeatureSchema().clone();
        fs.addAttribute(attr,at);
        
        MetaInformationHandler mih = new 
MetaInformationHandler(MetaInformationHandler.createPirolFeatureCollection(fc));
        
        PirolFeatureCollection newFc = 
MetaInformationHandler.createPirolFeatureCollection(new FeatureDataset(fs));
        
        if (mih.containsMetaInformation()){
            newFc.setMetaInformation(mih.getExistentMetaInformationMap());
        }
        mih = null;
        
        Feature feat, newFeat;
        
        if (at.equals(AttributeType.INTEGER)){
            if (Double.class.isInstance(defaultVal)){
                defaultVal = new Integer( ((Double)defaultVal).intValue() );
            }
        }
        
        Feature[] featArray = (Feature[])fc.getFeatures().toArray(new 
Feature[0]);
        
        if (clearOldFeatureCollection)
            fc.clear();        
        
        int featuresDone = 0;
        
        for ( int i=featArray.length-1; i>=0; i--, featuresDone++ ){
            feat = featArray[i];
            
            newFeat = 
FeatureCollectionTools.copyFeatureAndSetFeatureSchema(feat,fs);
            newFeat.setAttribute(attr, defaultVal);
            newFc.add(newFeat);
            
            if (i%10000 == 0 && i!=0){
                featArray = 
(Feature[])FeatureCollectionTools.resizeArray(featArray, featArray.length - 
featuresDone);
                featuresDone = 0;
                if (i%50000 == 0){
                    System.gc();
                }
            }
        }
        
        featArray = null;
        
        return newFc;
    }
    
    /**
     * Method to add a new attribute to an existing FeatureCollection. Since 
there is no "legal" way to
     * add an attribute to a FeatureCollection, this method creates (and 
returns) a new FeatureCollection with a new
     * FeatureSchema to do this operation. If a layer is to be manipulated the 
new FeatureCollection has to be set
     * as THE FeatureCollection for the layer...
     [EMAIL PROTECTED] fc the old feature collection
     [EMAIL PROTECTED] attr name of the new attribute
     [EMAIL PROTECTED] at type of the new attribute
     [EMAIL PROTECTED] defaultVal the initial value for the attribute, since we 
do not want NULL values in the attribute table
     [EMAIL PROTECTED] new FeatureCollection with a new FeatureSchema including 
the new attribute
     */
    public static PirolFeatureCollection addAttributeToFeatureCollection( 
FeatureCollection fc, String attr, AttributeType at, Object defaultVal ){
        return FeatureCollectionTools.addAttributeToFeatureCollection(fc, attr, 
at, defaultVal, true);
    }
    
    /**
     * Adds multiple attributes to the FeatureCollection
     [EMAIL PROTECTED] attributeInfos list containing the attributes (as 
AttributeInfo objects) to be added
     [EMAIL PROTECTED] a new FeatureCollection containing the old and the new 
attributes
     *
     [EMAIL PROTECTED] AttributeInfo
     */
    public PirolFeatureCollection addAttributesToFeatureCollection( List 
attributeInfos ){
        return FeatureCollectionTools.addAttributesToFeatureCollection(this.fc, 
attributeInfos);
    }
    
    /**
     * Adds multiple attributes to a FeatureCollection
     [EMAIL PROTECTED] fc the source feature collection
     [EMAIL PROTECTED] attributeInfos list containing the attributes (as 
AttributeInfo objects) to be added
     [EMAIL PROTECTED] a new FeatureCollection containing the old and the new 
attributes
     *
     [EMAIL PROTECTED] AttributeInfo
     */
    public static PirolFeatureCollection addAttributesToFeatureCollection( 
FeatureCollection fc, List<AttributeInfo> attributeInfos ){
        return FeatureCollectionTools.addAttributesToFeatureCollection(fc, 
(AttributeInfo[])attributeInfos.toArray(new AttributeInfo[0]));
    }
    
    public static PirolFeatureCollection addAttributesToFeatureCollection( 
FeatureCollection fc, AttributeInfo[] attributeInfos ){
        return FeatureCollectionTools.addAttributesToFeatureCollection(fc, 
attributeInfos, true);
    }
    
    /**
     * Adds multiple attributes to a FeatureCollection
     [EMAIL PROTECTED] fc the source feature collection
     [EMAIL PROTECTED] attributeInfos array containing the attributes to be 
added
     [EMAIL PROTECTED] clearOriginalFeatureCollection set true, if you want to 
save RAM by 
     *clearing the original FeatureCollection, false if you still want to use 
it.
     [EMAIL PROTECTED] a new FeatureCollection containing the old and the new 
attributes
     */
    public static PirolFeatureCollection addAttributesToFeatureCollection( 
FeatureCollection fc, AttributeInfo[] attributeInfos, boolean 
clearOriginalFeatureCollection ){
        FeatureSchema fs = (FeatureSchema)fc.getFeatureSchema().clone();
        
        MetaInformationHandler mih = new 
MetaInformationHandler(MetaInformationHandler.createPirolFeatureCollection(fc));
        
        
        AttributeInfo attrInfo;
        
        for (int i=0; i<attributeInfos.length; i++){
            attrInfo = attributeInfos[i]; 
            fs.addAttribute(attrInfo.getUniqueAttributeName(), 
attrInfo.getAttributeType());
        }
        
        PirolFeatureCollection newFc = 
MetaInformationHandler.createPirolFeatureCollection(new FeatureDataset(fs));
        
        if (mih.containsMetaInformation()){
            newFc.setMetaInformation(mih.getExistentMetaInformationMap());
        }
        mih = null;
        
        Feature feat, newFeat;
        
        Feature[] featArray = (Feature[])fc.getFeatures().toArray(new 
Feature[0]);
        
        if (clearOriginalFeatureCollection)
                fc.clear();
        
        int featuresDone = 0;
        
        for ( int i=featArray.length-1; i>=0; i--, featuresDone++ ){
            feat = featArray[i];
            
            newFeat = 
FeatureCollectionTools.copyFeatureAndSetFeatureSchema(feat,fs);
            

            for (int j=0; j<attributeInfos.length; j++){
                attrInfo = attributeInfos[j]; 
                newFeat.setAttribute(attrInfo.getUniqueAttributeName(), 
attrInfo.getNullValue());
            }
            
            newFc.add(newFeat);

            if (i%10000 == 0 && i!=0){
                featArray = 
(Feature[])FeatureCollectionTools.resizeArray(featArray, featArray.length - 
featuresDone);
                featuresDone = 0;
                if (i%50000 == 0){
                    System.gc();
                }
                logger.printDebug("adding attribute, features left to do " + i);
            }
        }
        featArray = null;
        
        return newFc;
    }

    /**
    * Reallocates an array with a new size, and copies the contents
    * of the old array to the new array.
    * @param oldArray  the old array, to be reallocated.
    * @param newSize   the new array size.
    * @return          A new array with the same contents.
    */
    public static Object resizeArray (Object oldArray, int newSize) {
       int oldSize = java.lang.reflect.Array.getLength(oldArray);
       Class elementType = oldArray.getClass().getComponentType();
       Object newArray = java.lang.reflect.Array.newInstance(
             elementType,newSize);
       int preserveLength = Math.min(oldSize,newSize);
       if (preserveLength > 0)
          System.arraycopy (oldArray,0,newArray,0,preserveLength);
       return newArray; 
    }
    
    public static double[] getMinMaxAttributeValue( Feature[] featArray, 
FeatureSchema fs, String attr ){
        double[] minmax = new double[]{ Double.MAX_VALUE, -Double.MAX_VALUE };
        
        
        if (fs.getAttributeType(attr) == AttributeType.INTEGER || 
fs.getAttributeType(attr) == AttributeType.DOUBLE){

            Feature feat;
            double value;
            
            for ( int i=featArray.length-1; i>=0; i-- ){
                feat = featArray[i];
                
                if (feat.getAttribute(attr) != null){
                        value = 
ObjectComparator.getDoubleValue(feat.getAttribute(attr));
                        
                        if (value<minmax[0]){
                            minmax[0] = value;
                        }
                        if (value>minmax[1]){
                            minmax[1] = value;
                        }
                } else {
                    FeatureCollectionTools.logger.printMinorError("skipped 
value (NULL), when checking min./max. values for Attribute " + attr);
                }
            }
        }
        
        return minmax;
    }
    
    public static double[] getMinMaxAttributeValue( FeatureCollection features, 
String attr ){
        return 
FeatureCollectionTools.getMinMaxAttributeValue(FeatureCollectionTools.FeatureCollection2FeatureArray(features),
 features.getFeatureSchema(), attr);
    }
    
    
    /**
     * Converts a given FeatureCollection into an array of Feature, that can - 
by far - be faster iterated.
     [EMAIL PROTECTED] fc the feature Collection
     [EMAIL PROTECTED] an array of the features of the feature collection
     */
    public static Feature[] FeatureCollection2FeatureArray( FeatureCollection 
fc ){
        return (Feature[])fc.getFeatures().toArray(new Feature[0]);
    }
    
    /**
     * Converts a given list of features into an array of Feature, that can - 
by far - be faster iterated.
     [EMAIL PROTECTED] features list of features
     [EMAIL PROTECTED] an array of the features of the feature list
     */
    public static Feature[] FeatureCollection2FeatureArray( List<Feature> 
features ){
        return (Feature[])features.toArray(new Feature[0]);
    }
}
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel

Reply via email to