001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2004-2006, Geotools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data.vpf;
017:
018: import java.io.File;
019: import java.io.IOException;
020: import java.sql.SQLException;
021: import java.util.AbstractSet;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Vector;
026: import java.net.URI;
027:
028: import org.geotools.data.vpf.file.VPFFile;
029: import org.geotools.data.vpf.file.VPFFileFactory;
030: import org.geotools.data.vpf.ifc.FCode;
031: import org.geotools.data.vpf.ifc.FileConstants;
032: import org.geotools.data.vpf.ifc.VPFCoverageIfc;
033: import org.geotools.feature.Feature;
034: import org.geotools.feature.SchemaException;
035:
036: /**
037: * A VPF coverage. This class constructs and contains both feature
038: * classes and feature types.
039: * @author <a href="mailto:jeff@ionicenterprise.com">Jeff Yutzler</a>
040: *
041: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/vpf/src/main/java/org/geotools/data/vpf/VPFCoverage.java $
042: */
043: public class VPFCoverage implements FCode, FileConstants,
044: VPFCoverageIfc {
045: /**
046: * The description attribute of the coverage
047: */
048: private final String description;
049:
050: /** List of feature classes part of this coverage */
051: private final List featureClasses = new Vector();
052:
053: /** List of feature types part of this coverage */
054: private final List featureTypes = new Vector(25);
055:
056: /** The owning library */
057: private final VPFLibrary library;
058: /** Path name for the directory containing this coverage */
059: private final String pathName;
060: /**
061: * The topology level (0-3)
062: */
063: private final int topologyLevel;
064:
065: /**
066: * The namespace to create features with.
067: */
068: private final URI namespace;
069:
070: /**
071: * Constructor
072: *
073: * @param cLibrary
074: * @param feature
075: * @param cDirectoryName path to directory containing coverage
076: *
077: * @throws IOException if the directory does not contain a valid FCS file
078: * @throws SchemaException For problems making one of the feature classes as a FeatureType.
079: */
080: public VPFCoverage(VPFLibrary cLibrary, Feature feature,
081: String cDirectoryName) throws IOException, SchemaException {
082: this (cLibrary, feature, cDirectoryName, null);
083: }
084:
085: /**
086: * Constructor with namespace
087: *
088: * @param cLibrary
089: * @param feature
090: * @param cDirectoryName path to directory containing coverage
091: * @param namespace
092: *
093: * @throws IOException if the directory does not contain a valid FCS file
094: * @throws SchemaException For problems making one of the feature classes as a FeatureType.
095: */
096: public VPFCoverage(VPFLibrary cLibrary, Feature feature,
097: String cDirectoryName, URI namespace) throws IOException,
098: SchemaException {
099: topologyLevel = Short.parseShort(feature.getAttribute(
100: FIELD_LEVEL).toString());
101: library = cLibrary;
102: description = feature.getAttribute(
103: VPFCoverageIfc.FIELD_DESCRIPTION).toString();
104: this .namespace = namespace;
105: pathName = cDirectoryName.concat(File.separator).concat(
106: feature.getAttribute(FIELD_COVERAGE_NAME).toString());
107: discoverFeatureClasses();
108: discoverFeatureTypes();
109: }
110:
111: /**
112: * Builds feature classes for the coverage
113: *
114: * @throws SQLException
115: */
116: private void discoverFeatureClasses() throws IOException,
117: SchemaException {
118: VPFFeatureClass featureClass = null;
119: boolean hasFeatureClass;
120: String fcsFileName = pathName + File.separator + TABLE_FCS;
121: AbstractSet featureClassNames = new HashSet();
122: String featureClassName;
123:
124: // We need to record all of the possible files
125: // for each of the feature classes in this coverage
126: VPFFile file = VPFFileFactory.getInstance()
127: .getFile(fcsFileName);
128:
129: // We might want to grab the FCS list and pass it to the feature class
130: // constructor just to save time.
131: Iterator iter = file.readAllRows().iterator();
132: while (iter.hasNext()) {
133: Feature row = (Feature) iter.next();
134: featureClassName = row.getAttribute("feature_class")
135: .toString().trim();
136: featureClass = new VPFFeatureClass(this , featureClassName,
137: pathName, namespace);
138: featureClasses.add(featureClass);
139: }
140: }
141:
142: /**
143: * The point of this block of code is
144: * to scan the CHAR.VDT file for FACC codes.
145: * There is a one to one relationship
146: * between FACC codes and feature types,
147: * but there is a one to many relationship
148: * between feature classes
149: * and feature types/FACC codes.
150: * Since objects are stored
151: * in the file system by feature class,
152: * this mechanism allows us
153: * to separate features
154: * of different feature types
155: * in the same feature class.
156: *
157: * Some coverages do not have a CHAR.VDT file.
158: * In these cases, there is a 1:1:1 relationship
159: * between the coverage, feature class,
160: * and feature type.
161: */
162: private void discoverFeatureTypes() {
163: try {
164: Iterator charVDTIter = getCharVDT().readAllRows()
165: .iterator();
166:
167: while (charVDTIter.hasNext()) {
168: // Figure out which featureClass owns it
169: Feature row = (Feature) charVDTIter.next();
170: String attr = row.getAttribute("attribute").toString()
171: .trim().toLowerCase();
172:
173: if (!ALLOWED_FCODE_ATTRIBUTES_LIST.contains(attr))
174: continue;
175:
176: String tableFileName = row.getAttribute("table")
177: .toString().trim();
178:
179: // We need to go through all of this
180: // so that entries match what is in FCS
181: String featureClassName = tableFileName.substring(0,
182: tableFileName.indexOf("."));
183: Iterator featureClassIter = featureClasses.iterator();
184:
185: while (featureClassIter.hasNext()) {
186: VPFFeatureClass featureClass = (VPFFeatureClass) featureClassIter
187: .next();
188:
189: if (featureClassName.equals(featureClass
190: .getTypeName())) {
191: VPFFeatureType featureType = new VPFFeatureType(
192: featureClass, row);
193: featureTypes.add(featureType);
194:
195: break;
196: }
197: }
198: }
199: } catch (IOException exc) {
200: // If there is no char.vdt,
201: // we can assume there is only one feature type
202: // and only one feature class
203: VPFFeatureClass coverageClass = (VPFFeatureClass) featureClasses
204: .get(0);
205: VPFFeatureType featureType = new VPFFeatureType(
206: coverageClass);
207: featureTypes.add(featureType);
208: }
209: }
210:
211: /**
212: * Look for a char.vdt
213: *
214: * @return a TableInputStream for the char.vdt for this coverage
215: *
216: * @throws IOException on any IO problems, particularly not being able to find the char.vdt file
217: */
218: private VPFFile getCharVDT() throws IOException {
219: VPFFile charvdtInputStream = null;
220: String charvdtFileName = pathName + File.separator
221: + CHARACTER_VALUE_DESCRIPTION_TABLE;
222: charvdtInputStream = VPFFileFactory.getInstance().getFile(
223: charvdtFileName);
224:
225: return charvdtInputStream;
226: }
227:
228: /**
229: * Returns the feature classes in the coverage
230: *
231: * @return the feature classes in the coverage
232: */
233: public List getFeatureClasses() {
234: return featureClasses;
235: }
236:
237: /**
238: * Returns the feature types for this coverage
239: *
240: * @return a <code>List</code> of the feature types
241: */
242: public List getFeatureTypes() {
243: return featureTypes;
244: }
245:
246: /**
247: * Returns the owning Module (When refactored this will be the
248: * VPFDataSource))
249: *
250: * @return the owning Module
251: */
252: public VPFLibrary getLibrary() {
253: return library;
254: }
255:
256: /**
257: * Returns the coverage name
258: *
259: * @return the coverage name
260: */
261: public String getName() {
262: String result = pathName.substring(pathName
263: .lastIndexOf(File.separator) + 1);
264:
265: return result;
266: }
267:
268: /**
269: * Returns the name of the path of the directory containing the coverage
270: *
271: * @return the path of the directory containing the coverage
272: */
273: public String getPathName() {
274: return pathName;
275: }
276:
277: /**
278: * @return Returns the topologyLevel.
279: */
280: public int getTopologyLevel() {
281: return topologyLevel;
282: }
283:
284: /*
285: * (non-Javadoc)
286: * @see java.lang.Object#toString()
287: */
288: public String toString() {
289: return "VPF Coverage " + getName() + ". " + description + "\n"
290: + "Topology level " + topologyLevel;
291: }
292: }
|