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();
}
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();
}
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();
}
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);
}
}
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);
}
}
Aggregations