Search in sources :

Example 1 with DbaseFileHeader

use of org.geotoolkit.data.dbf.DbaseFileHeader in project geotoolkit by Geomatys.

the class ShapefileFeatureStore method createFeatureType.

// //////////////////////////////////////////////////////////////////////////
// schema manipulation /////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////
/**
 * Set the FeatureType of this DataStore. This method will delete any
 * existing local resources or throw an IOException if the featurestore is
 * remote.
 *
 * @param featureType The desired FeatureType.
 * @throws DataStoreException If the featurestore is remote.
 *
 * @todo must synchronize this properly
 */
@Override
public void createFeatureType(final FeatureType featureType) throws DataStoreException {
    final GenericName typeName = featureType.getName();
    if (!isWritable(typeName.toString())) {
        throw new DataStoreException("Read-only acces prevent type creation.");
    }
    if (typeName == null) {
        throw new DataStoreException("Type name can not be null.");
    }
    if (!featureType.isSimple()) {
        throw new DataStoreException("Feature type must not be null and must be a simple feature type.");
    }
    if (!featureType.getName().equals(typeName)) {
        throw new DataStoreException("Shapefile featurestore can only hold typename same as feature type name.");
    }
    try {
        // delete the files
        shpFiles.delete();
    } catch (IOException ex) {
        throw new DataStoreException("Cannot reset datastore content", ex);
    }
    final AccessManager locker = shpFiles.createLocker();
    // update schema and name
    name = typeName;
    schema = featureType;
    AttributeType desc;
    try {
        desc = Features.toAttribute(FeatureExt.getDefaultGeometry(featureType)).orElse(null);
    } catch (PropertyNotFoundException e) {
        getLogger().log(Level.FINE, e, () -> String.format("No geometry can be found in given datatype%n%s", featureType));
        desc = null;
    }
    CoordinateReferenceSystem crs = null;
    final Class<?> geomType;
    final ShapeType shapeType;
    if (desc != null) {
        crs = FeatureExt.getCRS(desc);
        geomType = desc.getValueClass();
        shapeType = ShapeType.findBestGeometryType(geomType);
    } else {
        geomType = null;
        shapeType = ShapeType.NULL;
    }
    if (shapeType == ShapeType.UNDEFINED) {
        throw new DataStoreException("Cannot create a shapefile whose geometry type is " + geomType);
    }
    try (Closeable disposeLocker = locker::disposeReaderAndWriters) {
        final StorageFile shpStoragefile = locker.getStorageFile(SHP);
        final StorageFile shxStoragefile = locker.getStorageFile(SHX);
        final StorageFile dbfStoragefile = locker.getStorageFile(DBF);
        final StorageFile prjStoragefile = locker.getStorageFile(PRJ);
        final StorageFile cpgStoragefile = locker.getStorageFile(CPG);
        try (FileChannel shpChannel = shpStoragefile.getWriteChannel();
            FileChannel shxChannel = shxStoragefile.getWriteChannel()) {
            try (ShapefileWriter writer = new ShapefileWriter(shpChannel, shxChannel)) {
                // try to get the domain first
                final Envelope domain = CRS.getDomainOfValidity(crs);
                if (domain != null) {
                    writer.writeHeaders(new JTSEnvelope2D(domain), shapeType, 0, 100);
                } else {
                    // try to reproject the single overall envelope keeping poles out of the way
                    final JTSEnvelope2D env = new JTSEnvelope2D(-179, 179, -89, 89, CommonCRS.WGS84.normalizedGeographic());
                    JTSEnvelope2D transformedBounds;
                    if (crs != null) {
                        try {
                            transformedBounds = env.transform(crs);
                        } catch (Exception t) {
                            getLogger().log(Level.WARNING, t.getLocalizedMessage(), t);
                            // It can happen for local projections :
                            transformedBounds = new JTSEnvelope2D(crs);
                        }
                    } else {
                        transformedBounds = env;
                    }
                    writer.writeHeaders(transformedBounds, shapeType, 0, 100);
                }
            }
        }
        final DbaseFileHeader dbfheader = DbaseFileHeader.createDbaseHeader(schema);
        dbfheader.setNumRecords(0);
        try (WritableByteChannel dbfChannel = dbfStoragefile.getWriteChannel()) {
            dbfheader.writeHeader(dbfChannel);
        }
        if (crs != null) {
            // .prj files should have no carriage returns in them, this messes up
            // ESRI's ArcXXX software, so we'll be compatible
            final WKTFormat format = new WKTFormat(Locale.ENGLISH, null);
            format.setConvention(Convention.WKT1_COMMON_UNITS);
            format.setNameAuthority(Citations.ESRI);
            format.setIndentation(WKTFormat.SINGLE_LINE);
            final String s = format.format(crs);
            IOUtilities.writeString(s, prjStoragefile.getFile(), Charset.forName("ISO-8859-1"));
        } else {
            getLogger().warning("PRJ file not generated for null CoordinateReferenceSystem");
            Path prjFile = prjStoragefile.getFile();
            Files.deleteIfExists(prjFile);
        }
        // write dbf encoding .cpg
        CpgFiles.write(dbfCharset, cpgStoragefile.getFile());
    } catch (IOException ex) {
        throw new DataStoreException(ex);
    }
    // Once all writings have succeeded, we can commit them
    try {
        locker.replaceStorageFiles();
    } catch (IOException e) {
        throw new DataStoreException("Failed commiting file changes", e);
    }
    // force reading it again since the file type may be a little different
    name = null;
    schema = null;
    // we still preserve the original type name and attribute classes which may be more restricted
    final FeatureTypeBuilder ftb = new FeatureTypeBuilder(getFeatureType());
    ftb.setName(typeName);
    final AttributeTypeBuilder gtb = (AttributeTypeBuilder) ftb.getProperty("the_geom");
    if (Geometry.class.equals(gtb.getValueClass())) {
        gtb.setValueClass(shapeType.bestJTSClass());
    }
    gtb.setName(desc.getName());
    for (PropertyType pt : featureType.getProperties(true)) {
        if (pt instanceof AttributeType) {
            final AttributeType at = (AttributeType) pt;
            if (!Geometry.class.isAssignableFrom(at.getValueClass())) {
                try {
                    ((AttributeTypeBuilder) ftb.getProperty(at.getName().toString())).setValueClass(at.getValueClass()).setName(at.getName());
                } catch (PropertyNotFoundException ex) {
                }
            }
        }
    }
    schema = ftb.build();
    name = schema.getName();
}
Also used : AccessManager(org.geotoolkit.data.shapefile.lock.AccessManager) PropertyNotFoundException(org.opengis.feature.PropertyNotFoundException) Closeable(java.io.Closeable) PropertyType(org.opengis.feature.PropertyType) Envelope(org.opengis.geometry.Envelope) AttributeTypeBuilder(org.apache.sis.feature.builder.AttributeTypeBuilder) GenericName(org.opengis.util.GenericName) AttributeType(org.opengis.feature.AttributeType) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) WKTFormat(org.apache.sis.io.wkt.WKTFormat) Path(java.nio.file.Path) FeatureTypeBuilder(org.apache.sis.feature.builder.FeatureTypeBuilder) DataStoreException(org.apache.sis.storage.DataStoreException) FileChannel(java.nio.channels.FileChannel) ShapeType(org.geotoolkit.data.shapefile.shp.ShapeType) WritableByteChannel(java.nio.channels.WritableByteChannel) IOException(java.io.IOException) DataStoreException(org.apache.sis.storage.DataStoreException) FeatureStoreRuntimeException(org.geotoolkit.storage.feature.FeatureStoreRuntimeException) UnsupportedQueryException(org.apache.sis.storage.UnsupportedQueryException) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) PropertyNotFoundException(org.opengis.feature.PropertyNotFoundException) DbaseFileHeader(org.geotoolkit.data.dbf.DbaseFileHeader) Geometry(org.locationtech.jts.geom.Geometry) JTSEnvelope2D(org.geotoolkit.geometry.jts.JTSEnvelope2D) StorageFile(org.geotoolkit.data.shapefile.lock.StorageFile) ShapefileWriter(org.geotoolkit.data.shapefile.shp.ShapefileWriter)

