/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.importer;
import static org.apache.commons.io.FilenameUtils.getBaseName;
import static org.apache.commons.io.FilenameUtils.getExtension;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.apache.commons.io.FileUtils;
import org.geotools.referencing.CRS;
import org.geoserver.catalog.StyleHandler;
import org.geoserver.catalog.Styles;
import org.geoserver.importer.job.ProgressMonitor;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import javax.annotation.Nullable;
public class SpatialFile extends FileData {
private static final long serialVersionUID = -280215815681792790L;
static EPSGCodeLookupCache EPSG_LOOKUP_CACHE = new EPSGCodeLookupCache();
/**
* .prj file
*/
File prjFile;
/**
* style file
*/
File styleFile;
/** supplementary files, like indexes, etc... */
List<File> suppFiles = new ArrayList<File>();
/**
* Create from file system
*
* @param file the spatial file
*/
public SpatialFile(File file) {
super(file);
}
public SpatialFile(SpatialFile other) {
super(other);
this.prjFile = other.getPrjFile();
this.suppFiles.addAll(other.getSuppFiles());
}
public File getPrjFile() {
return prjFile;
}
public void setPrjFile(File prjFile) {
this.prjFile = prjFile;
}
public List<File> getSuppFiles() {
return suppFiles;
}
public List<File> allFiles() {
ArrayList<File> all = new ArrayList<File>();
all.add(file);
if (prjFile != null) {
all.add(prjFile);
}
if (styleFile != null) {
all.add(styleFile);
}
all.addAll(suppFiles);
return all;
}
@Override
public void prepare(ProgressMonitor m) throws IOException {
//round up all the files with the same name
suppFiles = new ArrayList();
prjFile = null;
styleFile = null;
final List<String> styleExtensions = Lists.transform(Styles.handlers(), new Function<StyleHandler, String>() {
@Nullable
@Override
public String apply(@Nullable StyleHandler input) {
return input.getFileExtension();
}
});
// getBaseName only gets the LAST extension so beware for .shp.aux.xml stuff
final String baseName = getBaseName(file.getName());
for (File f : file.getParentFile().listFiles()) {
if (f.equals(file)) {
continue;
}
if (!f.getName().startsWith(baseName)) {
continue;
}
if (!f.isFile()) {
continue;
}
String ext = f.getName().substring(baseName.length());
// once the basename is stripped, extension(s) should be present
if (ext.charAt(0) == '.') {
if (".prj".equalsIgnoreCase(ext)) {
prjFile = f;
}
else if (styleFile == null && styleExtensions.contains(ext.substring(1))) {
// TODO: deal with multiple style files? for now we just grab the first
styleFile = f;
}
else {
suppFiles.add(f);
}
}
}
if (format == null) {
format = DataFormat.lookup(file);
}
//fix the prj file (match to official epsg wkt)
try {
fixPrjFile();
}
catch(Exception e) {
LOGGER.log(Level.WARNING, "Error fixing prj file", e);
}
}
public void fixPrjFile() throws IOException {
CoordinateReferenceSystem crs = readPrjToCRS();
if (crs == null) {
return;
}
try {
CoordinateReferenceSystem epsgCrs = null;
Integer epsgCode = EPSG_LOOKUP_CACHE.lookupEPSGCode(crs);
if (epsgCode != null) {
epsgCrs = CRS.decode("EPSG:" + epsgCode);
}
if (epsgCrs != null) {
String epsgWKT = epsgCrs.toWKT();
FileUtils.writeStringToFile(getPrjFile(), epsgWKT);
}
}
catch (FactoryException e) {
throw (IOException) new IOException().initCause(e);
}
}
public CoordinateReferenceSystem readPrjToCRS() throws IOException {
File prj = getPrjFile();
if (prj == null || !prj.exists()) {
return null;
}
String wkt = FileUtils.readFileToString(prj);
try {
return CRS.parseWKT(wkt);
}
catch (Exception e) {
throw (IOException) new IOException().initCause(e);
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((suppFiles == null) ? 0 : suppFiles.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
SpatialFile other = (SpatialFile) obj;
if (suppFiles == null) {
if (other.suppFiles != null)
return false;
} else if (!suppFiles.equals(other.suppFiles))
return false;
return true;
}
private Object readResolve() {
suppFiles = suppFiles == null ? new ArrayList<File>() : suppFiles;
return this;
}
public File getStyleFile() {
return styleFile;
}
public void setStyleFile(File styleFile) {
this.styleFile = styleFile;
}
}