package au.org.aurin.wif.impl;
import java.io.IOException;
import java.util.HashSet;
import java.util.concurrent.Future;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.geotools.feature.FeatureCollection;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import au.org.aurin.wif.config.GeoServerConfig;
import au.org.aurin.wif.config.WifConfig;
import au.org.aurin.wif.exception.config.WifInvalidConfigException;
import au.org.aurin.wif.exception.io.DataStoreCreationException;
import au.org.aurin.wif.exception.io.DataStoreUnavailableException;
import au.org.aurin.wif.exception.io.MiddlewarePersistentException;
import au.org.aurin.wif.exception.io.ShapeFile2PostGISCreationException;
import au.org.aurin.wif.exception.io.WifIOException;
import au.org.aurin.wif.exception.validate.InvalidFFNameException;
import au.org.aurin.wif.exception.validate.InvalidLabelException;
import au.org.aurin.wif.exception.validate.WifInvalidInputException;
import au.org.aurin.wif.io.DataStoreToPostgisExporter;
import au.org.aurin.wif.io.GeodataFinder;
import au.org.aurin.wif.io.PostgisToDataStoreExporter;
import au.org.aurin.wif.model.WifProject;
import au.org.aurin.wif.model.suitability.SuitabilityConfig;
import au.org.aurin.wif.repo.impl.CouchWifProjectDao;
import au.org.aurin.wif.svc.AllocationLUService;
import au.org.aurin.wif.svc.AsyncProjectService;
import au.org.aurin.wif.svc.WifKeys;
import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
/**
* The Class AsyncProjectServiceImpl.
*/
@Service
@Qualifier("asyncProjectService")
public class AsyncProjectServiceImpl implements AsyncProjectService {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 213432423433L;
/** The Constant LOGGER. */
private static final Logger LOGGER = LoggerFactory
.getLogger(AsyncProjectServiceImpl.class);
/** The geoserver publisher. */
@Autowired
private GeoServerRESTPublisher geoserverPublisher;
/** The postgis to data store exporter. */
@Autowired
private PostgisToDataStoreExporter postgisToDataStoreExporter;
/** The geoserver config. */
@Autowired
private GeoServerConfig geoserverConfig;
/** The wif config. */
@Resource
private WifConfig wifConfig;
/** The validator crs. */
@Resource
private ValidatorCRS validatorCRS;
/** The wif project dao. */
@Autowired
private CouchWifProjectDao wifProjectDao;
/** The exporter. */
@Autowired
private DataStoreToPostgisExporter exporter;
/** The geodata finder. */
@Autowired
private GeodataFinder geodataFinder;
/** The validator crs. */
@Resource
private ValidatorUAZ validatorUAZ;
@Resource
private AllocationLUService allocationLUService;
/**
* Inits the.
*/
@PostConstruct
public void init() {
LOGGER.trace("Initializing version: " + WifKeys.WIF_KEY_VERSION);
}
/**
* Cleanup.
*/
@PreDestroy
public void cleanup() {
LOGGER.trace("Service succesfully cleared! ");
}
/*
* (non-Javadoc)
* @see
* au.org.aurin.wif.svc.AsyncProjectService#setupProjectAsync(au.org.aurin
* .wif.model.WifProject, java.lang.String)
*/
@Override
@Async
public Future<String> setupProjectAsync(final WifProject project,
final String username) throws WifInvalidInputException,
DataStoreUnavailableException, DataStoreCreationException, WifInvalidConfigException, InvalidLabelException, InvalidFFNameException {
return new AsyncResult<String>(setupProject(project, username));
}
/**
* Setup project.
*
* @param project
* the project
* @param username
* the username
* @return the string
* @throws WifInvalidInputException
* the wif invalid input exception
* @throws DataStoreUnavailableException
* the data store unavailable exception
* @throws DataStoreCreationException
* the data store creation exception
* @throws InvalidFFNameException
* @throws InvalidLabelException
* @throws WifInvalidConfigException
*/
public String setupProject(WifProject project, final String username)
throws WifInvalidInputException, DataStoreUnavailableException,
DataStoreCreationException, WifInvalidConfigException, InvalidLabelException, InvalidFFNameException {
String tableName = "";
CoordinateReferenceSystem crs = null;
String geometryColumnName = WifKeys.DEFAULT_COLUMN_NAME;
final String bbox = "";
final String msg = "Creating postGIS spatial store with table name"
+ tableName + " failed";
tableName = "wif_"
+ project.getId().toString().replaceAll(" ", "_").replaceAll("-", "_")
.toLowerCase();
LOGGER
.info("Creating postGIS spatial store with table name {} ", tableName);
if (project.getOwnGeoDatastoreName() != null) {
project = this.reuseDBTable(tableName, project);
} else {
SimpleFeatureType featureType = null;
try {
project = this.createDatastore(project, username, tableName);
} catch (final Exception e) {
LOGGER.error(msg);
throw new DataStoreCreationException(msg, e);
}
featureType = project.getSchema();
crs = featureType.getCoordinateReferenceSystem();
crs = validatorCRS.validateSimple(crs, msg);
geometryColumnName = featureType.getGeometryDescriptor().getLocalName();
LOGGER.info("Geometry column name= {} ", geometryColumnName);
LOGGER.info("bounding box is= {} ", project.getBbox());
}
LOGGER.info("Creating suitabilityConfig with uaz name {} ", tableName);
final SuitabilityConfig suitabilityConfig = this
.createSuitabilityConfig(tableName);
suitabilityConfig.setWifProject(project);
project.setSuitabilityConfig(suitabilityConfig);
project.setGeometryColumnName(geometryColumnName);
project.setSrs(CRS.toSRS(crs));
project.setReady(true);
project.setLocalShpFile(null);
/*
* LOGGER .info("New Validate UAZ Started"); try {
* validatorUAZ.validateSimple(project, msg); } catch (IOException e) {
* LOGGER.error(msg); throw new DataStoreCreationException(msg, e); }
*/
wifProjectDao.updateProject(project);
// ali
// creating metadata in aurin
// TODO enable in the next iteration oof what if
// try {
// postgisToDataStoreExporter.persistInAurin(project, roleId);
// } catch (MiddlewarePersistentException e) {
// LOGGER.warn("sharing with aurin is not enabled!");
// }
// ali- also call postgisToDataStoreExporter.exportUAZ
// ////////////////
// LOGGER.info(
// "Creating AllocationLUs!");
// final String uazTbl = suitabilityConfig.getUnifiedAreaZone();
// final String attr = null;
// final List<String> lst= geodataFinder.getDistinctEntriesForUAZAttribute(uazTbl, attr);
// for (final String str: lst)
// {
// final AllocationLU allocationLU = new AllocationLU();
// allocationLU.setProjectId(project.getId());
// allocationLU.setLabel(str);
// allocationLU.setFeatureFieldName(str);
// allocationLUService.createAllocationLU(allocationLU,
// project.getId());
// }
/////////////////////////////
LOGGER.info(
"setup process for project {},with id= {} has completed successfully!",
project.getName(), project.getId());
return project.getId().toString();
}
/**
* Reuse db table.
*
* @param tableName
* the table name
* @param project
* the project
* @return the wif project
* @throws DataStoreCreationException
* the data store creation exception
* @throws IOException
* Signals that an I/O exception has occurred.
*/
private WifProject reuseDBTable(final String tableName,
final WifProject project) throws DataStoreCreationException {
LOGGER
.info(
"Creating feature collection from table already present in the database! tablename is={}",
tableName);
FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection = null;
featureCollection = exporter.getFeatures(project.getOwnGeoDatastoreName());
final ReferencedEnvelope bbox = featureCollection.getBounds();
final String bboxJson = new StringBuffer().append("[")
.append(bbox.getMinX()).append(",").append(bbox.getMinY()).append(",")
.append(bbox.getMaxX()).append(",").append(bbox.getMaxY()).append("]")
.toString();
project.setBbox(bboxJson);
project.setSchema(featureCollection.getSchema());
try {
exporter.storeFeatureCollectionToPostgis(featureCollection, tableName);
} catch (final IOException e) {
final String msg = "creating postGIS spatial features from table name "
+ tableName + " failed";
LOGGER.error(msg);
throw new DataStoreCreationException(msg, e);
}
return project;
}
/**
* Creates the datastore.
*
* @param project
* the project
* @param username
* the username
* @param tableName
* the table name
* @return the simple feature type
* @throws WifInvalidInputException
* the wif invalid input exception
* @throws DataStoreUnavailableException
* the data store unavailable exception
* @throws DataStoreCreationException
* the data store creation exception
* @throws ShapeFile2PostGISCreationException
* the shape file2 post gis creation exception
*/
public WifProject createDatastore(WifProject project, final String username,
final String tableName) throws WifInvalidInputException,
DataStoreUnavailableException, DataStoreCreationException,
ShapeFile2PostGISCreationException {
// handle the datastore to postgis export process here...
try {
LOGGER.info("exporting to postGIS, with tableName={}", tableName);
final long startTime = System.nanoTime();
project = exporter.exportToPostgis(username, project, tableName);
final long endTime = System.nanoTime();
final long duration = endTime - startTime;
LOGGER.info(">>>>>>>>>>>>>>*************** Export to Postgis took in ms "
+ duration / 1000000);
return project;
} catch (final IOException e) {
LOGGER.error("Error occurred while exporting to Postgis", e);
throw new WifInvalidInputException(
"Error occurred while exporting to Postgis", e);
}
}
/**
* Creates the suitability config.
*
* @param tableName
* the table name
* @return the suitability config
* @throws WifInvalidInputException
* the wif invalid input exception
* @throws DataStoreUnavailableException
* the data store unavailable exception
*/
public SuitabilityConfig createSuitabilityConfig(final String tableName)
throws WifInvalidInputException, DataStoreUnavailableException {
final SuitabilityConfig suitabilityConfig = new SuitabilityConfig();
suitabilityConfig.setUnifiedAreaZone(tableName);
LOGGER.debug("using UAZ table={}", suitabilityConfig.getUnifiedAreaZone());
suitabilityConfig.setScoreColumns(new HashSet<String>());
suitabilityConfig.setSuitabilityColumns(new HashSet<String>());
return suitabilityConfig;
}
/*
* (non-Javadoc)
* @see
* au.org.aurin.wif.svc.AsyncProjectService#uploadUAZAsync(au.org.aurin.wif
* .model.WifProject, java.lang.String)
*/
@Override
@Async
public Future<String> uploadUAZAsync(final WifProject project,
final String roleId) throws WifIOException, IOException,
DataStoreCreationException, MiddlewarePersistentException {
return new AsyncResult<String>(uploadUAZ(project, roleId));
}
/**
* Upload uaz of the project into AURIN middleware persistence services.
*
* @param project
* the project
* @param roleId
* the role id
* @return the string
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws DataStoreCreationException
* the data store creation exception
* @throws MiddlewarePersistentException
* the middleware persistent exception
*/
private String uploadUAZ(final WifProject project, final String roleId)
throws IOException, DataStoreCreationException,
MiddlewarePersistentException {
final String dataStoreUri = postgisToDataStoreExporter.exportUAZ(project,
roleId);
return dataStoreUri;
}
}