Example 2 with DbaseFileHeader

use of org.geotoolkit.data.dbf.DbaseFileHeader in project geotoolkit by Geomatys.

the class DbaseFileTest method testEmptyFields.

@Test
public void testEmptyFields() throws Exception {
    DbaseFileHeader header = new DbaseFileHeader();
    header.addColumn("emptyString", 'C', 20, 0);
    header.addColumn("emptyInt", 'N', 20, 0);
    header.addColumn("emptyDouble", 'N', 20, 5);
    header.addColumn("emptyFloat", 'F', 20, 5);
    header.addColumn("emptyLogical", 'L', 1, 0);
    header.addColumn("emptyDate", 'D', 20, 0);
    header.setNumRecords(20);
    File f = new File(System.getProperty("java.io.tmpdir"), "scratchDBF.dbf");
    f.deleteOnExit();
    FileOutputStream fout = new FileOutputStream(f);
    DbaseFileWriter dbf = new DbaseFileWriter(header, fout.getChannel(), Charset.defaultCharset());
    for (int i = 0; i < header.getNumRecords(); i++) {
        dbf.write(new Object[] { String.valueOf(900 + i), null, null, null, null, null });
    }
    dbf.close();
    final ShpFiles tempShpFiles = new ShpFiles(f);
    final AccessManager locker = tempShpFiles.createLocker();
    DbaseFileReader r = locker.getDBFReader(false, ShapefileFeatureStore.DEFAULT_STRING_CHARSET);
    int cnt = 0;
    while (r.hasNext()) {
        cnt++;
        Object[] o = r.next().readAll(null);
        assertTrue(o.length == r.getHeader().getNumFields());
    }
    assertEquals("Bad number of records", cnt, 20);
    // make sure the channel is closed
    r.close();
    f.delete();
}
Also used : AccessManager(org.geotoolkit.data.shapefile.lock.AccessManager) DbaseFileWriter(org.geotoolkit.data.dbf.DbaseFileWriter) DbaseFileReader(org.geotoolkit.data.dbf.DbaseFileReader) FileOutputStream(java.io.FileOutputStream) ShpFiles(org.geotoolkit.data.shapefile.lock.ShpFiles) File(java.io.File) DbaseFileHeader(org.geotoolkit.data.dbf.DbaseFileHeader) Test(org.junit.Test)

