Java tutorial
/*---------------- FILE HEADER KALYPSO ------------------------------------------ * * This file is part of kalypso. * Copyright (C) 2004 by: * * Technical University Hamburg-Harburg (TUHH) * Institute of River and coastal engineering * Denickestrae 22 * 21073 Hamburg, Germany * http://www.tuhh.de/wb * * and * * Bjoernsen Consulting Engineers (BCE) * Maria Trost 3 * 56070 Koblenz, Germany * http://www.bjoernsen.de * * 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; either * version 2.1 of the License, or (at your option) any later version. * * 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. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: * * E-Mail: * belger@bjoernsen.de * schlienger@bjoernsen.de * v.doemming@tuhh.de * * ---------------------------------------------------------------------------*/ package org.kalypso.shape.deegree; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.Formatter; import java.util.regex.Pattern; import javax.xml.namespace.QName; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Plugin; import org.kalypso.commons.xml.XmlTypes; import org.kalypso.contribs.eclipse.ui.progress.ProgressUtilities; import org.kalypso.gmlschema.GMLSchemaCatalog; import org.kalypso.gmlschema.GMLSchemaException; import org.kalypso.gmlschema.IGMLSchema; import org.kalypso.gmlschema.KalypsoGMLSchemaPlugin; import org.kalypso.gmlschema.feature.IFeatureType; import org.kalypso.gmlschema.property.relation.IRelationType; import org.kalypso.gmlschema.types.IMarshallingTypeHandler; import org.kalypso.gmlschema.types.ITypeRegistry; import org.kalypso.gmlschema.types.MarshallingTypeRegistrySingleton; import org.kalypso.shape.ShapeFile; import org.kalypso.shape.ShapeType; import org.kalypso.shape.dbf.FieldType; import org.kalypso.shape.dbf.IDBFField; import org.kalypso.shape.geometry.ISHPGeometry; import org.kalypsodeegree.KalypsoDeegreePlugin; import org.kalypsodeegree.model.feature.GMLWorkspace; import org.kalypsodeegree.model.geometry.GM_Object; import org.kalypsodeegree_impl.gml.binding.shape.AbstractShape; import org.kalypsodeegree_impl.gml.binding.shape.ShapeCollection; import org.kalypsodeegree_impl.model.feature.FeatureFactory; import com.google.common.base.Charsets; /** * @author Holer Albert * @author Gernot Belger */ public final class Shape2GML { private Shape2GML() { throw new UnsupportedOperationException(); } public static ShapeCollection convertShp2Gml(final String featureTypeKey, final ShapeFile shape, final String shapeSRS, final IProgressMonitor monitor) throws Exception { // System.out.format( "%s: %s%n", shape.getFileBase(), featureTypeKey ); final int count = shape.getNumRecords(); monitor.beginTask("Converting shape entries", count); final IFeatureType featureType = createFeatureType(featureTypeKey, shape); final GMLWorkspace workspace = createShapeWorkspace(shape.getShapeType(), featureType); final ShapeCollection collection = (ShapeCollection) workspace.getRootFeature(); final IRelationType listRelation = (IRelationType) collection.getFeatureType() .getProperty(ShapeCollection.MEMBER_FEATURE_LOCAL); final int fieldCount = shape.getFields().length; for (int i = 0; i < count; i++) { ProgressUtilities.workedModulo(monitor, i, count, 100, "reading feature %d / %d"); /* directly create feature from row values -> we know the feature type fits the specification */ final String featureId = Integer.toString(i); /* get values */ final Object[] properties = new Object[fieldCount]; if (shape.readRow(i, properties)) { /* convert geometry */ final ISHPGeometry geometry = shape.getShape(i); final GM_Object geom = SHP2GM_Object.transform(shapeSRS, geometry); /* Build properties including geometry, we know that geom is at pos 0 */ final Object[] propertiesWithGeom = new Object[fieldCount + 1]; propertiesWithGeom[0] = geom; System.arraycopy(properties, 0, propertiesWithGeom, 1, fieldCount); final AbstractShape newFeature = (AbstractShape) FeatureFactory.createFeature(collection, listRelation, featureId, featureType, propertiesWithGeom); /* add to workspace */ workspace.addFeatureAsComposition(collection, listRelation, -1, newFeature); } } return collection; } public static IFeatureType createFeatureType(final String key, final ShapeFile shape) { final ShapeType shapeType = shape.getShapeType(); final IDBFField[] fields = shape.getFields(); return createFeatureType(key, shapeType, fields); } /** * REMARK: key: was formerly (in dbase file) m_suffix = "" + m_fname.hashCode() */ public static IFeatureType createFeatureType(final String key, final ShapeType shapeType, final IDBFField[] fields) { try { final String targetNamespace = ShapeCollection.SHP_NAMESPACE_URI + ".custom_" + key; /* geometry property: overwrites the one defined in '_Shape' */ final String geomTypeName = getGeometryName(shapeType); /* The value properties */ final String propertyElementsSchemaFragment = buildValueElementsDefinition(fields); /* Read schema template and replace placeholders */ final URL resource = Shape2GML.class.getResource("resources/shapeCustomTemplate.xsd"); String schemaString = IOUtils.toString(resource, Charsets.UTF_8.name()); schemaString = schemaString.replaceAll(Pattern.quote("${CUSTOM_NAMESPACE_SUFFIX}"), key); schemaString = schemaString.replaceAll(Pattern.quote("${CUSTOM_FEATURE_PROPERTY_ELEMENTS}"), propertyElementsSchemaFragment); schemaString = schemaString.replaceAll(Pattern.quote("${GEOM_TYPE_NAME}"), geomTypeName); final File tempFile = createTempFile(KalypsoDeegreePlugin.getDefault(), "temporaryCustomSchemas", "customSchema", ".xsd"); tempFile.deleteOnExit(); // TODO: why write this file to disk? Why not directly parse the schema from it and add the schema to the cache? FileUtils.writeStringToFile(tempFile, schemaString, Charsets.UTF_8.name()); /* read schema via catalog and retrieve the feature type from the freshly loaded schema */ final GMLSchemaCatalog catalog = KalypsoGMLSchemaPlugin.getDefault().getSchemaCatalog(); final IGMLSchema schema = catalog.getSchema(null, tempFile.toURI().toURL()); //$NON-NLS-1$ final QName memberFeatureType = new QName(targetNamespace, "Shape"); //$NON-NLS-1$ return schema.getFeatureType(memberFeatureType); } catch (final IOException e) { // This should never happen, as we always are allowed to access plugin state. // Encapsulate into runtime exception, so we do not need to catch it everywhere. e.printStackTrace(); throw new IllegalStateException(e); } } /** * Create a temp file in the subDirName of the plugin's state location (where files can be created, deleted, etc.). * Uses File.createTempFile() so as written in the File javadoc, you should call .deleteOnExit() on the returned file * instance to make it a real 'temp' file. */ private static File createTempFile(final Plugin plugin, final String subDirName, String prefix, final String suffix) throws IOException { if (prefix.length() < 3) prefix += "___"; final IPath path = plugin.getStateLocation(); final File dir = new File(path.toFile(), subDirName); if (!dir.exists()) dir.mkdir(); // TODO as org.kalypso.commons.java.io.FileUtilities.validateName() should be moved to JavaApiContribs and could be // used here final String cleanPrefix = prefix.replaceAll("[\\\\/:\\*\\?\"<>|]", "_"); return File.createTempFile(cleanPrefix, suffix, dir); } private static String buildValueElementsDefinition(final IDBFField[] fields) { final Formatter formatter = new Formatter(); for (final IDBFField field : fields) { final IMarshallingTypeHandler th = findTypeHandler(field); final String name = field.getName(); final String type = th.getTypeName().getLocalPart(); formatter.format("<element name='%s' type='%s'/>%n", name, type); } return formatter.toString(); } private static IMarshallingTypeHandler findTypeHandler(final IDBFField field) { final ITypeRegistry<IMarshallingTypeHandler> registry = MarshallingTypeRegistrySingleton.getTypeRegistry(); final FieldType type = field.getType(); switch (type) { case C: return registry.getTypeHandlerForTypeName(XmlTypes.XS_STRING); case D: return registry.getTypeHandlerForTypeName(XmlTypes.XS_DATE); case F: case N: final short decimal = field.getDecimalCount(); final short size = field.getLength(); if (decimal == 0) { if (size < 10) return registry.getTypeHandlerForTypeName(XmlTypes.XS_INT); return registry.getTypeHandlerForTypeName(XmlTypes.XS_LONG); } if (size < 8) return registry.getTypeHandlerForTypeName(XmlTypes.XS_FLOAT); return registry.getTypeHandlerForTypeName(XmlTypes.XS_DOUBLE); case L: return registry.getTypeHandlerForTypeName(XmlTypes.XS_BOOLEAN); case M: return registry.getTypeHandlerForTypeName(XmlTypes.XS_STRING); // case B: // final IMarshallingTypeHandler byteArrayOutputStreamTH = registry.getTypeHandlerForClassName( // ByteArrayOutputStream.class ); default: throw new IllegalStateException(); } } private static String getGeometryName(final ShapeType shapeType) { switch (shapeType) { case NULL: return "Null"; //$NON-NLS-1$ case POINT: case POINTM: case POINTZ: return "Point"; //$NON-NLS-1$ case MULTIPOINT: case MULTIPOINTM: case MULTIPOINTZ: return "MultiPoint"; //$NON-NLS-1$ case POLYLINE: case POLYLINEM: case POLYLINEZ: return "Polyline"; case POLYGON: case POLYGONM: case POLYGONZ: return "Polygon"; } throw new UnsupportedOperationException(); } private static GMLWorkspace createShapeWorkspace(final ShapeType shapeFileType, final IFeatureType elementType) throws GMLSchemaException { final String customNamespace = elementType.getQName().getNamespaceURI(); final QName concreteCollectionQName = new QName(customNamespace, "ShapeCollection"); //$NON-NLS-1$ final GMLWorkspace workspace = FeatureFactory.createGMLWorkspace(concreteCollectionQName, null, null); final ShapeCollection collection = (ShapeCollection) workspace.getRootFeature(); collection.setShapeType(shapeFileType); return workspace; } }