Package org.geotools.data.vpf

Source Code of org.geotools.data.vpf.VPFFeatureReader

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
*
*    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.geotools.data.vpf;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import org.geotools.data.FeatureReader;
import org.geotools.data.vpf.file.VPFFile;
import org.geotools.data.vpf.file.VPFFileFactory;

import static org.geotools.data.vpf.ifc.FCode.*;

import org.geotools.feature.IllegalAttributeException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.type.AnnotationFeatureType;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.Name;

/**
*
* @author  <a href="mailto:knuterik@onemap.org">Knut-Erik Johnsen</a>, Project OneMap
* @author Chris Holmes, Fulbright.
*
*
*
* @source $URL$
*/
public class VPFFeatureReader
    implements FeatureReader<SimpleFeatureType, SimpleFeature> {
    private boolean hasNext = true;
    private boolean nextCalled = true;
    private SimpleFeature currentFeature = null;
    private final VPFFeatureType featureType;

    /** Creates a new instance of VPFFeatureReader */
    public VPFFeatureReader(VPFFeatureType type) {
        this.featureType = type;
    }

    /* (non-Javadoc)
     * @see org.geotools.data.FeatureReader#close()
     */
    public void close() throws IOException {
        reset();
    }

    /**
     * Put together a map of VPF files and their corresponding
     * TableRows
     *
     * @param file
     * @param row
     */
    private Map generateFileRowMap(VPFFile file, SimpleFeature row)
            throws IOException{
        String tileFileName = null;
        Map rows = new HashMap();
        rows.put(file, row);
        Iterator joinIter = featureType.getFeatureClass().getJoinList().iterator();
        while (joinIter.hasNext()) {
            ColumnPair columnPair = (ColumnPair) joinIter.next();
            VPFFile primaryFile = getVPFFile(columnPair.column1);
            VPFFile joinFile = null;
            joinFile = getVPFFile(columnPair.column2);
   
            if (!rows.containsKey(joinFile) && rows.containsKey(primaryFile)) {
                SimpleFeature joinRow = (SimpleFeature) rows.get(primaryFile);
   
                try {
                    int joinID = Integer.parseInt(joinRow.getAttribute(columnPair.column1.getName()).toString());
                    rows.put(joinFile, getVPFFile(columnPair.column2).getRowFromId(columnPair.column2.getName(), joinID));
                } catch (NullPointerException exc) {
                    // Non-matching joins - just put in a NULL
                    rows.put(joinFile, null);
                } catch (IllegalAttributeException exc) {
                    // I really don't expect to see this one
                    exc.printStackTrace();
                    rows.put(joinFile, null);
                }
            }
        }
        return rows;
   
    }

    /* (non-Javadoc)
     * @see org.geotools.data.FeatureReader#getFeatureType()
     */
    public SimpleFeatureType getFeatureType() {
        return featureType;
    }

    /* (non-Javadoc)
     * @see org.geotools.data.FeatureReader#hasNext()
     */
    public boolean hasNext() throws IOException {
        if (nextCalled) {
            while(readNext());
          nextCalled = false;
      }
        return hasNext;
    }

    /* (non-Javadoc)
     * @see org.geotools.data.FeatureReader#next()
     */
    public SimpleFeature next() throws IOException, IllegalAttributeException,
                                 NoSuchElementException {
        nextCalled = true;
        return currentFeature;
    }
    /**
     * Read a row and determine if it matches the feature type
     * Three possibilities here:
     * row is null -- hasNext = false, do not try again
     * row matches -- hasNext = true, do not try again
     * row does not match -- hasNext is undefined because we must try again
     * @return Whether we need to read again
     */
    private boolean readNext() throws IOException {
        boolean result = true;
        VPFFile file = (VPFFile) featureType.getFeatureClass().getFileList().get(0);
        hasNext = false;
        SimpleFeature row = null;
        try {
            if(file.hasNext()){
                row = file.readFeature();
            }
        } catch (IOException exc1) {
            // TODO Auto-generated catch block
            exc1.printStackTrace();
        } catch (IllegalAttributeException exc1) {
            // TODO Auto-generated catch block
            exc1.printStackTrace();
        }
        if ((row == null)) {
            hasNext = false;
            result = false;
        }
        // Exclude objects with a different FACC Code
        else if (featureType.getFaccCode() != null){
            try {
                Object temp = null;
                for (int i = 0; temp == null && i < ALLOWED_FCODE_ATTRIBUTES.length; i++) {
                    temp = row.getAttribute( ALLOWED_FCODE_ATTRIBUTES[i] );
                }
                String faccCode = temp.toString().trim();
                if(featureType.getFaccCode().equals(faccCode)){
                    retrieveObject(file, row);
                    hasNext = true;
                    result = false;
                }
            } catch (RuntimeException exc) {
                // Ignore this case because it typically means the f_code is invalid
            }
        }
        return result;
    }
    /**
     * Get the values from all of the columns
     * based on their presence (or absense) in the rows
     *
     * Potential cases:
     * simple column
     * join column
     * non-matching join
     * null value
     * geometry
     *
     * @param file the file
     * @param row the row
     *
     */
    private void retrieveObject(VPFFile file, SimpleFeature row) throws IOException{
        VPFFile secondFile = null;
        VPFColumn column = null;
        Map rows = generateFileRowMap(file, row);
        List<AttributeDescriptor> attributes = featureType.getFeatureClass().getAttributeDescriptors();
        Object[] values = new Object[featureType.getAttributeCount()];
        Object value = null;
        String featureId = null;
        // Pass 1 - identify the feature identifier
        for(int inx = 0; inx < attributes.size(); inx++){
            // I am thinking it is probably safer to look this up
            // by column name than by position, but if it breaks,
            // it is easy enough to change
            if (attributes.get(inx).getLocalName().equals("id")) {
                value = row.getAttribute(inx);
                if(value != null) {
                    featureId = value.toString();
                }
                break;
            }
        }
        try {
            currentFeature = SimpleFeatureBuilder.build(featureType,values, featureId);
        } catch (IllegalAttributeException exc) {
            // This shouldn't happen since everything should be nillable
            exc.printStackTrace();
        }
       
        // Pass 2 - get the attributes, including the geometry
        for(int inx = 0; inx < attributes.size(); inx++){
            try {
                if (attributes.get(inx).getLocalName().equals(AnnotationFeatureType.ANNOTATION_ATTRIBUTE_NAME)) {
                    try{
                        //TODO: are we sure this is the intended action? Hard-coding an attribute to "nam"?
                        currentFeature.setAttribute(inx, "nam");
                    } catch (IllegalAttributeException exc) {
                        exc.printStackTrace();
                    }
                    continue;
                }
                column = (VPFColumn) attributes.get(inx);
                value = null;
                secondFile = getVPFFile(column);
                SimpleFeature tempRow = (SimpleFeature) rows.get(secondFile);
                if(tempRow != null){
                    value = tempRow.getAttribute(column.getName());
                    if (column.isAttemptLookup()){
                        try {
                            // Attempt to perform a lookup and conversion
                            String featureClassName = getVPFFile(column).getFileName();
                            String intVdtFileName = featureType.getFeatureClass().getDirectoryName().concat(File.separator).concat("int.vdt");
                            VPFFile intVdtFile = VPFFileFactory.getInstance().getFile(intVdtFileName);
                            Iterator intVdtIter = intVdtFile.readAllRows().iterator();
                            while(intVdtIter.hasNext()){
                                SimpleFeature intVdtRow = (SimpleFeature)intVdtIter.next();
                                if(intVdtRow.getAttribute("table").toString().trim().equals(featureClassName) &&
                                        (Short.parseShort(intVdtRow.getAttribute("value").toString()) == Short.parseShort(value.toString()) &&
                                        (intVdtRow.getAttribute("attribute").toString().trim().equals(column.getName())))){
                                    value = intVdtRow.getAttribute("description").toString().trim();
                                    break;
                                }
                            }
                        // If there is a problem, forget about mapping and continue
                        } catch (IOException exc) {
                        } catch (RuntimeException exc) {
                        }
                    }
                }
                try {
                    currentFeature.setAttribute(inx, value);
                } catch (ArrayIndexOutOfBoundsException exc) {
                    // TODO Auto-generated catch block
                    exc.printStackTrace();
                } catch (IllegalAttributeException exc) {
                    // TODO Auto-generated catch block
                    exc.printStackTrace();
                }
            } catch (ClassCastException exc2) {
                try {
                    // This is the area geometry case
                    featureType.getFeatureClass().getGeometryFactory().createGeometry(featureType, currentFeature);
                } catch (IllegalAttributeException exc) {
                    // TODO Auto-generated catch block
                    exc.printStackTrace();
                } catch (SQLException exc) {
                    // TODO Auto-generated catch block
                    exc.printStackTrace();
                }
            }
        }

    }
    /**
     * Returns the VPFFile for a particular column.
     * It will only find the first match, but that should be okay
     * because duplicate columns will cause even bigger problems elsewhere.
     * @param column the column to search for
     * @return the VPFFile that owns this column
     */
    private VPFFile getVPFFile(VPFColumn column){
        String columnName = column.getName();
        VPFFile result = null;
        VPFFile temp;
        Iterator<VPFFile> iter = featureType.getFeatureClass().getFileList().iterator();
        while(iter.hasNext()){
            temp = (VPFFile)iter.next();
            if((temp != null) && (temp.getColumn(columnName) != null)){
                result = temp;
                break;
            }
        }
        return result;
    }
    /**
     * Returns the VPFFile for a particular column.
     * It will only find the first match, but that should be okay
     * because duplicate columns will cause even bigger problems elsewhere.
     * @param column the column to search for
     * @return the VPFFile that owns this column
     */
    private VPFFile getVPFFile(AttributeDescriptor column){
        Name columnName = column.getName();
        VPFFile result = null;
        VPFFile temp;
        Iterator<VPFFile> iter = featureType.getFeatureClass().getFileList().iterator();
        while(iter.hasNext()){
            temp = iter.next();
            if((temp != null) && (temp.getColumn(columnName.getLocalPart()) != null)){
                result = temp;
                break;
            }
        }
        return result;
    }
    /**
     * Need to reset the stream for the next time Resets the iterator by
     * resetting the stream.
     *
     */
    public void reset(){
            VPFFile file = (VPFFile) featureType.getFeatureClass()
                    .getFileList().get(0);
            file.reset();
            VPFFileFactory.getInstance().reset();
    }
}
TOP

Related Classes of org.geotools.data.vpf.VPFFeatureReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.