Example 3 with DbaseFileHeader

use of org.geotoolkit.data.dbf.DbaseFileHeader in project geotoolkit by Geomatys.

the class ShapefileFeatureStore method buildSchema.

// //////////////////////////////////////////////////////////////////////////
// utils ///////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////
/**
 * Obtain the FeatureType of the given name. ShapefileFeatureStore contains
 * only one FeatureType.
 *
 * @return The FeatureType that this featurestore contains.
 * @throws IOException If a type by the requested name is not present.
 */
private synchronized FeatureType buildSchema() throws DataStoreException {
    // add an identifier field
    final FeatureTypeBuilder builder = new FeatureTypeBuilder();
    final String name = shpFiles.getTypeName();
    builder.setName(name);
    builder.addAttribute(String.class).setName(AttributeConvention.IDENTIFIER_PROPERTY);
    // read all attributes///////////////////////////////////////////////////
    final AccessManager locker = shpFiles.createLocker();
    try (Closeable disposeLocker = locker::disposeReaderAndWriters) {
        final ShapefileReader shp = locker.getSHPReader(true, useMemoryMappedBuffer, true, null);
        final DbaseFileReader dbf = locker.getDBFReader(useMemoryMappedBuffer, dbfCharset);
        CoordinateReferenceSystem crs = null;
        // read the projection
        final boolean qpjExists = shpFiles.exists(QPJ);
        final boolean prjExists = shpFiles.exists(PRJ);
        if (qpjExists || prjExists) {
            try (final ReadableByteChannel channel = qpjExists ? shpFiles.getReadChannel(QPJ) : shpFiles.getReadChannel(PRJ)) {
                crs = PrjFiles.read(channel, true);
            } catch (IOException ex) {
                getLogger().log(Level.WARNING, ex.getMessage(), ex);
                crs = null;
            }
        }
        final AttributeType geomDescriptor;
        // get the descriptor from shp
        geomDescriptor = shp.getHeader().createDescriptor(crs);
        builder.addAttribute(geomDescriptor).addRole(AttributeRole.DEFAULT_GEOMETRY);
        // get dbf attributes if exist
        if (dbf != null) {
            final DbaseFileHeader header = dbf.getHeader();
            for (AttributeType at : header.createDescriptors()) {
                builder.addAttribute(at);
            }
        }
    } catch (IOException ex) {
        throw new DataStoreException(ex);
    }
    return builder.build();
}
Also used : AccessManager(org.geotoolkit.data.shapefile.lock.AccessManager) FeatureTypeBuilder(org.apache.sis.feature.builder.FeatureTypeBuilder) ReadableByteChannel(java.nio.channels.ReadableByteChannel) DataStoreException(org.apache.sis.storage.DataStoreException) Closeable(java.io.Closeable) ShapefileReader(org.geotoolkit.data.shapefile.shp.ShapefileReader) IOException(java.io.IOException) DbaseFileHeader(org.geotoolkit.data.dbf.DbaseFileHeader) DbaseFileReader(org.geotoolkit.data.dbf.DbaseFileReader) AttributeType(org.opengis.feature.AttributeType) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem)

