/* * 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.AbstractSet; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Vector; import java.net.URI; import org.geotools.data.vpf.file.VPFFile; import org.geotools.data.vpf.file.VPFFileFactory; import org.geotools.data.vpf.ifc.FCode; import org.geotools.data.vpf.ifc.FileConstants; import org.geotools.data.vpf.ifc.VPFCoverageIfc; import org.geotools.feature.SchemaException; import org.opengis.feature.simple.SimpleFeature; /** * A VPF coverage. This class constructs and contains both feature * classes and feature types. * @author <a href="mailto:jeff@ionicenterprise.com">Jeff Yutzler</a> * * * * @source $URL$ */ public class VPFCoverage implements FCode, FileConstants, VPFCoverageIfc { /** * The description attribute of the coverage */ private final String description; /** List of feature classes part of this coverage */ private final List featureClasses = new Vector(); /** List of feature types part of this coverage */ private final List featureTypes = new Vector(25); /** The owning library */ private final VPFLibrary library; /** Path name for the directory containing this coverage */ private final String pathName; /** * The topology level (0-3) */ private final int topologyLevel; /** * The namespace to create features with. */ private final URI namespace; /** * Constructor * * @param cLibrary * @param feature * @param cDirectoryName path to directory containing coverage * * @throws IOException if the directory does not contain a valid FCS file * @throws SchemaException For problems making one of the feature classes as a FeatureType. */ public VPFCoverage(VPFLibrary cLibrary, SimpleFeature feature, String cDirectoryName) throws IOException, SchemaException { this(cLibrary, feature, cDirectoryName, null); } /** * Constructor with namespace * * @param cLibrary * @param feature * @param cDirectoryName path to directory containing coverage * @param namespace * * @throws IOException if the directory does not contain a valid FCS file * @throws SchemaException For problems making one of the feature classes as a FeatureType. */ public VPFCoverage(VPFLibrary cLibrary, SimpleFeature feature, String cDirectoryName, URI namespace) throws IOException, SchemaException { topologyLevel = Short.parseShort(feature.getAttribute(FIELD_LEVEL).toString()); library = cLibrary; description = feature.getAttribute(VPFCoverageIfc.FIELD_DESCRIPTION).toString(); this.namespace = namespace; pathName = cDirectoryName.concat(File.separator).concat(feature.getAttribute(FIELD_COVERAGE_NAME).toString()); discoverFeatureClasses(); discoverFeatureTypes(); } /** * Builds feature classes for the coverage * * @throws SQLException */ private void discoverFeatureClasses() throws IOException, SchemaException{ VPFFeatureClass featureClass = null; boolean hasFeatureClass; String fcsFileName = pathName + File.separator + TABLE_FCS; AbstractSet featureClassNames = new HashSet(); String featureClassName; // We need to record all of the possible files // for each of the feature classes in this coverage VPFFile file = VPFFileFactory.getInstance().getFile(fcsFileName); // We might want to grab the FCS list and pass it to the feature class // constructor just to save time. Iterator iter = file.readAllRows().iterator(); while (iter.hasNext()) { SimpleFeature row = (SimpleFeature) iter.next(); featureClassName = row.getAttribute("feature_class").toString().trim(); featureClass = new VPFFeatureClass(this, featureClassName, pathName, namespace); featureClasses.add(featureClass); } } /** * The point of this block of code is * to scan the CHAR.VDT file for FACC codes. * There is a one to one relationship * between FACC codes and feature types, * but there is a one to many relationship * between feature classes * and feature types/FACC codes. * Since objects are stored * in the file system by feature class, * this mechanism allows us * to separate features * of different feature types * in the same feature class. * * Some coverages do not have a CHAR.VDT file. * In these cases, there is a 1:1:1 relationship * between the coverage, feature class, * and feature type. */ private void discoverFeatureTypes() { try { Iterator charVDTIter = getCharVDT().readAllRows().iterator(); while (charVDTIter.hasNext()) { // Figure out which featureClass owns it SimpleFeature row = (SimpleFeature) charVDTIter.next(); String attr = row.getAttribute("attribute").toString().trim().toLowerCase(); if (!ALLOWED_FCODE_ATTRIBUTES_LIST.contains(attr)) continue; String tableFileName = row.getAttribute("table").toString().trim(); // We need to go through all of this // so that entries match what is in FCS String featureClassName = tableFileName.substring(0, tableFileName.indexOf(".")); Iterator featureClassIter = featureClasses.iterator(); while (featureClassIter.hasNext()) { VPFFeatureClass featureClass = (VPFFeatureClass) featureClassIter.next(); if (featureClassName.equals(featureClass.getTypeName())) { VPFFeatureType featureType = new VPFFeatureType(featureClass, row); featureTypes.add(featureType); break; } } } } catch (IOException exc) { // If there is no char.vdt, // we can assume there is only one feature type // and only one feature class VPFFeatureClass coverageClass = (VPFFeatureClass) featureClasses .get(0); VPFFeatureType featureType = new VPFFeatureType(coverageClass); featureTypes.add(featureType); } } /** * Look for a char.vdt * * @return a TableInputStream for the char.vdt for this coverage * * @throws IOException on any IO problems, particularly not being able to find the char.vdt file */ private VPFFile getCharVDT() throws IOException { VPFFile charvdtInputStream = null; String charvdtFileName = pathName + File.separator + CHARACTER_VALUE_DESCRIPTION_TABLE; charvdtInputStream = VPFFileFactory.getInstance() .getFile(charvdtFileName); return charvdtInputStream; } /** * Returns the feature classes in the coverage * * @return the feature classes in the coverage */ public List getFeatureClasses() { return featureClasses; } /** * Returns the feature types for this coverage * * @return a <code>List</code> of the feature types */ public List getFeatureTypes() { return featureTypes; } /** * Returns the owning Module (When refactored this will be the * VPFDataSource)) * * @return the owning Module */ public VPFLibrary getLibrary() { return library; } /** * Returns the coverage name * * @return the coverage name */ public String getName() { String result = pathName.substring(pathName.lastIndexOf( File.separator) + 1); return result; } /** * Returns the name of the path of the directory containing the coverage * * @return the path of the directory containing the coverage */ public String getPathName() { return pathName; } /** * @return Returns the topologyLevel. */ public int getTopologyLevel() { return topologyLevel; } /* * (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { return "VPF Coverage " + getName() + ". " + description + "\n" + "Topology level " + topologyLevel; } }