Example 4 with DbaseFileHeader

use of org.geotoolkit.data.dbf.DbaseFileHeader in project geotoolkit by Geomatys.

the class DbaseFileTest method testHeader.

@Test
public void testHeader() throws Exception {
    DbaseFileHeader header = new DbaseFileHeader();
    Level before = LOGGER.getLevel();
    try {
        LOGGER.setLevel(Level.INFO);
        header.addColumn("emptyString", 'C', 20, 0);
        header.addColumn("emptyInt", 'N', 20, 0);
        header.addColumn("emptyDouble", 'N', 20, 5);
        header.addColumn("emptyFloat", 'F', 20, 5);
        header.addColumn("emptyLogical", 'L', 1, 0);
        header.addColumn("emptyDate", 'D', 20, 0);
        int length = header.getRecordLength();
        header.removeColumn("emptyDate");
        assertTrue(length != header.getRecordLength());
        header.addColumn("emptyDate", 'D', 20, 0);
        assertTrue(length == header.getRecordLength());
        header.removeColumn("billy");
        assertTrue(length == header.getRecordLength());
    } finally {
        LOGGER.setLevel(before);
    }
}
Also used : Level(java.util.logging.Level) DbaseFileHeader(org.geotoolkit.data.dbf.DbaseFileHeader) Test(org.junit.Test)

Example 5 with DbaseFileHeader

use of org.geotoolkit.data.dbf.DbaseFileHeader in project geotoolkit by Geomatys.

the class DbaseFileTest method testAddColumn.

@Test
public void testAddColumn() throws Exception {
    DbaseFileHeader header = new DbaseFileHeader();
    Level before = LOGGER.getLevel();
    try {
        LOGGER.setLevel(Level.INFO);
        header.addColumn("emptyInt", 'N', 9, 0);
        assertSame(Integer.class, header.getFieldClass(0));
        assertEquals(9, header.getFieldLength(0));
        header.addColumn("emptyString", 'C', 20, 0);
        assertSame(String.class, header.getFieldClass(1));
        assertEquals(20, header.getFieldLength(1));
    } finally {
        LOGGER.setLevel(before);
    }
}
Also used : Level(java.util.logging.Level) DbaseFileHeader(org.geotoolkit.data.dbf.DbaseFileHeader) Test(org.junit.Test)

Aggregations

DbaseFileHeader (org.geotoolkit.data.dbf.DbaseFileHeader)5 AccessManager (org.geotoolkit.data.shapefile.lock.AccessManager)3 Test (org.junit.Test)3 Closeable (java.io.Closeable)2 IOException (java.io.IOException)2 Level (java.util.logging.Level)2 FeatureTypeBuilder (org.apache.sis.feature.builder.FeatureTypeBuilder)2 DataStoreException (org.apache.sis.storage.DataStoreException)2 DbaseFileReader (org.geotoolkit.data.dbf.DbaseFileReader)2 AttributeType (org.opengis.feature.AttributeType)2 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)2 File (java.io.File)1 FileOutputStream (java.io.FileOutputStream)1 MalformedURLException (java.net.MalformedURLException)1 FileChannel (java.nio.channels.FileChannel)1 ReadableByteChannel (java.nio.channels.ReadableByteChannel)1 WritableByteChannel (java.nio.channels.WritableByteChannel)1 Path (java.nio.file.Path)1 AttributeTypeBuilder (org.apache.sis.feature.builder.AttributeTypeBuilder)1 WKTFormat (org.apache.sis.io.wkt.WKTFormat)1