version 1.1
This commit is contained in:
parent
d81fb678e3
commit
836a412a6d
141
build/release.sh
Normal file
141
build/release.sh
Normal file
@ -0,0 +1,141 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Create release of the project, which means a tag on a separate branch, with a fixed version.
|
||||
# NOTE : we expect this script to be in the following directory : ROOT_POM_DIR/build/
|
||||
#
|
||||
|
||||
# Release version for the tag to create
|
||||
releaseVersion=
|
||||
|
||||
# change SNAPSHOT version after release.
|
||||
newSnapshot=
|
||||
|
||||
# A prefix for the temporary release branch
|
||||
releaseBranchPrefix="release-"
|
||||
|
||||
# Keep original branch to come back to it after release.
|
||||
sourceBranch=
|
||||
|
||||
# Original code from 'http://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides'
|
||||
# Absolute path to this script, e.g. /home/user/bin/foo.sh
|
||||
SCRIPT=$(readlink -f "$BASH_SOURCE")
|
||||
# Absolute path this script is in, thus /home/user/bin
|
||||
SCRIPT_PATH=$(dirname "$SCRIPT")
|
||||
|
||||
###################### FUNCTIONS ############################
|
||||
|
||||
# Print help on standard output.
|
||||
function printHelp {
|
||||
echo "
|
||||
Create a release tag for the current project. Release number will be something like X.x where X is major release version, and x is minor.
|
||||
"
|
||||
echo " WARNING : No check is done to ensure the project is well-formed (no compilation, test, syntax check, etc.)
|
||||
"
|
||||
echo " MANDATORY ARGUMENT : "
|
||||
echo " -r --release-version : Version to set on new release."
|
||||
echo " OPTIONAL ARGUMENT : "
|
||||
echo " -s --snapshot-version : If set, and once the tag is done, the version on original branch is changed according to this argument value."
|
||||
echo " -- help, -h : Print this help."
|
||||
}
|
||||
|
||||
function printError() {
|
||||
echo "
|
||||
"
|
||||
tput setaf 1; tput setab 7; tput bold;
|
||||
echo "$*"
|
||||
tput sgr0;
|
||||
echo "
|
||||
"
|
||||
}
|
||||
|
||||
# Print the given parameters to standard error output, then exit the script in failure mode.
|
||||
function error() {
|
||||
printError "$*"
|
||||
git checkout $sourceBranch # come back on the initial branch before exit
|
||||
exit 1
|
||||
}
|
||||
|
||||
# do the job
|
||||
function execute {
|
||||
# We place ourself in the script directory. It MUST BE into the git project directory.
|
||||
cd $SCRIPT_PATH/..
|
||||
|
||||
# Save original branch name to go back to it at the end of the release.
|
||||
sourceBranch="$(git symbolic-ref --short HEAD)"
|
||||
echo "Original branch is $sourceBranch"
|
||||
createTag
|
||||
updateSnapshot
|
||||
}
|
||||
|
||||
# Create the tag itself
|
||||
function createTag {
|
||||
echo "Create temporary branch for release $releaseVersion"
|
||||
tmpReleaseBranch="$releaseBranchPrefix$releaseVersion"
|
||||
git branch $tmpReleaseBranch || error "Cannot create a temporary branch for release creation."
|
||||
git checkout $tmpReleaseBranch || error "Cannot access created branch $tmpReleaseBranch"
|
||||
|
||||
echo "Perform version update for release $releaseVersion"
|
||||
mvn versions:set -DnewVersion=$releaseVersion || error "Cannot update project version to $releaseVersion"
|
||||
|
||||
echo "Commit release versions"
|
||||
git commit -m "Project release $releaseVersion" -a || error "Cannot commit updated poms to the temporary release branch"
|
||||
|
||||
echo "Create tag named $releaseVersion"
|
||||
git tag $releaseVersion $tmpReleaseBranch || error "Cannot create the tag $releaseVersion"
|
||||
|
||||
echo "Remove temporary release branch"
|
||||
git checkout $sourceBranch || error "Cannot come back to the source branch $sourceBranch"
|
||||
git branch -D $tmpReleaseBranch || printError "WARNING : Cannot delete temporary branch $tmpReleaseBranch. You will have to do it yourself ! "
|
||||
}
|
||||
|
||||
# Update project version on initial branch
|
||||
function updateSnapshot {
|
||||
if [ ! -z "$releaseVersion" ]
|
||||
then
|
||||
echo "Update snapshot version $newSnapshot"
|
||||
mvn versions:set -DnewVersion=$newSnapshot || error "Cannot update project version to $newSnapshot"
|
||||
|
||||
echo "Commit updated snapshot"
|
||||
git commit -m "Snapshot update $newSnapshot" -a || error "Cannot commit updated poms to the source branch"
|
||||
fi
|
||||
}
|
||||
|
||||
########################### MAIN #############################
|
||||
|
||||
# ARGUMENT CHECK
|
||||
while [ "$1" != "" ]; do
|
||||
case $1 in
|
||||
-r | --release-version ) shift
|
||||
releaseVersion=$1
|
||||
;;
|
||||
-s | --snapshot-version ) shift
|
||||
newSnapshot=$1
|
||||
;;
|
||||
# etc.
|
||||
-h | --help ) printHelp
|
||||
exit
|
||||
;;
|
||||
* ) printHelp
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
|
||||
if [ -z "$releaseVersion" ]
|
||||
then echo "ERROR: MINOR RELEASE VERSION IS NOT AN INTEGER. FOUND VALUE --> $releaseMinor" >&2; exit 1
|
||||
fi
|
||||
|
||||
# We must ensure that no tag already exists with the same name.
|
||||
tagDoublon="$(git tag -l|grep $releaseVersion)"
|
||||
|
||||
if [ ! -z "$tagDoublon" ]
|
||||
then echo "ERROR : A tag already exists for the following version : $releaseVersion" >&2; exit 1
|
||||
fi
|
||||
|
||||
echo "Execute for version $releaseVersion"
|
||||
|
||||
# Make release
|
||||
execute
|
||||
167
core/pom.xml
Normal file
167
core/pom.xml
Normal file
@ -0,0 +1,167 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.cenra.rhomeo</groupId>
|
||||
<artifactId>rhomeo</artifactId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>fr.cenra.rhomeo</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Core</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.el</groupId>
|
||||
<artifactId>javax.el-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.web</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- FTP -->
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
<artifactId>commons-net</artifactId>
|
||||
<version>3.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- formats -->
|
||||
<dependency>
|
||||
<groupId>org.geotoolkit</groupId>
|
||||
<artifactId>geotk-feature-shapefile</artifactId>
|
||||
<version>${geotoolkit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.geotoolkit</groupId>
|
||||
<artifactId>geotk-feature-kml</artifactId>
|
||||
<version>${geotoolkit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.geotoolkit</groupId>
|
||||
<artifactId>geotk-feature-geojson</artifactId>
|
||||
<version>${geotoolkit.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.geotoolkit</groupId>
|
||||
<artifactId>geotk-feature-store</artifactId>
|
||||
<version>${geotoolkit.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.geotoolkit</groupId>
|
||||
<artifactId>geotk-feature-csv</artifactId>
|
||||
<version>${geotoolkit.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.geotoolkit</groupId>
|
||||
<artifactId>geotk-client-wfs</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.geotoolkit</groupId>
|
||||
<artifactId>geotk-jaxp-xsd</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derby</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JAI -->
|
||||
<dependency>
|
||||
<groupId>javax.media</groupId>
|
||||
<artifactId>jai_core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.media</groupId>
|
||||
<artifactId>jai_codec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.media</groupId>
|
||||
<artifactId>jai_imageio</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- TESTS -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.sis.core</groupId>
|
||||
<artifactId>sis-utility</artifactId>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>test-jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api;
|
||||
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class EditableIdentifiedObject implements IdentifiedObject {
|
||||
|
||||
protected final SimpleStringProperty nameProperty = new SimpleStringProperty();
|
||||
protected final SimpleStringProperty remarksProperty = new SimpleStringProperty();
|
||||
protected ObservableList<String> alias;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return nameProperty.get();
|
||||
}
|
||||
|
||||
public void setName(final String newName) {
|
||||
nameProperty.set(newName);
|
||||
}
|
||||
|
||||
public StringProperty nameProperty() {
|
||||
return nameProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObservableList<String> getAlias() {
|
||||
if (alias == null) {
|
||||
alias = FXCollections.observableArrayList();
|
||||
}
|
||||
return alias;
|
||||
}
|
||||
|
||||
public void setAlias(final ObservableList<String> alias) {
|
||||
this.alias = alias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemarks() {
|
||||
return remarksProperty.get();
|
||||
}
|
||||
|
||||
public void setRemarks(final String remarks) {
|
||||
remarksProperty.set(remarks);
|
||||
}
|
||||
|
||||
public StringProperty remarksProperty() {
|
||||
return remarksProperty;
|
||||
}
|
||||
}
|
||||
88
core/src/main/java/fr/cenra/rhomeo/api/IdentifiedObject.java
Normal file
88
core/src/main/java/fr/cenra/rhomeo/api/IdentifiedObject.java
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* A simplified version of {@link org.opengis.referencing.IdentifiedObject} from
|
||||
* GeoAPI. The aim is to ease manipulation by working only with Strings.
|
||||
*
|
||||
* Note : The {@link #getName() } is the identifier of the object.
|
||||
* The {@link #getAlias() } is a list of alternative names to use as proper title.
|
||||
* By default, the {@link #getTitle() } method returns the first alias available,
|
||||
* or the name of the object if none is available.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface IdentifiedObject {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Identifier of the object.
|
||||
*/
|
||||
@NotBlank
|
||||
String getName();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Available titles / alternative names. Can be empty, but should never be null.
|
||||
*/
|
||||
@NotNull
|
||||
Collection<String> getAlias();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return A short description of the object.
|
||||
*/
|
||||
String getRemarks();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The most appropriate title from available aliases.
|
||||
*/
|
||||
default String getTitle() {
|
||||
if (getAlias().isEmpty()) {
|
||||
return getName();
|
||||
}
|
||||
return getAlias().iterator().next();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api;
|
||||
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* An object able to provide some title and description for given (or default) locales.
|
||||
*
|
||||
* This interface provides a default implementation based on the class {@link ResourceBundle}.
|
||||
*
|
||||
* According to the default implementation, the title and the description are the values
|
||||
* of the keys {@link InternationalDescription#LABEL_KEY} and {@link InternationalDescription#DESCRIPTION_KEY} respectively.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*/
|
||||
public interface InternationalDescription {
|
||||
|
||||
/**
|
||||
* The bundle key of the title value provided by the default implementation.
|
||||
*/
|
||||
String LABEL_KEY = "_label";
|
||||
|
||||
/**
|
||||
* The bundle key of the description value provided by the default implementation.
|
||||
*/
|
||||
String DESCRIPTION_KEY = "_description";
|
||||
|
||||
/**
|
||||
* Gets a title for the object.
|
||||
*
|
||||
* Default implementation returns the value of the {@link InternationalDescription#LABEL_KEY}
|
||||
* key stored into the class {@link ResourceBundle} for the given {@link Locale}.
|
||||
*
|
||||
* @param locale
|
||||
* @return
|
||||
*/
|
||||
default String getLabel(final Locale locale) {
|
||||
try {
|
||||
final ResourceBundle bundle = ResourceBundle.getBundle(getClass().getName(), locale);
|
||||
return bundle.getString(LABEL_KEY);
|
||||
} catch (Exception e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "Cannot find any title for this object.", e);
|
||||
return "No title available";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a description for the object.
|
||||
*
|
||||
* Default implementation returns the value of the {@link InternationalDescription#DESCRIPTION_KEY}
|
||||
* key stored into the class {@link ResourceBundle} for the given {@link Locale}.
|
||||
*
|
||||
* @param locale
|
||||
* @return
|
||||
*/
|
||||
default String getDescription(final Locale locale){
|
||||
try {
|
||||
final ResourceBundle bundle = ResourceBundle.getBundle(getClass().getName(), locale);
|
||||
return bundle.getString(DESCRIPTION_KEY);
|
||||
} catch (Exception e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "Cannot find any title for this object.", e);
|
||||
return "No title available";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut method to avoid to specify locale parameter.
|
||||
*
|
||||
* Default implementation maps the {@link Locale#getDefault() } {@link Locale}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
default String getLabel(){return getLabel(Locale.getDefault());}
|
||||
|
||||
/**
|
||||
* Shortcut method to avoid to specify locale parameter.
|
||||
*
|
||||
* Default implementation maps the {@link Locale#getDefault() } {@link Locale}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
default String getDescription(){return getDescription(Locale.getDefault());}
|
||||
}
|
||||
@ -0,0 +1,249 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api;
|
||||
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
|
||||
/**
|
||||
* An object able to provide some resource strings for given (or default) locales.
|
||||
*
|
||||
* This interface provides a default implementation based on the class
|
||||
* {@link ResourceBundle}. So, if you do not redefine its methods, make sure
|
||||
* the {@link ResourceBundle} associated to the class exists.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*/
|
||||
public interface InternationalResource {
|
||||
|
||||
/**
|
||||
* Default {@link InternationalResource} behaviour for a given class and a
|
||||
* given locale, retrieving the associated {@link ResourceBundle}.
|
||||
*
|
||||
* The resource can be associated to a simple key or a complex one.
|
||||
*
|
||||
* The default implementation assumes the key parts are separated by a dot.
|
||||
*
|
||||
* For instance, let's assume the class my.package.MyClass implementq
|
||||
* {@link InternationalResource} without overriding methods and is
|
||||
* associated to the following resource bundle : /my/package/MyClass.properties
|
||||
* which content is below :
|
||||
*
|
||||
* keyPart1.keyPart2=resource value
|
||||
*
|
||||
* The resource string "resource value" can be retrived from a my.package.MyClass
|
||||
* instance, calling this method either specifying only one key part
|
||||
* "keyPart1.keyPart2", or two key parts "keyPart1" and "keyPart2".
|
||||
*
|
||||
* @param c
|
||||
* @param locale
|
||||
* @param keyParts
|
||||
* @return
|
||||
*
|
||||
* @throws IllegalArgumentException if the class parameter or the locale is null or no key is provided
|
||||
* @throws MissingResourceException if no resource bundle for the specified class can be found or no object for the key can be found
|
||||
*/
|
||||
static String getResourceString(final Class<? extends InternationalResource> c, final Locale locale, final String... keyParts){
|
||||
ArgumentChecks.ensureNonNull("class", c);
|
||||
ArgumentChecks.ensureNonNull("locale", locale);
|
||||
ArgumentChecks.ensureNonNull("keyParts", keyParts);
|
||||
|
||||
final ResourceBundle bundle;
|
||||
try{
|
||||
bundle = ResourceBundle.getBundle(c.getName(), locale);
|
||||
}
|
||||
catch(MissingResourceException e){
|
||||
// Warns about InternationalResource default behaviour is not fulfilled.
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "No resource found for the class {0}. Default {1} behaviour use resource bundle.",
|
||||
new Object[]{c.getCanonicalName(), InternationalResource.class.getSimpleName()});
|
||||
// Then, re-throw the exception…
|
||||
throw e;
|
||||
}
|
||||
|
||||
final StringJoiner joiner = new StringJoiner(".");
|
||||
for(final String keyPart : keyParts){
|
||||
joiner.add(keyPart);
|
||||
}
|
||||
return bundle.getString(joiner.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param c
|
||||
* @param keyParts
|
||||
* @return
|
||||
*
|
||||
* @see InternationalResource#getResourceString(java.lang.Class, java.util.Locale, java.lang.String...) , with default locale.
|
||||
*
|
||||
* @throws IllegalArgumentException if the class parameter is null or no key is provided
|
||||
* @throws MissingResourceException if no resource bundle for the specified class can be found or no object for the key can be found
|
||||
*/
|
||||
static String getResourceString(final Class<? extends InternationalResource> c, final String... keyParts){
|
||||
return getResourceString(c, Locale.getDefault(), keyParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the default behaviour to retrieve the property mapping the given key for
|
||||
* the given class before formating the result using the given arguments.
|
||||
*
|
||||
* Note the key cannot be split into dot-separated key parts because of the
|
||||
* arguments vararg parameter.
|
||||
*
|
||||
* @param c
|
||||
* @param locale
|
||||
* @param key
|
||||
* @param arguments
|
||||
* @return
|
||||
*
|
||||
* @see InternationalResource#getResourceString(java.lang.Class, java.util.Locale, java.lang.String...) , with default locale.
|
||||
*
|
||||
* @throws IllegalArgumentException if the class parameter or the locale are null or no key is provided
|
||||
* @throws MissingResourceException if no resource bundle for the specified class can be found or no object for the key can be found
|
||||
*/
|
||||
static String getFormatedResourceString(final Class<? extends InternationalResource> c, final Locale locale, final String key, final Object... arguments){
|
||||
return MessageFormat.format(getResourceString(c, locale, key), arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Same behaviour as {@link InternationalResource#getFormatedResourceString(java.lang.Class, java.util.Locale, java.lang.String, java.lang.Object...) },
|
||||
* with default locale.
|
||||
*
|
||||
* @param c
|
||||
* @param key
|
||||
* @param arguments
|
||||
* @return
|
||||
*
|
||||
* @see InternationalResource#getResourceString(java.lang.Class, java.lang.String...).
|
||||
*
|
||||
* @throws IllegalArgumentException if no key is provided
|
||||
* @throws MissingResourceException if no object for the key can be found
|
||||
*/
|
||||
static String getFormatedResourceString(final Class<? extends InternationalResource> c, final String key, final Object... arguments){
|
||||
return MessageFormat.format(getResourceString(c, key), arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a string resource for the given locale.
|
||||
*
|
||||
* The resource can be associated to a simple key or a complex one.
|
||||
*
|
||||
* The default implementation assumes the key parts are separated by a dot.
|
||||
*
|
||||
* For instance, let's assume the class my.package.MyClass implementq
|
||||
* {@link InternationalResource} without overriding methods and is
|
||||
* associated to the following resource bundle : /my/package/MyClass.properties
|
||||
* which content is below :
|
||||
*
|
||||
* keyPart1.keyPart2=resource value
|
||||
*
|
||||
* The resource string "resource value" can be retrived from a my.package.MyClass
|
||||
* instance, calling this method either specifying only one key part
|
||||
* "keyPart1.keyPart2", or two key parts "keyPart1" and "keyPart2".
|
||||
*
|
||||
* @param keyParts
|
||||
* @param locale
|
||||
* @return
|
||||
*
|
||||
* @throws IllegalArgumentException if the locale is null or no key is provided
|
||||
* @throws MissingResourceException if no resource bundle can be found for the class of the current object or no object for the key can be found
|
||||
*/
|
||||
default String getResourceString(final Locale locale, final String... keyParts) {
|
||||
return getResourceString(getClass(), locale, keyParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut method to avoid to specify locale parameter.
|
||||
*
|
||||
* Default implementation maps the {@link Locale#getDefault() } {@link Locale}.
|
||||
*
|
||||
* @param keyParts
|
||||
* @return
|
||||
*
|
||||
* @see InternationalResource#getResourceString(java.util.Locale, java.lang.String...) ...).
|
||||
*
|
||||
* @throws IllegalArgumentException if no key is provided
|
||||
* @throws MissingResourceException if no resource bundle can be found for the class of the current object or no object for the key can be found
|
||||
*/
|
||||
default String getResourceString(final String... keyParts) {
|
||||
return getResourceString(Locale.getDefault(), keyParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a string resource for the given locale and formats the result
|
||||
* using the given arguments.
|
||||
*
|
||||
* @param locale
|
||||
* @param key
|
||||
* @param arguments
|
||||
* @return
|
||||
*
|
||||
* @see InternationalResource#getFormatedResourceString(java.lang.Class, java.util.Locale, java.lang.String, java.lang.Object...)
|
||||
*
|
||||
* @throws IllegalArgumentException if the locale is null or no key is provided
|
||||
* @throws MissingResourceException if no resource bundle for the class can be found for the class of the current object or no object for the key can be found
|
||||
*/
|
||||
default String getFormatedResourceString(final Locale locale, final String key, final Object... arguments) {
|
||||
return getFormatedResourceString(getClass(), locale, key, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut method to avoid to specify locale parameter.
|
||||
*
|
||||
* Default implementation maps the {@link Locale#getDefault() } {@link Locale}.
|
||||
*
|
||||
* @param key
|
||||
* @param arguments
|
||||
* @return
|
||||
*
|
||||
* @see InternationalResource#getFormatedResourceString(java.util.Locale, java.lang.String, java.lang.Object...) ...).
|
||||
*
|
||||
* @throws IllegalArgumentException if no key is provided
|
||||
* @throws MissingResourceException if no resource bundle for the class can be found for the class of the current object or no object for the key can be found
|
||||
*/
|
||||
default String getFormatedResourceString(final String key, final Object... arguments) {
|
||||
return getFormatedResourceString(Locale.getDefault(), key, arguments);
|
||||
}
|
||||
}
|
||||
138
core/src/main/java/fr/cenra/rhomeo/api/Version.java
Normal file
138
core/src/main/java/fr/cenra/rhomeo/api/Version.java
Normal file
@ -0,0 +1,138 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.sis.util.logging.Logging;
|
||||
|
||||
/**
|
||||
* A comparable to hold version values and allow for comparison between them.
|
||||
* This object will try to split an input string to extract a suite of digits,
|
||||
* which will compose the version. The weight of each digit in the suit is
|
||||
* determined by its encounter order in the string. First encountered are priorized
|
||||
* over the last ones.
|
||||
*
|
||||
* Ex : the String "1.2.3" will result in the following digit suite : 1 2 3,
|
||||
* where 1 is the major version, 2 the minor version, and 3 the update version.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class Version implements Comparable<Version> {
|
||||
|
||||
private static final Logger LOGGER = Logging.getLogger("fr.cenra.core");
|
||||
|
||||
final String stringVersion;
|
||||
final int[] version;
|
||||
|
||||
public Version(String inputVersion) {
|
||||
stringVersion = inputVersion == null? "" : inputVersion;
|
||||
|
||||
String[] splitted = stringVersion.split("[^\\d]+");
|
||||
if (splitted.length < 1) {
|
||||
version = new int[0];
|
||||
} else {
|
||||
int[] tmpVersion = new int[splitted.length];
|
||||
try {
|
||||
for (int i = 0; i < splitted.length; i++) {
|
||||
tmpVersion[i] = Integer.parseInt(splitted[i]);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
LOGGER.log(Level.WARNING, "Input version cannot be split as a suite of numbers : "+ inputVersion, e);
|
||||
tmpVersion = new int[0];
|
||||
}
|
||||
|
||||
version = tmpVersion;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Version o) {
|
||||
if (o == null) {
|
||||
return -1;
|
||||
} else if (version.length < 1 || o.version.length < 1) {
|
||||
return stringVersion.compareTo(o.stringVersion);
|
||||
} else {
|
||||
final int maxIndex = Math.min(version.length, o.version.length);
|
||||
int comparison;
|
||||
for (int i = 0 ; i < maxIndex ; i++) {
|
||||
comparison = version[i] - o.version[i];
|
||||
if (comparison != 0) {
|
||||
return comparison;
|
||||
}
|
||||
}
|
||||
|
||||
// if we arrived here, common version parts are equals. The longest should be the last version.
|
||||
return version.length - o.version.length;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A string representing current application version.
|
||||
*
|
||||
* @return current application version.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return stringVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Version) {
|
||||
return compareTo((Version) obj) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (version.length < 1) {
|
||||
return Arrays.hashCode(version);
|
||||
} else {
|
||||
return stringVersion.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.annotations;
|
||||
|
||||
import fr.cenra.rhomeo.core.validation.ReferenceValidator;
|
||||
import java.beans.Introspector;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.function.Predicate;
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
|
||||
/**
|
||||
* Describe a link between the source (annotated) property, and another one,
|
||||
* located in the specified class. This annotation should be positioned on a
|
||||
* property getter.
|
||||
*
|
||||
* IMPORTANT : we talk about properties in java.beans term, which means a data
|
||||
* accessible via public getter. The property name is defined by the terms used
|
||||
* to define the getter name. For more information, see {@link Introspector}
|
||||
* documentation.
|
||||
*
|
||||
* IMPORTANT : This annotation is also a validation flag, to ensure the property
|
||||
* value is referring to an existing object. However, it tests NEITHER nullity
|
||||
* NOR blankness.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Constraint(validatedBy = ReferenceValidator.class)
|
||||
@Documented
|
||||
public @interface RefersTo {
|
||||
String message() default "Aucune correspondance trouvée";
|
||||
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The class in which is located the property we're refering to.
|
||||
*/
|
||||
Class type();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The name of the property refered in {@link #type() }.
|
||||
*/
|
||||
String property();
|
||||
|
||||
/**
|
||||
* Provides a predicate to keep only objects which respects it.
|
||||
* @return A class (should not be an interface nor abstract one) from which
|
||||
* a {@link Predicate} can be created using {@link Class#newInstance() }.
|
||||
*
|
||||
*/
|
||||
Class<? extends Predicate> filterClass() default Predicate.class;
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import fr.cenra.rhomeo.api.process.Indicator;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Abstract implementation of {@link Protocol}.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*/
|
||||
public abstract class AbstractProtocol implements Protocol {
|
||||
|
||||
private final String name;
|
||||
private final String remarks;
|
||||
protected final Class<? extends Statement> dataType;
|
||||
protected final Set<ReferenceDescription> referenceTypes = new HashSet<>();
|
||||
|
||||
@Autowired // Need all subclasses to be Spring components.
|
||||
protected List<Indicator> indicators;
|
||||
|
||||
public AbstractProtocol(final String name, final String remarks, final Class<? extends Statement> dataType, final ReferenceDescription... referenceTypes){
|
||||
this.name = name;
|
||||
this.remarks = remarks;
|
||||
this.dataType = dataType;
|
||||
if (referenceTypes != null && referenceTypes.length > 0) {
|
||||
for (final ReferenceDescription referenceType : referenceTypes) {
|
||||
if (referenceType != null) {
|
||||
this.referenceTypes.add(referenceType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Statement> getDataType() {
|
||||
return dataType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ReferenceDescription> getReferenceTypes() {
|
||||
return referenceTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAlias() {
|
||||
return Collections.singleton(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemarks() {
|
||||
return remarks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation checking at least one {@link Indicator} exists
|
||||
* referencing this {@link Protocol} instance and compatible with the given
|
||||
* {@link Site} zone type code.
|
||||
*
|
||||
* @param site
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isCompatible(Site site) {
|
||||
if (site == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(final Indicator indicator : indicators){
|
||||
if(indicator.getProtocol()==this && indicator.getZoneTypeCodes() != null
|
||||
&& indicator.getZoneTypeCodes().contains(site.getZoneType())) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final Protocol p){
|
||||
return this.getName().compareTo(p.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AbstractProtocol{" + "name=" + name + ", remarks=" + remarks + '}';
|
||||
}
|
||||
|
||||
}
|
||||
132
core/src/main/java/fr/cenra/rhomeo/api/data/DataContext.java
Normal file
132
core/src/main/java/fr/cenra/rhomeo/api/data/DataContext.java
Normal file
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import fr.cenra.rhomeo.api.Version;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.HashMap;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableMap;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
|
||||
/**
|
||||
* Contains all data from the seizure context :
|
||||
* - Target Site
|
||||
* - Input protocol
|
||||
* - References versions
|
||||
* - Additional user data
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class DataContext {
|
||||
|
||||
private final Site site;
|
||||
private final Protocol protocol;
|
||||
|
||||
private final SimpleObjectProperty<ZonedDateTime> dateProperty;
|
||||
|
||||
private final ObservableMap<Class<Reference>, Version> references;
|
||||
|
||||
private final ObservableMap<String, Object> userData;
|
||||
|
||||
public DataContext(Site site, Protocol protocol) {
|
||||
ArgumentChecks.ensureNonNull("Input site", site);
|
||||
ArgumentChecks.ensureNonNull("Source protocol", protocol);
|
||||
this.site = site;
|
||||
this.protocol = protocol;
|
||||
dateProperty = new SimpleObjectProperty<>(ZonedDateTime.now());
|
||||
references = FXCollections.observableMap(new HashMap<>());
|
||||
userData = FXCollections.observableMap(new HashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Protocol currently used for seizure.
|
||||
*/
|
||||
@NotNull
|
||||
public Protocol getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Site chosen for current session.
|
||||
*/
|
||||
@NotNull
|
||||
public Site getSite() {
|
||||
return site;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return References used for this seizure, along with the chosen version for
|
||||
* each of them.
|
||||
*/
|
||||
@NotNull
|
||||
public ObservableMap<Class<Reference>, Version> getReferences() {
|
||||
return references;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return References used for this seizure, along with the chosen version for
|
||||
* each of them.
|
||||
*/
|
||||
@NotNull
|
||||
public ObservableMap<String, Object> getUserData() {
|
||||
return userData;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return Creation date of this dataset.
|
||||
*/
|
||||
public ZonedDateTime getDate() {
|
||||
return dateProperty.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set given date as creation date of this dataset.
|
||||
* @param date The date to use as new creation date.
|
||||
*/
|
||||
public void setDate(final ZonedDateTime date) {
|
||||
dateProperty.set(date);
|
||||
}
|
||||
}
|
||||
589
core/src/main/java/fr/cenra/rhomeo/api/data/Dataset.java
Normal file
589
core/src/main/java/fr/cenra/rhomeo/api/data/Dataset.java
Normal file
@ -0,0 +1,589 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.MethodDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.logging.Level;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.collections.ObservableSet;
|
||||
import javafx.collections.SetChangeListener;
|
||||
import javafx.collections.transformation.SortedList;
|
||||
import javafx.util.Callback;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
|
||||
/**
|
||||
* Data filled or imported in application.
|
||||
*
|
||||
* IMPORTANT : Avoid modifying {@link #getItems() } list outside of FX thread,
|
||||
* because UI could use filtered / sorted lists based on it.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
* @param <T> Type of statements pointed by this dataset.
|
||||
*/
|
||||
public class Dataset<T extends Statement> {
|
||||
|
||||
private final Protocol protocol;
|
||||
|
||||
/**
|
||||
* Keep a set of computed tracking points to speed up research and updates.
|
||||
*
|
||||
* TODO : replace with a map whose key is the tracking point, and value is the count of attached statements.
|
||||
*/
|
||||
private ObservableSet<TrackingPoint> internalPoints;
|
||||
/**
|
||||
* List of tracking points exposed to user.
|
||||
*/
|
||||
private ObservableList<TrackingPoint> points;
|
||||
/**
|
||||
* Seized statements.
|
||||
*/
|
||||
private final ObservableList<T> items;
|
||||
|
||||
/**
|
||||
* When an item date change, this listener update available tracking point list.
|
||||
*/
|
||||
private final ChangeListener<LocalDate> dateListener;
|
||||
/**
|
||||
* When an item name change, this listener update available tracking point list.
|
||||
*/
|
||||
private final ChangeListener<String> nameListener;
|
||||
/**
|
||||
* On a change in {@link #getItems() }, this listener check added/removed
|
||||
* objects to update tracking point list.
|
||||
*/
|
||||
private final TrackingPointListener tPointListener;
|
||||
private SetToListListener mirroring;
|
||||
|
||||
public Dataset(final Protocol target) {
|
||||
ArgumentChecks.ensureNonNull("Target protocol", target);
|
||||
protocol = target;
|
||||
|
||||
final Callback<T, Observable[]> extractor = createCallback();
|
||||
if (extractor == null) {
|
||||
items = FXCollections.observableArrayList();
|
||||
} else {
|
||||
items = FXCollections.observableArrayList(extractor);
|
||||
}
|
||||
|
||||
dateListener = (obs, oldDate, newDate) -> {
|
||||
if (obs instanceof Property) {
|
||||
Object bean = ((Property)obs).getBean();
|
||||
if (bean instanceof Statement) {
|
||||
final String name = ((Statement)bean).getTrackingPoint();
|
||||
if (name != null) {
|
||||
if (oldDate != null) {
|
||||
final TrackingPoint p = protocol.createTrackingPoint(name, oldDate);
|
||||
if (getSubSet(p).isEmpty()) {
|
||||
internalPoints.remove(p);
|
||||
}
|
||||
}
|
||||
if (newDate != null) {
|
||||
internalPoints.add(protocol.createTrackingPoint(name, newDate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
nameListener = (obs, oldName, newName) -> {
|
||||
if (obs instanceof Property) {
|
||||
Object bean = ((Property) obs).getBean();
|
||||
if (bean instanceof Statement) {
|
||||
final LocalDate date = ((Statement) bean).getDate();
|
||||
if (date != null) {
|
||||
if (oldName != null) {
|
||||
final TrackingPoint p = protocol.createTrackingPoint(oldName, date);
|
||||
if (getSubSet(p).isEmpty()) {
|
||||
internalPoints.remove(p);
|
||||
}
|
||||
}
|
||||
if (newName != null) {
|
||||
internalPoints.add(protocol.createTrackingPoint(newName, date));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tPointListener = new TrackingPointListener();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return List of associated data. Can be empty, but never null.
|
||||
*/
|
||||
@NotNull
|
||||
@Valid
|
||||
public synchronized ObservableList<T> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
@Valid
|
||||
public Protocol getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
private Callback<T, Observable[]> createCallback() {
|
||||
final ArrayList<Method> extractors = new ArrayList<>();
|
||||
try {
|
||||
final BeanInfo info = Introspector.getBeanInfo(protocol.getDataType(), Object.class);
|
||||
MethodDescriptor[] descs = info.getMethodDescriptors();
|
||||
for (final MethodDescriptor desc : descs) {
|
||||
final Method method = desc.getMethod();
|
||||
if (method.getParameterCount() < 1 && Observable.class.isAssignableFrom(method.getReturnType())) {
|
||||
method.setAccessible(true);
|
||||
extractors.add(method);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "Cannot analyze datatype for protocol ".concat(protocol.getName()), e);
|
||||
}
|
||||
|
||||
if (extractors.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return input -> {
|
||||
final ArrayList<Object> result = new ArrayList<>(extractors.size());
|
||||
for (int i = 0 ; i < extractors.size() ; i++) {
|
||||
try {
|
||||
result.add((Observable) extractors.get(i).invoke(input));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "Cannot extract a property !", e);
|
||||
}
|
||||
}
|
||||
|
||||
return result.toArray(new Observable[result.size()]);
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public synchronized ObservableList<TrackingPoint> getTrackingPoints() {
|
||||
if(points==null) {
|
||||
final HashSet<TrackingPoint> tmpSet = new HashSet<>();
|
||||
if (items != null) {
|
||||
String name;
|
||||
LocalDate date;
|
||||
for (final Statement statement : items) {
|
||||
name = statement.getTrackingPoint();
|
||||
date = statement.getDate();
|
||||
if (name != null && statement.getDate() != null) {
|
||||
final TrackingPoint p = protocol.createTrackingPoint(name, date);
|
||||
p.setRemarks(statement.getRemarks());
|
||||
tmpSet.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internalPoints = FXCollections.synchronizedObservableSet(FXCollections.observableSet(tmpSet));
|
||||
points = FXCollections.observableArrayList(tmpSet);
|
||||
removeListeners();
|
||||
addListeners();
|
||||
}
|
||||
return FXCollections.unmodifiableObservableList(points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query an unmodifiable view of the items contained in this dataset matching
|
||||
* the given tracking point. All modifications in {@link #getItems() } will
|
||||
* be mirrored in the returned view.
|
||||
*
|
||||
* If the given point is null, a list of all statements which are not bound
|
||||
* to any point is returned.
|
||||
*
|
||||
* @param filter The tracking point to get data for.
|
||||
* @return items matching a given tracking point (contained in it).
|
||||
*/
|
||||
@NotNull
|
||||
public synchronized ObservableList<T> getSubSet(final TrackingPoint... filter) {
|
||||
return getSubSet(filter == null || (filter.length == 1 && filter[0] == null)? null : Arrays.asList(filter));
|
||||
}
|
||||
|
||||
public synchronized ObservableList<T> getSubSet(Collection<TrackingPoint> filter) {
|
||||
final Predicate<T> predicate;
|
||||
if (filter == null || filter.isEmpty()) {
|
||||
predicate = input -> {
|
||||
return input.getTrackingPoint() == null || input.getDate() == null;
|
||||
};
|
||||
} else if (filter.size() == 1) {
|
||||
final TrackingPoint tp = filter.iterator().next();
|
||||
final String filterName = tp.getName();
|
||||
final LocalDate filterStart = tp.getYearStart().minusDays(1);
|
||||
final LocalDate filterEnd = tp.getYearEnd().plusDays(1);
|
||||
predicate = input -> {
|
||||
return filterName.equals(input.getTrackingPoint())
|
||||
&& input.getDate() != null
|
||||
&& input.getDate().isAfter(filterStart)
|
||||
&& input.getDate().isBefore(filterEnd);
|
||||
};
|
||||
} else {
|
||||
// Remove doublons
|
||||
if (!(filter instanceof Set)) {
|
||||
filter = new HashSet(filter);
|
||||
}
|
||||
|
||||
// Multiple tracking point filter. For each name, we build a set of
|
||||
// date range, for each tracking with the same name but different year range.
|
||||
final HashMap<String, List<LocalDate[]>> filters = new HashMap<>(filter.size());
|
||||
for (final TrackingPoint tp : filter) {
|
||||
filters.computeIfAbsent(tp.getName(), str -> new ArrayList())
|
||||
.add(new LocalDate[]{tp.getYearStart().minusDays(1), tp.getYearEnd().plusDays(1)});
|
||||
}
|
||||
|
||||
predicate = input -> {
|
||||
if (input.getTrackingPoint() == null || input.getDate() == null)
|
||||
return false;
|
||||
|
||||
final List<LocalDate[]> dates = filters.get(input.getTrackingPoint());
|
||||
if (dates == null)
|
||||
return false;
|
||||
|
||||
for (final LocalDate[] range : dates) {
|
||||
if (input.getDate().isAfter(range[0]) &&
|
||||
input.getDate().isBefore(range[1]))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
return getItems().filtered(predicate);
|
||||
}
|
||||
|
||||
public boolean deletePoints(final Collection<TrackingPoint> points) {
|
||||
final ArrayList<TrackingPoint> defCopy = new ArrayList<>(points);
|
||||
return items.removeIf(item -> {
|
||||
for (final TrackingPoint tp : defCopy) {
|
||||
if (tp.getName().equals(item.getTrackingPoint()) &&
|
||||
item.getDate() != null &&
|
||||
(item.getDate().isEqual(tp.getYearStart()) || item.getDate().isAfter(tp.getYearStart())) &&
|
||||
(item.getDate().isEqual(tp.getYearEnd()) || item.getDate().isBefore(tp.getYearEnd()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove listeners in charge of updating tracking point list.
|
||||
*/
|
||||
private void removeListeners() {
|
||||
if (mirroring != null && internalPoints != null) {
|
||||
internalPoints.removeListener(mirroring);
|
||||
}
|
||||
|
||||
if (items != null) {
|
||||
items.removeListener(tPointListener);
|
||||
items.forEach(item -> {
|
||||
item.dateProperty().removeListener(dateListener);
|
||||
item.trackingPointProperty().removeListener(nameListener);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add listeners on items and tracking points. The aim is to check statement
|
||||
* changes to update tracking point list accordingly.
|
||||
*/
|
||||
private void addListeners() {
|
||||
if (items != null && points != null) {
|
||||
mirroring = new SetToListListener(points);
|
||||
internalPoints.addListener(mirroring);
|
||||
items.forEach(item -> {
|
||||
item.dateProperty().addListener(dateListener);
|
||||
item.trackingPointProperty().addListener(nameListener);
|
||||
});
|
||||
items.addListener(tPointListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check changes on statement list, to update available tracking points
|
||||
* according to dataset content.
|
||||
*/
|
||||
private class TrackingPointListener implements ListChangeListener<Statement> {
|
||||
|
||||
@Override
|
||||
public void onChanged(Change<? extends Statement> c) {
|
||||
final HashSet<TrackingPoint> toRemove = new HashSet<>();
|
||||
final HashSet<TrackingPoint> toAdd = new HashSet<>();
|
||||
|
||||
TrackingPoint point;
|
||||
while (c.next()) {
|
||||
if (c.wasRemoved()) {
|
||||
for (Statement remitem : c.getRemoved()) {
|
||||
remitem.dateProperty().removeListener(dateListener);
|
||||
remitem.trackingPointProperty().removeListener(nameListener);
|
||||
|
||||
point = createTrackingPoint(remitem);
|
||||
if (point != null) {
|
||||
toRemove.add(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c.wasAdded()) {
|
||||
for (Statement additem : c.getAddedSubList()) {
|
||||
additem.dateProperty().addListener(dateListener);
|
||||
additem.trackingPointProperty().addListener(nameListener);
|
||||
|
||||
point = createTrackingPoint(additem);
|
||||
if (point != null) {
|
||||
toRemove.remove(point);
|
||||
toAdd.add(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there's still statements referencing removed statement tracking points, we keep them.
|
||||
final Iterator<TrackingPoint> it = toRemove.iterator();
|
||||
while (it.hasNext()) {
|
||||
point = it.next();
|
||||
if (!getSubSet(point).isEmpty())
|
||||
it.remove();
|
||||
}
|
||||
|
||||
internalPoints.removeAll(toRemove);
|
||||
internalPoints.addAll(toAdd);
|
||||
}
|
||||
|
||||
private TrackingPoint createTrackingPoint(final Statement statement) {
|
||||
final String name = statement.getTrackingPoint();
|
||||
final LocalDate date = statement.getDate();
|
||||
if (name != null && date != null) {
|
||||
final TrackingPoint p = protocol.createTrackingPoint(name, date);
|
||||
p.setRemarks(statement.getRemarks());
|
||||
return p;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors changes happening in a set to the parameterised list.
|
||||
*/
|
||||
private class SetToListListener implements SetChangeListener<TrackingPoint> {
|
||||
|
||||
private final List destination;
|
||||
|
||||
public SetToListListener(final List destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged(Change<? extends TrackingPoint> c) {
|
||||
if (c.wasRemoved()) {
|
||||
destination.remove(c.getElementRemoved());
|
||||
} else if (c.wasAdded()) {
|
||||
destination.add(c.getElementAdded());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the tracking point attached to given statement.
|
||||
* @param data The statement to find parent tracking point for.
|
||||
* @return A tracking point matching given parameter, or nothing.
|
||||
*/
|
||||
public Optional<TrackingPoint> findPoint(final Statement data) {
|
||||
if (data == null)
|
||||
return Optional.empty();
|
||||
return findPoint(data.getTrackingPoint(), data.getDate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a tracking point whose name is equal to the given one, and validity
|
||||
* period contains given date.
|
||||
* @param name The name to get a tracking point for.
|
||||
* @param date The date to get a tracking point for.
|
||||
* @return A tracking point matching given parameters, or nothing.
|
||||
*/
|
||||
public Optional<TrackingPoint> findPoint(String name, final LocalDate date) {
|
||||
if (!items.isEmpty() && date != null && name != null && !(name = name.trim()).isEmpty()) {
|
||||
final ObservableList<TrackingPoint> tps = getTrackingPoints();
|
||||
if (!tps.isEmpty()) {
|
||||
for (final TrackingPoint tp : tps) {
|
||||
if (tp.getName().equals(name) &&
|
||||
(date.isAfter(tp.getYearStart()) || date.isEqual(tp.getYearStart())) &&
|
||||
(date.isBefore(tp.getYearEnd()) || date.isEqual(tp.getYearEnd()))) {
|
||||
return Optional.of(tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public synchronized Map<TrackingPoint, List<T>> groupByPoint() {
|
||||
final List<TrackingPoint> trackingPoints = getTrackingPoints().sorted((TrackingPoint o1, TrackingPoint o2) -> {
|
||||
if (o1 == null) {
|
||||
return o2 == null ? 0 : 1;
|
||||
} else if (o2 == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final int nameOrder = o1.getName().compareTo(o2.getName());
|
||||
if (nameOrder != 0) {
|
||||
return nameOrder;
|
||||
}
|
||||
|
||||
return o1.getYear() - o2.getYear();
|
||||
});
|
||||
|
||||
final Map<TrackingPoint, List<T>> statements = new HashMap<>();
|
||||
|
||||
final SortedList<T> sortedSet = getItems().sorted((Comparator) ORDER_BY_POINT);
|
||||
final Iterator<TrackingPoint> tit = trackingPoints.iterator();
|
||||
final Iterator<T> sit = sortedSet.iterator();
|
||||
if (tit.hasNext()) {
|
||||
TrackingPoint tp = tit.next();
|
||||
Predicate predicate = new BelongsToTrackingPoint(tp);
|
||||
ArrayList<T> ptList = new ArrayList<>();
|
||||
statements.put(tp, ptList);
|
||||
while (sit.hasNext()) {
|
||||
final T st = sit.next();
|
||||
if (!predicate.test(st)) {
|
||||
if (tit.hasNext()) {
|
||||
tp = tit.next();
|
||||
predicate = new BelongsToTrackingPoint(tp);
|
||||
ptList = new ArrayList<>();
|
||||
statements.put(tp, ptList);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ptList.add(st);
|
||||
}
|
||||
}
|
||||
|
||||
return statements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given statement belongs to given tracking point.
|
||||
* @param point The point to test
|
||||
* @param statement The statement to test against input point.
|
||||
* @return True if given statement belongs to given tracking point, false otherwise.
|
||||
*/
|
||||
public static boolean belongToPoint(final TrackingPoint point, final Statement statement) {
|
||||
final LocalDate date = statement.getDate();
|
||||
if (date == null || statement.getTrackingPoint() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (point.getName().equals(statement.getTrackingPoint())
|
||||
&& (date.isAfter(point.getYearStart()) || date.isEqual(point.getYearStart()))
|
||||
&& (date.isBefore(point.getYearEnd()) || date.isEqual(point.getYearEnd())));
|
||||
}
|
||||
|
||||
private static class BelongsToTrackingPoint implements Predicate<Statement> {
|
||||
final String name;
|
||||
final LocalDate filterStart;
|
||||
final LocalDate filterEnd;
|
||||
|
||||
private BelongsToTrackingPoint(final TrackingPoint tp) {
|
||||
name = tp.getName();
|
||||
filterStart = tp.getYearStart().minusDays(1);
|
||||
filterEnd = tp.getYearEnd().plusDays(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Statement t) {
|
||||
return name.equals(t.getTrackingPoint())
|
||||
&& t.getDate() != null
|
||||
&& t.getDate().isAfter(filterStart)
|
||||
&& t.getDate().isBefore(filterEnd);
|
||||
}
|
||||
}
|
||||
|
||||
private static Comparator<? extends Statement> ORDER_BY_POINT = (s1, s2) -> {
|
||||
final String t1 = s1.getTrackingPoint();
|
||||
final String t2 = s2.getTrackingPoint();
|
||||
|
||||
int comp;
|
||||
if (t1 == t2)
|
||||
comp = 0;
|
||||
else if (t1 != null)
|
||||
comp = t1.compareTo(t2);
|
||||
else
|
||||
comp = 1;
|
||||
|
||||
if (comp == 0) {
|
||||
final LocalDate d1 = s1.getDate();
|
||||
final LocalDate d2 = s2.getDate();
|
||||
if (d1 != d2) {
|
||||
if (d1 == null)
|
||||
comp = 1;
|
||||
else
|
||||
comp = d1.compareTo(d2);
|
||||
}
|
||||
}
|
||||
|
||||
return comp;
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A simple function designed to wrap an object of type I into another of type
|
||||
* O.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
* @param <I> Type of the objects to wrap (parameter).
|
||||
* @param <O> Type of the wrapper object (returned).
|
||||
*/
|
||||
public interface ObjectWrapper<I, O> extends Function<I, O> {
|
||||
|
||||
Class<I> getInputType();
|
||||
|
||||
Class<O> getOutputType();
|
||||
}
|
||||
104
core/src/main/java/fr/cenra/rhomeo/api/data/Protocol.java
Normal file
104
core/src/main/java/fr/cenra/rhomeo/api/data/Protocol.java
Normal file
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import fr.cenra.rhomeo.api.IdentifiedObject;
|
||||
import fr.cenra.rhomeo.api.process.Indicator;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Set;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Defines a scientific protocol designed to hold a specific set of measures.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface Protocol extends IdentifiedObject, Comparable<Protocol> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {@link Statement} class defining measure content. Must not be null.
|
||||
*/
|
||||
@NotNull
|
||||
Class<? extends Statement> getDataType();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Set of reference types needed to complete seizure / processing of
|
||||
* the protocol measures. Should never be null, but can be empty.
|
||||
*/
|
||||
@NotNull
|
||||
Set<ReferenceDescription> getReferenceTypes();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param site A site to analyze.
|
||||
* @return True if we can process {@link Indicator}s associated to the current
|
||||
* protocol with given site. False otherwise.
|
||||
*/
|
||||
boolean isCompatible(Site site);
|
||||
|
||||
/**
|
||||
* Create a tracking point with the provided name, whose year contains the
|
||||
* given date. This method is useful when you've got a {@link Statement},
|
||||
* and want to know which stating year owns it.
|
||||
*
|
||||
* @param name The name of the tracking point.
|
||||
* @param statementDate A date to get matching year for.
|
||||
* @return A new tracking point. Never null.
|
||||
*/
|
||||
default TrackingPoint createTrackingPoint(final String name, final LocalDate statementDate) {
|
||||
return new TrackingPoint(name, statementDate.getYear());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new tracking point named as specified, on the given year. A year
|
||||
* is not always a calendar year. It can go between two chosen dates.
|
||||
*
|
||||
* Ex : You can specify that year 2015 goes from September, 1st of 2014 to
|
||||
* August, 31th of 2015
|
||||
*
|
||||
* @param name The name to set on the new tracking point.
|
||||
* @param year The year to affect to the tracking point.
|
||||
* @return A new tracking point. Never null.
|
||||
*/
|
||||
default TrackingPoint createTrackingPoint(final String name, final int year) {
|
||||
return new TrackingPoint(name, year);
|
||||
}
|
||||
}
|
||||
46
core/src/main/java/fr/cenra/rhomeo/api/data/Reference.java
Normal file
46
core/src/main/java/fr/cenra/rhomeo/api/data/Reference.java
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface Reference {
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import fr.cenra.rhomeo.api.IdentifiedObject;
|
||||
|
||||
/**
|
||||
* Contains generic information about a specific {@link Reference} implementation.
|
||||
* There should be a unique instance for each type of reference available in application.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
* @param <T> The type of reference described by this object.
|
||||
*/
|
||||
public interface ReferenceDescription<T extends Reference> extends IdentifiedObject {
|
||||
|
||||
Class<T> getReferenceType();
|
||||
|
||||
}
|
||||
66
core/src/main/java/fr/cenra/rhomeo/api/data/Site.java
Normal file
66
core/src/main/java/fr/cenra/rhomeo/api/data/Site.java
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import com.vividsolutions.jts.geom.MultiPolygon;
|
||||
import fr.cenra.rhomeo.api.IdentifiedObject;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface Site extends IdentifiedObject, Comparable<Site> {
|
||||
|
||||
@NotNull
|
||||
MultiPolygon getGeometry();
|
||||
|
||||
String getCountyCode();
|
||||
|
||||
String getReferent();
|
||||
|
||||
String getOrganization();
|
||||
|
||||
String getZoneType();
|
||||
|
||||
String getOdonateType();
|
||||
|
||||
String getOrthoptereType();
|
||||
}
|
||||
122
core/src/main/java/fr/cenra/rhomeo/api/data/Statement.java
Normal file
122
core/src/main/java/fr/cenra/rhomeo/api/data/Statement.java
Normal file
@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import fr.cenra.rhomeo.api.InternationalDescription;
|
||||
import fr.cenra.rhomeo.api.InternationalResource;
|
||||
import java.time.LocalDate;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Represents an entry in a {@link Dataset}. It's an entity containing several
|
||||
* physical measures.
|
||||
*
|
||||
* Note : we force overriding of {@link #equals(java.lang.Object) } and {@link #hashCode()
|
||||
* } methods, because statements will be compared in application to remove
|
||||
* potential doublons.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public abstract class Statement implements InternationalResource, InternationalDescription {
|
||||
|
||||
protected final SimpleStringProperty trackingPoint = new SimpleStringProperty(this, "trackingPoint");
|
||||
|
||||
protected final SimpleObjectProperty<LocalDate> date = new SimpleObjectProperty<>(this, "date");
|
||||
|
||||
protected final StringProperty remarksProperty = new SimpleStringProperty();
|
||||
|
||||
protected Statement() {}
|
||||
|
||||
protected Statement(final String trackingPoint, final LocalDate date) {
|
||||
this.trackingPoint.set(trackingPoint);
|
||||
this.date.set(date);
|
||||
}
|
||||
|
||||
protected Statement(final String trackingPoint, final LocalDate date, final String remarks) {
|
||||
this(trackingPoint, date);
|
||||
this.remarksProperty.set(remarks);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LocalDate getDate() {
|
||||
return date.get();
|
||||
}
|
||||
|
||||
public void setDate(final LocalDate date) {
|
||||
this.date.set(date);
|
||||
}
|
||||
|
||||
public ObjectProperty<LocalDate> dateProperty() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public String getTrackingPoint() {
|
||||
return trackingPoint.get();
|
||||
}
|
||||
|
||||
public void setTrackingPoint(final String tPoint) {
|
||||
trackingPoint.set(tPoint);
|
||||
}
|
||||
|
||||
public StringProperty trackingPointProperty() {
|
||||
return trackingPoint;
|
||||
}
|
||||
|
||||
public String getRemarks() {
|
||||
return remarksProperty.get();
|
||||
}
|
||||
|
||||
public void setRemarks(final String remarks) {
|
||||
this.remarksProperty.set(remarks);
|
||||
}
|
||||
|
||||
public StringProperty remarksProperty() {
|
||||
return remarksProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(Object obj);
|
||||
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
}
|
||||
210
core/src/main/java/fr/cenra/rhomeo/api/data/TrackingPoint.java
Normal file
210
core/src/main/java/fr/cenra/rhomeo/api/data/TrackingPoint.java
Normal file
@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import fr.cenra.rhomeo.api.IdentifiedObject;
|
||||
import fr.cenra.rhomeo.api.InternationalResource;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
|
||||
/**
|
||||
* A point on which a series of statements have been done. The point is
|
||||
* identified by a name and the year on which statements have been done.
|
||||
*
|
||||
* It's an (almost) immutable object, because its just a reflection of
|
||||
* statements name and date property, to use grouping. Moreover, introducing
|
||||
* points with null year would be problematic for computing work flow. The only
|
||||
* editable attribute is the remarks property, as it's not a defining data.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public final class TrackingPoint implements IdentifiedObject, InternationalResource, Externalizable {
|
||||
|
||||
protected static final long serialVersionUID = 1L;
|
||||
|
||||
private String name;
|
||||
|
||||
private int year;
|
||||
|
||||
private LocalDate yearStart;
|
||||
private LocalDate yearEnd;
|
||||
|
||||
private final StringProperty remarks;
|
||||
|
||||
public TrackingPoint() {
|
||||
this("default", 2016);
|
||||
}
|
||||
|
||||
public TrackingPoint(final String name, final int year) {
|
||||
this(name, year, null, null);
|
||||
}
|
||||
|
||||
public TrackingPoint(final String name, final LocalDate yearStart, final LocalDate yearEnd) {
|
||||
this(
|
||||
name,
|
||||
// Try to find a valid year from input dates.
|
||||
yearEnd != null ? yearEnd.getYear() : yearStart != null ? yearStart.getYear() : LocalDate.now().getYear(),
|
||||
yearStart,
|
||||
yearEnd
|
||||
);
|
||||
}
|
||||
|
||||
public TrackingPoint(String name, final int year, LocalDate yearStart, LocalDate yearEnd) {
|
||||
if (name == null || (name = name.trim()).isEmpty()) {
|
||||
throw new IllegalArgumentException("Given name is blank !");
|
||||
}
|
||||
this.name = name;
|
||||
this.remarks = new SimpleStringProperty();
|
||||
|
||||
if (yearStart == null) {
|
||||
if (yearEnd != null) {
|
||||
yearStart = yearEnd.minusYears(1).plusDays(1);
|
||||
} else {
|
||||
yearStart = LocalDate.of(year, 01, 01);
|
||||
}
|
||||
}
|
||||
|
||||
if (yearEnd == null) {
|
||||
yearEnd = yearStart.plusYears(1).minusDays(1);
|
||||
}
|
||||
|
||||
if (yearStart.isBefore(yearEnd)) {
|
||||
this.yearStart = yearStart;
|
||||
this.yearEnd = yearEnd;
|
||||
} else {
|
||||
this.yearStart = yearEnd;
|
||||
this.yearEnd = yearStart;
|
||||
}
|
||||
|
||||
ArgumentChecks.ensureBetween("Year", this.yearStart.getYear(), this.yearEnd.getYear(), year);
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Year associated to this point.
|
||||
*/
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 71 * hash + this.year;
|
||||
hash = 71 * hash + this.name.hashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final TrackingPoint other = (TrackingPoint) obj;
|
||||
return this.year == other.year && this.name.equals(other.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("TrackingPoint{ name=").append(name).append(" year=").append(year).append(" }").toString();
|
||||
}
|
||||
|
||||
public LocalDate getYearStart() {
|
||||
return yearStart;
|
||||
}
|
||||
|
||||
public LocalDate getYearEnd() {
|
||||
return yearEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemarks() {
|
||||
return remarks.get();
|
||||
}
|
||||
|
||||
public void setRemarks(String remarks) {
|
||||
this.remarks.set(remarks);
|
||||
}
|
||||
|
||||
public StringProperty remarksProperty() {
|
||||
return remarks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAlias() {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
out.writeUTF(name);
|
||||
out.writeInt(year);
|
||||
RhomeoCore.writeDate(yearStart, out);
|
||||
RhomeoCore.writeDate(yearEnd, out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
name = in.readUTF();
|
||||
year = in.readInt();
|
||||
yearStart = RhomeoCore.readDate(in);
|
||||
yearEnd = RhomeoCore.readDate(in);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class TrackingPointFilter implements Predicate<Statement>, Serializable {
|
||||
|
||||
public TrackingPoint point;
|
||||
|
||||
public TrackingPointFilter() {}
|
||||
|
||||
public TrackingPointFilter(final TrackingPoint tp) {
|
||||
point = tp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Statement t) {
|
||||
if (t == null)
|
||||
return false;
|
||||
if (!Objects.equals(point == null? null : point.getName(), t.getTrackingPoint()))
|
||||
return false;
|
||||
return checkDateRange(t.getDate());
|
||||
}
|
||||
|
||||
private boolean checkDateRange(final LocalDate toTest) {
|
||||
final LocalDate yearStart = (point == null)? null : point.getYearStart();
|
||||
final LocalDate yearEnd = (point == null)? null : point.getYearEnd();
|
||||
if (toTest == yearStart || toTest == yearEnd)
|
||||
return true;
|
||||
if (toTest == null)
|
||||
return false;
|
||||
if (yearStart != null && toTest.isBefore(yearStart))
|
||||
return false;
|
||||
|
||||
return !(yearEnd != null && toTest.isAfter(yearEnd));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 89 * hash + Objects.hashCode(this.point);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final TrackingPointFilter other = (TrackingPointFilter) obj;
|
||||
return Objects.equals(this.point, other.point);
|
||||
}
|
||||
}
|
||||
51
core/src/main/java/fr/cenra/rhomeo/api/data/Warning.java
Normal file
51
core/src/main/java/fr/cenra/rhomeo/api/data/Warning.java
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.data;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Payload;
|
||||
|
||||
/**
|
||||
* A simple interface defining that the attached {@link ConstraintViolation} is
|
||||
* a warning, a recoverable error.
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface Warning extends Payload {
|
||||
|
||||
}
|
||||
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.preferences;
|
||||
|
||||
import fr.cenra.rhomeo.api.InternationalDescription;
|
||||
import static fr.cenra.rhomeo.api.InternationalDescription.DESCRIPTION_KEY;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.logging.Level;
|
||||
import static fr.cenra.rhomeo.api.InternationalDescription.LABEL_KEY;
|
||||
|
||||
/**
|
||||
* An interface to be implemented by preference keys which have an international
|
||||
* description.
|
||||
*
|
||||
* This interface provides a default implementation usefull for {@link Enum}
|
||||
* based implementations, assuming the {@link InternationalPreferenceKey#name() }
|
||||
* method is implemented.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*/
|
||||
public interface InternationalPreferenceKey extends InternationalDescription, SimplePreferenceKey {
|
||||
|
||||
/**
|
||||
* The name of the key.
|
||||
*
|
||||
* The purpose of this method is to provide a default implementation of
|
||||
* {@link InternationalPreferenceKey#getLabel(java.util.Locale) } and
|
||||
* {@link InternationalPreferenceKey#getDescription(java.util.Locale) } for
|
||||
* {@link Enum} based implementations. In case the default implementation is
|
||||
* overriden, the InternationalPreferenceKey#name() method implementation is
|
||||
* free and even posibly useless.
|
||||
*
|
||||
* @see Enum#name()
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param locale
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
default String getDescription(final Locale locale) {
|
||||
try {
|
||||
return ResourceBundle.getBundle(getClass().getName(), locale).getString(name() + '.' + DESCRIPTION_KEY);
|
||||
} catch (Exception e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "A bundle key cannot be found !", e);
|
||||
return name().concat(" (No traduction available)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param locale
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
default String getLabel(final Locale locale) {
|
||||
try {
|
||||
return ResourceBundle.getBundle(getClass().getName(), locale).getString(name() + '.' + LABEL_KEY);
|
||||
} catch (Exception e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "A bundle key cannot be found !", e);
|
||||
return name().concat(" (No traduction available)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.preferences;
|
||||
|
||||
/**
|
||||
* A simple interface to identify a {@link SimplePreferenceKey} as holding the
|
||||
* value of a password. It's useful to adapt preference editors.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface PasswordKey {
|
||||
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.preferences;
|
||||
|
||||
import fr.cenra.rhomeo.api.InternationalDescription;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A group of preferences.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*
|
||||
* @param <T> The type of preference keys.
|
||||
*/
|
||||
public interface PreferenceGroup <T> extends InternationalDescription, Comparable<PreferenceGroup> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key
|
||||
* @return The value of the preference associated to the given key in the preference group.
|
||||
*/
|
||||
String getPreference(T key);
|
||||
|
||||
/**
|
||||
* Sets the value of the preference associated to the given key in the preference group.
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
void setPreference(T key, String value);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The list of the keys of the preference group.
|
||||
*/
|
||||
List<T> getKeys();
|
||||
|
||||
/**
|
||||
* Priority of this group, used for comparison.
|
||||
*
|
||||
* @return The priority of this group.
|
||||
*/
|
||||
int getPriority();
|
||||
|
||||
|
||||
@Override
|
||||
default int compareTo(PreferenceGroup o) {
|
||||
return getPriority() - o.getPriority();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.preferences;
|
||||
|
||||
/**
|
||||
* A simple interface for preference keys, providing a default value.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*/
|
||||
public interface SimplePreferenceKey {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The key used to retrive a preference value from the storage, for
|
||||
* a given implementation.
|
||||
*/
|
||||
String getKey();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The default value associated to this preference key.
|
||||
*/
|
||||
String getDefaultValue();
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.preferences;
|
||||
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
/**
|
||||
* Abstract {@link PreferenceGroup} using {@link Preferences#userNodeForPackage(java.lang.Class) } storage.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class UserPackagePreferenceGroup<T extends SimplePreferenceKey> implements PreferenceGroup<T>{
|
||||
|
||||
protected final Preferences prefs = Preferences.userNodeForPackage(getClass());
|
||||
|
||||
@Override
|
||||
public String getPreference(final T key) {
|
||||
return prefs.get(key.getKey(), key.getDefaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPreference(final T key, String value){
|
||||
if (value == null || (value = value.trim()).isEmpty())
|
||||
prefs.remove(key.getKey());
|
||||
else prefs.put(key.getKey(), value);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.process;
|
||||
|
||||
import fr.cenra.rhomeo.api.Version;
|
||||
import fr.cenra.rhomeo.api.data.DataContext;
|
||||
import fr.cenra.rhomeo.api.data.Reference;
|
||||
import fr.cenra.rhomeo.api.data.ReferenceDescription;
|
||||
import fr.cenra.rhomeo.core.Session;
|
||||
import fr.cenra.rhomeo.core.data.ReferenceManager;
|
||||
import fr.cenra.rhomeo.core.list.HumidZoneType;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*/
|
||||
public abstract class AbstractIndicator implements Indicator {
|
||||
|
||||
private final String name;
|
||||
private final String remarks;
|
||||
|
||||
public AbstractIndicator(final String name, final String remarks){
|
||||
this.name = name;
|
||||
this.remarks = remarks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAlias() {
|
||||
return Collections.singleton(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemarks() {
|
||||
return remarks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation. If some {@link Indicator} subclass is not compatible
|
||||
* with all {@link HumidZoneType}, this method MUST be overriden.
|
||||
*
|
||||
* @return a set containing all environment codes because this indicator is
|
||||
* compatible with all of them.
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getZoneTypeCodes() {
|
||||
final Set<String> result = new HashSet<>();
|
||||
for(final HumidZoneType type : HumidZoneType.values()){
|
||||
result.add(type.getCode());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final Indicator i){
|
||||
return this.getName().compareTo(i.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AbstractIndicator{" + "name=" + name + ", remarks=" + remarks + '}';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the references relative to the reference description parameter.
|
||||
*
|
||||
* => DEPLACER VERS ReferenceManager ?
|
||||
*
|
||||
* @param <T>
|
||||
* @param description
|
||||
* @return
|
||||
* @throws IntrospectionException
|
||||
*/
|
||||
public static <T extends Reference> List<T> getReferences(final ReferenceDescription<T> description) throws IntrospectionException {
|
||||
final ReferenceManager<T> referenceManager = ReferenceManager.getOrCreate(description);
|
||||
final DataContext dc = Session.getInstance().getDataContext();
|
||||
final Version versionSel = dc.getReferences().get(description.getReferenceType());
|
||||
return referenceManager.getValues(versionSel != null ? versionSel : referenceManager.getInstalledVersions().iterator().next());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.process;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javafx.concurrent.Task;
|
||||
|
||||
/**
|
||||
* Note : this process is made for the need of "complementary values" provided
|
||||
* along indicator indices. However, this is still an abstract concept for now,
|
||||
* and will need to be completed later.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface AdditionalProcessSpi {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return set of indicators for which this
|
||||
*/
|
||||
Set<Indicator> getTargets();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param results Set of processes finished and succeeded, sorted by indicator.
|
||||
*
|
||||
* @return A task to compute complementary values over the given indicators,
|
||||
* or nothing if we cannot extract enough data from input parameters.
|
||||
*/
|
||||
Optional<Task> prepareProcess(final Map<Indicator, Set<Process>> results);
|
||||
}
|
||||
101
core/src/main/java/fr/cenra/rhomeo/api/process/Indicator.java
Normal file
101
core/src/main/java/fr/cenra/rhomeo/api/process/Indicator.java
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.process;
|
||||
|
||||
import fr.cenra.rhomeo.api.IdentifiedObject;
|
||||
import fr.cenra.rhomeo.api.data.Dataset;
|
||||
import fr.cenra.rhomeo.api.data.Protocol;
|
||||
import fr.cenra.rhomeo.api.data.Site;
|
||||
import fr.cenra.rhomeo.api.result.Index;
|
||||
import fr.cenra.rhomeo.core.list.HumidZoneType;
|
||||
import java.util.Set;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface Indicator extends IdentifiedObject, Comparable<Indicator> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Source protocol to work with. Defines input {@link Statement} type.
|
||||
*/
|
||||
@NotNull
|
||||
Protocol getProtocol();
|
||||
|
||||
/**
|
||||
* Create all processes needed to complete {@link Index} computation over
|
||||
* current session {@link Dataset}.
|
||||
* The statements inside the {@link Dataset} must match the type given by
|
||||
* {@link Protocol#getDataType()} from this indicator {@link #getProtocol() }.
|
||||
*
|
||||
* Each process is designed to compute part or all of this indicator indices,
|
||||
* on part or all of the input dataset. Which means developper is completely
|
||||
* free to split his processes by data or by result. The only important point
|
||||
* is that once all processes are over and succeeded, the union of their
|
||||
* results represents all possible indices on the entire input dataset.
|
||||
*
|
||||
* @param ctx The context to use as input for the newly created processes.
|
||||
*
|
||||
* @return A set of processes ready to be run. No insurance is done on
|
||||
* execution order nor on parallelisation. The processes returned here should
|
||||
* be independants.
|
||||
*/
|
||||
@NotNull
|
||||
Set<Process> createProcesses(ProcessContext ctx);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Name of the index considered as the main result for processes of
|
||||
* this indicator.
|
||||
*/
|
||||
String getDefaultIndex();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The compatible environment codes to determine if the indicator is
|
||||
* applicable to potential sites.
|
||||
*
|
||||
* @see Site
|
||||
* @see HumidZoneType
|
||||
*
|
||||
*/
|
||||
Set<String> getZoneTypeCodes();
|
||||
}
|
||||
79
core/src/main/java/fr/cenra/rhomeo/api/process/Process.java
Normal file
79
core/src/main/java/fr/cenra/rhomeo/api/process/Process.java
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.process;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.TrackingPoint;
|
||||
import fr.cenra.rhomeo.api.result.Index;
|
||||
import java.util.Set;
|
||||
import javafx.concurrent.Task;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
|
||||
/**
|
||||
* A Calculation over a {@link TrackingPoint}. This class represents a process
|
||||
* created from an {@link Indicator}.
|
||||
*
|
||||
* Note : For process independent of any indicator, you should prefer implementing
|
||||
* {@link AdditionalProcessSpi}.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public abstract class Process extends Task<Set<? extends Index>> {
|
||||
|
||||
protected final ProcessContext ctx;
|
||||
|
||||
protected Process(final ProcessContext ctx) {
|
||||
ArgumentChecks.ensureNonNull("Process context", ctx);
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The indicator bound to this process. Should never be null.
|
||||
*/
|
||||
@NotNull
|
||||
public abstract Indicator getIndicator();
|
||||
|
||||
/**
|
||||
* @return The processing context which provide input data. Never null.
|
||||
*/
|
||||
@NotNull
|
||||
public ProcessContext getContext() {
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,214 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.process;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.DataContext;
|
||||
import fr.cenra.rhomeo.api.data.Dataset;
|
||||
import fr.cenra.rhomeo.api.data.Statement;
|
||||
import fr.cenra.rhomeo.api.data.TrackingPoint;
|
||||
import fr.cenra.rhomeo.api.result.Index;
|
||||
import java.io.Externalizable;
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Predicate;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.collections.ObservableSet;
|
||||
import javafx.collections.SetChangeListener;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
|
||||
/**
|
||||
* Contains all source needed for {@link Index} processing.
|
||||
*
|
||||
* IMPORTANT : Application attempts to save restore state of this object in case
|
||||
* of unexpected shutdown. For the {@link #getFilter() } property to be saved,
|
||||
* it MUST be {@link Serializable} or {@link Externalizable}.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class ProcessContext {
|
||||
|
||||
private final Dataset source;
|
||||
private final DataContext dataCtx;
|
||||
private final ObservableSet<Indicator> targetIndicators = FXCollections.observableSet();
|
||||
|
||||
private Dataset processData;
|
||||
|
||||
/**
|
||||
* A filter which allow user to specify a filter for source to take in
|
||||
* account.
|
||||
*/
|
||||
private final ObjectProperty<Predicate<? extends Statement>> filterProperty = new SimpleObjectProperty<>(this, "filter", null);
|
||||
|
||||
public ProcessContext(Dataset data, DataContext dataCtx) {
|
||||
ArgumentChecks.ensureNonNull("Input data", data);
|
||||
ArgumentChecks.ensureNonNull("Input data context", dataCtx);
|
||||
this.source = data;
|
||||
this.dataCtx = dataCtx;
|
||||
targetIndicators.addListener((SetChangeListener) this::indicatorsChanged);
|
||||
filterProperty.addListener(this::filterChanged);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dataset to use for indicator computing. It contains imported data that
|
||||
* has been selected by user for processing.
|
||||
*
|
||||
* Note : User selection is reflected by {@link #filterProperty}. But if it
|
||||
* changes, previously returned dataset won't be updated. To get an up to
|
||||
* date dataset, you must acquire a new dataset by calling this method
|
||||
* again.
|
||||
*
|
||||
* @return A dataset built from user selected data. Every time this
|
||||
* method is called, the same dataset is returned, until {@link #filterProperty()}
|
||||
* change. At this time a new dataset is generated, updating contained data
|
||||
* to match new filter.
|
||||
*/
|
||||
@NotNull
|
||||
public synchronized Dataset getData() {
|
||||
if (processData == null) {
|
||||
if (filterProperty.get() == null)
|
||||
processData = source;
|
||||
else {
|
||||
processData = new Dataset(source.getProtocol());
|
||||
processData.getItems().addAll(source.getItems().filtered(filterProperty.get()));
|
||||
}
|
||||
}
|
||||
|
||||
return processData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return data seized by user as total dataset. This dataset should not be
|
||||
* used for processing, as it represents all data imported, not the
|
||||
* selection made after it.
|
||||
*
|
||||
* WARNING : Do not use this dataset for processing indicators. Use {@link #getData()
|
||||
* }
|
||||
* instead.
|
||||
*
|
||||
* @return Dataset which has been used for building process data.
|
||||
*/
|
||||
@NotNull
|
||||
public Dataset getSourceDataset() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Seizure context. Contains chosen site and protocol for computing.
|
||||
*/
|
||||
@NotNull
|
||||
public DataContext getDataCtx() {
|
||||
return dataCtx;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return a set of tracking points, never {@code null}.
|
||||
*/
|
||||
@NotNull
|
||||
public ObservableList<TrackingPoint> getTrackingPoints() {
|
||||
return FXCollections.unmodifiableObservableList(getData().getTrackingPoints());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ObservableSet<Indicator> getIndicators() {
|
||||
return targetIndicators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow user to filter source dataset. The filter will be applied when
|
||||
* calling {@link #getData() }. It serves to decimate data used by indicator
|
||||
* processes.
|
||||
*
|
||||
* @return Currently configured filter, or null if no filter is defined.
|
||||
*/
|
||||
public Predicate<? extends Statement> getFilter() {
|
||||
return filterProperty.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow user to specify a filter to apply on top of tracking point
|
||||
* decimation. If any, previous, configured filter is completely forgotten
|
||||
* after this call. To chain previously configured filter with your new one,
|
||||
* you can do something like :
|
||||
* {@code
|
||||
* final Predicate myFilter = createFilter(); // Prepare your stuff
|
||||
* final Predicate previous = processContext.getFilter();
|
||||
* processContext.setAdditionalFilter(previous.andThen(myFilter));
|
||||
* }
|
||||
*
|
||||
* @param filter Filter to configure for current processing context.
|
||||
*/
|
||||
public void setFilter(Predicate<? extends Statement> filter) {
|
||||
this.filterProperty.set(filter);
|
||||
}
|
||||
|
||||
public ObjectProperty<Predicate<? extends Statement>> filterProperty() {
|
||||
return filterProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* A listener which check added values for {@link #targetIndicators}. It
|
||||
* automatically remove indicators not compatible with source site.
|
||||
*
|
||||
* @param c
|
||||
*/
|
||||
private void indicatorsChanged(final SetChangeListener.Change<Indicator> c) {
|
||||
if (c.wasAdded() && !c.getElementAdded().getZoneTypeCodes().contains(getDataCtx().getSite().getZoneType())) {
|
||||
c.getSet().remove(c.getElementAdded());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger data refresh when filter property change. The process data will
|
||||
* be regenerated on next call to {@link #getData() }
|
||||
*
|
||||
* @param obs
|
||||
* @param oldFilter
|
||||
* @param newFilter
|
||||
*/
|
||||
private synchronized void filterChanged(final Observable obs) {
|
||||
processData = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.TrackingPoint;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Abstract {@link Index} implementation which contains a value for a given entity
|
||||
* (for instance a {@link TrackingPoint}) and references a specific {@link IndexSpi}.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*
|
||||
* @param <V> The type of index value.
|
||||
* @param <B> The type of the index base the index value is associated with (for instance, a {@link TrackingPoint}…).
|
||||
*/
|
||||
public abstract class AbstractParametrableIndex<V extends Number, B> implements Index<V> {
|
||||
|
||||
protected final V value;
|
||||
protected final IndexSpi<V, B> indexSpi;
|
||||
protected final B base;
|
||||
protected final Class<B> baseClass;
|
||||
|
||||
public AbstractParametrableIndex(final V value, final IndexSpi<V, B> indexSpi, final B base, final Class<B> baseClass){
|
||||
this.value = value;
|
||||
this.indexSpi = indexSpi;
|
||||
this.base = base;
|
||||
this.baseClass = baseClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public B getBase(){
|
||||
return base;
|
||||
}
|
||||
|
||||
public Class<B> getBaseClass(){return baseClass;}
|
||||
|
||||
@Override
|
||||
public abstract int getYear();
|
||||
|
||||
@Override
|
||||
public IndexSpi<V, B> getSpi() {
|
||||
return indexSpi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 83 * hash + this.getYear();
|
||||
hash = 83 * hash + Objects.hashCode(this.value);
|
||||
hash = 83 * hash + Objects.hashCode(this.indexSpi);
|
||||
hash = 83 * hash + Objects.hashCode(this.base);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final AbstractParametrableIndex<V, B> other = (AbstractParametrableIndex<V, B>) obj;
|
||||
if (this.getYear() != other.getYear()) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.value, other.value)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.indexSpi, other.indexSpi)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.base, other.base)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
/**
|
||||
* Complementary data computed from protocol data and indicator indices.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface AdditionalValue {
|
||||
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A service whose aim is to serialize / deserialize {@link AdditionalValue }
|
||||
* from file-system.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface AdditionalValueMapper {
|
||||
|
||||
/**
|
||||
* Read additional data contained in given folder, if any.
|
||||
*
|
||||
* @param folder The directory containing data to read.
|
||||
* @return Set of read values. Can be empty, but should not be null.
|
||||
* @throws java.io.IOException If values have been found, but an error
|
||||
* occurred while reading them.
|
||||
*/
|
||||
Set<AdditionalValue> readValues(final Path folder) throws IOException;
|
||||
|
||||
/**
|
||||
* Write a given set of {@link AdditionalValue} in a specific folder, if the
|
||||
* current service is designed to treat input data type. Do nothing
|
||||
* otherwise.
|
||||
*
|
||||
* @param folder To put data into.
|
||||
* @param toWrite Set of values to serialise.
|
||||
* @return True if current service is able to write input values (and has
|
||||
* succeeded in doing so). False otherwise.
|
||||
* @throws java.io.IOException If an error occurs while writing given
|
||||
* values.
|
||||
*/
|
||||
boolean writeValues(final Path folder, final Set<AdditionalValue> toWrite) throws IOException;
|
||||
}
|
||||
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
/**
|
||||
* POJO representing a result item in the dashboard table.
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public class DashboardResultItem {
|
||||
private int year;
|
||||
private String site;
|
||||
private String indicator;
|
||||
private Double value;
|
||||
private boolean published;
|
||||
|
||||
public DashboardResultItem() {
|
||||
}
|
||||
|
||||
public DashboardResultItem(int year, String site, String indicator, Double value, boolean published) {
|
||||
this.year = year;
|
||||
this.site = site;
|
||||
this.indicator = indicator;
|
||||
this.value = value;
|
||||
this.published = published;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public void setYear(int year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public String getSite() {
|
||||
return site;
|
||||
}
|
||||
|
||||
public void setSite(String site) {
|
||||
this.site = site;
|
||||
}
|
||||
|
||||
public String getIndicator() {
|
||||
return indicator;
|
||||
}
|
||||
|
||||
public void setIndicator(String indicator) {
|
||||
this.indicator = indicator;
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean isPublished() {
|
||||
return published;
|
||||
}
|
||||
|
||||
public void setPublished(boolean published) {
|
||||
this.published = published;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
DashboardResultItem that = (DashboardResultItem) o;
|
||||
|
||||
if (year != that.year) return false;
|
||||
if (!site.equals(that.site)) return false;
|
||||
return indicator.equals(that.indicator);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = year;
|
||||
result = 31 * result + site.hashCode();
|
||||
result = 31 * result + indicator.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
112
core/src/main/java/fr/cenra/rhomeo/api/result/DefaultIndex.java
Normal file
112
core/src/main/java/fr/cenra/rhomeo/api/result/DefaultIndex.java
Normal file
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* {@link Index} implementation which contains a value for a given year
|
||||
* and references a specific {@link IndexSpi}.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*
|
||||
* @param <V> The type of the {@link Index} value.
|
||||
*/
|
||||
public class DefaultIndex<V extends Number> implements Index<V> {
|
||||
|
||||
private final V value;
|
||||
private final int year;
|
||||
private final IndexSpi indexSpi;
|
||||
|
||||
/**
|
||||
* @param value
|
||||
* @param indexSpi
|
||||
* @param year
|
||||
*/
|
||||
public DefaultIndex(final V value, final IndexSpi<V, Integer> indexSpi, final int year){
|
||||
this.value = value;
|
||||
this.indexSpi = indexSpi;
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexSpi<V, Integer> getSpi() {
|
||||
return indexSpi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 83 * hash + this.year;
|
||||
hash = 83 * hash + Objects.hashCode(this.value);
|
||||
hash = 83 * hash + Objects.hashCode(this.indexSpi);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final DefaultIndex<?> other = (DefaultIndex<?>) obj;
|
||||
if (this.year != other.year) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.value, other.value)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.indexSpi, other.indexSpi);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.TrackingPoint;
|
||||
import java.util.Objects;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
|
||||
/**
|
||||
* Holds a value for a specific indicator, at a given tracking point.
|
||||
*
|
||||
* @param <V> The type of the {@link Index} value.
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class DefaultTrackingPointIndex<V extends Number> implements TrackingPointIndex<V> {
|
||||
|
||||
private final V value;
|
||||
private final TrackingPoint location;
|
||||
private final IndexSpi spi;
|
||||
|
||||
public DefaultTrackingPointIndex(final V value, final TrackingPoint location, final IndexSpi spi) {
|
||||
ArgumentChecks.ensureNonNull("Value", value);
|
||||
ArgumentChecks.ensureNonNull("Tracking point", location);
|
||||
ArgumentChecks.ensureNonNull("Index spi", spi);
|
||||
this.value = value;
|
||||
this.location = location;
|
||||
this.spi = spi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getYear() {
|
||||
return location.getYear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexSpi getSpi() {
|
||||
return spi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackingPoint getPoint() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 47 * hash + Objects.hashCode(this.value);
|
||||
hash = 47 * hash + Objects.hashCode(this.location);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (!TrackingPointIndex.class.isAssignableFrom(obj.getClass()))
|
||||
return false;
|
||||
|
||||
final TrackingPointIndex other = (TrackingPointIndex) obj;
|
||||
return Objects.equals(this.value, other.getValue())
|
||||
&& Objects.equals(this.location, other.getPoint());
|
||||
}
|
||||
}
|
||||
71
core/src/main/java/fr/cenra/rhomeo/api/result/Index.java
Normal file
71
core/src/main/java/fr/cenra/rhomeo/api/result/Index.java
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
import fr.cenra.rhomeo.api.process.Indicator;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* An index computed from an {@link Indicator}. Should be immutable, as it
|
||||
* describes a result of a finished process.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
* @param <T> Type of number value (double, int, etc.).
|
||||
*/
|
||||
public interface Index<T extends Number> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Computed value. Should never be null.
|
||||
*/
|
||||
T getValue();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The year for which this index is valid.
|
||||
*/
|
||||
int getYear();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Thee SPI associated with this value.
|
||||
*/
|
||||
@NotNull
|
||||
IndexSpi getSpi();
|
||||
}
|
||||
122
core/src/main/java/fr/cenra/rhomeo/api/result/IndexMapper.java
Normal file
122
core/src/main/java/fr/cenra/rhomeo/api/result/IndexMapper.java
Normal file
@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* An utility class to map association between instances from a given base
|
||||
* class and some indexed numeric values.
|
||||
*
|
||||
* The equality of two {@link IndexMapper} is based ont the equality of their
|
||||
* included "key" instances.
|
||||
*
|
||||
* @param <C> The type of the base class.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public class IndexMapper<C> {
|
||||
|
||||
private final ObjectProperty<C> keyProperty = new SimpleObjectProperty<>();
|
||||
|
||||
private final Map<String, ObjectProperty<Number>> map = new HashMap<>();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public IndexMapper(final C key){
|
||||
this.keyProperty.set(key);
|
||||
}
|
||||
|
||||
public C getKey(){return keyProperty.get();}
|
||||
|
||||
public ReadOnlyObjectProperty<C> keyProperty(){return keyProperty;}
|
||||
|
||||
public ReadOnlyObjectProperty valueProperty(final String k){return map.get(k);}
|
||||
|
||||
public void setValue(final String k, final Number v){
|
||||
if(valueProperty(k)==null){
|
||||
map.put(k, new SimpleObjectProperty<>());
|
||||
}
|
||||
map.get(k).set(v);
|
||||
}
|
||||
|
||||
public Collection<ObjectProperty<Number>> getValues() {
|
||||
return map.values();
|
||||
}
|
||||
|
||||
public Set<String> getValueAccessors(){
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 97 * hash + Objects.hashCode(this.keyProperty);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final IndexMapper<?> other = (IndexMapper<?>) obj;
|
||||
if (!Objects.equals(this.keyProperty, other.keyProperty)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
106
core/src/main/java/fr/cenra/rhomeo/api/result/IndexSpi.java
Normal file
106
core/src/main/java/fr/cenra/rhomeo/api/result/IndexSpi.java
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
import fr.cenra.rhomeo.api.IdentifiedObject;
|
||||
import fr.cenra.rhomeo.api.data.TrackingPoint;
|
||||
import fr.cenra.rhomeo.api.process.Indicator;
|
||||
import javax.measure.unit.Unit;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Describe a particular type of index, including its name, description, unit, etc.
|
||||
*
|
||||
* Note : Must be a Spring component
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*
|
||||
* @param <V> Type of index value
|
||||
* @param <B> Type of index base (Integer for a year, {@link TrackingPoint}…)
|
||||
*/
|
||||
public interface IndexSpi<V extends Number, B> extends IdentifiedObject, Comparable<IndexSpi> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The unit of this index value. Should never be null. If no unit is
|
||||
* defined for the value, {@link Unit#ONE} should be returned.
|
||||
*/
|
||||
@NotNull
|
||||
Unit<?> getUnit();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The indicator associated to this index.
|
||||
*/
|
||||
@NotNull
|
||||
Indicator getIndicator();
|
||||
|
||||
/**
|
||||
* Create an index initialized with given value.
|
||||
* @param value The value to set on created index.
|
||||
* @param entity The base the index is associated with. For instance an integer to represent a year, a {@link TrackingPoint}…
|
||||
* @return The created index.
|
||||
*/
|
||||
@NotNull
|
||||
Index<V> createIndex(final V value, final B entity);
|
||||
|
||||
/**
|
||||
* Denotes this index as a major indicator, or a minor indicator. It differs
|
||||
* from {@link Indicator#getDefaultIndex() } by the fact that multiple
|
||||
* indice types can be primary for an indicator, but only one is the default
|
||||
* index shown on dashboard.
|
||||
*
|
||||
* @return True if this spi indices are considered as main results for the
|
||||
* target indicator (see {@link #getIndicator() }. False if it describes a
|
||||
* complementary index.
|
||||
*/
|
||||
default boolean isPrimary() {
|
||||
return getName().equals(getIndicator().getDefaultIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
default int compareTo(IndexSpi o) {
|
||||
if (o == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (getIndicator() == o.getIndicator())? 0 :
|
||||
getIndicator() == null? 1 : getIndicator().compareTo(o.getIndicator());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* POJO regrouping indicator values for each year.
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public class IndicatorValuesByYearItem implements Comparable<IndicatorValuesByYearItem> {
|
||||
private final int year;
|
||||
|
||||
private final Map<String, PublishedValue> indicatorValues = new HashMap<>();
|
||||
|
||||
public IndicatorValuesByYearItem(final int year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value for the given indicator. May return {@code null} if not found.
|
||||
*
|
||||
* @param indicator Indicator name.
|
||||
* @return The value or {@code null} if not defined for this indicator
|
||||
*/
|
||||
public PublishedValue getValueForIndicator(final String indicator) {
|
||||
return indicatorValues.get(indicator);
|
||||
}
|
||||
|
||||
public void addValueForIndicator(final String indicator, final Double value, final boolean published) {
|
||||
indicatorValues.put(indicator, new PublishedValue(value, published));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(IndicatorValuesByYearItem o) {
|
||||
if (o == null) {
|
||||
return -1;
|
||||
}
|
||||
return year < o.getYear() ? -1 : year == o.getYear() ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find if the value for this indicator is published.
|
||||
*
|
||||
* @param indicatorName
|
||||
* @return True or false depending if the value has been published or not for this indicator,
|
||||
* or {@code null} if not defined for this indicator.
|
||||
*/
|
||||
public Boolean isPublished(final String indicatorName) {
|
||||
final PublishedValue pubVal = indicatorValues.get(indicatorName);
|
||||
if (pubVal == null) {
|
||||
return null;
|
||||
}
|
||||
return pubVal.published;
|
||||
}
|
||||
|
||||
public static final class PublishedValue {
|
||||
|
||||
private Double value;
|
||||
private boolean published;
|
||||
|
||||
PublishedValue(final Double value, final boolean published) {
|
||||
this.value = value;
|
||||
this.published = published;
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isPublished() {
|
||||
return published;
|
||||
}
|
||||
|
||||
public void setPublished(boolean published) {
|
||||
this.published = published;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.result;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.TrackingPoint;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Describe an index computed on a single {@link TrackingPoint}. Should be
|
||||
* immutable, as it describes a result of a finished process.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
* @param <T> Type of number value (double, int, etc.).
|
||||
*/
|
||||
public interface TrackingPointIndex<T extends Number> extends Index<T> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The point on which this index has been computed on.
|
||||
*/
|
||||
@NotNull
|
||||
TrackingPoint getPoint();
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.ui;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Protocol;
|
||||
import fr.cenra.rhomeo.api.result.AdditionalValue;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import javafx.scene.Node;
|
||||
|
||||
/**
|
||||
* An SPI providing view component to display a set of additional results.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface AdditionalResultSpi {
|
||||
|
||||
Protocol getProtocol();
|
||||
|
||||
Optional<Node> getResultNode(final Collection<AdditionalValue> values);
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.ui;
|
||||
|
||||
import fr.cenra.rhomeo.api.result.IndicatorValuesByYearItem;
|
||||
import java.util.Optional;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.control.TableView;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Describe a menu item which an be added to the context menu of the dashboard
|
||||
* result table.
|
||||
*
|
||||
* Note : implementations should be {@link Component}s. This way, the dashboard
|
||||
* will be able to inject all available items.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface DashboardMenuItem {
|
||||
|
||||
public Optional<MenuItem> createItem(final TableView<IndicatorValuesByYearItem> target);
|
||||
}
|
||||
58
core/src/main/java/fr/cenra/rhomeo/api/ui/FilterTable.java
Normal file
58
core/src/main/java/fr/cenra/rhomeo/api/ui/FilterTable.java
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.ui;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Statement;
|
||||
import java.util.function.Predicate;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.scene.control.TableView;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
* @param <T> Type of filter given by this component.
|
||||
*/
|
||||
public abstract class FilterTable<T extends Predicate> extends TableView<T> {
|
||||
|
||||
public abstract Predicate<? super Statement> getPreFilter();
|
||||
|
||||
public abstract void setPreFilter(final Predicate<Statement> filter);
|
||||
|
||||
public abstract ObjectProperty<Predicate<? super Statement>> preFilterProperty();
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.ui;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Protocol;
|
||||
import java.util.function.Predicate;
|
||||
import javafx.scene.control.TableView;
|
||||
|
||||
/**
|
||||
* A simple pojo capable to provide a {@link TableView} to display information
|
||||
* of filters o apply on a specific dataset.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface FilterTableSpi {
|
||||
|
||||
Protocol getProtocol();
|
||||
|
||||
FilterTable<Predicate> createEmptyTable();
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.ui;
|
||||
|
||||
import fr.cenra.rhomeo.api.preferences.PreferenceGroup;
|
||||
import javafx.scene.Node;
|
||||
|
||||
/**
|
||||
*
|
||||
* A simple interface which allows to discover JavaFX components able to edit
|
||||
* a specific {@link PreferenceGroup}.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
* @param <T>
|
||||
*/
|
||||
public interface PreferencePane<T> {
|
||||
|
||||
/**
|
||||
* Saves preferences edited by the pane.
|
||||
*/
|
||||
void save();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
PreferenceGroup<T> getPreferenceGroup();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The editor node to include in the scene.
|
||||
*/
|
||||
Node getEditor();
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.ui;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Protocol;
|
||||
import fr.cenra.rhomeo.core.WorkflowStep;
|
||||
import java.util.Set;
|
||||
import javafx.scene.Node;
|
||||
|
||||
/**
|
||||
* Define edition rules for a specific protocol. For example, it allows to
|
||||
* replace a {@link WorkflowStep} panel by one chosen here.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface ProtocolEditorSpi {
|
||||
|
||||
Protocol getProtocol();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param step The step user required to display.
|
||||
* @return A node allowing to edit protocol related data for the given step.
|
||||
* Can be null, in which case application considers it can use a default
|
||||
* editor.
|
||||
*/
|
||||
Node getEditor(final WorkflowStep step);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return A set of steps which must be ignored for given protocol. Can be
|
||||
* empty, but should never be null.
|
||||
*/
|
||||
Set<WorkflowStep> getStepsToIgnore();
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.ui;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Statement;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
/**
|
||||
* An editor created from {@link StatementEditorSpi#createEditor() }.
|
||||
* @author Alexis Manin (Geomatys)
|
||||
* @param <T> Manageable data type.
|
||||
*/
|
||||
public interface StatementEditor<T extends Statement> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Data type manageable by current editor.
|
||||
*/
|
||||
Class<T> getDataType();
|
||||
|
||||
/**
|
||||
* Asks the editor to focus on a particular item. Optionally, user can also
|
||||
* give a property name to focus on into input object.
|
||||
*
|
||||
* @param item The item to focus on in the editor.
|
||||
* @param propertyName If not null, this represents a property of the given
|
||||
* item to focus on.
|
||||
*/
|
||||
void focusOn(final T item, final String propertyName);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return List of items contained (to edit) in this component.
|
||||
*/
|
||||
ObservableList<T> getItems();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param items Configure this component to work with given set of items.
|
||||
*/
|
||||
void setItems(ObservableList<T> items);
|
||||
|
||||
ObjectProperty<ObservableList<T>> itemsProperty();
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.api.ui;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Statement;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* A provider which can return back an editor to fill objects of a specific type.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
* @param <T> Manageable data type.
|
||||
*/
|
||||
public interface StatementEditorSpi<T extends Statement> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return A new editor for data seizure. Never null.
|
||||
*/
|
||||
@NotNull
|
||||
StatementEditor<T> createEditor();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Data type manageable by current editor provider.
|
||||
*/
|
||||
@NotNull
|
||||
Class<T> getDataType();
|
||||
}
|
||||
98
core/src/main/java/fr/cenra/rhomeo/core/BeanUtils.java
Normal file
98
core/src/main/java/fr/cenra/rhomeo/core/BeanUtils.java
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core;
|
||||
|
||||
import org.geotoolkit.data.bean.BeanFeature;
|
||||
import org.geotoolkit.feature.type.FeatureType;
|
||||
import org.opengis.feature.Feature;
|
||||
import org.opengis.filter.identity.FeatureId;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class BeanUtils {
|
||||
|
||||
/**
|
||||
* Build a feature type corresponding to given bean class, i.e which reproduce
|
||||
* its properties.
|
||||
*
|
||||
* @param beanClass The class to build a feature type for.
|
||||
* @return A feature type to map pojo properties into {@link Feature} API.
|
||||
*/
|
||||
public static FeatureType createFeatureType(final Class beanClass) {
|
||||
return createMapping(beanClass).featureType;
|
||||
}
|
||||
|
||||
public static BeanFeature.Mapping createMapping(final Class beanClass) {
|
||||
return new Mapping(beanClass, "no namespace", null, null);
|
||||
}
|
||||
|
||||
public static BeanFeature.Mapping createMapping(final Class beanClass, final String namespace) {
|
||||
return new Mapping(beanClass, namespace, null, null);
|
||||
}
|
||||
|
||||
private static class Mapping extends BeanFeature.Mapping {
|
||||
|
||||
public Mapping(Class clazz, String namespace, CoordinateReferenceSystem crs, String idField) {
|
||||
super(clazz, namespace, crs, idField);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureId buildId(Object bean) {
|
||||
if (idAccessor == null) {
|
||||
return new FeatureId() {
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object o) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return super.buildId(bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
426
core/src/main/java/fr/cenra/rhomeo/core/CSVDecoder.java
Normal file
426
core/src/main/java/fr/cenra/rhomeo/core/CSVDecoder.java
Normal file
@ -0,0 +1,426 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.sis.util.Numbers;
|
||||
import org.apache.sis.util.ObjectConverter;
|
||||
import org.apache.sis.util.ObjectConverters;
|
||||
import org.geotoolkit.util.collection.CloseableIterator;
|
||||
|
||||
/**
|
||||
* Read a given CSV file, trying to create a list of pojo of the given type to hold
|
||||
* its data.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class CSVDecoder<T> extends CSVMapper<T> {
|
||||
|
||||
/**
|
||||
* At runtime, we detect doubled double-quote in escaped strings, to replace
|
||||
* them by single ones.
|
||||
*/
|
||||
static final Pattern DOUBLED_DOUBLE_QUOTE = Pattern.compile("\"\"");
|
||||
static final String DOUBLE_QUOTE_REPLACEMENT = "\"";
|
||||
|
||||
/**
|
||||
* Contains all cell value decoders. For each line read, we take each column
|
||||
* value, and give it to an appropriate converter which will put them into
|
||||
* the right properties of a target Pojo.
|
||||
*/
|
||||
private final BiConsumer<T, String>[] propertySetters;
|
||||
|
||||
/**
|
||||
* Create a new decoder whose aim is to read data hold by input file, and
|
||||
* return it as a list of pojos of the given type.
|
||||
* @param input The file to read. MUST BE READABLE
|
||||
* @param beanClass The class defining POJO object to use as data container.
|
||||
* @throws IOException If we cannot analyze input file header.
|
||||
* @throws IntrospectionException If we cannot analyze input pojo type.
|
||||
*/
|
||||
public CSVDecoder(Path input, Class<T> beanClass) throws IOException, IntrospectionException {
|
||||
this(input, beanClass, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new decoder whose aim is to read data hold by input file, and
|
||||
* return it as a list of pojos of the given type.
|
||||
* @param input The file to read. MUST BE READABLE
|
||||
* @param beanClass The class defining POJO object to use as data container.
|
||||
* to read.
|
||||
* @param fileEncoding Encoding to use for reading.
|
||||
* @throws IOException If we cannot analyze input file header.
|
||||
* @throws IntrospectionException If we cannot analyze input pojo type.
|
||||
*/
|
||||
public CSVDecoder(Path input, Class<T> beanClass, Charset fileEncoding) throws IOException, IntrospectionException {
|
||||
this(input, beanClass, fileEncoding, null);
|
||||
}
|
||||
|
||||
public CSVDecoder(Path input, Class<T> beanClass, Charset fileEncoding, Set<String> ignorableProperties) throws IOException, IntrospectionException {
|
||||
this(input, beanClass, null, fileEncoding, ignorableProperties);
|
||||
}
|
||||
|
||||
public CSVDecoder(Path input, Class<T> beanClass, final Character separator, final Charset fileEncoding, final Set<String> ignorableProperties) throws IOException, IntrospectionException {
|
||||
super(input, beanClass, separator, fileEncoding, ignorableProperties);
|
||||
|
||||
if (!Files.isReadable(input)) {
|
||||
throw new IOException("Given file is not readable : ".concat(input.toString()));
|
||||
}
|
||||
|
||||
/* Prepare data conversion. For each property present in input bean type,
|
||||
* we ensure that a read method is available. Then, we analyze its return
|
||||
* type. We try to find an appropriate converter to get a string
|
||||
* representation writable in CSV file.
|
||||
*/
|
||||
final PropertyDescriptor[] pDescriptors = beanInfo.getPropertyDescriptors();
|
||||
propertySetters = new BiConsumer[pDescriptors.length];
|
||||
for (int i = 0; i < pDescriptors.length; i++) {
|
||||
final PropertyDescriptor p = pDescriptors[i];
|
||||
final Method writeMethod = p.getWriteMethod();
|
||||
if (writeMethod == null)
|
||||
throw new IllegalArgumentException(
|
||||
new StringBuilder("Property ")
|
||||
.append(p.getName())
|
||||
.append(" from class ")
|
||||
.append(beanClass.getCanonicalName())
|
||||
.append("is not writable.")
|
||||
.toString());
|
||||
|
||||
writeMethod.setAccessible(true);
|
||||
final Class propertyType = p.getPropertyType();
|
||||
final Function<String, ?> conv = createPropertyConverter(propertyType);
|
||||
|
||||
final BiConsumer<T, Object> setter;
|
||||
setter = (pojo, value) -> {
|
||||
try {
|
||||
writeMethod.invoke(pojo, value);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RhomeoRuntimeException(e);
|
||||
}
|
||||
};
|
||||
|
||||
if (conv == null) {
|
||||
propertySetters[i] = (BiConsumer) setter;
|
||||
} else {
|
||||
propertySetters[i] = (pojo, strValue) -> setter.accept(pojo, conv.apply(strValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read given string (must be a line in the csv, not header) and map its
|
||||
* data into a POJO.
|
||||
*
|
||||
* @param line A line of the CSV file.
|
||||
* @param lineNumber Number of the read line. It serves to build error messages.
|
||||
* @return A Pojo containing line data. If input line is blank, a null value is returned.
|
||||
* @throws InstantiationException
|
||||
* @throws IllegalAccessException
|
||||
* @throws IOException
|
||||
*/
|
||||
private T decodeLine(final String line, int lineNumber) throws InstantiationException, IllegalAccessException, IOException {
|
||||
final List<CharBuffer> groups = splitByProperty(line);
|
||||
if (groups.isEmpty())
|
||||
return null;
|
||||
final T newInstance = dataType.newInstance();
|
||||
CharBuffer buffer;
|
||||
for (int i = 0; i < groups.size(); i++) {
|
||||
buffer = groups.get(i);
|
||||
try {
|
||||
if (buffer.hasRemaining() && propertyOrder[i] >= 0) {
|
||||
propertySetters[propertyOrder[i]].accept(newInstance, unescape(buffer));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throwWithDescription(lineNumber, i, buffer, e);
|
||||
}
|
||||
}
|
||||
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return A list of POJO, each one containing data of a line. Pojos are
|
||||
* sorted according to line number in the source file.
|
||||
*
|
||||
* @throws IOException Reading fails.
|
||||
* @throws InstantiationException Cannot create a new pojo (Mostly no default builder found).
|
||||
* @throws IllegalAccessException A property of the pojo type cannot be used by the decoder.
|
||||
*/
|
||||
public List<T> decode() throws IOException, InstantiationException, IllegalAccessException {
|
||||
try (final BufferedReader reader = Files.newBufferedReader(target, charset)) {
|
||||
// No data ...
|
||||
String line = reader.readLine();
|
||||
if (line == null) {
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
updatePropertyOrder(line);
|
||||
}
|
||||
|
||||
// Do not check header content. It has been done at built.
|
||||
final List<T> result = new ArrayList<>();
|
||||
int lineCount = 1;
|
||||
T read;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
read = decodeLine(line, lineCount++);
|
||||
if (read != null)
|
||||
result.add(read);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* /!\ You MUST CLOSE the iterator once you're done with it.
|
||||
* @return An iterator which will decode lines of the source file as we iterate
|
||||
* on them.
|
||||
*/
|
||||
public CloseableIterator<T> decodeLazy() {
|
||||
return new CloseableIterator<T>() {
|
||||
|
||||
BufferedReader fileReader;
|
||||
T next;
|
||||
int lineCount = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (next == null) {
|
||||
try {
|
||||
// first time, check header.
|
||||
if (fileReader == null) {
|
||||
fileReader = Files.newBufferedReader(target, charset);
|
||||
final String header = fileReader.readLine();
|
||||
lineCount++;
|
||||
// check header
|
||||
if (header == null)
|
||||
return false;
|
||||
else
|
||||
updatePropertyOrder(header);
|
||||
}
|
||||
|
||||
// read next line
|
||||
String line;
|
||||
while (next == null) {
|
||||
line = fileReader.readLine();
|
||||
if (line == null)
|
||||
break;
|
||||
next = decodeLine(line, ++lineCount);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RhomeoRuntimeException(e.getMessage(), e);
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "Cannot set output properties.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return next != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
if (next == null) {
|
||||
throw new IllegalStateException("No more element available !");
|
||||
}
|
||||
|
||||
try {
|
||||
return next;
|
||||
} finally {
|
||||
next = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (fileReader != null) {
|
||||
try {
|
||||
fileReader.close();
|
||||
} catch (IOException ex) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "A reader cannot be closed on file ".concat(target.toString()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze a line of input CSV file, and split its character by column. To
|
||||
* find columns, we search for separators which are not enclosed in an
|
||||
* escaped character sequence.
|
||||
*
|
||||
* NOTE : return char buffers are already trimmed, but are still escaped (if any).
|
||||
*
|
||||
* @param line input line to find property indices for.
|
||||
* @return A list of buffer. Each represents a part of the original string.
|
||||
* They're sorted by order of appearance in the input string.
|
||||
*/
|
||||
private List<CharBuffer> splitByProperty(final String line) {
|
||||
final CharBuffer cLine = CharBuffer.wrap(line);
|
||||
final ArrayList<CharBuffer> groups = new ArrayList<>();
|
||||
int lastGroup = cLine.position();
|
||||
boolean escapeMode = false;
|
||||
char c;
|
||||
for (int i = cLine.position(); i < cLine.limit(); i++) {
|
||||
c = cLine.get(i);
|
||||
if (c == '"') {
|
||||
escapeMode = !escapeMode;// If two double quotes follows, escape mode is reactivated.
|
||||
} else if (!escapeMode) {
|
||||
if (c == separator) {
|
||||
groups.add(cLine.subSequence(lastGroup, i));
|
||||
lastGroup = i + 1;
|
||||
} else if (Character.isWhitespace(c) && i == lastGroup) {
|
||||
lastGroup++; // remove trailing spaces
|
||||
} else if (c == COMMENT_CHAR) {
|
||||
break; // A comment have been found.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// last value on the line
|
||||
if (lastGroup < cLine.limit()) {
|
||||
groups.add(cLine.subSequence(lastGroup, cLine.remaining()));
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param input A char buffer representing one cell data.
|
||||
* @return A string which is the cell data, from which we remove trailing
|
||||
* double-quotes and doubled ones if needed.
|
||||
*/
|
||||
private String unescape(final CharBuffer input) {
|
||||
if (!input.hasRemaining()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (input.get(input.position()) == '"' && input.get(input.limit() -1) == '"') {
|
||||
if (input.remaining() < 3) // Empty escaped sequence.
|
||||
return "";
|
||||
return DOUBLED_DOUBLE_QUOTE.matcher(input.subSequence(1, input.remaining() -1)).replaceAll(DOUBLE_QUOTE_REPLACEMENT);
|
||||
}
|
||||
|
||||
return input.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for an appropriate converter between given type and string.
|
||||
*
|
||||
* Note : for numbers and primitives, we use direct conversion using wrapping
|
||||
* class utilities. We make a distinction between primitive and wrapping class
|
||||
* case, as the first one cannot hold null value information.
|
||||
*
|
||||
* @param inputType Type of object to convert.
|
||||
* @return A ready-to-use converter, or null if we do not need any.
|
||||
*/
|
||||
private Function<String, ?> createPropertyConverter(final Class inputType) {
|
||||
final Function<String, ?> result;
|
||||
if (CharSequence.class.isAssignableFrom(inputType)) {
|
||||
return null;
|
||||
// boolean
|
||||
} else if (Boolean.class.isAssignableFrom(inputType)) {
|
||||
result = input -> Boolean.valueOf(input);
|
||||
} else if (Boolean.TYPE.isAssignableFrom(inputType)) {
|
||||
result = input -> Boolean.parseBoolean(input);
|
||||
// character
|
||||
} else if (Character.class.isAssignableFrom(inputType)) {
|
||||
result = input -> input == null || input.isEmpty()? null : input.charAt(0);
|
||||
} else if (Character.TYPE.isAssignableFrom(inputType)) {
|
||||
result = input -> input == null || input.isEmpty()? '?' : input.charAt(0);
|
||||
// bytes
|
||||
} else if (Byte.class.isAssignableFrom(inputType)) {
|
||||
result = input -> Byte.valueOf(input);
|
||||
} else if (Byte.TYPE.isAssignableFrom(inputType)) {
|
||||
result = input -> input == null || input.isEmpty()? 0 : Byte.parseByte(input);
|
||||
// short
|
||||
} else if (Short.class.isAssignableFrom(inputType)) {
|
||||
result = input -> Short.valueOf(input);
|
||||
} else if (Short.TYPE.isAssignableFrom(inputType)) {
|
||||
result = input -> input == null || input.isEmpty()? 0 : Short.parseShort(input);
|
||||
// integer
|
||||
} else if (Integer.class.isAssignableFrom(inputType)) {
|
||||
result = input -> Integer.valueOf(input);
|
||||
} else if (Integer.TYPE.isAssignableFrom(inputType)) {
|
||||
result = input -> input == null || input.isEmpty()? 0 : Integer.parseInt(input);
|
||||
// long
|
||||
} else if (Long.class.isAssignableFrom(inputType)) {
|
||||
result = input -> Long.valueOf(input);
|
||||
} else if (Long.TYPE.isAssignableFrom(inputType)) {
|
||||
result = input -> input == null || input.isEmpty()? 0 : Long.parseLong(input);
|
||||
// float
|
||||
} else if (Float.class.isAssignableFrom(inputType)) {
|
||||
result = input -> Float.valueOf(input);
|
||||
} else if (Float.TYPE.isAssignableFrom(inputType)) {
|
||||
result = input -> input == null || input.isEmpty()? Float.NaN : Float.parseFloat(input);
|
||||
// double
|
||||
} else if (Double.class.isAssignableFrom(inputType)) {
|
||||
result = input -> Double.valueOf(input);
|
||||
} else if (Double.TYPE.isAssignableFrom(inputType)) {
|
||||
result = input -> input == null || input.isEmpty()? Double.NaN : Double.parseDouble(input);
|
||||
} else {
|
||||
final Class tmpClass = Numbers.primitiveToWrapper(inputType);
|
||||
final ObjectConverter<? super String, ?> sisConverter = ObjectConverters.find(String.class, tmpClass);
|
||||
result = input -> (input == null || input.isEmpty())? null : sisConverter.apply(input);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
298
core/src/main/java/fr/cenra/rhomeo/core/CSVEncoder.java
Normal file
298
core/src/main/java/fr/cenra/rhomeo/core/CSVEncoder.java
Normal file
@ -0,0 +1,298 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.sis.util.Numbers;
|
||||
import org.apache.sis.util.ObjectConverter;
|
||||
import org.apache.sis.util.ObjectConverters;
|
||||
|
||||
/**
|
||||
* Encode data holded by POJO of a specific type into a CSV file.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class CSVEncoder<T> extends CSVMapper<T> {
|
||||
|
||||
static final Pattern DOUBLE_QUOTE = Pattern.compile("\"");
|
||||
static final String DOUBLE_QUOTE_REPLACEMENT = "\"\"";
|
||||
|
||||
private final Function[] converters;
|
||||
|
||||
/**
|
||||
* Create a new encoder whose aim is to write pojo properties in the given file.
|
||||
* @param output The file to write. If not exists, we'll try to create it.
|
||||
* However, its parent directory MUST exist already.
|
||||
* @param beanClass The class defining POJO object we'll have to extract data from.
|
||||
* @throws IOException If we cannot create the file, or it already exists and we cannot analyze its header.
|
||||
* @throws IntrospectionException If we cannot analyze input pojo type.
|
||||
*/
|
||||
public CSVEncoder(Path output, Class<T> beanClass) throws IOException, IntrospectionException {
|
||||
this(output, beanClass, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new encoder whose aim is to write pojo preoprties in the given file.
|
||||
* @param output The file to write. If not exists, we'll try to create it.
|
||||
* However, its parent directory MUST exist already.
|
||||
* @param beanClass The class defining POJO object we'll have to extract data from.
|
||||
* to read.
|
||||
* @param fileEncoding Encoding to use for writing.
|
||||
* @throws IOException If we cannot create the file, or it already exists and we cannot analyze its header.
|
||||
* @throws IntrospectionException If we cannot analyze input pojo type.
|
||||
*/
|
||||
public CSVEncoder(Path output, Class<T> beanClass, Charset fileEncoding) throws IOException, IntrospectionException {
|
||||
this(output, beanClass, fileEncoding, null);
|
||||
}
|
||||
|
||||
public CSVEncoder(Path output, Class<T> beanClass, Charset fileEncoding, Set<String> ignorableProperties) throws IOException, IntrospectionException {
|
||||
this(output, beanClass, null, fileEncoding, ignorableProperties);
|
||||
}
|
||||
|
||||
public CSVEncoder(final Path output, final Class<T> beanClass, final Character separator, final Charset fileEncoding, final Set<String> ignorableProperties) throws IOException, IntrospectionException {
|
||||
super(output, beanClass, separator, fileEncoding, ignorableProperties);
|
||||
|
||||
/* Prepare data conversion. For each property present in input bean type,
|
||||
* we ensure that a read method is available. Then, we analyze its return
|
||||
* type. We try to find an appropriate converter to get a string
|
||||
* representation writable in CSV file.
|
||||
*/
|
||||
final PropertyDescriptor[] pDescriptors = beanInfo.getPropertyDescriptors();
|
||||
converters = new Function[pDescriptors.length];
|
||||
for (int i = 0 ; i < pDescriptors.length; i++) {
|
||||
final PropertyDescriptor p = pDescriptors[i];
|
||||
final Method readMethod = p.getReadMethod();
|
||||
if (readMethod == null)
|
||||
throw new IllegalArgumentException(
|
||||
new StringBuilder("Property ")
|
||||
.append(p.getName())
|
||||
.append(" from class ")
|
||||
.append(beanClass.getCanonicalName())
|
||||
.append("is not readable.")
|
||||
.toString());
|
||||
|
||||
readMethod.setAccessible(true);
|
||||
final Class returnType = readMethod.getReturnType();
|
||||
Function conv = createPropertyConverter(returnType);
|
||||
final Function getter = in -> {
|
||||
try {
|
||||
return readMethod.invoke(in);
|
||||
} catch (IllegalAccessException|InvocationTargetException e) {
|
||||
throw new RhomeoRuntimeException(e);
|
||||
}
|
||||
};
|
||||
|
||||
if (conv ==null) {
|
||||
converters[i] = getter;
|
||||
} else {
|
||||
converters[i] = getter.andThen(conv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create string representation of a given object.
|
||||
* @param data the object to encode in CSV.
|
||||
* @return A line to put in CSV file.
|
||||
*/
|
||||
private String encode(T data) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
Object value = getPropertyValue(data, 0);
|
||||
if (value != null) {
|
||||
builder.append(trimAndEscape(value));
|
||||
}
|
||||
|
||||
for (int i = 1; i < converters.length; i++) {
|
||||
builder.append(this.separator);
|
||||
value = getPropertyValue(data, i);
|
||||
if (value != null) {
|
||||
builder.append(trimAndEscape(value));
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract value of a property from input pojo, the one located on the given
|
||||
* column index in the file.
|
||||
* @param data The pojo to extract value from.
|
||||
* @param colIndex Index of the property to extract in target file columns.
|
||||
* @return The extracted value or a default one if input object property is
|
||||
* null or does not exists. Can return a null value.
|
||||
*/
|
||||
private Object getPropertyValue(final T data, final int colIndex) {
|
||||
Object value;
|
||||
final int pIndex = propertyOrder[colIndex];
|
||||
if (pIndex < 0)
|
||||
value = null;
|
||||
else
|
||||
value = converters[pIndex].apply(data);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data pointed by given iterator.
|
||||
* @param data An iterator which provides objects to write.
|
||||
* @param replaceExisting If true, data previously written will be erased.
|
||||
* Otherwise, we'll append data at the end of the file.
|
||||
* @throws IOException If an error occurs while writing data.
|
||||
*/
|
||||
public synchronized void encode(Iterator<T> data, final boolean replaceExisting) throws IOException {
|
||||
if (!Files.exists(target)) {
|
||||
Files.createFile(target);
|
||||
}
|
||||
|
||||
/* Check target file header. If we're in append mode, but no header exists,
|
||||
* we set a flag to ensure it will be created. If it is here but is not
|
||||
* compatible with our data type, we raise an exception.
|
||||
*/
|
||||
boolean emptyHeader = false;
|
||||
try (final BufferedReader reader = Files.newBufferedReader(target, charset)) {
|
||||
final String firstLine = reader.readLine();
|
||||
if (firstLine == null) {
|
||||
emptyHeader = true;
|
||||
} else if (!replaceExisting) {
|
||||
if (isValidHeader(firstLine)) {
|
||||
updatePropertyOrder(firstLine);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Given file already exists, but its header is not complient with given data type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(target, charset,
|
||||
StandardOpenOption.CREATE,
|
||||
replaceExisting ? StandardOpenOption.TRUNCATE_EXISTING : StandardOpenOption.APPEND)) {
|
||||
if (replaceExisting || emptyHeader) {
|
||||
writer.write(buildHeader());
|
||||
}
|
||||
while (data.hasNext()) {
|
||||
writer.newLine();
|
||||
writer.write(encode(data.next()));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data pointed by given collection.
|
||||
* @param data A collection which provides objects to write.
|
||||
* @param replaceExisting If true, data previously written will be erased.
|
||||
* Otherwise, we'll append data at the end of the file.
|
||||
* @throws IOException If an error occurs while writing data.
|
||||
*/
|
||||
public void encode(Iterable<T> data, final boolean replaceExisting) throws IOException {
|
||||
final Iterator<T> it = data.iterator();
|
||||
try {
|
||||
encode(it, replaceExisting);
|
||||
} finally {
|
||||
if (it instanceof AutoCloseable) {
|
||||
try {
|
||||
((AutoCloseable)it).close();
|
||||
} catch (Exception ex) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "Cannot close a resource !", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for an appropriate converter between given type and string.
|
||||
* @param <I> Type of object to convert.
|
||||
* @param inputType Type of object to convert.
|
||||
* @return A ready-to-use converter, or null if we don't need any.
|
||||
*/
|
||||
private <I> Function<I, String> createPropertyConverter(final Class<I> inputType) {
|
||||
final Function<I, String> result;
|
||||
if (inputType.isPrimitive()
|
||||
|| Number.class.isAssignableFrom(inputType)
|
||||
|| CharSequence.class.isAssignableFrom(inputType)
|
||||
|| Boolean.class.isAssignableFrom(inputType)) {
|
||||
result = null;
|
||||
|
||||
} else {
|
||||
final Class tmpClass = Numbers.primitiveToWrapper(inputType);
|
||||
ObjectConverter<? super I, ? extends String> sisConverter = ObjectConverters.find(tmpClass, String.class);
|
||||
result = input -> {
|
||||
return input == null? null : sisConverter.apply(input);
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze input string, and modify it if the CSV separator character is
|
||||
* found inside. First, we remove blank spaces at start and end of the
|
||||
* string. Then, we'll search for provided separator character. If we find
|
||||
* it, we escape the string using '"' character. If the string also contains
|
||||
* '"' characters, we double them.
|
||||
*
|
||||
* @param input String to analyze.
|
||||
* @return Input string if we don't have to escape it. A new one otherwise.
|
||||
*/
|
||||
private String trimAndEscape(final Object input) {
|
||||
String result = input.toString().trim();
|
||||
if (result.contains(String.valueOf(separator)) || result.contains(String.valueOf(COMMENT_CHAR))) {
|
||||
result = new StringBuilder(result.length() +2)
|
||||
.append('"')
|
||||
.append(DOUBLE_QUOTE.matcher(result).replaceAll(DOUBLE_QUOTE_REPLACEMENT))
|
||||
.append('"')
|
||||
.toString();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
286
core/src/main/java/fr/cenra/rhomeo/core/CSVMapper.java
Normal file
286
core/src/main/java/fr/cenra/rhomeo/core/CSVMapper.java
Normal file
@ -0,0 +1,286 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
|
||||
/**
|
||||
* TODO : Create a builder, to manage encoder / decoder creation.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
* @param <T> Type of java bean to map to the CSV file.
|
||||
*/
|
||||
public abstract class CSVMapper<T> {
|
||||
|
||||
public static final char COMMENT_CHAR = '#';
|
||||
public static final char DEFAULT_SEPARATOR = ';';
|
||||
|
||||
/**
|
||||
* Expected objects in input or output of the file.
|
||||
*/
|
||||
protected final Class<T> dataType;
|
||||
|
||||
/**
|
||||
* Information about {@link #dataType}.
|
||||
*/
|
||||
protected final BeanInfo beanInfo;
|
||||
|
||||
/**
|
||||
* Separator between columns.
|
||||
*/
|
||||
protected final char separator;
|
||||
|
||||
/**
|
||||
* Charset to use with given file.
|
||||
*/
|
||||
protected final Charset charset;
|
||||
|
||||
/**
|
||||
* Path to the CSV file to read or write.
|
||||
*/
|
||||
protected final Path target;
|
||||
|
||||
/**
|
||||
* For each column of the file, give the property index corresponding in
|
||||
* {@link #beanInfo}.
|
||||
*/
|
||||
protected int[] propertyOrder;
|
||||
|
||||
/**
|
||||
* List properties that can be missing in the read / written file.
|
||||
*/
|
||||
private final Set<String> ignorable;
|
||||
|
||||
protected CSVMapper(Path target, Class<T> beanClass, Character separator, Charset fileEncoding) throws IOException, IntrospectionException {
|
||||
this(target, beanClass, separator, fileEncoding, null);
|
||||
}
|
||||
|
||||
protected CSVMapper(Path target, Class<T> beanClass, Character separator, Charset fileEncoding, Set<String> ignorableProperties) throws IOException, IntrospectionException {
|
||||
ArgumentChecks.ensureNonNull("Output path", target);
|
||||
ArgumentChecks.ensureNonNull("Data type", beanClass);
|
||||
|
||||
if (ignorableProperties != null) {
|
||||
ignorable = Collections.unmodifiableSet(ignorableProperties);
|
||||
} else {
|
||||
ignorable = Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
// Check global information
|
||||
beanInfo = Introspector.getBeanInfo(beanClass, Object.class);
|
||||
this.dataType = beanClass;
|
||||
|
||||
this.separator = separator == null ? DEFAULT_SEPARATOR : separator;
|
||||
|
||||
charset = fileEncoding == null ? Charset.defaultCharset() : fileEncoding;
|
||||
|
||||
// If input file exists, we check its header is compatible with given data type.
|
||||
String firstLine;
|
||||
if (Files.isReadable(target)) {
|
||||
try (final BufferedReader reader = Files.newBufferedReader(target, charset)) {
|
||||
// We read lines until we find the first not empty / commented line.
|
||||
firstLine = reader.readLine();
|
||||
while (firstLine != null && ((firstLine = firstLine.trim()).isEmpty() || firstLine.charAt(0) == COMMENT_CHAR))
|
||||
firstLine = reader.readLine();
|
||||
|
||||
if (firstLine != null && !isValidHeader(firstLine)) {
|
||||
throw new IllegalArgumentException("L'entête du fichier n'est pas compatible avec le type de donnée associé.");
|
||||
}
|
||||
} catch (CharacterCodingException e) {
|
||||
throw new IllegalArgumentException("Le jeu de caractères du fichier est invalide. Attendu : ".concat(charset.displayName()));
|
||||
}
|
||||
} else if (Files.exists(target)) {
|
||||
throw new IllegalArgumentException("Le fichier source est illisible !");
|
||||
} else {
|
||||
firstLine = null;
|
||||
}
|
||||
|
||||
updatePropertyOrder(firstLine);
|
||||
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public Class<T> getDataType() {
|
||||
return dataType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a string displaying names of all properties (except the transient
|
||||
* and {@link Object} inherited ones) defined by given bean information.
|
||||
*
|
||||
* @return A string which is the list of found properties, splitted by a
|
||||
* given separator.
|
||||
*/
|
||||
public String buildHeader() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final PropertyDescriptor[] pDs = beanInfo.getPropertyDescriptors();
|
||||
|
||||
for (int i = 0; i < propertyOrder.length; i++) {
|
||||
final PropertyDescriptor p = pDs[propertyOrder[i]];
|
||||
// Ignore properties inherited from object.
|
||||
if (p.getReadMethod() == null || p.getReadMethod().getDeclaringClass().equals(Object.class))
|
||||
continue;
|
||||
builder.append(p.getName()).append(separator);
|
||||
}
|
||||
|
||||
return builder.substring(0, builder.length() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if given header lists all properties defined in given bean type.
|
||||
*
|
||||
* @param firstLine The header to check.
|
||||
* @return True if the file header describes the current reference type,
|
||||
* false otherwise.
|
||||
*/
|
||||
public final boolean isValidHeader(final String firstLine) {
|
||||
return isValidHeader(firstLine, separator, beanInfo, ignorable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if given header lists all properties defined in given bean type.
|
||||
*
|
||||
* @param firstLine The header to check.
|
||||
* @param separator The character which is used as separator between
|
||||
* columns.
|
||||
* @param beanInfo Bean information to check header against.
|
||||
* @return True if the file header describes the current reference type,
|
||||
* false otherwise.
|
||||
*/
|
||||
public static boolean isValidHeader(final String firstLine, final char separator, final BeanInfo beanInfo) {
|
||||
return isValidHeader(firstLine, separator, beanInfo, null);
|
||||
}
|
||||
|
||||
public static boolean isValidHeader(final String firstLine, final char separator, final BeanInfo beanInfo, final Set<String> ignorable) {
|
||||
|
||||
final String[] splitted = firstLine.split(new StringBuilder("\\s*").append(separator).append("\\s*").toString());
|
||||
final Set<String> headerNames = new HashSet<>(Arrays.asList(splitted));
|
||||
if (ignorable != null)
|
||||
headerNames.addAll(ignorable);
|
||||
|
||||
for (final PropertyDescriptor p : beanInfo.getPropertyDescriptors()) {
|
||||
// Ignore properties unreadable or inherited from object.
|
||||
if (p.getReadMethod() == null || p.getReadMethod().getDeclaringClass().equals(Object.class))
|
||||
continue;
|
||||
|
||||
if (!headerNames.remove(p.getName())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we arrive here, it means all mandatory properties have been found
|
||||
* in input header. If we're in read-only mode, we set it as valid,
|
||||
* because for columns not present in java model, we can ignore them.
|
||||
* On the contrary, if we must write into the file, we cannot allow
|
||||
* losing data contained in it, so we ensure each column of the header
|
||||
* can be bound to the java model.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Index property columns.
|
||||
*
|
||||
* @param header the header of the file.
|
||||
*/
|
||||
protected final void updatePropertyOrder(String header) {
|
||||
// No header. Natural order initialized.
|
||||
if (header == null) {
|
||||
propertyOrder = new int[beanInfo.getPropertyDescriptors().length];
|
||||
for (int i = 0; i < propertyOrder.length; i++) {
|
||||
propertyOrder[i] = i;
|
||||
}
|
||||
} else {
|
||||
final String[] splitted = header.split(new StringBuilder("\\s*").append(separator).append("\\s*").toString());
|
||||
propertyOrder = new int[splitted.length];
|
||||
Arrays.fill(propertyOrder, -1);
|
||||
final Map<String, Integer> columns = new HashMap<>(splitted.length);
|
||||
int i = 0;
|
||||
for (final String columnName : splitted) {
|
||||
columns.put(columnName, i++);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (final PropertyDescriptor p : beanInfo.getPropertyDescriptors()) {
|
||||
final Integer colIndex = columns.get(p.getName());
|
||||
if (colIndex != null)
|
||||
propertyOrder[colIndex] = i;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a new IOException whose message describe location (line, column) of
|
||||
* the error.
|
||||
*
|
||||
* @param line Number of the line where error happened. Must be > 0.
|
||||
* @param column Index of the field (not character column) on which error occurred. Must be > 0.
|
||||
* @param token The field value we failed against.
|
||||
* @param cause Original exception raised.
|
||||
* @throws IOException In all cases.
|
||||
*/
|
||||
protected static void throwWithDescription(final int line, int column, Object token, final Exception cause) throws IOException {
|
||||
final StringBuilder msg = new StringBuilder("Erreur : ");
|
||||
if (line > 0) {
|
||||
msg.append("ligne ").append(line).append(", ");
|
||||
}
|
||||
|
||||
if (column > 0) {
|
||||
msg.append("colonne ").append(column).append(", ");
|
||||
}
|
||||
msg.append("valeur ").append(token);
|
||||
throw new IOException(msg.toString(), cause);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class CSVMappingBuilder {
|
||||
|
||||
Path target;
|
||||
|
||||
Charset charset;
|
||||
|
||||
char separator = CSVMapper.DEFAULT_SEPARATOR;
|
||||
|
||||
public CSVMappingBuilder forPath(final Path target) {
|
||||
if (Files.isDirectory(target)) {
|
||||
throw new IllegalArgumentException("Provided path is a directory !");
|
||||
}
|
||||
|
||||
this.target = target;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CSVMappingBuilder withEncoding(final Charset charset) {
|
||||
this.charset = charset;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CSVMappingBuilder withSeparator(final char separator) {
|
||||
this.separator = separator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public <T> TypedCSVMappingBuilder<T> forType(final Class<T> dataType) {
|
||||
return new TypedCSVMappingBuilder<>(this, dataType);
|
||||
}
|
||||
}
|
||||
554
core/src/main/java/fr/cenra/rhomeo/core/RhomeoCore.java
Normal file
554
core/src/main/java/fr/cenra/rhomeo/core/RhomeoCore.java
Normal file
@ -0,0 +1,554 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import fr.cenra.rhomeo.api.Version;
|
||||
import fr.cenra.rhomeo.core.data.UpdateInfo;
|
||||
import fr.cenra.rhomeo.core.preferences.net.NetPreferences;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.sis.referencing.CRS;
|
||||
import org.apache.sis.util.logging.Logging;
|
||||
import org.geotoolkit.factory.Hints;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
import org.opengis.util.FactoryException;
|
||||
import fr.cenra.rhomeo.core.list.CodeValue;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.ParseException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.util.Callback;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
|
||||
/**
|
||||
* Regroups generic methods / constants used by the whole application.
|
||||
* JavaFX features should be deported to fr.cenra.rhomeo.Rhomeo class,
|
||||
* in the desktop module, not here.
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public class RhomeoCore {
|
||||
/**
|
||||
* Generic logger to use in the whole application.
|
||||
*/
|
||||
public static final Logger LOGGER = Logging.getLogger("fr.cenra.rhomeo");
|
||||
|
||||
/**
|
||||
* Title to display for all popups in the application.
|
||||
*/
|
||||
public static final String APPLICATION_TITLE = "Calculette RhoMeo";
|
||||
|
||||
/**
|
||||
* Application main folder, in the user home.
|
||||
*/
|
||||
public static final String NAME = "rhomeo";
|
||||
|
||||
/**
|
||||
* Key for the environment variable for the .rhomeo folder.
|
||||
*/
|
||||
public static final String ENV_RHOMEO_PATH_KEY = "rhomeo.path";
|
||||
|
||||
/**
|
||||
* Path for the configuration app main folder.
|
||||
*/
|
||||
public static final Path CONFIGURATION_PATH;
|
||||
static {
|
||||
final String rhomeoPath = System.getProperty(ENV_RHOMEO_PATH_KEY) != null ? System.getProperty(ENV_RHOMEO_PATH_KEY) : NAME;
|
||||
Path tmpPath = Paths.get(System.getProperty("user.home"), "."+ rhomeoPath);
|
||||
|
||||
if (!Files.isDirectory(tmpPath)) {
|
||||
try {
|
||||
Files.createDirectory(tmpPath);
|
||||
} catch (IOException ex) {
|
||||
try {
|
||||
tmpPath = Files.createTempDirectory(NAME);
|
||||
} catch (IOException ex1) {
|
||||
ex.addSuppressed(ex1);
|
||||
throw new ExceptionInInitializerError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
CONFIGURATION_PATH = tmpPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* System preference for the home directory of derby.
|
||||
*/
|
||||
public static final String DERBY_HOME_KEY = "derby.system.home";
|
||||
|
||||
/**
|
||||
* Spring application context path in the resources.
|
||||
*/
|
||||
public static final String SPRING_CONTEXT_XML = "/fr/cenra/rhomeo/spring/spring-context.xml";
|
||||
|
||||
/**
|
||||
* Path of the EPSG database.
|
||||
*/
|
||||
public static final Path EPSG_PATH = CONFIGURATION_PATH.resolve("EPSG");
|
||||
|
||||
/**
|
||||
* Path to the folder which will contain reference lists.
|
||||
*/
|
||||
public static final Path REFERENCE_PATH = CONFIGURATION_PATH.resolve("references");
|
||||
|
||||
/**
|
||||
* Path to the folder which will contain geographic reference datas.
|
||||
* Path content will look like :
|
||||
* ./site_id/dataname_year/*.shp
|
||||
*/
|
||||
public static final Path REFERENCIELS_GEO_PATH = CONFIGURATION_PATH.resolve("referential_geo");
|
||||
|
||||
/**
|
||||
* Sites folder and shp name.
|
||||
*/
|
||||
public static final String SITES = "sites";
|
||||
|
||||
/**
|
||||
* Path of the sites folder.
|
||||
*/
|
||||
public static final Path SITES_PATH = CONFIGURATION_PATH.resolve(SITES);
|
||||
|
||||
/**
|
||||
* Path of the sites folder.
|
||||
*/
|
||||
public static final Path SITES_SHP_PATH = SITES_PATH.resolve(SITES +".shp");
|
||||
|
||||
/**
|
||||
* Path of the CSV file for dashboard published results.
|
||||
*/
|
||||
public static final Path DASHBOARD_PUBLISHED_RESULTS = CONFIGURATION_PATH.resolve("dashboard_results.csv");
|
||||
|
||||
/**
|
||||
* Path of the JSON file for data contexts for sites / protocols.
|
||||
*/
|
||||
public static final Path DATA_CONTEXT_SITE_PATH = CONFIGURATION_PATH.resolve("data_contexts.json");
|
||||
|
||||
public static final Path RESULT_PATH = CONFIGURATION_PATH.resolve("results");
|
||||
/**
|
||||
* Path to the context restoration folder.
|
||||
*/
|
||||
public static final Path RESTORATION_FOLDER = CONFIGURATION_PATH.resolve("state");
|
||||
|
||||
/**
|
||||
* Number of millis for opening the connection before timeout.
|
||||
*/
|
||||
public static final int CONNECTION_TIMEOUT = 5000;
|
||||
|
||||
/**
|
||||
* Number of millis to wait after launching a timeout if no data has been transferred.
|
||||
*/
|
||||
public static final int READ_TIMEOUT = 20000;
|
||||
|
||||
private static CoordinateReferenceSystem SITES_CRS;
|
||||
private static final int SRID = 2154;
|
||||
|
||||
/**
|
||||
* Check for word character at the start of a text.
|
||||
*/
|
||||
public static final Pattern CODE_PATTERN = Pattern.compile("^[\\w\\.]+");
|
||||
|
||||
public enum FT_PROPERTIES {
|
||||
the_geom, NAME, COUNTY, ODONATE, ORTHOPTERE, REFERENT, ORG, TYPE, REMARKS
|
||||
}
|
||||
|
||||
/**
|
||||
* A regex to detect file extensions.
|
||||
*/
|
||||
public static final Pattern EXT_PATTERN = Pattern.compile("\\.\\w+$");
|
||||
|
||||
public static final DecimalFormat SIMPLE_DECIMAL_FORMAT = new DecimalFormat("0.##");
|
||||
public static final DecimalFormat SECOND_DECIMAL_FORMAT = new DecimalFormat("0.00");
|
||||
|
||||
/**
|
||||
* Initializes the EPSG database, generating it if not yet present on the computer.
|
||||
*
|
||||
* @throws FactoryException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void initEpsgDB() throws FactoryException, IOException {
|
||||
initEpsgDB(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize properties needed by EPSG database. If input boolean is true,
|
||||
* we'll fully load the database.
|
||||
*
|
||||
* @param checkInit Set to true if you want to ensure EPSG database is fully
|
||||
* initialized.
|
||||
*
|
||||
* @throws FactoryException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void initEpsgDB(final boolean checkInit) throws FactoryException, IOException {
|
||||
// create a database in user directory
|
||||
Files.createDirectories(RhomeoCore.EPSG_PATH);
|
||||
|
||||
// work in lazy mode, do your best for lenient datum shift
|
||||
Hints.putSystemDefault(Hints.LENIENT_DATUM_SHIFT, Boolean.TRUE);
|
||||
|
||||
String derbyProp = null;
|
||||
try {
|
||||
derbyProp = System.getProperty(DERBY_HOME_KEY);
|
||||
} finally {
|
||||
if (derbyProp == null) {
|
||||
System.setProperty(DERBY_HOME_KEY, EPSG_PATH.toAbsolutePath().toString());
|
||||
}
|
||||
}
|
||||
|
||||
// force loading epsg
|
||||
if (checkInit) {
|
||||
getSiteCRS();
|
||||
}
|
||||
}
|
||||
|
||||
public static CoordinateReferenceSystem getSiteCRS() throws FactoryException {
|
||||
if (SITES_CRS == null) {
|
||||
SITES_CRS = CRS.forCode("EPSG:"+ SRID);
|
||||
}
|
||||
|
||||
return SITES_CRS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current application version.
|
||||
*
|
||||
* @return The application version, may be empty or null if not found in the application packaging.
|
||||
*/
|
||||
public static String getVersion() {
|
||||
return RhomeoCore.class.getPackage().getImplementationVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the presence of a new update for the application.
|
||||
*
|
||||
* @return The new version to install if an update exists, {@code null} if no updates found
|
||||
* or no need to update.
|
||||
*/
|
||||
public static UpdateInfo existingUpdate() {
|
||||
final String version = getVersion();
|
||||
if (version == null || version.isEmpty()) {
|
||||
LOGGER.log(Level.INFO, "Invalid or not found version for this application");
|
||||
return null;
|
||||
}
|
||||
final Version localVersion = new Version(version);
|
||||
final NetPreferences netPrefs = new NetPreferences();
|
||||
final String updateUrl = netPrefs.getPreference(NetPreferences.UPDATE_URL);
|
||||
try (final InputStream stream = netPrefs.openConnection(netPrefs.getUpdateURL()).getInputStream()) {
|
||||
final UpdateInfo update = new ObjectMapper().readValue(stream, UpdateInfo.class);
|
||||
if (update.getVersion() != null && update.getVersion().compareTo(localVersion) > 0)
|
||||
return update;
|
||||
} catch (IOException|GeneralSecurityException e) {
|
||||
LOGGER.log(Level.WARNING, "Cannot access update service : ".concat(updateUrl), e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert byte number given in parameter in a human readable string. It tries
|
||||
* to fit the best unit. Ex : if you've got a number higher than a thousand,
|
||||
* input byte number will be expressed in kB. If you've got more than a million,
|
||||
* you've got it as MB
|
||||
* @param byteNumber Byte quantity to display
|
||||
* @return A string displaying byte number converted in fitting unit, along with unit symbol.
|
||||
*/
|
||||
public static String toReadableSize(final long byteNumber) {
|
||||
final NumberFormat format = NumberFormat.getNumberInstance();
|
||||
format.setMinimumFractionDigits(2);
|
||||
format.setMaximumFractionDigits(2);
|
||||
if (byteNumber < 0) {
|
||||
return "inconnu";
|
||||
} else if (byteNumber < 1e3) {
|
||||
return "" + byteNumber + " octets";
|
||||
} else if (byteNumber < 1e6) {
|
||||
return "" + format.format(byteNumber / 1e3) + " ko";
|
||||
} else if (byteNumber < 1e9) {
|
||||
return "" + format.format(byteNumber / 1e6) + " Mo";
|
||||
} else if (byteNumber < 1e12) {
|
||||
return "" + format.format(byteNumber / 1e9) + " Go";
|
||||
} else {
|
||||
return "" + (byteNumber / 1e12) + " To";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param first First string to test.
|
||||
* @param second Second string to test.
|
||||
* @return True if both strings are null or blank. False if at least one of
|
||||
* them contains something else than spaces.
|
||||
*/
|
||||
public static boolean bothEmpty(final String first, final String second) {
|
||||
return (first == null || first.trim().isEmpty()) && (second == null || second.trim().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param first First string to test.
|
||||
* @param second Second string to test.
|
||||
* @return True if both strings are equal or blank. False if one of them is
|
||||
* not blank, or they're not equal.
|
||||
*/
|
||||
public static boolean equivalent(final String first, final String second) {
|
||||
if (bothEmpty(first, second)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return first == null || second == null? false : first.equals(second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find an object of given type with the given code.
|
||||
* Note : Works only with enums.
|
||||
*
|
||||
* @param <T> Type of target coded list.
|
||||
* @param dataType Type of enum to search into
|
||||
* @param code Code of the object to return.
|
||||
* @return An object of the queried type with queried code, or nothing if we
|
||||
* cannot find any object matching.
|
||||
*/
|
||||
public static <T extends CodeValue> Optional<T> getByCode(final Class<T> dataType, Object code) {
|
||||
if (dataType.isEnum() && code != null) {
|
||||
for (final T candid : dataType.getEnumConstants()) {
|
||||
if (candid.getCode().equals(code)) {
|
||||
return Optional.of(candid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the quantile of a given data suite. For more details, see
|
||||
* https://en.wikipedia.org/wiki/Quantile
|
||||
*
|
||||
* Note : we differ from above wiki definition on even computing. Instead of
|
||||
* arbitrary ceiling computed position, we get the average of its two
|
||||
* ascending value in the data suite.
|
||||
*
|
||||
* @param data Data suite to find a quantile for. If input array is null or
|
||||
* empty, the method will miserably fail, so be careful.IMPORTANT : IT MUST
|
||||
* BE SORTED BY ASCENDING ORDER !
|
||||
* @param factor Quantile factor. It must be between 0 and 1 (otherwise, the
|
||||
* algorithm will end up very badly) representing which portion of the data
|
||||
* we want.
|
||||
* @return The queried quantile
|
||||
*/
|
||||
public static float quantile(final float[] data, final float factor) {
|
||||
final float position = (data.length -1) * factor;
|
||||
final double floor = StrictMath.floor(position);
|
||||
final int floorInt = (int)floor;
|
||||
if (position == floor) {
|
||||
// We take directly the pointed value.
|
||||
return data[floorInt];
|
||||
}
|
||||
|
||||
final double ratio = position - floor;
|
||||
final double extraValue = (data[floorInt + 1] - data[floorInt]) * ratio;
|
||||
|
||||
return (float) (data[floorInt] + extraValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the quantile of a given data suite. For more details, see
|
||||
* https://en.wikipedia.org/wiki/Quantile
|
||||
*
|
||||
* Note : we differ from above wiki definition on even computing. Instead of
|
||||
* arbitrary ceiling computed position, we get the average of its two
|
||||
* ascending value in the data suite.
|
||||
*
|
||||
* @param data Data suite to find a quantile for. If input array is null or
|
||||
* empty, the method will miserably fail, so be careful.IMPORTANT : IT MUST
|
||||
* BE SORTED BY ASCENDING ORDER !
|
||||
* @param factor Quantile factor. It must be between 0 and 1 (otherwise, the
|
||||
* algorithm will end up very badly) representing which portion of the data
|
||||
* we want.
|
||||
* @return The queried quantile
|
||||
*/
|
||||
public static double quantile(final double[] data, final float factor) {
|
||||
final float position = (data.length -1) * factor;
|
||||
final double floor = StrictMath.floor(position);
|
||||
final int floorInt = (int) floor;
|
||||
if (position == floor) {
|
||||
// We take directly the pointed value.
|
||||
return data[floorInt];
|
||||
}
|
||||
|
||||
final double ratio = position - floor;
|
||||
final double extraValue = (data[floorInt + 1] - data[floorInt]) * ratio;
|
||||
|
||||
return data[floorInt] + extraValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new file system, allowing to view the content of a zip file as
|
||||
* a file system.
|
||||
* /!\ Close the returned {@link FileSystem} once you're done with it !
|
||||
*
|
||||
* @param zipPath A path pointing on a zip file. If it does not exist, it
|
||||
* will be created.
|
||||
* @return A file system pointing on given zip file.
|
||||
* @throws URISyntaxException If we cannot create a valid URI from given
|
||||
* path.
|
||||
* @throws IOException If the file occurs while accessing zip file.
|
||||
*/
|
||||
public static FileSystem toZipFileSystem(final Path zipPath) throws URISyntaxException, IOException {
|
||||
// Don't call FileSystems.newFileSystems(URI, Map), because of a bug which
|
||||
// encode twice URIs in jar file system : https://bugs.openjdk.java.net/browse/JDK-8131067
|
||||
final List<FileSystemProvider> installedProviders = FileSystemProvider.installedProviders();
|
||||
for (final FileSystemProvider fsp : installedProviders) {
|
||||
if ("jar".equals(fsp.getScheme())) {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put("encoding", StandardCharsets.UTF_8.name());
|
||||
properties.put("create", "true");
|
||||
return fsp.newFileSystem(zipPath, properties);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IOException("No file system found for ZIP encoding.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure input dates are either strictly equals, or represent the same moment.
|
||||
* @param first
|
||||
* @param second
|
||||
* @return True if the 2 dates are same reference, or respect {@link LocalDate#isEqual(java.time.chrono.ChronoLocalDate) }.
|
||||
*/
|
||||
public static boolean checkEquality(final LocalDate first, final LocalDate second) {
|
||||
return first == second || first != null && second != null && first.isEqual(second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write given local date into the specified object output. If input is null,
|
||||
* a special flag is written, so a null value will be returned by {@link #readDate(java.io.ObjectInput) }.
|
||||
* @param toWrite Local date to serialize.
|
||||
* @param destination Output to write into.
|
||||
* @throws IOException If an error occcurs while writing in output stream.
|
||||
*/
|
||||
public static void writeDate(final LocalDate toWrite, final ObjectOutput destination) throws IOException {
|
||||
if (toWrite == null) {
|
||||
destination.writeBoolean(true);
|
||||
} else {
|
||||
destination.writeBoolean(false);
|
||||
destination.writeShort(toWrite.getYear());
|
||||
destination.write(toWrite.getMonthValue());
|
||||
destination.write(toWrite.getDayOfMonth());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read date contained in given source at current position.
|
||||
* IMPORTANT : Only read dates written using {@link #writeDate(java.time.LocalDate, java.io.ObjectOutput) }
|
||||
* method.
|
||||
* @param source Object stream to read from.
|
||||
* @return Read date, or null.
|
||||
* @throws IOException
|
||||
*/
|
||||
public static LocalDate readDate(final ObjectInput source) throws IOException {
|
||||
if (source.readBoolean())
|
||||
return null;
|
||||
return LocalDate.of(source.readShort(), source.readByte(), source.readByte());
|
||||
}
|
||||
|
||||
public static final Callback ROUNDING_CELL_FACTORY = value -> {
|
||||
return new TableCell<Object, Number>() {
|
||||
@Override
|
||||
protected void updateItem(Number item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (empty || item == null) {
|
||||
setText(null);
|
||||
} else {
|
||||
setText(SIMPLE_DECIMAL_FORMAT.format(item));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
public static final StringConverter DOUBLE_CONVERTER = new StringConverter<Double>() {
|
||||
@Override
|
||||
public String toString(Double object) {
|
||||
if (object == null)
|
||||
return "";
|
||||
else
|
||||
return SECOND_DECIMAL_FORMAT.format(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double fromString(String string) {
|
||||
if (string == null || (string = string.trim()).isEmpty()) {
|
||||
return 0d;
|
||||
} else
|
||||
try {
|
||||
return SECOND_DECIMAL_FORMAT.parse(string).doubleValue();
|
||||
} catch (ParseException ex) {
|
||||
try {
|
||||
return Double.valueOf(string);
|
||||
} catch (Exception ex2) {
|
||||
ex.addSuppressed(ex2);
|
||||
RhomeoCore.LOGGER.log(Level.FINE, "Unconvertible string.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return 0d;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core;
|
||||
|
||||
/**
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public class RhomeoRuntimeException extends RuntimeException {
|
||||
public RhomeoRuntimeException() {}
|
||||
|
||||
public RhomeoRuntimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RhomeoRuntimeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public RhomeoRuntimeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
533
core/src/main/java/fr/cenra/rhomeo/core/Session.java
Normal file
533
core/src/main/java/fr/cenra/rhomeo/core/Session.java
Normal file
@ -0,0 +1,533 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core;
|
||||
|
||||
import fr.cenra.rhomeo.api.Version;
|
||||
import fr.cenra.rhomeo.api.data.DataContext;
|
||||
import fr.cenra.rhomeo.api.data.Dataset;
|
||||
import fr.cenra.rhomeo.api.data.ObjectWrapper;
|
||||
import fr.cenra.rhomeo.api.data.Protocol;
|
||||
import fr.cenra.rhomeo.api.data.Reference;
|
||||
import fr.cenra.rhomeo.api.data.ReferenceDescription;
|
||||
import fr.cenra.rhomeo.api.data.Site;
|
||||
import fr.cenra.rhomeo.api.data.Statement;
|
||||
import fr.cenra.rhomeo.api.process.ProcessContext;
|
||||
import fr.cenra.rhomeo.api.result.Index;
|
||||
import fr.cenra.rhomeo.api.ui.StatementEditor;
|
||||
import fr.cenra.rhomeo.api.process.Indicator;
|
||||
import fr.cenra.rhomeo.api.result.AdditionalValue;
|
||||
import fr.cenra.rhomeo.api.ui.StatementEditorSpi;
|
||||
import fr.cenra.rhomeo.core.data.DashboardResultsManager;
|
||||
import fr.cenra.rhomeo.core.data.DataContextManager;
|
||||
import fr.cenra.rhomeo.core.data.ReferenceManager;
|
||||
import fr.cenra.rhomeo.core.preferences.ftp.FTPPreferences;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
import java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import fr.cenra.rhomeo.core.util.SerializableDataContext;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Represents the application session for a user.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public class Session implements ApplicationContextAware {
|
||||
|
||||
private static Session INSTANCE;
|
||||
private ApplicationContext ctx;
|
||||
|
||||
private Dataset dataset;
|
||||
private DataContext dataContext;
|
||||
private ProcessContext processContext;
|
||||
private Set<Index> results;
|
||||
private final Set<AdditionalValue> additionalValues = new HashSet<>();
|
||||
|
||||
@Autowired
|
||||
private List<Protocol> protocols;
|
||||
|
||||
@Autowired
|
||||
private List<Indicator> indicators;
|
||||
|
||||
@Autowired
|
||||
private DataContextManager contextManager;
|
||||
|
||||
@Autowired
|
||||
private DashboardResultsManager resultsManager;
|
||||
|
||||
private final ReadOnlyObjectWrapper<WorkflowStep> workflowStep = new ReadOnlyObjectWrapper<>();
|
||||
|
||||
public static Session getInstance() throws IllegalStateException {
|
||||
if (INSTANCE == null) {
|
||||
throw new IllegalStateException("Application context not initialized !");
|
||||
}
|
||||
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
if (applicationContext != null) {
|
||||
ctx = applicationContext;
|
||||
INSTANCE = this;
|
||||
} else {
|
||||
INSTANCE = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the session, releasing all resources.
|
||||
*/
|
||||
public void close() {
|
||||
if (ctx instanceof AbstractApplicationContext) {
|
||||
((AbstractApplicationContext)ctx).close();
|
||||
}
|
||||
|
||||
INSTANCE = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to create a new instance for given bean name.
|
||||
*
|
||||
* @param <T> Type of the wanted bean.
|
||||
* @param qualifier Name of the wanted prototype.
|
||||
* @param beanClass The class to use to create Spring prototype.
|
||||
* @return A new bean corresponding to the prototype registered for given qualifier.
|
||||
* @throws IllegalArgumentException If given bean definition is not a prototype.
|
||||
*/
|
||||
public <T> T createPrototype(final String qualifier, final Class<T> beanClass) throws IllegalArgumentException {
|
||||
if (ctx.getAutowireCapableBeanFactory().isPrototype(qualifier)) {
|
||||
return ctx.getBean(qualifier, beanClass);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Given qualifier does not represent a prototype object !");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to create a new instance for given bean name.
|
||||
*
|
||||
* @param qualifier Name of the wanted prototype.
|
||||
* @return A new bean corresponding to the prototype registered for given qualifier.
|
||||
* @throws IllegalArgumentException If given bean definition is not a prototype.
|
||||
*/
|
||||
public Object createPrototype(final String qualifier) throws IllegalArgumentException {
|
||||
if (ctx.getAutowireCapableBeanFactory().isPrototype(qualifier)) {
|
||||
return ctx.getBean(qualifier);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Given qualifier does not represent a prototype object !");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to create a new instance of given type.
|
||||
*
|
||||
* @param <T> Type of the wanted bean.
|
||||
* @param beanClass The class to use to find Spring prototype definition.
|
||||
* @param constructorArgs Possible list of constructor arguments for the requiered prototype.
|
||||
* @return A new bean of given type.
|
||||
* @throws IllegalArgumentException If given bean definition is not a prototype.
|
||||
*/
|
||||
public <T> T createPrototype(final Class<T> beanClass, final Object... constructorArgs) throws BeansException {
|
||||
return ctx.getBean(beanClass, constructorArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new connection over the FTP service providing {@link Reference}
|
||||
* data. The provided {@link FTPClient} must be closed using {@link FTPClient#disconnect() }
|
||||
* once you've finished your work.
|
||||
*
|
||||
* @return A client to exchange data with FTP service which contains reference files.
|
||||
*
|
||||
* @throws IOException If we cannot connect to distant service.
|
||||
* @throws java.security.GeneralSecurityException If an authentication is
|
||||
* required, but we cannot access to password.
|
||||
*/
|
||||
@NotNull
|
||||
public FTPClient connectReferenceFTP() throws IOException, GeneralSecurityException {
|
||||
return ctx.getBean(FTPPreferences.class).getAccess(FTPPreferences.ACCESS_POINTS.REFERENCES).createClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new connection over the FTP service providing result data.
|
||||
* data. The provided {@link FTPClient} must be closed using {@link FTPClient#disconnect() }
|
||||
* once you've finished your work.
|
||||
*
|
||||
* @return A client to exchange data with FTP service which contains result files.
|
||||
*
|
||||
* @throws UnknownHostException If we cannot connect to distant service.
|
||||
* @throws java.security.GeneralSecurityException If an authentication is
|
||||
* required, but we cannot access to password.
|
||||
*/
|
||||
@NotNull
|
||||
public FTPClient connectResultFTP() throws IOException, GeneralSecurityException {
|
||||
return ctx.getBean(FTPPreferences.class).getAccess(FTPPreferences.ACCESS_POINTS.RESULTS).createClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a singleton or prototype for the given class.
|
||||
*
|
||||
* @param <T> Type of the wanted bean.
|
||||
* @param beanClass The class to use to find Spring prototype definition.
|
||||
* @return A new bean of given type.
|
||||
*/
|
||||
public <T> T getBean(final Class<T> beanClass) {
|
||||
return ctx.getBean(beanClass);
|
||||
}
|
||||
/**
|
||||
* Try to find a singleton or prototype for the given class.
|
||||
*
|
||||
* @param beanName The name of a bean to find Spring prototype definition.
|
||||
* @return A new bean of given type.
|
||||
*/
|
||||
public Object getBean(final String beanName) {
|
||||
return ctx.getBean(beanName);
|
||||
}
|
||||
|
||||
|
||||
public DataContext getDataContext() {
|
||||
return dataContext;
|
||||
}
|
||||
|
||||
public Dataset getDataset() {
|
||||
return dataset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a new edition context for given site and protocol.
|
||||
*
|
||||
* /!\ Use with care ! Any call to this method will reset previously seized
|
||||
* data.
|
||||
*
|
||||
* @param site The site to start edition for.
|
||||
* @param protocol The protocol defining data type to seize.
|
||||
*/
|
||||
public void startEdition(final Site site, final Protocol protocol) {
|
||||
ArgumentChecks.ensureNonNull("Site", site);
|
||||
ArgumentChecks.ensureNonNull("Protocol", protocol);
|
||||
if (!protocol.isCompatible(site)) {
|
||||
throw new IllegalArgumentException("Target site is not compatible with chosen protocol !");
|
||||
}
|
||||
|
||||
final SerializableDataContext srDataContext;
|
||||
try {
|
||||
srDataContext = contextManager.loadContext(site, protocol);
|
||||
} catch (IOException ex) {
|
||||
throw new RhomeoRuntimeException(ex);
|
||||
}
|
||||
|
||||
if (srDataContext != null) {
|
||||
final DataContext context = srDataContext.toDataContext(this);
|
||||
if (context != null) {
|
||||
this.dataContext = context;
|
||||
} else {
|
||||
this.dataContext = new DataContext(site, protocol);
|
||||
}
|
||||
} else {
|
||||
this.dataContext = new DataContext(site, protocol);
|
||||
}
|
||||
|
||||
// Now that we've got the data context, we'll check that its reference
|
||||
// versions are installed. If not, we'll remove them from data context.
|
||||
checkDataContext(dataContext);
|
||||
|
||||
this.dataset = new Dataset(protocol);
|
||||
}
|
||||
|
||||
private static void checkDataContext(final DataContext ctx) {
|
||||
for (final ReferenceDescription description : ctx.getProtocol().getReferenceTypes()) {
|
||||
final ReferenceManager manager;
|
||||
try {
|
||||
manager = ReferenceManager.getOrCreate(description);
|
||||
} catch (IntrospectionException ex) {
|
||||
throw new RhomeoRuntimeException(ex);
|
||||
}
|
||||
if (!manager.getInstalledVersions().contains(ctx.getReferences().get(description.getReferenceType()))) {
|
||||
ctx.getReferences().remove(description.getReferenceType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A site name has been updated so update this old name in all serialized files
|
||||
* working on the old name.
|
||||
*
|
||||
* @param site New site containing new name.
|
||||
* @param oldName Old site name.
|
||||
*/
|
||||
public void serializeUpdateSiteName(Site site, String oldName) throws IOException, IntrospectionException, ReflectiveOperationException {
|
||||
resultsManager.updateDashboardResultsSiteName(site, oldName);
|
||||
contextManager.updateReferencesSiteName(oldName, site.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* A site has been deleted so delete all references of this site name in previously
|
||||
* serialized files for this site.
|
||||
*
|
||||
* @param siteName
|
||||
*/
|
||||
public void serializeDeleteSite(final String siteName) throws IOException, IntrospectionException, ReflectiveOperationException {
|
||||
resultsManager.removeDashboardResultsForSite(siteName);
|
||||
contextManager.removeReferencesForSite(siteName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get results for the current {@linkplain DataContext data context}.
|
||||
*
|
||||
* @return A set of results, may be {@code null} or empty.
|
||||
*/
|
||||
public Set<Index> getResults() {
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set results for the current {@linkplain DataContext data context}.
|
||||
*
|
||||
* @param results a set of results.
|
||||
*/
|
||||
public void setResults(final Set<Index> results) {
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
public Set<AdditionalValue> getAdditionalValues() {
|
||||
return additionalValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the process context.
|
||||
*
|
||||
* @return process context, may be {@code null}.
|
||||
*/
|
||||
public ProcessContext getProcessContext() {
|
||||
return processContext;
|
||||
}
|
||||
|
||||
public void setProcessContext(ProcessContext processContext) {
|
||||
this.processContext = processContext;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Observable property describing current application state.
|
||||
*/
|
||||
public ReadOnlyObjectProperty<WorkflowStep> workflowStepProperty() {
|
||||
return workflowStep.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return application current working step. If null, it means application is
|
||||
* waiting for the user to choose a protocol to operate on.
|
||||
*/
|
||||
public WorkflowStep getWorkflowStep() {
|
||||
return workflowStep.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request application to focus on given workflow step. This method will
|
||||
* first ensure that all needed data can be found. If not, the step is left
|
||||
* unchanged.
|
||||
*
|
||||
* @param newStep The step we want to go to.
|
||||
* @return True if session succeeded to update the application mode. False
|
||||
* if it cannot perform queried operation (due to missing data).
|
||||
*/
|
||||
public boolean requestWorkflowStep(final WorkflowStep newStep) {
|
||||
if (newStep == null) {
|
||||
clearWorkflow();
|
||||
|
||||
} else {
|
||||
switch (newStep) {
|
||||
case DATASET:
|
||||
if (dataContext != null)
|
||||
workflowStep.set(newStep);
|
||||
break;
|
||||
case PROCESS:
|
||||
if (processContext != null && dataContext != null) {
|
||||
checkDataContext(dataContext);
|
||||
if (dataContext.getReferences().size() >= dataContext.getProtocol().getReferenceTypes().size()) {
|
||||
workflowStep.set(newStep);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RESULT:
|
||||
case FINALIZATION:
|
||||
if (results != null)
|
||||
workflowStep.set(newStep);
|
||||
}
|
||||
}
|
||||
|
||||
return newStep == workflowStep.get();
|
||||
}
|
||||
|
||||
private void clearWorkflow() {
|
||||
dataContext = null;
|
||||
dataset = null;
|
||||
processContext = null;
|
||||
results = null;
|
||||
additionalValues.clear();
|
||||
|
||||
workflowStep.set(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all protocols found.
|
||||
*
|
||||
* @return All protocols.
|
||||
*/
|
||||
public List<Protocol> getProtocols() {
|
||||
return protocols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all indicators found.
|
||||
*
|
||||
* @return All indicators.
|
||||
*/
|
||||
public List<Indicator> getIndicators() {
|
||||
return indicators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the description object corresponding to given {@link Reference} class.
|
||||
* @param <T> Type of reference to get a description for.
|
||||
* @param refType Type of reference to get a description for.
|
||||
* @return Description object for requested reference class.
|
||||
*/
|
||||
public <T extends Reference> ReferenceDescription<T> getDescription(final Class<T> refType) {
|
||||
final Map<String, ReferenceDescription> beans = ctx.getBeansOfType(ReferenceDescription.class);
|
||||
for (final ReferenceDescription desc : beans.values()) {
|
||||
if (desc.getReferenceType().equals(refType)) {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze the given object, and inject autowired fields according to the
|
||||
* current application context content.
|
||||
* @param o The object to inject dependencies into.
|
||||
*/
|
||||
public void injectDependencies(Object o) {
|
||||
ctx.getAutowireCapableBeanFactory().autowireBean(o);
|
||||
}
|
||||
|
||||
public Optional<StatementEditor> findEditor(Class<? extends Statement> dataType) {
|
||||
ArgumentChecks.ensureNonNull("Data type", dataType);
|
||||
final Map<String, StatementEditorSpi> beans = ctx.getBeansOfType(StatementEditorSpi.class);
|
||||
StatementEditorSpi fallback = null;
|
||||
Class<? extends Statement> editorType;
|
||||
for (final StatementEditorSpi spi : beans.values()) {
|
||||
editorType = spi.getDataType();
|
||||
if (dataType.equals(editorType)) {
|
||||
return Optional.of(spi.createEditor());
|
||||
} else if (editorType.isAssignableFrom(dataType)) {
|
||||
if (fallback == null || fallback.getDataType().isAssignableFrom(editorType)) {
|
||||
fallback = spi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fallback == null? Optional.empty() : Optional.of(fallback.createEditor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return the first found wrapper for given data type, if any.
|
||||
*
|
||||
* @param <T> Data type to wrap.
|
||||
* @param dataType The type we want to export.
|
||||
* @return First found wrapper for input class, or an empty optional if no
|
||||
* wrapper can be found.
|
||||
*/
|
||||
public <T> Optional<ObjectWrapper<T, ?>> getWrapper(final Class<T> dataType) {
|
||||
if (dataType == null)
|
||||
return Optional.empty();
|
||||
final Map<String, ObjectWrapper> beans = ctx.getBeansOfType(ObjectWrapper.class);
|
||||
for (final ObjectWrapper wrapper : beans.values()) {
|
||||
if (wrapper.getInputType().equals(dataType))
|
||||
return Optional.of(wrapper);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new map whose keys are description for given reference type.
|
||||
* Values are not changed.
|
||||
*
|
||||
* We need this to convert reference versions provided by data context into
|
||||
* something usable for metadata export.
|
||||
*
|
||||
* @param input The map to get values and keys to transform from.
|
||||
* @return Copy of input map, with transformed keys.
|
||||
*/
|
||||
public Map<ReferenceDescription, Version> transform(final Map<Class<Reference>, Version> input) {
|
||||
if (input == null || input.isEmpty())
|
||||
return (Map)input;
|
||||
|
||||
final Map<ReferenceDescription, Version> result = new HashMap<>(input.size());
|
||||
for (final Map.Entry<Class<Reference>, Version> entry : ((Map<Class<Reference>, Version>) input).entrySet()) {
|
||||
result.put(getDescription(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class TypedCSVMappingBuilder<T> extends CSVMappingBuilder {
|
||||
|
||||
private final Class<T> type;
|
||||
|
||||
private final HashSet<String> ignorable = new HashSet<>();
|
||||
|
||||
public TypedCSVMappingBuilder(final CSVMappingBuilder builder, final Class<T> type) {
|
||||
this.target = builder.target;
|
||||
this.charset = builder.charset;
|
||||
this.separator = builder.separator;
|
||||
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public TypedCSVMappingBuilder<T> setIgnorable(String propertyName) {
|
||||
if (propertyName != null && !(propertyName = propertyName.trim()).isEmpty()) {
|
||||
ignorable.add(propertyName);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public final CSVEncoder<T> acquireEncoder() throws IOException, IntrospectionException {
|
||||
return new CSVEncoder<>(target, type, separator, charset, ignorable);
|
||||
}
|
||||
|
||||
|
||||
public final CSVDecoder<T> acquireDecoder() throws IOException, IntrospectionException {
|
||||
return new CSVDecoder<>(target, type, separator, charset, ignorable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedCSVMappingBuilder withSeparator(char separator) {
|
||||
super.withSeparator(separator);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedCSVMappingBuilder withEncoding(Charset charset) {
|
||||
super.withEncoding(charset);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedCSVMappingBuilder forPath(Path target) {
|
||||
super.forPath(target);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
55
core/src/main/java/fr/cenra/rhomeo/core/WorkflowStep.java
Normal file
55
core/src/main/java/fr/cenra/rhomeo/core/WorkflowStep.java
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core;
|
||||
|
||||
/**
|
||||
* Describes possible states for the application. More accurately, it represents
|
||||
* each step of the working process a user must go through to extract / publish
|
||||
* results. In apparition order it is :
|
||||
*
|
||||
* DATASET : Data seizure / import / edition.
|
||||
* PROCESS : Process parameterisation and execution.
|
||||
* RESULT : Result compilation and consultation.
|
||||
* FINALIZATION : Options of publication / extraction of the computed results.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public enum WorkflowStep {
|
||||
DATASET, PROCESS, RESULT, FINALIZATION;
|
||||
}
|
||||
@ -0,0 +1,560 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonEncoding;
|
||||
import fr.cenra.rhomeo.api.data.Protocol;
|
||||
import fr.cenra.rhomeo.api.data.Site;
|
||||
import fr.cenra.rhomeo.api.process.Indicator;
|
||||
import fr.cenra.rhomeo.api.result.DashboardResultItem;
|
||||
import fr.cenra.rhomeo.api.result.Index;
|
||||
import fr.cenra.rhomeo.api.result.IndicatorValuesByYearItem;
|
||||
import fr.cenra.rhomeo.core.CSVDecoder;
|
||||
import fr.cenra.rhomeo.core.CSVEncoder;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import fr.cenra.rhomeo.core.RhomeoRuntimeException;
|
||||
import fr.cenra.rhomeo.core.Session;
|
||||
import fr.cenra.rhomeo.core.result.ResultStorage;
|
||||
import fr.cenra.rhomeo.core.util.ExportUtils;
|
||||
import fr.cenra.rhomeo.core.util.GeometryUtils;
|
||||
import fr.cenra.rhomeo.core.data.site.SiteRepositoryImpl;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.sis.storage.DataStoreException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import org.geotoolkit.data.geojson.GeoJSONStreamWriter;
|
||||
import org.geotoolkit.nio.IOUtilities;
|
||||
|
||||
/**
|
||||
* Handle results displayed on the dashboard.
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public class DashboardResultsManager {
|
||||
|
||||
protected static final String HISTORY_LOG = "history.log";
|
||||
|
||||
@Autowired
|
||||
private Session session;
|
||||
|
||||
@Autowired
|
||||
private ResultStorage resultStorage;
|
||||
|
||||
/**
|
||||
* Get all previously-published result items in the dashboard.
|
||||
*
|
||||
* @return A list of results items.
|
||||
* @throws IOException
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws IntrospectionException
|
||||
*/
|
||||
private List<DashboardResultItem> getDashboardResultsItems() throws IOException, ReflectiveOperationException, IntrospectionException {
|
||||
if (!Files.exists(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
final CSVDecoder<DashboardResultItem> decoder = new CSVDecoder<>(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS, DashboardResultItem.class);
|
||||
return decoder.decode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Regroups results for indicator by year.
|
||||
*
|
||||
* @param site Site to use. Should not be {@code null}.
|
||||
* @return Results, never {@code null}
|
||||
* @throws IntrospectionException
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws IOException
|
||||
*/
|
||||
public ObservableList<IndicatorValuesByYearItem> getDashboardResultsByYear(final Site site) throws IntrospectionException, ReflectiveOperationException, IOException {
|
||||
final ObservableList<DashboardResultItem> items = getDashboardResultsForSite(site);
|
||||
final Map<Integer, IndicatorValuesByYearItem> indicatorsByYear = new HashMap<>();
|
||||
for (final DashboardResultItem item : items) {
|
||||
final int year = item.getYear();
|
||||
if (indicatorsByYear.containsKey(year)) {
|
||||
final IndicatorValuesByYearItem itemToUpdate = indicatorsByYear.get(year);
|
||||
itemToUpdate.addValueForIndicator(item.getIndicator(), item.getValue(), item.isPublished());
|
||||
} else {
|
||||
final IndicatorValuesByYearItem itemToAdd = new IndicatorValuesByYearItem(year);
|
||||
itemToAdd.addValueForIndicator(item.getIndicator(), item.getValue(), item.isPublished());
|
||||
indicatorsByYear.put(year, itemToAdd);
|
||||
}
|
||||
}
|
||||
return FXCollections.observableArrayList(indicatorsByYear.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get previously-published result items for the specified site.
|
||||
*
|
||||
* @param site the selected site.
|
||||
* @return A list of results items, never {@code null}
|
||||
* @throws IOException
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws IntrospectionException
|
||||
*/
|
||||
public ObservableList<DashboardResultItem> getDashboardResultsForSite(final Site site) throws IOException, ReflectiveOperationException, IntrospectionException {
|
||||
final List<DashboardResultItem> allRes = getDashboardResultsItems();
|
||||
final ObservableList<DashboardResultItem> resForSite = FXCollections.observableArrayList();
|
||||
resForSite.addAll(allRes.stream()
|
||||
.filter(item -> site.getName() != null && site.getName().equals(item.getSite()))
|
||||
.collect(Collectors.toList()));
|
||||
return resForSite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or replace a list of result items.
|
||||
*
|
||||
* @param itemsToAdd A list of items to serialize.
|
||||
* @throws IOException
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws IntrospectionException
|
||||
*/
|
||||
public void addDashboardResultsItems(final List<DashboardResultItem> itemsToAdd) throws IOException, ReflectiveOperationException, IntrospectionException {
|
||||
// Ensures the CSV file to write will exist
|
||||
if (!Files.exists(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS)) {
|
||||
Files.createFile(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS);
|
||||
}
|
||||
|
||||
// First get existing results
|
||||
final List<DashboardResultItem> existingResults = getDashboardResultsItems();
|
||||
|
||||
// Merge new / updates results into existing results.
|
||||
for (final DashboardResultItem itemToAdd : itemsToAdd) {
|
||||
boolean toAdd = true;
|
||||
for (final DashboardResultItem existing : existingResults) {
|
||||
if (existing.getSite().equals(itemToAdd.getSite()) &&
|
||||
existing.getIndicator().equals(itemToAdd.getIndicator()) &&
|
||||
existing.getYear() == itemToAdd.getYear())
|
||||
{
|
||||
// Same site, indicator and year, so just update the value
|
||||
existing.setValue(itemToAdd.getValue());
|
||||
existing.setPublished(itemToAdd.isPublished());
|
||||
toAdd = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found for update, so just add it.
|
||||
if (toAdd) {
|
||||
existingResults.add(itemToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize them
|
||||
final CSVEncoder<DashboardResultItem> encoder = new CSVEncoder<>(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS, DashboardResultItem.class);
|
||||
encoder.encode(existingResults, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename site name in dashboard results. Use it when a site is renamed.
|
||||
*
|
||||
* @param site New site containing new name.
|
||||
* @param oldName Old site name.
|
||||
* @throws IntrospectionException
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws IOException
|
||||
*/
|
||||
public void updateDashboardResultsSiteName(final Site site, final String oldName) throws IntrospectionException, ReflectiveOperationException, IOException {
|
||||
if (!Files.exists(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS)) {
|
||||
return;
|
||||
}
|
||||
// First get existing results
|
||||
final List<DashboardResultItem> existingResults = getDashboardResultsItems();
|
||||
existingResults.stream().filter(item -> item.getSite().equals(oldName))
|
||||
.forEach(item -> item.setSite(site.getName()));
|
||||
|
||||
// Serialize them
|
||||
final CSVEncoder<DashboardResultItem> encoder = new CSVEncoder<>(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS, DashboardResultItem.class);
|
||||
encoder.encode(existingResults, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update existing results, for published and value properties.
|
||||
*
|
||||
* @param itemsToUpdate
|
||||
* @throws IntrospectionException
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws IOException
|
||||
*/
|
||||
public void updateResults(final List<DashboardResultItem> itemsToUpdate) throws IntrospectionException, ReflectiveOperationException, IOException {
|
||||
if (itemsToUpdate == null || itemsToUpdate.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final CSVEncoder<DashboardResultItem> encoder = new CSVEncoder<>(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS, DashboardResultItem.class);
|
||||
// Ensures the CSV file to write will exist. If not, create it and directly serialize them
|
||||
if (!Files.exists(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS)) {
|
||||
Files.createFile(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS);
|
||||
// Serialize them
|
||||
encoder.encode(itemsToUpdate, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// First get existing results
|
||||
final List<DashboardResultItem> existingResults = getDashboardResultsItems();
|
||||
for (final DashboardResultItem itemToUp : itemsToUpdate) {
|
||||
final int index = existingResults.indexOf(itemToUp);
|
||||
if (index > -1) {
|
||||
existingResults.set(index, itemToUp);
|
||||
}
|
||||
}
|
||||
|
||||
encoder.encode(existingResults, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove results entries for the specified site name.
|
||||
*
|
||||
* @param siteName
|
||||
* @throws IntrospectionException
|
||||
* @throws ReflectiveOperationException
|
||||
* @throws IOException
|
||||
*/
|
||||
public void removeDashboardResultsForSite(final String siteName) throws IntrospectionException, ReflectiveOperationException, IOException {
|
||||
if (siteName == null) {
|
||||
return;
|
||||
}
|
||||
if (!Files.exists(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// First get existing results
|
||||
final List<DashboardResultItem> existingResults = getDashboardResultsItems();
|
||||
final List<DashboardResultItem> filteredList = existingResults.stream()
|
||||
.filter(item -> !item.getSite().equals(siteName))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Delete all result files associated to the site
|
||||
resultStorage.deleteIfExists(siteName);
|
||||
|
||||
// Serialize them
|
||||
final CSVEncoder<DashboardResultItem> encoder = new CSVEncoder<>(RhomeoCore.DASHBOARD_PUBLISHED_RESULTS, DashboardResultItem.class);
|
||||
encoder.encode(filteredList, true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Send results currently contained in the session to the FTP service for
|
||||
* result publication.
|
||||
*
|
||||
* Structure on the FTP is:
|
||||
* <pre>
|
||||
* results
|
||||
* |- county code
|
||||
* |--|- SHA1 geometry site
|
||||
* |--|--|- protocol
|
||||
* |--|--|--|- UUID
|
||||
* |--|--|--|--|- site.geojson
|
||||
* |--|--|--|--|- metadata.json
|
||||
* |--|--|--|--|- result.csv
|
||||
* ...
|
||||
* </pre>
|
||||
*/
|
||||
public void publishResults() throws IOException, DataStoreException, IntrospectionException, GeneralSecurityException {
|
||||
// Move to the right directory
|
||||
final AtomicReference dirRef = new AtomicReference();
|
||||
resultStorage.publish(() -> {
|
||||
FTPClient ftpClient = null;
|
||||
try {
|
||||
ftpClient = session.connectResultFTP();
|
||||
final String rootDir = ftpClient.printWorkingDirectory();
|
||||
prepareSiteDirectory(session.getDataContext().getSite(), ftpClient);
|
||||
prepareResultDirectory(session.getDataContext().getProtocol(), ftpClient);
|
||||
dirRef.set(ftpClient.printWorkingDirectory().replace(rootDir, ""));
|
||||
return ftpClient;
|
||||
} catch (Exception e) {
|
||||
if (ftpClient != null)
|
||||
try {
|
||||
ftpClient.disconnect();
|
||||
} catch (IOException ex) {
|
||||
e.addSuppressed(ex);
|
||||
}
|
||||
throw new RhomeoRuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
// log publication
|
||||
final Object bundlePath = dirRef.get();
|
||||
if (bundlePath != null) {
|
||||
Optional<Log> log = fromSession(session, bundlePath.toString());
|
||||
if (log.isPresent()) {
|
||||
log(session.connectResultFTP(), log.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish site results on the FTP.
|
||||
* Structure on the FTP is:
|
||||
* <pre>
|
||||
* results
|
||||
* |- county code
|
||||
* |--|- SHA1 geometry site
|
||||
* |--|--|- protocol
|
||||
* |--|--|--|- UUID
|
||||
* |--|--|--|--|- site.geojson
|
||||
* |--|--|--|--|- metadata.json
|
||||
* |--|--|--|--|- result.csv
|
||||
* ...
|
||||
* </pre>
|
||||
*
|
||||
* @param site
|
||||
* @param resultsForSite
|
||||
* @param ftpClient
|
||||
* @throws IOException
|
||||
* @throws IntrospectionException
|
||||
* @throws ReflectiveOperationException
|
||||
*/
|
||||
public void publishResults(final Site site, final List<DashboardResultItem> resultsForSite, final FTPClient ftpClient)
|
||||
throws IOException, IntrospectionException, ReflectiveOperationException, DataStoreException
|
||||
{
|
||||
final Path tempFolder = Files.createTempDirectory("site");
|
||||
final Path siteJsonPath = ExportUtils.writeGeoJson(site, tempFolder);
|
||||
final ArrayList<DashboardResultItem> reallyPublished = new ArrayList<>(resultsForSite.size());
|
||||
final ArrayList<Log> logs = new ArrayList<>(resultsForSite.size());
|
||||
final String rootDir = ftpClient.printWorkingDirectory();
|
||||
try {
|
||||
prepareSiteDirectory(site, ftpClient);
|
||||
for (final DashboardResultItem item : resultsForSite) {
|
||||
final Object prototypeIndic = session.getBean(item.getIndicator());
|
||||
if (prototypeIndic instanceof Indicator) {
|
||||
final Indicator indicator = (Indicator) prototypeIndic;
|
||||
prepareResultDirectory(indicator.getProtocol(), ftpClient);
|
||||
|
||||
try (final InputStream in = Files.newInputStream(siteJsonPath, StandardOpenOption.READ)) {
|
||||
ftpClient.storeFile("site.geojson", in);
|
||||
}
|
||||
|
||||
resultStorage.publish(item, ftpClient);
|
||||
item.setPublished(true);
|
||||
reallyPublished.add(item);
|
||||
|
||||
logs.add(new Log(site, ftpClient.printWorkingDirectory().replace(rootDir, ""), new int[]{item.getYear()}, indicator));
|
||||
|
||||
if (!ftpClient.changeToParentDirectory()) {
|
||||
throw new IOException("Unable to change to parent directory");
|
||||
}
|
||||
if (!ftpClient.changeToParentDirectory()) {
|
||||
throw new IOException("Unable to change to parent directory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
try {
|
||||
IOUtilities.deleteRecursively(tempFolder);
|
||||
} catch (Exception e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "Cannot clear temporary files.", e);
|
||||
}
|
||||
|
||||
if (!logs.isEmpty() && ftpClient.changeToParentDirectory() && ftpClient.changeToParentDirectory()) {
|
||||
log(ftpClient, logs.toArray(new Log[logs.size()]));
|
||||
}
|
||||
|
||||
// Update results publication state.
|
||||
updateResults(reallyPublished);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create (if needed) folders in which input site results will be put.
|
||||
* Working directory is changed to the created/detected directory.
|
||||
* @param site The site we want to post results for.
|
||||
* @param ftpClient The FTP connection to work with.
|
||||
*/
|
||||
private static void prepareSiteDirectory(final Site site, final FTPClient ftpClient) throws IOException, DataStoreException {
|
||||
// Move to county code ftp folder
|
||||
String department = site.getCountyCode();
|
||||
if (department == null || department.trim().isEmpty())
|
||||
department = "00";
|
||||
ftpClient.makeDirectory(department);
|
||||
if (!ftpClient.changeWorkingDirectory(department)) {
|
||||
throw new IOException("Unable to change of directory to " + department);
|
||||
}
|
||||
|
||||
// Move to geom SHA1 ftp folder
|
||||
final String sha1geom = GeometryUtils.getSha1(site.getGeometry());
|
||||
ftpClient.makeDirectory(sha1geom);
|
||||
if (!ftpClient.changeWorkingDirectory(sha1geom)) {
|
||||
throw new IOException("Unable to change of directory to " + sha1geom);
|
||||
}
|
||||
|
||||
if (ftpClient.listFiles(ExportUtils.SITE_JSON).length < 1) {
|
||||
try (final OutputStream out = ftpClient.storeFileStream(ExportUtils.SITE_JSON)) {
|
||||
GeoJSONStreamWriter.writeSingleFeature(out, SiteRepositoryImpl.toFeature(site), JsonEncoding.UTF8, 2, true);
|
||||
}
|
||||
ftpClient.completePendingCommand();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check directories for result publication for a specific protocol. It will
|
||||
* find or create, and then move to a folder named as input protocol, and
|
||||
* then create and move to a folder whose name is an UUID.
|
||||
*
|
||||
* Note : For publication, you should already be in the site folder, i.e
|
||||
* have called {@link #prepareSiteDirectory(fr.cenra.rhomeo.api.data.Site, org.apache.commons.net.ftp.FTPClient) }.
|
||||
*
|
||||
* @param p The protocol to post results for.
|
||||
* @param ftpClient The FTP connection to work with.
|
||||
*/
|
||||
public static void prepareResultDirectory(final Protocol p, final FTPClient ftpClient) throws IOException {
|
||||
final String protocolName = p.getName();
|
||||
ftpClient.makeDirectory(protocolName);
|
||||
if (!ftpClient.changeWorkingDirectory(protocolName)) {
|
||||
throw new IOException("Unable to change of directory to " + protocolName);
|
||||
}
|
||||
|
||||
final String uuid = UUID.randomUUID().toString();
|
||||
ftpClient.makeDirectory(uuid);
|
||||
if (!ftpClient.changeWorkingDirectory(uuid)) {
|
||||
throw new IOException("Unable to change of directory to " + uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private static void log(final FTPClient ftpClient, Log... toLog) throws IOException {
|
||||
try (OutputStream out = ftpClient.appendFileStream(HISTORY_LOG);
|
||||
final OutputStreamWriter outWriter = new OutputStreamWriter(out, StandardCharsets.UTF_8);
|
||||
final BufferedWriter writer = new BufferedWriter(outWriter)) {
|
||||
for (final Log log : toLog) {
|
||||
writer.newLine();
|
||||
writer.write(log.toString());
|
||||
}
|
||||
} finally {
|
||||
ftpClient.completePendingCommand();
|
||||
}
|
||||
}
|
||||
|
||||
private static Optional<Log> fromSession(final Session session, final String bundlePath) {
|
||||
if (session.getDataContext() == null || session.getResults() == null || session.getResults().isEmpty())
|
||||
return Optional.empty();
|
||||
|
||||
final Set<Integer> years = new HashSet<>();
|
||||
final Set<Indicator> indicators = new HashSet<>();
|
||||
|
||||
for (final Index i : session.getResults()) {
|
||||
years.add(i.getYear());
|
||||
indicators.add(i.getSpi().getIndicator());
|
||||
}
|
||||
|
||||
if (years.isEmpty() || indicators.isEmpty())
|
||||
return Optional.empty();
|
||||
|
||||
final int[] primYears = new int[years.size()];
|
||||
int count = 0;
|
||||
for (Integer year : years)
|
||||
primYears[count++] = year;
|
||||
|
||||
return Optional.of(new Log(session.getDataContext().getSite(), bundlePath, primYears, indicators.toArray(new Indicator[indicators.size()])));
|
||||
}
|
||||
|
||||
private static class Log {
|
||||
final String siteName;
|
||||
final String referent;
|
||||
final String organisation;
|
||||
final String targetBundle;
|
||||
final String indicateurs;
|
||||
final String annees;
|
||||
|
||||
public Log(final Site site, final String targetBundle, final int[] years, final Indicator... indicators) {
|
||||
this(targetBundle, site.getName(), site.getReferent(), site.getOrganization(), years, indicators);
|
||||
}
|
||||
|
||||
public Log(final String target, final String siteName, final String ref, final String org, final int[] years, final Indicator... indicators) {
|
||||
this.siteName = siteName;
|
||||
referent = ref;
|
||||
organisation = org;
|
||||
targetBundle = target;
|
||||
|
||||
Arrays.sort(years);
|
||||
StringJoiner joiner = new StringJoiner(", ");
|
||||
for (final int year : years)
|
||||
joiner.add(String.valueOf(year));
|
||||
this.annees = joiner.toString();
|
||||
|
||||
Arrays.sort(indicators);
|
||||
joiner = new StringJoiner(", ");
|
||||
for (final Indicator i : indicators)
|
||||
joiner.add(i.getName());
|
||||
indicateurs = joiner.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder(256)
|
||||
.append(ZonedDateTime.now().toString()).append(" : ")
|
||||
.append(siteName).append(", ")
|
||||
.append(referent == null || referent.isEmpty()? "referent inconnu" : referent)
|
||||
.append(" (").append(organisation == null || organisation.isEmpty()? "organisation inconnue" : organisation).append(")")
|
||||
.append(" publie ").append(targetBundle)
|
||||
.append(" pour ").append(indicateurs)
|
||||
.append(" en ").append(annees)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import fr.cenra.rhomeo.api.data.DataContext;
|
||||
import fr.cenra.rhomeo.api.data.Protocol;
|
||||
import fr.cenra.rhomeo.api.data.Site;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import fr.cenra.rhomeo.core.util.SerializableDataContext;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Handle data context serialization.
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public class DataContextManager {
|
||||
private final ObjectMapper jsonMapper;
|
||||
|
||||
public DataContextManager() {
|
||||
jsonMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data context
|
||||
* @param dc Data context to serialize.
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writeDataContext(final DataContext dc) throws IOException {
|
||||
SerializableDataContext[] contexts = getContexts();
|
||||
final SerializableDataContext srDataContext = SerializableDataContext.fromDataContext(dc);
|
||||
boolean found = false;
|
||||
for (int i=0; i<contexts.length; i++) {
|
||||
SerializableDataContext candidate = contexts[i];
|
||||
if (candidate.protocolName.equals(srDataContext.protocolName) && candidate.siteName.equals(srDataContext.siteName)) {
|
||||
found = true;
|
||||
contexts[i] = srDataContext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
contexts = Arrays.copyOf(contexts, contexts.length + 1);
|
||||
contexts[contexts.length - 1] = srDataContext;
|
||||
}
|
||||
|
||||
final Path contextsPath = RhomeoCore.DATA_CONTEXT_SITE_PATH;
|
||||
if (Files.notExists(contextsPath)) {
|
||||
Files.createFile(contextsPath);
|
||||
}
|
||||
try (final BufferedWriter writer = Files.newBufferedWriter(contextsPath, StandardCharsets.UTF_8)) {
|
||||
jsonMapper.writeValue(writer, contexts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data context for the given site and protocol.
|
||||
*
|
||||
* @param site Site to consider, must not be {@code null}
|
||||
* @param protocol Protocol to consider, must not be {@code null}
|
||||
* @return A data context stored previously or {@code null} if not found.
|
||||
* @throws IOException
|
||||
*/
|
||||
public SerializableDataContext loadContext(final Site site, final Protocol protocol) throws IOException {
|
||||
ArgumentChecks.ensureNonNull("Site", site);
|
||||
ArgumentChecks.ensureNonNull("Protocol", protocol);
|
||||
final SerializableDataContext[] contexts = getContexts();
|
||||
for (final SerializableDataContext context : contexts) {
|
||||
if (context.siteName.equals(site.getName()) && context.protocolName.equals(protocol.getName())) {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SerializableDataContext[] getContexts() throws IOException {
|
||||
final Path contextsPath = RhomeoCore.DATA_CONTEXT_SITE_PATH;
|
||||
if (Files.notExists(contextsPath)) {
|
||||
return new SerializableDataContext[0];
|
||||
}
|
||||
try (final BufferedReader reader = Files.newBufferedReader(contextsPath, StandardCharsets.UTF_8)) {
|
||||
return jsonMapper.readValue(reader, SerializableDataContext[].class);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeReferencesForSite(final String siteName) throws IOException {
|
||||
final SerializableDataContext[] contexts = getContexts();
|
||||
if (contexts.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<SerializableDataContext> finalContexts =
|
||||
Stream.of(contexts).filter(context -> !context.siteName.equals(siteName))
|
||||
.collect(Collectors.toList());
|
||||
// Something to serialize if we have less contexts in the end
|
||||
if (contexts.length != finalContexts.size()) {
|
||||
final Path contextsPath = RhomeoCore.DATA_CONTEXT_SITE_PATH;
|
||||
try (final BufferedWriter writer = Files.newBufferedWriter(contextsPath, StandardCharsets.UTF_8)) {
|
||||
jsonMapper.writeValue(writer, finalContexts.toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateReferencesSiteName(final String oldName, final String newName) throws IOException {
|
||||
final SerializableDataContext[] contexts = getContexts();
|
||||
if (contexts.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean aChange = false;
|
||||
final List<SerializableDataContext> finalContexts = new ArrayList<>();
|
||||
for (final SerializableDataContext context : contexts) {
|
||||
if (context.siteName.equals(oldName)) {
|
||||
aChange = true;
|
||||
context.siteName = newName;
|
||||
}
|
||||
finalContexts.add(context);
|
||||
}
|
||||
|
||||
// Something to serialize if we have less contexts in the end
|
||||
if (aChange) {
|
||||
final Path contextsPath = RhomeoCore.DATA_CONTEXT_SITE_PATH;
|
||||
try (final BufferedWriter writer = Files.newBufferedWriter(contextsPath, StandardCharsets.UTF_8)) {
|
||||
jsonMapper.writeValue(writer, finalContexts.toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,508 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data;
|
||||
|
||||
import fr.cenra.rhomeo.api.Version;
|
||||
import fr.cenra.rhomeo.api.data.Reference;
|
||||
import fr.cenra.rhomeo.api.data.ReferenceDescription;
|
||||
import fr.cenra.rhomeo.core.CSVDecoder;
|
||||
import fr.cenra.rhomeo.core.CSVMapper;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import fr.cenra.rhomeo.core.RhomeoRuntimeException;
|
||||
import fr.cenra.rhomeo.core.Session;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableMap;
|
||||
import javafx.concurrent.Task;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
import org.apache.sis.util.collection.Cache;
|
||||
|
||||
/**
|
||||
* Contains the list of available and installed version of a specific reference
|
||||
* type. Also allow to get data contained in each installed version.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
* @param <T> Type of reference managed.
|
||||
*/
|
||||
public class ReferenceManager<T extends Reference> {
|
||||
|
||||
/**
|
||||
* A regex to detect CSV files containing a version number composed of dot separated digits .
|
||||
*/
|
||||
private static final Pattern REF_FILE_PATTERN = Pattern.compile("(?i)(\\d+(?:\\.\\d+)*)(.csv)?$");
|
||||
|
||||
/**
|
||||
* We register created managers here.
|
||||
*/
|
||||
private static final Cache<String, ReferenceManager> INSTANCES = new Cache<>(13, 13, true);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param <R> The type of reference to get a manager for.
|
||||
* @param descriptor A descriptor for the reference list to check.
|
||||
* @return The manager corresponding to the given reference description.
|
||||
* @throws java.beans.IntrospectionException If we cannot analyze given reference type.
|
||||
*/
|
||||
public static <R extends Reference> ReferenceManager<R> getOrCreate(final ReferenceDescription<R> descriptor) throws IntrospectionException {
|
||||
try {
|
||||
return INSTANCES.getOrCreate(descriptor.getName(), () -> new ReferenceManager<>(descriptor));
|
||||
} catch (IntrospectionException | RuntimeException ex) {
|
||||
throw ex;
|
||||
} catch (Exception e) {
|
||||
throw new RhomeoRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Target (managed) reference type.
|
||||
*/
|
||||
private final ReferenceDescription<T> refType;
|
||||
/**
|
||||
* Information about reference pojo (properties, methods, etc.).
|
||||
*/
|
||||
private final BeanInfo refInfo;
|
||||
|
||||
/**
|
||||
* Directory where installed versions should be located.
|
||||
*/
|
||||
private final Path refDir;
|
||||
|
||||
/**
|
||||
* A map containing installed versions we found on {@link #refresh() }.
|
||||
*/
|
||||
private final ObservableMap<Version, Path> installed;
|
||||
/**
|
||||
* A map containing versions found in FTP server on {@link #refresh() }.
|
||||
*/
|
||||
private final ObservableMap<Version, FTPFile> distant;
|
||||
|
||||
private final Cache<Version, List<T>> loadedVersions = new Cache(2, 0, false);
|
||||
|
||||
private WeakReference<List<T>> lastLoaded;
|
||||
|
||||
private final Set<Version> operations;
|
||||
|
||||
private Task refreshTask;
|
||||
|
||||
private ReferenceManager(@NotNull ReferenceDescription<T> refType) throws IntrospectionException {
|
||||
this.refType = refType;
|
||||
final String refName = refType.getName();
|
||||
ArgumentChecks.ensureNonEmpty("Reference type name", refName);
|
||||
|
||||
refInfo = Introspector.getBeanInfo(refType.getReferenceType(), Object.class);
|
||||
refDir = RhomeoCore.REFERENCE_PATH.resolve(refName);
|
||||
|
||||
installed = FXCollections.observableMap(new HashMap<>());
|
||||
distant = FXCollections.observableMap(new HashMap<>());
|
||||
|
||||
operations = new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Force this manager to rebuild its data from scratch. The local files and
|
||||
* FTP service will be scanned anew to find available and installed reference
|
||||
* lists.
|
||||
*
|
||||
* Note : local data is checked first, so if the distant service does not
|
||||
* provide correct answers and the task fails, we can still access installed
|
||||
* versions.
|
||||
* @return A task which refresh data. If a refresh is ready to run or
|
||||
* already running, the corresponding task is returned. Otherwise, a new
|
||||
* task is returned which must be launched by the caller.
|
||||
*/
|
||||
public synchronized Task<ReferenceManager> refresh() {
|
||||
if (refreshTask == null || refreshTask.isDone()) {
|
||||
refreshTask = new Task() {
|
||||
|
||||
@Override
|
||||
protected Object call() throws Exception {
|
||||
updateTitle("Recherche de versions : ".concat(refType.getTitle()));
|
||||
|
||||
updateMessage("Vérification des versions installées");
|
||||
installed.clear();
|
||||
Files.createDirectories(refDir);
|
||||
|
||||
Files.walkFileTree(refDir, new SimpleFileVisitor<Path>() {
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
final Matcher matcher = REF_FILE_PATTERN.matcher(file.getFileName().toString());
|
||||
if (matcher.find()) {
|
||||
if (isValid(file)) {
|
||||
installed.put(new Version(matcher.group(1)), file);
|
||||
}
|
||||
}
|
||||
return super.visitFile(file, attrs);
|
||||
}
|
||||
});
|
||||
|
||||
updateMessage("Vérification des versions disponibles sur le FTP");
|
||||
distant.clear();
|
||||
final FTPClient ftp = Session.getInstance().connectReferenceFTP();
|
||||
try {
|
||||
if (ftp.changeWorkingDirectory(refType.getName())) {
|
||||
ftp.listFiles(".", file -> {
|
||||
if (file.isFile() && file.getSize() > 0) {
|
||||
final Matcher matcher = REF_FILE_PATTERN.matcher(file.getName());
|
||||
if (matcher.find()) {
|
||||
try (final InputStream retStream = ftp.retrieveFileStream(file.getName())) {
|
||||
if (isValid(retStream)) {
|
||||
distant.put(new Version(matcher.group(1)), file);
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "An error occurred while reading an FTP file : ".concat(file.getName()), e);
|
||||
} finally {
|
||||
try {
|
||||
// Ensures pending command are finished
|
||||
if (!ftp.completePendingCommand()) {
|
||||
final int replyCode = ftp.getReplyCode();
|
||||
final String replyMessage = ftp.getReplyString();
|
||||
final Supplier<String> msgSupplier = () -> {
|
||||
final StringBuilder builder = new StringBuilder("Error on pending command completion.");
|
||||
builder.append(System.lineSeparator()).append("File : ").append(file.getName());
|
||||
builder.append(System.lineSeparator()).append("Reply code : ").append(replyCode);
|
||||
builder.append(System.lineSeparator()).append("Reply message : ").append(replyMessage);
|
||||
return builder.toString();
|
||||
};
|
||||
RhomeoCore.LOGGER.log(Level.INFO, msgSupplier);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "An error occurred while trying to complete pending command for FTP file : ".concat(file.getName()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
ftp.disconnect();
|
||||
} catch (IOException e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "An FTP client cannot be disconnected : References.", e);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return refreshTask;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Set of versions available on FTP server. Unmodifiable. The Set is
|
||||
* automatically updated when the manager is refreshed.
|
||||
*/
|
||||
public Set<Version> getDistantVersions() {
|
||||
return distant.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Set of versions installed locally. Unmodifiable. The Set is
|
||||
* automatically updated when the manager is refreshed.
|
||||
*/
|
||||
public Set<Version> getInstalledVersions() {
|
||||
return installed.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a task in charge of the installation of a new reference version.
|
||||
* @param toInstall Version of the reference list to install.
|
||||
* @return A task (not submitted yet) to run to install given version.
|
||||
* @throws IllegalStateException If an installation or uninstallation procedure
|
||||
* is already running for the version.
|
||||
*/
|
||||
public Task install(@NotNull final Version toInstall) throws IllegalStateException {
|
||||
synchronized (operations) {
|
||||
if (operations.contains(toInstall)) {
|
||||
throw new IllegalStateException(
|
||||
new StringBuilder("An operation is already running for version ")
|
||||
.append(toInstall.toString())
|
||||
.append(" of list ")
|
||||
.append(refType.getName())
|
||||
.toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new Task() {
|
||||
|
||||
@Override
|
||||
protected Object call() throws Exception {
|
||||
final boolean alreadyRunning;
|
||||
synchronized (operations) {
|
||||
alreadyRunning = !operations.add(toInstall);
|
||||
}
|
||||
try {
|
||||
if (alreadyRunning) {
|
||||
updateMessage(
|
||||
new StringBuilder("An operation is already running for version ")
|
||||
.append(toInstall.toString())
|
||||
.append(" of list ")
|
||||
.append(refType.getName())
|
||||
.toString()
|
||||
);
|
||||
cancel();
|
||||
|
||||
} else if (installed.containsKey(toInstall)) {
|
||||
updateMessage("Queried version is already installed : ".concat(toInstall.toString()));
|
||||
cancel();
|
||||
|
||||
} else {
|
||||
updateTitle("Téléchargement ".concat(toInstall.toString()));
|
||||
FTPFile ftpFile = distant.get(toInstall);
|
||||
if (distant == null) {
|
||||
throw new IllegalArgumentException("Queried version is not available : ".concat(toInstall.toString()));
|
||||
}
|
||||
|
||||
final Path newRef = refDir.resolve(toInstall.toString().concat(".csv"));
|
||||
final FTPClient ftp = Session.getInstance().connectReferenceFTP();
|
||||
ftp.changeWorkingDirectory(refType.getName());
|
||||
try (final OutputStream out = Files.newOutputStream(newRef)) {
|
||||
ftp.retrieveFile(ftpFile.getName(), out);
|
||||
} finally {
|
||||
try {
|
||||
ftp.disconnect();
|
||||
} catch (IOException e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "An FTP client cannot be disconnected : References.", e);
|
||||
}
|
||||
}
|
||||
|
||||
installed.put(toInstall, newRef);
|
||||
return newRef;
|
||||
}
|
||||
} finally {
|
||||
synchronized (operations) {
|
||||
if (!alreadyRunning) {
|
||||
operations.remove(toInstall);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a task in charge of removing a local reference version.
|
||||
* @param toUninstall Version of the reference list to uninstall.
|
||||
* @return A task (not submitted yet) to run to uninstall given version.
|
||||
* @throws IllegalStateException If an installation or uninstallation procedure
|
||||
* is already running for the version.
|
||||
*/
|
||||
public Task uninstall(@NotNull final Version toUninstall) throws IllegalStateException {
|
||||
synchronized (operations) {
|
||||
if (operations.contains(toUninstall)) {
|
||||
throw new IllegalStateException(
|
||||
new StringBuilder("An operation is already running for version ")
|
||||
.append(toUninstall.toString())
|
||||
.append(" of list ")
|
||||
.append(refType.getName())
|
||||
.toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new Task() {
|
||||
|
||||
@Override
|
||||
protected Object call() throws Exception {
|
||||
final boolean alreadyRunning;
|
||||
synchronized (operations) {
|
||||
alreadyRunning = !operations.add(toUninstall);
|
||||
}
|
||||
try {
|
||||
if (alreadyRunning) {
|
||||
updateMessage(
|
||||
new StringBuilder("An operation is already running for version ")
|
||||
.append(toUninstall.toString())
|
||||
.append(" of list ")
|
||||
.append(refType.getName())
|
||||
.toString()
|
||||
);
|
||||
cancel();
|
||||
|
||||
} else if (!installed.containsKey(toUninstall)) {
|
||||
updateMessage("Queried version is already uninstalled : ".concat(toUninstall.toString()));
|
||||
cancel();
|
||||
|
||||
} else {
|
||||
updateTitle("Suppression ".concat(toUninstall.toString()));
|
||||
final Path toDelete = installed.get(toUninstall);
|
||||
Files.delete(toDelete);
|
||||
return installed.remove(toUninstall);
|
||||
}
|
||||
} finally {
|
||||
synchronized (operations) {
|
||||
if (!alreadyRunning) {
|
||||
operations.remove(toUninstall);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if given file header lists all properties defined in reference
|
||||
* type.
|
||||
*
|
||||
* @param file The file to check.
|
||||
* @return True if the file header describes the current reference type,
|
||||
* false otherwise.
|
||||
* @throws IOException If we cannot read the file.
|
||||
* @throws IntrospectionException If we cannot extract property description
|
||||
* from current reference type.
|
||||
*/
|
||||
private boolean isValid(@NotNull final Path file) throws IOException {
|
||||
final String line;
|
||||
try (final BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
|
||||
line = reader.readLine();
|
||||
}
|
||||
|
||||
return isValidHeader(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if given file header lists all properties defined in reference
|
||||
* type.
|
||||
*
|
||||
* @param file The file to check.
|
||||
* @return True if the file header describes the current reference type,
|
||||
* false otherwise.
|
||||
* @throws IOException If we cannot read the file.
|
||||
* @throws IntrospectionException If we cannot extract property description
|
||||
* from current reference type.
|
||||
*/
|
||||
private boolean isValid(@NotNull final InputStream file) throws IOException {
|
||||
final String line;
|
||||
try (final InputStreamReader in = new InputStreamReader(file, StandardCharsets.UTF_8);
|
||||
final BufferedReader reader = new BufferedReader(in)) {
|
||||
line = reader.readLine();
|
||||
}
|
||||
|
||||
return isValidHeader(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if given header lists all properties defined in reference type.
|
||||
*
|
||||
* @param firstLine The header to check.
|
||||
* @return True if the file header describes the current reference type,
|
||||
* false otherwise.
|
||||
*/
|
||||
private boolean isValidHeader(@NotNull final String firstLine) {
|
||||
return CSVMapper.isValidHeader(firstLine, CSVMapper.DEFAULT_SEPARATOR, refInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load reference values for the given version. Before calling this
|
||||
* method, you MUST have called
|
||||
* {@link #refresh() } at least once, and checked the queried version is
|
||||
* already installed.
|
||||
* @param toLoad The version of the list to load.
|
||||
* @return A read-only list containing all values for the queried references.
|
||||
* @throws IllegalArgumentException If the queried version is not installed,
|
||||
* or the manager has not been refreshed yet.
|
||||
* @throws RhomeoRuntimeException If an error occurs while reading list file.
|
||||
*/
|
||||
public synchronized List<T> getValues(final Version toLoad) throws IllegalArgumentException, RhomeoRuntimeException {
|
||||
try {
|
||||
final List<T> result = loadedVersions.getOrCreate(toLoad, () -> {
|
||||
final Path p = installed.get(toLoad);
|
||||
if (p == null) {
|
||||
throw new IllegalArgumentException("Queried version is not installed, or the manager has not been refreshed yet !");
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(
|
||||
new CSVDecoder<>(p, refType.getReferenceType(), StandardCharsets.UTF_8).decode());
|
||||
});
|
||||
lastLoaded = new WeakReference(result);
|
||||
return result;
|
||||
} catch (Exception ex) {
|
||||
throw new RhomeoRuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The list of references which have been loaded the last time {@link #getValues(fr.cenra.rhomeo.api.Version) }
|
||||
* has been called, if any.
|
||||
*/
|
||||
public synchronized Optional<List<T>> getLastLoaded() {
|
||||
if (lastLoaded == null)
|
||||
return Optional.empty();
|
||||
else return Optional.ofNullable(lastLoaded.get());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.TrackingPoint;
|
||||
|
||||
/**
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public class TrackingPointValue implements Comparable<TrackingPointValue> {
|
||||
private final TrackingPoint trackingPoint;
|
||||
private final Double value;
|
||||
|
||||
public TrackingPointValue(final TrackingPoint trackingPoint, final Double value) {
|
||||
this.trackingPoint = trackingPoint;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public TrackingPoint getTrackingPoint() {
|
||||
return trackingPoint;
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(TrackingPointValue o) {
|
||||
if (value == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (o == null || o.getValue() == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return getValue().compareTo(o.getValue());
|
||||
}
|
||||
}
|
||||
163
core/src/main/java/fr/cenra/rhomeo/core/data/UpdateInfo.java
Normal file
163
core/src/main/java/fr/cenra/rhomeo/core/data/UpdateInfo.java
Normal file
@ -0,0 +1,163 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import fr.cenra.rhomeo.api.Version;
|
||||
import fr.cenra.rhomeo.core.util.VersionDeserializer;
|
||||
import fr.cenra.rhomeo.core.util.VersionSerializer;
|
||||
import fr.cenra.rhomeo.core.util.ZonedDateTimeDeserializer;
|
||||
import fr.cenra.rhomeo.core.util.ZonedDateTimeSerializer;
|
||||
import java.net.URL;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
/**
|
||||
* A simple pojo which contains information about application available package
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class UpdateInfo {
|
||||
|
||||
private Version version;
|
||||
private ZonedDateTime date;
|
||||
private String[] releaseNote;
|
||||
private URL win32;
|
||||
private String win32MD5;
|
||||
private URL deb64;
|
||||
private String deb64MD5;
|
||||
private URL rpm64;
|
||||
private String rpm64MD5;
|
||||
private URL macOS64;
|
||||
private String macOS64MD5;
|
||||
|
||||
@JsonSerialize(using = VersionSerializer.class)
|
||||
public Version getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@JsonDeserialize(using = VersionDeserializer.class)
|
||||
public void setVersion(Version version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public URL getWin32() {
|
||||
return win32;
|
||||
}
|
||||
|
||||
@JsonSerialize(using = ZonedDateTimeSerializer.class)
|
||||
public ZonedDateTime getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
@JsonDeserialize(using = ZonedDateTimeDeserializer.class)
|
||||
public void setDate(ZonedDateTime date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String[] getReleaseNote() {
|
||||
return releaseNote;
|
||||
}
|
||||
|
||||
public void setReleaseNote(String[] releaseNote) {
|
||||
this.releaseNote = releaseNote;
|
||||
}
|
||||
|
||||
public void setWin32(URL win32) {
|
||||
this.win32 = win32;
|
||||
}
|
||||
|
||||
public URL getDeb64() {
|
||||
return deb64;
|
||||
}
|
||||
|
||||
public void setDeb64(URL deb64) {
|
||||
this.deb64 = deb64;
|
||||
}
|
||||
|
||||
public URL getRpm64() {
|
||||
return rpm64;
|
||||
}
|
||||
|
||||
public void setRpm64(URL rpm64) {
|
||||
this.rpm64 = rpm64;
|
||||
}
|
||||
|
||||
public URL getMacOS64() {
|
||||
return macOS64;
|
||||
}
|
||||
|
||||
public void setMacOS64(URL macOS64) {
|
||||
this.macOS64 = macOS64;
|
||||
}
|
||||
|
||||
public String getWin32MD5() {
|
||||
return win32MD5;
|
||||
}
|
||||
|
||||
public void setWin32MD5(String win32MD5) {
|
||||
this.win32MD5 = win32MD5;
|
||||
}
|
||||
|
||||
public String getDeb64MD5() {
|
||||
return deb64MD5;
|
||||
}
|
||||
|
||||
public void setDeb64MD5(String deb64MD5) {
|
||||
this.deb64MD5 = deb64MD5;
|
||||
}
|
||||
|
||||
public String getRpm64MD5() {
|
||||
return rpm64MD5;
|
||||
}
|
||||
|
||||
public void setRpm64MD5(String rpm64MD5) {
|
||||
this.rpm64MD5 = rpm64MD5;
|
||||
}
|
||||
|
||||
public String getMacOS64MD5() {
|
||||
return macOS64MD5;
|
||||
}
|
||||
|
||||
public void setMacOS64MD5(String macOS64MD5) {
|
||||
this.macOS64MD5 = macOS64MD5;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.county;
|
||||
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
|
||||
/**
|
||||
* A simple POJO to display the name and code of a county.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class County implements Comparable<County> {
|
||||
|
||||
/**
|
||||
* Code of the county. An Integer most of the time, except for Corse (2A, 2B).
|
||||
*/
|
||||
protected final String code;
|
||||
/**
|
||||
* Name of the county (Corse, Isère, etc.).
|
||||
*/
|
||||
protected final String name;
|
||||
|
||||
/**
|
||||
* Build a new county object.
|
||||
* @param code The code of the county. Not null
|
||||
* @param name The name of the county. Not null.
|
||||
*/
|
||||
protected County(final String code, final String name) {
|
||||
ArgumentChecks.ensureNonNull("County code", code);
|
||||
ArgumentChecks.ensureNonNull("County name", name);
|
||||
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder(code).append(' ').append(name).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(County o) {
|
||||
return o == null? -1 : code.compareTo(o.code);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,255 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.county;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Matcher;
|
||||
import javafx.util.StringConverter;
|
||||
import javax.annotation.PreDestroy;
|
||||
import org.apache.sis.storage.DataStoreException;
|
||||
import org.geotoolkit.data.FeatureCollection;
|
||||
import org.geotoolkit.data.FeatureReader;
|
||||
import org.geotoolkit.data.query.QueryBuilder;
|
||||
import org.geotoolkit.data.shapefile.ShapefileFeatureStore;
|
||||
import org.geotoolkit.factory.FactoryFinder;
|
||||
import org.geotoolkit.factory.Hints;
|
||||
import org.geotoolkit.feature.Feature;
|
||||
import org.geotoolkit.nio.IOUtilities;
|
||||
import org.geotoolkit.referencing.CRS;
|
||||
import org.opengis.filter.FilterFactory2;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
import org.opengis.util.FactoryException;
|
||||
import org.opengis.util.GenericName;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* A repository to load / search for counties.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public final class CountyRepository implements AutoCloseable {
|
||||
|
||||
/**
|
||||
* List of resources to load to read County data.
|
||||
*/
|
||||
private static final String[] RESOURCES = new String[]{
|
||||
"DEPARTEMENT.shp",
|
||||
"DEPARTEMENT.shx",
|
||||
"DEPARTEMENT.dbf",
|
||||
"DEPARTEMENT.prj"
|
||||
};
|
||||
|
||||
/**
|
||||
* Attributes to read into the shapefile embedding county data.
|
||||
*/
|
||||
private static final String COUNTY_CODE = "CODE_DEPT";
|
||||
private static final String COUNTY_NAME = "NOM_DEPT";
|
||||
|
||||
private final ShapefileFeatureStore store;
|
||||
private final GenericName name;
|
||||
private final StringConverter converter;
|
||||
private final CoordinateReferenceSystem siteCRS;
|
||||
private final FilterFactory2 ff;
|
||||
|
||||
private final Map<String, County> counties;
|
||||
|
||||
private final Path dataDir;
|
||||
|
||||
CountyRepository() throws IOException, URISyntaxException, DataStoreException, FactoryException {
|
||||
// Copy resources on local filesystem
|
||||
dataDir = Files.createTempDirectory("countyShape");
|
||||
for (final String str : RESOURCES) {
|
||||
try (final InputStream tmpStream = County.class.getResourceAsStream(str)) {
|
||||
Files.copy(tmpStream, dataDir.resolve(str));
|
||||
}
|
||||
}
|
||||
|
||||
siteCRS = RhomeoCore.getSiteCRS();
|
||||
store = new ShapefileFeatureStore(dataDir.resolve(RESOURCES[0]).toUri());
|
||||
name = store.getName();
|
||||
converter = new Converter();
|
||||
|
||||
final Hints hints = new Hints();
|
||||
hints.put(Hints.FILTER_FACTORY, FilterFactory2.class);
|
||||
ff = (FilterFactory2) FactoryFinder.getFilterFactory(hints);
|
||||
|
||||
counties = readCounties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a county for the given code.
|
||||
* @param code The code of the county. Ex : 34 for Hérault.
|
||||
* @return The matching county, or null if we cannot find any.
|
||||
*/
|
||||
public County get(final String code) {
|
||||
return code == null? null : counties.get(code);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param geom The geometry to find counties for.
|
||||
* @return List of counties intersecting the input geometry. Never null, but
|
||||
* can be empty.
|
||||
*/
|
||||
public List<County> get(final Geometry geom) {
|
||||
final ArrayList<County> result = new ArrayList<>();
|
||||
if (geom == null || geom.isEmpty())
|
||||
return result;
|
||||
try {
|
||||
final QueryBuilder builder = new QueryBuilder(name);
|
||||
final CoordinateReferenceSystem fCRS = store.getFeatureType(name).getCoordinateReferenceSystem();
|
||||
if (fCRS != null && !CRS.equalsApproximatively(fCRS, siteCRS)) {
|
||||
builder.setCRS(siteCRS);
|
||||
}
|
||||
|
||||
final GenericName geomName = store.getFeatureType().getGeometryDescriptor().getName();
|
||||
builder.setProperties(new String[]{COUNTY_CODE, geomName.tip().toString()});
|
||||
|
||||
builder.setFilter(ff.intersects(ff.property(geomName), ff.literal(geom)));
|
||||
try (FeatureReader reader = store.getFeatureReader(builder.buildQuery())) {
|
||||
while (reader.hasNext()) {
|
||||
result.add(counties.get(reader.next().getPropertyValue(COUNTY_CODE)));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
RhomeoCore.LOGGER.log(Level.FINE, "Cannot perform intersection on counties !", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Complete list of metropolitan France counties, indexed by code.
|
||||
*/
|
||||
public Map<String, County> getAll() {
|
||||
return counties;
|
||||
}
|
||||
|
||||
public FeatureCollection getFeatures() {
|
||||
return store.createSession(false).getFeatureCollection(QueryBuilder.all(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all counties in memory.
|
||||
* @return An unmodifiable map of available counties. Key is code, value is
|
||||
* county.
|
||||
* @throws DataStoreException
|
||||
* @throws FactoryException
|
||||
*/
|
||||
private Map<String, County> readCounties() throws DataStoreException, FactoryException {
|
||||
final QueryBuilder builder = new QueryBuilder(name);
|
||||
final CoordinateReferenceSystem fCRS = store.getFeatureType(name).getCoordinateReferenceSystem();
|
||||
if (fCRS != null && !CRS.equalsApproximatively(fCRS, siteCRS)) {
|
||||
builder.setCRS(siteCRS);
|
||||
}
|
||||
|
||||
builder.setProperties(new String[]{COUNTY_CODE, COUNTY_NAME});
|
||||
|
||||
// read and convert data.
|
||||
Map<String, County> tmpCounties = new HashMap();
|
||||
try (FeatureReader reader = store.getFeatureReader(builder.buildQuery())) {
|
||||
Feature dep;
|
||||
County county;
|
||||
while (reader.hasNext()) {
|
||||
dep = reader.next();
|
||||
county = new County(
|
||||
dep.getPropertyValue(COUNTY_CODE).toString(),
|
||||
dep.getPropertyValue(COUNTY_NAME).toString()
|
||||
);
|
||||
tmpCounties.put(county.code, county);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(tmpCounties);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
try {
|
||||
store.close();
|
||||
} finally {
|
||||
IOUtilities.deleteRecursively(dataDir);
|
||||
}
|
||||
}
|
||||
|
||||
public StringConverter<County> getStringConverter() {
|
||||
return converter;
|
||||
}
|
||||
|
||||
private class Converter extends StringConverter<County> {
|
||||
|
||||
@Override
|
||||
public String toString(County object) {
|
||||
if (object != null)
|
||||
return object.toString();
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public County fromString(String string) {
|
||||
if (string == null || (string = string.trim()).isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Matcher matcher = RhomeoCore.CODE_PATTERN.matcher(string);
|
||||
if (matcher.find()) {
|
||||
return get(matcher.group());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,140 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Reference;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public class FloreBassinReference implements Reference {
|
||||
/**
|
||||
* Primary key.
|
||||
*/
|
||||
private int cd_nom;
|
||||
|
||||
private int cd_ref;
|
||||
|
||||
private String nom;
|
||||
private Integer nutriment;
|
||||
private Integer humidite;
|
||||
private Integer cc;
|
||||
|
||||
public FloreBassinReference() {
|
||||
}
|
||||
|
||||
public FloreBassinReference(@NotNull int cdNom, String nom, Integer nutriment, Integer humidite, Integer cc) {
|
||||
this.cd_nom = cdNom;
|
||||
this.nom = nom;
|
||||
this.nutriment = nutriment;
|
||||
this.humidite = humidite;
|
||||
this.cc = cc;
|
||||
}
|
||||
|
||||
public @NotNull int getCd_nom() {
|
||||
return cd_nom;
|
||||
}
|
||||
|
||||
public void setCd_nom(@NotNull int cd_nom) {
|
||||
this.cd_nom = cd_nom;
|
||||
}
|
||||
|
||||
public @NotNull int getCd_ref() {
|
||||
return cd_ref;
|
||||
}
|
||||
|
||||
public void setCd_ref(@NotNull int cd_ref) {
|
||||
this.cd_ref = cd_ref;
|
||||
}
|
||||
|
||||
public String getNom() {
|
||||
return nom;
|
||||
}
|
||||
|
||||
public void setNom(String nom) {
|
||||
this.nom = nom;
|
||||
}
|
||||
|
||||
public Integer getNutriment() {
|
||||
return nutriment;
|
||||
}
|
||||
|
||||
public void setNutriment(Integer nutriment) {
|
||||
this.nutriment = nutriment;
|
||||
}
|
||||
|
||||
public Integer getHumidite() {
|
||||
return humidite;
|
||||
}
|
||||
|
||||
public void setHumidite(Integer humidite) {
|
||||
this.humidite = humidite;
|
||||
}
|
||||
|
||||
public Integer getCc() {
|
||||
return cc;
|
||||
}
|
||||
|
||||
public void setCc(Integer cc) {
|
||||
this.cc = cc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FloreBassinReference that = (FloreBassinReference) o;
|
||||
|
||||
return cd_nom == that.cd_nom;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return cd_nom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return nom;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.ReferenceDescription;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public class FloreBassinReferenceDescription implements ReferenceDescription<FloreBassinReference> {
|
||||
|
||||
@Override
|
||||
public Class<FloreBassinReference> getReferenceType() {
|
||||
return FloreBassinReference.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "flore_bassin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAlias() {
|
||||
return Collections.singletonList("Valeurs indicatrices des espèces floristiques");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemarks() {
|
||||
return "Référentiel flore agrégeant l'ensemble des taxons du bassin RMC (cf. Gilles PACHE)";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,325 @@
|
||||
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import fr.cenra.rhomeo.api.data.Site;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import fr.cenra.rhomeo.core.util.GeometryUtils;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javafx.beans.binding.BooleanExpression;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import org.apache.sis.internal.system.DefaultFactories;
|
||||
import org.apache.sis.storage.DataStoreException;
|
||||
import org.geotoolkit.data.FeatureCollection;
|
||||
import org.geotoolkit.data.FeatureIterator;
|
||||
import org.geotoolkit.data.FeatureStore;
|
||||
import org.geotoolkit.data.query.QueryBuilder;
|
||||
import org.geotoolkit.data.session.Session;
|
||||
import org.geotoolkit.filter.DefaultPropertyName;
|
||||
import org.geotoolkit.geometry.jts.JTS;
|
||||
import org.geotoolkit.storage.DataStores;
|
||||
import org.opengis.filter.FilterFactory;
|
||||
import org.opengis.filter.FilterFactory2;
|
||||
import org.opengis.util.GenericName;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Johann Sorel (Geomatys)
|
||||
*/
|
||||
public class GeoReferential implements Comparable<GeoReferential>, AutoCloseable{
|
||||
|
||||
private final Site site;
|
||||
private final int year;
|
||||
private final SimpleBooleanProperty zoneHydro = new SimpleBooleanProperty();
|
||||
private final SimpleBooleanProperty tacheUrbaine = new SimpleBooleanProperty();
|
||||
private final SimpleBooleanProperty tacheArtif = new SimpleBooleanProperty();
|
||||
private final SimpleBooleanProperty rpg = new SimpleBooleanProperty();
|
||||
private final SimpleBooleanProperty wfszoneHydro = new SimpleBooleanProperty();
|
||||
private final SimpleBooleanProperty wfstacheUrbaine = new SimpleBooleanProperty();
|
||||
private final SimpleBooleanProperty wfstacheArtif = new SimpleBooleanProperty();
|
||||
private final SimpleBooleanProperty wfsrpg = new SimpleBooleanProperty();
|
||||
private final SimpleBooleanProperty download = new SimpleBooleanProperty();
|
||||
|
||||
private FeatureStore store;
|
||||
|
||||
public GeoReferential(Site site, int year) {
|
||||
this.site = site;
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public BooleanProperty zoneHydroLocal() {
|
||||
return zoneHydro;
|
||||
}
|
||||
|
||||
public BooleanProperty tacheUrbaineLocal() {
|
||||
return tacheUrbaine;
|
||||
}
|
||||
|
||||
public BooleanProperty tacheArtifLocal() {
|
||||
return tacheArtif;
|
||||
}
|
||||
|
||||
public BooleanProperty rpgLocal() {
|
||||
return rpg;
|
||||
}
|
||||
|
||||
public BooleanProperty zoneHydroWFS() {
|
||||
return wfszoneHydro;
|
||||
}
|
||||
|
||||
public BooleanProperty tacheUrbaineWFS() {
|
||||
return wfstacheUrbaine;
|
||||
}
|
||||
|
||||
public BooleanProperty tacheArtifWFS() {
|
||||
return wfstacheArtif;
|
||||
}
|
||||
|
||||
public BooleanProperty rpgWFS() {
|
||||
return wfsrpg;
|
||||
}
|
||||
|
||||
public BooleanProperty toDownloadProperty() {
|
||||
return download;
|
||||
}
|
||||
|
||||
public boolean hasLocalTypes(String ... types){
|
||||
for(String type : types){
|
||||
switch(type.toLowerCase()){
|
||||
case GeoReferentials.TYPE_RPG:
|
||||
if(!rpg.get()) return false;
|
||||
break;
|
||||
case GeoReferentials.TYPE_ZONE_HYDRO:
|
||||
if(!zoneHydro.get()) return false;
|
||||
break;
|
||||
case GeoReferentials.TYPE_TACHE_ARTIF:
|
||||
if(!tacheArtif.get()) return false;
|
||||
break;
|
||||
case GeoReferentials.TYPE_TACHE_URBAINE:
|
||||
if(!tacheUrbaine.get()) return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasWFSTypes(String ... types){
|
||||
for(String type : types){
|
||||
switch(type.toLowerCase()){
|
||||
case GeoReferentials.TYPE_RPG:
|
||||
if(!wfsrpg.get()) return false;
|
||||
break;
|
||||
case GeoReferentials.TYPE_ZONE_HYDRO:
|
||||
if(!wfszoneHydro.get()) return false;
|
||||
break;
|
||||
case GeoReferentials.TYPE_TACHE_ARTIF:
|
||||
if(!wfstacheArtif.get()) return false;
|
||||
break;
|
||||
case GeoReferentials.TYPE_TACHE_URBAINE:
|
||||
if(!wfstacheUrbaine.get()) return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if given types are available either locally or on configured WFS service.
|
||||
* @param types Name of the types to check presence. If null, empty, or if
|
||||
* no valid name is present, we consider that predicate cannot be tested, so
|
||||
* we return false.
|
||||
* @return True if all given names can be found locally or on WFS service.
|
||||
* False otherwise, or if input data is null or empty.
|
||||
*/
|
||||
public boolean areAvailable(final String... types) {
|
||||
if (types == null || types.length < 1)
|
||||
return false;
|
||||
boolean validNameFound = false;
|
||||
for (final String type : types) {
|
||||
if (type != null && !type.isEmpty()) {
|
||||
validNameFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!validNameFound)
|
||||
return false; // No valid name to test.
|
||||
|
||||
for (final String type : types) {
|
||||
if (type == null || type.isEmpty())
|
||||
continue;
|
||||
if (!(hasLocalTypes(type) || hasWFSTypes(type)))
|
||||
return false; // One of the given names is not available.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeName
|
||||
* @return
|
||||
* @throws DataStoreException
|
||||
*/
|
||||
public FeatureCollection getFeatureCollection(String typeName, Geometry intersectGeom) throws DataStoreException{
|
||||
if (store == null) {
|
||||
Path folder = RhomeoCore.REFERENCIELS_GEO_PATH.resolve(GeometryUtils.getSha1(site.getGeometry())).resolve(String.valueOf(year));
|
||||
if (!Files.isDirectory(folder)) {
|
||||
folder = RhomeoCore.REFERENCIELS_GEO_PATH.resolve(site.getName()).resolve(String.valueOf(year));
|
||||
}
|
||||
final Map parameters = new HashMap();
|
||||
parameters.put("identifier", "shapefile-folder");
|
||||
parameters.put("path", folder.toUri());
|
||||
parameters.put("namespace", "no namespace");
|
||||
store = (FeatureStore) DataStores.open(parameters);
|
||||
}
|
||||
|
||||
Set<GenericName> names = store.getNames();
|
||||
if (names == null || names.isEmpty())
|
||||
throw new DataStoreException("No geo-reference available !");
|
||||
GenericName name = null;
|
||||
final String lcTypeName = typeName.toLowerCase();
|
||||
for (final GenericName tmpName : names) {
|
||||
if (tmpName.tip().toString().toLowerCase().startsWith(lcTypeName)) {
|
||||
name = tmpName;
|
||||
}
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
throw new IllegalArgumentException("No reference available for name ".concat(typeName));
|
||||
|
||||
final Session session = store.createSession(true);
|
||||
final QueryBuilder qb = new QueryBuilder();
|
||||
qb.setTypeName(name);
|
||||
|
||||
if(intersectGeom!=null){
|
||||
final FilterFactory2 ff = ((FilterFactory2)DefaultFactories.forBuildin(FilterFactory.class));
|
||||
qb.setFilter(ff.intersects(new DefaultPropertyName("the_geom"), ff.literal(intersectGeom)));
|
||||
}
|
||||
|
||||
return session.getFeatureCollection(qb.buildQuery());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute a geometry which is the union of all geometries in specified
|
||||
* referential which intersect the geometry given as input.
|
||||
* @param typeName Name of the geo-referential to use to get geometies to merge.
|
||||
* @param source Filter geometry.
|
||||
* @return Computed union, or nothing if we cannot find any geometry intercepting given source.
|
||||
* @throws IllegalArgumentException If given type name is not available locally.
|
||||
* @throws DataStoreException If an error occurs while accessing reference data.
|
||||
*/
|
||||
public Optional<Geometry> unionIntersecting(final String typeName, final Geometry source) throws DataStoreException {
|
||||
final FeatureCollection refData = getFeatureCollection(GeoReferentials.TYPE_ZONE_HYDRO, source);
|
||||
Geometry union = null;
|
||||
try (FeatureIterator ite = refData.iterator()) {
|
||||
if (ite.hasNext())
|
||||
while (ite.hasNext()) {
|
||||
final Geometry tmp = (Geometry) ite.next().getDefaultGeometryProperty().getValue();
|
||||
union = union==null ? tmp : tmp.union(union);
|
||||
}
|
||||
}
|
||||
|
||||
if (union != null) {
|
||||
JTS.setCRS(union, refData.getFeatureType().getCoordinateReferenceSystem());
|
||||
}
|
||||
return Optional.ofNullable(union);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(GeoReferential o) {
|
||||
return year - o.year;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if(store!=null){
|
||||
store.close();
|
||||
}
|
||||
}
|
||||
|
||||
public BooleanExpression completed(final String... types) {
|
||||
if (types == null || types.length < 1)
|
||||
return new ReadOnlyBooleanWrapper(false).getReadOnlyProperty();
|
||||
|
||||
final ArrayList<BooleanProperty> deps = new ArrayList<>(types.length);
|
||||
for (final String type : types) {
|
||||
if (type == null || type.isEmpty())
|
||||
continue;
|
||||
switch (type.toLowerCase()) {
|
||||
case GeoReferentials.TYPE_RPG:
|
||||
deps.add(rpg);
|
||||
break;
|
||||
case GeoReferentials.TYPE_ZONE_HYDRO:
|
||||
deps.add(zoneHydro);
|
||||
break;
|
||||
case GeoReferentials.TYPE_TACHE_ARTIF:
|
||||
deps.add(tacheArtif);
|
||||
break;
|
||||
case GeoReferentials.TYPE_TACHE_URBAINE:
|
||||
deps.add(tacheUrbaine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (deps.isEmpty())
|
||||
return new ReadOnlyBooleanWrapper(false).getReadOnlyProperty();
|
||||
|
||||
BooleanExpression result = deps.get(0);
|
||||
for (int i = 1 ; i < deps.size(); i++) {
|
||||
result = result.and(deps.get(i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,531 @@
|
||||
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import fr.cenra.rhomeo.api.data.Site;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import fr.cenra.rhomeo.core.preferences.net.NetPreferences;
|
||||
import fr.cenra.rhomeo.core.util.GeometryUtils;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import org.apache.sis.storage.DataStoreException;
|
||||
import org.geotoolkit.data.FeatureReader;
|
||||
import org.geotoolkit.data.FeatureStoreRuntimeException;
|
||||
import org.geotoolkit.data.FeatureWriter;
|
||||
import org.geotoolkit.data.query.Query;
|
||||
import org.geotoolkit.data.query.QueryBuilder;
|
||||
import org.geotoolkit.data.shapefile.ShapefileFeatureStore;
|
||||
import org.geotoolkit.data.wfs.GetFeatureRequest;
|
||||
import org.geotoolkit.data.wfs.WebFeatureClient;
|
||||
import org.geotoolkit.data.wfs.WebFeatureException;
|
||||
import org.geotoolkit.display2d.GO2Utilities;
|
||||
import org.geotoolkit.feature.Feature;
|
||||
import org.geotoolkit.feature.FeatureTypeBuilder;
|
||||
import org.geotoolkit.feature.FeatureUtilities;
|
||||
import org.geotoolkit.feature.type.AttributeDescriptor;
|
||||
import org.geotoolkit.feature.type.FeatureType;
|
||||
import org.geotoolkit.feature.type.PropertyDescriptor;
|
||||
import org.geotoolkit.feature.xml.XmlFeatureReader;
|
||||
import org.geotoolkit.feature.xml.jaxp.JAXPStreamFeatureReader;
|
||||
import org.geotoolkit.filter.DefaultPropertyName;
|
||||
import org.geotoolkit.map.FeatureMapLayer;
|
||||
import org.geotoolkit.map.MapBuilder;
|
||||
import org.geotoolkit.map.MapItem;
|
||||
import org.geotoolkit.nio.IOUtilities;
|
||||
import org.geotoolkit.wfs.xml.WFSVersion;
|
||||
import org.opengis.filter.Filter;
|
||||
import org.opengis.util.FactoryException;
|
||||
import org.opengis.util.GenericName;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Manage geographic referential.
|
||||
*
|
||||
* @author Johann Sorel (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public class GeoReferentials {
|
||||
|
||||
public static final String TYPE_ZONE_HYDRO = "zonehydro";
|
||||
public static final String TYPE_RPG = "rpg";
|
||||
public static final String TYPE_TACHE_ARTIF = "tacheartif";
|
||||
public static final String TYPE_TACHE_URBAINE = "tacheurbaine";
|
||||
private static final List<String> NAMES = Arrays.asList(TYPE_ZONE_HYDRO,TYPE_RPG,TYPE_TACHE_ARTIF,TYPE_TACHE_URBAINE);
|
||||
|
||||
@Autowired
|
||||
private NetPreferences prefs;
|
||||
|
||||
//cache WFS client
|
||||
private WebFeatureClient wfs;
|
||||
|
||||
private synchronized WebFeatureClient getWFSClient() throws MalformedURLException, DataStoreException, WebFeatureException{
|
||||
if(wfs==null){
|
||||
String url = prefs.getPreference(NetPreferences.WFS_URL);
|
||||
if (url == null || (url = url.trim()).isEmpty())
|
||||
throw new IllegalStateException("Aucune URL disponible pour les référentiels géographiques");
|
||||
wfs = new WebFeatureClient(new URL(url), null, WFSVersion.v110, true);
|
||||
wfs.getNames();
|
||||
}
|
||||
return wfs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine local and server referentials.
|
||||
*
|
||||
* @param site
|
||||
* @return
|
||||
*/
|
||||
public ObservableList<GeoReferential> getReferentials(Site site) throws IllegalArgumentException, IOException, DataStoreException{
|
||||
final ObservableList<GeoReferential> refs = getLocalReferentials(site);
|
||||
|
||||
try {
|
||||
ObservableList<GeoReferential> wfsReferentials = getWFSReferentials();
|
||||
loop:
|
||||
for(GeoReferential gr : wfsReferentials){
|
||||
for(GeoReferential r : refs){
|
||||
if(r.compareTo(gr)==0){
|
||||
r.tacheArtifWFS().set(gr.tacheArtifWFS().get());
|
||||
r.tacheUrbaineWFS().set(gr.tacheUrbaineWFS().get());
|
||||
r.zoneHydroWFS().set(gr.zoneHydroWFS().get());
|
||||
r.rpgWFS().set(gr.rpgWFS().get());
|
||||
continue loop;
|
||||
}
|
||||
}
|
||||
refs.add(gr);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if(refs.isEmpty()){
|
||||
throw ex;
|
||||
}else{
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
//sort by year
|
||||
Collections.sort(refs);
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
/**
|
||||
* List available local referentials for given site.
|
||||
*
|
||||
* @param site
|
||||
* @param year
|
||||
* @return
|
||||
*/
|
||||
public GeoReferential getLocalReferential(Site site, int year) throws IllegalArgumentException, IOException {
|
||||
Path folder = RhomeoCore.REFERENCIELS_GEO_PATH.resolve(GeometryUtils.getSha1(site.getGeometry()));
|
||||
if (!Files.isDirectory(folder)) {
|
||||
folder = RhomeoCore.REFERENCIELS_GEO_PATH.resolve(site.getName());
|
||||
}
|
||||
final String strYear = String.valueOf(year);
|
||||
for(Path p : IOUtilities.listChildren(folder)){
|
||||
if(Files.isDirectory(p)){
|
||||
if(p.getFileName().toString().equals(strYear)){
|
||||
final GeoReferential ref = new GeoReferential(site, year);
|
||||
for(Path tp : IOUtilities.listChildren(p)){
|
||||
final String tName = tp.getFileName().toString().toLowerCase();
|
||||
if(tName.startsWith(TYPE_ZONE_HYDRO)){
|
||||
ref.zoneHydroLocal().set(true);
|
||||
}else if(tName.startsWith(TYPE_TACHE_URBAINE)){
|
||||
ref.tacheUrbaineLocal().set(true);
|
||||
}else if(tName.startsWith(TYPE_TACHE_ARTIF)){
|
||||
ref.tacheArtifLocal().set(true);
|
||||
}else if(tName.startsWith(TYPE_RPG)){
|
||||
ref.rpgLocal().set(true);
|
||||
}
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IOException("Referential for year "+year+" not found");
|
||||
}
|
||||
|
||||
/**
|
||||
* List available local referentials for given site.
|
||||
*
|
||||
* @param site
|
||||
* @return
|
||||
*/
|
||||
public ObservableList<GeoReferential> getLocalReferentials(Site site) throws IllegalArgumentException, IOException {
|
||||
final ObservableList<GeoReferential> lst = FXCollections.observableArrayList();
|
||||
Path folder = RhomeoCore.REFERENCIELS_GEO_PATH.resolve(GeometryUtils.getSha1(site.getGeometry()));
|
||||
if (!Files.isDirectory(folder)) {
|
||||
folder = RhomeoCore.REFERENCIELS_GEO_PATH.resolve(site.getName());
|
||||
}
|
||||
if(Files.isDirectory(folder)){
|
||||
for(Path p : IOUtilities.listChildren(folder)) {
|
||||
if (Files.isDirectory(p)) {
|
||||
final int year;
|
||||
// Ignore directories not matching year names.
|
||||
try {
|
||||
year = Integer.valueOf(p.getFileName().toString());
|
||||
} catch (NumberFormatException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final GeoReferential ref = new GeoReferential(site,year);
|
||||
for(Path tp : IOUtilities.listChildren(p)){
|
||||
final String tName = tp.getFileName().toString().toLowerCase();
|
||||
if(tName.startsWith(TYPE_ZONE_HYDRO)){
|
||||
ref.zoneHydroLocal().set(true);
|
||||
}else if(tName.startsWith(TYPE_TACHE_URBAINE)){
|
||||
ref.tacheUrbaineLocal().set(true);
|
||||
}else if(tName.startsWith(TYPE_TACHE_ARTIF)){
|
||||
ref.tacheArtifLocal().set(true);
|
||||
}else if(tName.startsWith(TYPE_RPG)){
|
||||
ref.rpgLocal().set(true);
|
||||
}
|
||||
}
|
||||
lst.add(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
/**
|
||||
* List server referentials.
|
||||
*
|
||||
* @return
|
||||
* @throws DataStoreException
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public ObservableList<GeoReferential> getWFSReferentials() throws DataStoreException, MalformedURLException, WebFeatureException{
|
||||
|
||||
final Map<String,GeoReferential> count = new HashMap<>();
|
||||
try (WebFeatureClient client = getWFSClient()) {
|
||||
final Set<GenericName> names = client.getNames();
|
||||
for(GenericName name : names){
|
||||
final String[] parts = name.tip().toString().toLowerCase().split("_");
|
||||
if(parts.length==2 && NAMES.contains(parts[0])){
|
||||
GeoReferential ref = count.get(parts[1]);
|
||||
if(ref==null) ref = new GeoReferential(null, Integer.valueOf(parts[1]));
|
||||
switch(parts[0]){
|
||||
case TYPE_ZONE_HYDRO : ref.zoneHydroWFS().set(true); break;
|
||||
case TYPE_RPG : ref.rpgWFS().set(true); break;
|
||||
case TYPE_TACHE_URBAINE : ref.tacheUrbaineWFS().set(true); break;
|
||||
case TYPE_TACHE_ARTIF : ref.tacheArtifWFS().set(true); break;
|
||||
}
|
||||
count.put(parts[1], ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FXCollections.observableArrayList(count.values());
|
||||
}
|
||||
|
||||
public MapItem getWFSLayers(final Optional<Filter> filter, final String... referentialNames) throws DataStoreException, MalformedURLException {
|
||||
MapItem result = MapBuilder.createItem();
|
||||
result.setName("WFS layers");
|
||||
try (WebFeatureClient client = getWFSClient()) {
|
||||
final Set<GenericName> names = client.getNames().stream()
|
||||
.filter(name -> {
|
||||
if (referentialNames == null || referentialNames.length < 1)
|
||||
return true;
|
||||
for (final String refName : referentialNames) {
|
||||
if (name.tip().toString().toLowerCase().startsWith(refName.toLowerCase()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.collect(Collectors.toSet());
|
||||
for (GenericName name : names) {
|
||||
Query q = filter
|
||||
.map(f -> {
|
||||
final QueryBuilder builder = new QueryBuilder(name);
|
||||
builder.setFilter(f);
|
||||
builder.setProperties(new String[]{"geom"});
|
||||
return builder.buildQuery();
|
||||
})
|
||||
.orElseGet(() -> QueryBuilder.all(name));
|
||||
final FeatureMapLayer layer = MapBuilder.createFeatureLayer(
|
||||
client.createSession(false).getFeatureCollection(q)
|
||||
);
|
||||
layer.setName(name.tip().toString());
|
||||
layer.setVisible(false);
|
||||
result.items().add(layer);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download from WFS service the referential for specified year.
|
||||
*
|
||||
* @param site analyze site
|
||||
* @param year georeferential year
|
||||
* @throws IllegalArgumentException If we cannot find any hydrographic zone
|
||||
* intersecting site buffer.
|
||||
* @throws Exception Any other exception is a read/write error.
|
||||
*/
|
||||
public void downloadReferential(Site site, int year) throws Exception {
|
||||
|
||||
final Path localFolder = RhomeoCore.REFERENCIELS_GEO_PATH.resolve(GeometryUtils.getSha1(site.getGeometry())).resolve(String.valueOf(year));
|
||||
|
||||
//extract only data on site envelope
|
||||
//not : this will be replace by hydro area after it has been downloaded
|
||||
final Geometry buffer = GeometryUtils.computeBuffer(site.getGeometry());
|
||||
|
||||
//connect to WFS service
|
||||
try (WebFeatureClient client = getWFSClient()) {
|
||||
// First, we download hydrology data, because there's a special treatment over it.
|
||||
downloadReferential(TYPE_ZONE_HYDRO + '_' + year, localFolder, buffer, false, client);
|
||||
Geometry[] zhs = getLocalReferential(site, year).getFeatureCollection(TYPE_ZONE_HYDRO, null).stream()
|
||||
.map(feat -> feat.getDefaultGeometryProperty().getValue())
|
||||
.filter(geom -> geom instanceof Geometry)
|
||||
.toArray(size -> new Geometry[size]);
|
||||
Geometry zhUnion = GO2Utilities.JTS_FACTORY.createGeometryCollection(zhs).union();
|
||||
|
||||
// Get other referentials
|
||||
final Set<String> names = new HashSet<>(NAMES);
|
||||
names.remove(TYPE_ZONE_HYDRO);
|
||||
for (String name : names) {
|
||||
//some layers may be missing, P08 and P09 use different refentials.
|
||||
try {
|
||||
downloadReferential(name + '_' + year, localFolder, zhUnion, true, client);
|
||||
} catch (IllegalArgumentException e) {
|
||||
RhomeoCore.LOGGER.log(Level.FINE, "Cannot download referential", e);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
//erase local folder if an error occurs
|
||||
IOUtilities.deleteRecursively(localFolder);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a single referential using given parameters.
|
||||
* @param refName Name of the layer to request.
|
||||
* @param targetDir Folder to put downloaded data into.
|
||||
* @param zone Geometry delimiting the area to download (intersection filter performed).
|
||||
* @param cut
|
||||
* @param client Client to use to query WFS service.
|
||||
* @throws DataStoreException Error on reading / writing.
|
||||
* @throws IOException Error on reading / writing.
|
||||
* @throws FactoryException Error on reading / writing.
|
||||
* @throws XMLStreamException Error on reading / writing.
|
||||
* @throws IllegalArgumentException If we cannot find given layer name on
|
||||
* the server, or no data intersects given zone.
|
||||
*/
|
||||
protected void downloadReferential(final String refName, final Path targetDir, final Geometry zone, final boolean cut, final WebFeatureClient client)
|
||||
throws DataStoreException, IOException, FactoryException, XMLStreamException {
|
||||
//find feature type full name
|
||||
GenericName fullName = null;
|
||||
for (GenericName n : client.getNames()) {
|
||||
if (n.tip().toString().equalsIgnoreCase(refName)) {
|
||||
fullName = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fullName == null) { // TODO : throw illegalArgumentException managed above.
|
||||
throw new IllegalArgumentException("No layer found for name ".concat(refName));
|
||||
}
|
||||
|
||||
//prepare query
|
||||
final FeatureType featureType = client.getFeatureType(fullName);
|
||||
final FeatureTypeBuilder outputBuilder = new FeatureTypeBuilder();
|
||||
outputBuilder.setName(fullName);
|
||||
final QueryBuilder qb = new QueryBuilder(fullName);
|
||||
// We are only able to store simple features, so we remove complex
|
||||
// structure from WFS data.
|
||||
final List<String> props = new ArrayList<>();
|
||||
for (PropertyDescriptor desc : featureType.getDescriptors()) {
|
||||
if (isSimpleAttribute(desc)) {
|
||||
props.add(desc.getName().toString());
|
||||
outputBuilder.add(desc);
|
||||
}
|
||||
}
|
||||
|
||||
qb.setProperties(props.toArray(new String[0]));
|
||||
qb.setCRS(RhomeoCore.getSiteCRS());
|
||||
//extract only data on site envelope
|
||||
qb.setFilter(GO2Utilities.FILTER_FACTORY.intersects(
|
||||
new DefaultPropertyName(featureType.getGeometryDescriptor().getName().tip().toString()),
|
||||
GO2Utilities.FILTER_FACTORY.literal(zone)
|
||||
));
|
||||
|
||||
//copy data to local folder
|
||||
Files.createDirectories(targetDir);
|
||||
try (final FeatureReader reader = getStreamingReader(client, qb.buildQuery());
|
||||
final ShapefileFeatureStore outStore = new ShapefileFeatureStore(targetDir.resolve(refName + ".shp").toUri())) {
|
||||
if (!reader.hasNext())
|
||||
throw new IllegalArgumentException("No data intersects given zone for layer ".concat(fullName.toString()));
|
||||
outStore.createFeatureType(fullName, outputBuilder.buildSimpleFeatureType());
|
||||
try (final FeatureWriter writer = outStore.getFeatureWriterAppend(fullName)) {
|
||||
if (cut) {
|
||||
while (reader.hasNext()) {
|
||||
final Feature next = reader.next();
|
||||
Object value = next.getDefaultGeometryProperty().getValue();
|
||||
if (value instanceof Geometry)
|
||||
next.getDefaultGeometryProperty().setValue(zone.intersection((Geometry) value));
|
||||
FeatureUtilities.copy(next, writer.next(), false);
|
||||
}
|
||||
} else {
|
||||
while (reader.hasNext()) {
|
||||
FeatureUtilities.copy(reader.next(), writer.next(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSimpleAttribute(final PropertyDescriptor property) {
|
||||
return property.getMinOccurs() == 1 &&
|
||||
property.getMaxOccurs() == 1 &&
|
||||
property instanceof AttributeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a getFeature on the distant server, browing its content lazily.
|
||||
* @param client The client to use for request.
|
||||
* @param query The query which contains reading parameters.
|
||||
* @return A reader to stream service response.
|
||||
* @throws DataStoreException
|
||||
* @throws IOException
|
||||
* @throws XMLStreamException
|
||||
*/
|
||||
private FeatureReader getStreamingReader(final WebFeatureClient client, final Query query) throws DataStoreException, IOException, XMLStreamException {
|
||||
|
||||
final GetFeatureRequest request = client.createGetFeature();
|
||||
request.setTypeName(new QName(query.getTypeName().tip().toString()));
|
||||
|
||||
final Filter filter = query.getFilter();
|
||||
if (filter == null) {
|
||||
request.setFilter(Filter.INCLUDE);
|
||||
} else {
|
||||
request.setFilter(filter);
|
||||
}
|
||||
|
||||
final Integer max = query.getMaxFeatures();
|
||||
if (max != null) {
|
||||
request.setMaxFeatures(max);
|
||||
}
|
||||
|
||||
request.setPropertyNames(query.getPropertyNames());
|
||||
|
||||
XmlFeatureReader reader = null;
|
||||
reader = new JAXPStreamFeatureReader(client.getFeatureType(query.getTypeName()));
|
||||
reader.getProperties().put(JAXPStreamFeatureReader.SKIP_UNEXPECTED_PROPERTY_TAGS, true);
|
||||
final InputStream stream;
|
||||
if (client.getUsePost()) {
|
||||
stream = request.getResponseStream();
|
||||
} else {
|
||||
final URL url = request.getURL();
|
||||
stream = url.openStream();
|
||||
}
|
||||
|
||||
// If reader creation fails, stream isn't hanging on.
|
||||
try {
|
||||
return new StreamingFeatureReader(reader.readAsStream(stream), stream);
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Throwable t1) {
|
||||
t.addSuppressed(t1);
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
private static class StreamingFeatureReader implements FeatureReader {
|
||||
|
||||
final FeatureReader source;
|
||||
final InputStream dataSource;
|
||||
|
||||
public StreamingFeatureReader(final FeatureReader source, final InputStream dataSource) {
|
||||
this.source = source;
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureType getFeatureType() {
|
||||
return source.getFeatureType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Feature next() throws FeatureStoreRuntimeException {
|
||||
return source.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() throws FeatureStoreRuntimeException {
|
||||
return source.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
source.close();
|
||||
} finally {
|
||||
try {
|
||||
dataSource.close();
|
||||
} catch (IOException ex) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "An error occurred while closing data stream.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,218 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Reference;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Odonata presence by department.
|
||||
*
|
||||
* Colonne | Type | Modificateurs
|
||||
* ---------+------------------------+---------------
|
||||
* espece | character varying(255) |
|
||||
* dept | character varying(255) |
|
||||
* valeur | double precision |
|
||||
* id_dept | character varying(2) |
|
||||
* cd_nom | integer |
|
||||
* cd_ref | integer |
|
||||
*
|
||||
* (Source : base issue du script RhoMéO_Geomatys.backup)
|
||||
*
|
||||
* Note : There is no explicit primary key, but it seems logic for the key to be
|
||||
* (cd_nom, id_dept).
|
||||
*
|
||||
* Remarques :
|
||||
*
|
||||
* L'absence de contrainte d'intégrité rend l'analyse sémantique de la table non
|
||||
* triviale.
|
||||
*
|
||||
* Sémantique
|
||||
* ==========
|
||||
*
|
||||
* Même si logiquement la clef devrait être (cd_nom, id_dept), il
|
||||
* semble que les combinaisons (cd_ref, id_dept) soient également "sémantiquement" uniques
|
||||
* car en nombre identique.
|
||||
*
|
||||
* select count(*) from (select distinct cd_ref, id_dept from odo_especes_par_dept) as tab;
|
||||
* count
|
||||
*-------
|
||||
* 2436
|
||||
*
|
||||
* select count(*) from (select distinct cd_nom, id_dept from odo_especes_par_dept) as tab;
|
||||
* count
|
||||
*-------
|
||||
* 2436
|
||||
*
|
||||
* Toutefois, on ne peut pas en déduire l'identité entre cd_nom et cd_ref dans la
|
||||
* table (ce qui est logique). Nous avons d'ailleurs :
|
||||
*
|
||||
* select distinct cd_nom, cd_ref from odo_especes_par_dept where cd_nom<>cd_ref;
|
||||
* cd_nom | cd_ref
|
||||
*--------+--------
|
||||
* 820003 | 645873
|
||||
*
|
||||
*
|
||||
* Creation of the reference list from the database
|
||||
* ================================================
|
||||
*
|
||||
* Export csv
|
||||
* ----------
|
||||
* copy (
|
||||
* select * from odo_especes_par_dept
|
||||
* )
|
||||
* to '/…/odo_especes_par_dept.csv' delimiter ';' csv header;
|
||||
*
|
||||
* Dumps
|
||||
* -----
|
||||
* pg_dump -t referentiels_non_geo.odo_especes_par_dept rhomeo > /…/odo_especes_par_dept.copy.sql
|
||||
* pg_dump --inserts -t referentiels_non_geo.odo_especes_par_dept rhomeo > /…/odo_especes_par_dept.inserts.sql
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys) <samuel.andres at geomatys.com>
|
||||
*/
|
||||
public class OdonataDepartmentReference implements Reference {
|
||||
|
||||
// META-INFORMATION : ATTRIBUTE NAMES
|
||||
// MUST BE CONSISTENT WITH CLASS ATTRIBUTES
|
||||
public static final String ATT_CD_NOM = "cd_nom";
|
||||
public static final String ATT_CD_REF = "cd_ref";
|
||||
public static final String ATT_ESPECE = "espece";
|
||||
public static final String ATT_ID_DEPT = "id_dept";
|
||||
public static final String ATT_DEPT = "dept";
|
||||
public static final String ATT_VALEUR = "valeur";
|
||||
|
||||
// Species attributes
|
||||
private int cd_nom;
|
||||
private int cd_ref;
|
||||
private String espece;
|
||||
|
||||
// Department attributes
|
||||
private String id_dept;
|
||||
private String dept;
|
||||
|
||||
private double valeur;
|
||||
|
||||
public int getCd_nom() {
|
||||
return cd_nom;
|
||||
}
|
||||
|
||||
public void setCd_nom(int cd_nom) {
|
||||
this.cd_nom = cd_nom;
|
||||
}
|
||||
|
||||
public int getCd_ref() {
|
||||
return cd_ref;
|
||||
}
|
||||
|
||||
public void setCd_ref(int cd_ref) {
|
||||
this.cd_ref = cd_ref;
|
||||
}
|
||||
|
||||
public String getEspece() {
|
||||
return espece;
|
||||
}
|
||||
|
||||
public void setEspece(String espece) {
|
||||
this.espece = espece;
|
||||
}
|
||||
|
||||
public String getId_dept() {
|
||||
return id_dept;
|
||||
}
|
||||
|
||||
public void setId_dept(String id_dept) {
|
||||
this.id_dept = id_dept;
|
||||
}
|
||||
|
||||
public String getDept() {
|
||||
return dept;
|
||||
}
|
||||
|
||||
public void setDept(String dept) {
|
||||
this.dept = dept;
|
||||
}
|
||||
|
||||
public double getValeur() {
|
||||
return valeur;
|
||||
}
|
||||
|
||||
public void setValeur(double valeur) {
|
||||
this.valeur = valeur;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 89 * hash + this.cd_nom; // same cd_nom => same cd_ref and same espece (interpretation)
|
||||
hash = 89 * hash + Objects.hashCode(this.id_dept); // same id_dept => same dept
|
||||
hash = 89 * hash + (int) (Double.doubleToLongBits(this.valeur) ^ (Double.doubleToLongBits(this.valeur) >>> 32));
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final OdonataDepartmentReference other = (OdonataDepartmentReference) obj;
|
||||
if (this.cd_nom != other.cd_nom) {
|
||||
return false;
|
||||
} // same cd_nom => same cd_ref and same espece (interpretation)
|
||||
if (Double.doubleToLongBits(this.valeur) != Double.doubleToLongBits(other.valeur)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.id_dept, other.id_dept)) {
|
||||
return false;
|
||||
} // same id_dept => same dept
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder(Integer.toString(cd_nom)).append('|').append(espece).append('|').append(dept).append('|').append(valeur).toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.ReferenceDescription;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys) <samuel.andres at geomatys.com>
|
||||
*/
|
||||
@Component
|
||||
public class OdonataDepartmentReferenceDescription implements ReferenceDescription<OdonataDepartmentReference> {
|
||||
|
||||
public static final String ODONATA_DEPARTMENT_DESCRIPTION_NAME = "odo_especes_par_dept";
|
||||
|
||||
@Override
|
||||
public Class<OdonataDepartmentReference> getReferenceType() {
|
||||
return OdonataDepartmentReference.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return ODONATA_DEPARTMENT_DESCRIPTION_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAlias() {
|
||||
return Collections.singleton("Répartition des odonates par département");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemarks() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,208 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Reference;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* Affinity of Odonata species with different kinds of odonatologic habitat.
|
||||
*
|
||||
* Value range is from 1 to 4.
|
||||
*
|
||||
* Colonne | Type | Modificateurs
|
||||
*---------+------------------------+---------------
|
||||
* espece | character varying(255) |
|
||||
* biogeo | character varying(255) |
|
||||
* habitat | character varying(255) |
|
||||
* valeur | character varying(255) |
|
||||
* zbio | character varying(255) |
|
||||
* cd_nom | integer |
|
||||
* cd_ref | integer |
|
||||
*
|
||||
* (Source : base issue du script RhoMéO_Geomatys.backup)
|
||||
*
|
||||
* Note : There is no explicit primary key, but it seems logic for the key to be
|
||||
* (cd_nom, zbio, habitat).
|
||||
*
|
||||
* Creation of the reference list from the database
|
||||
* ================================================
|
||||
*
|
||||
* Export csv
|
||||
* ----------
|
||||
* copy (
|
||||
* select * from odo_dependance_habitat
|
||||
* )
|
||||
* to '/…/odo_dependance_habitat.csv' delimiter ';' csv header;
|
||||
*
|
||||
* Dumps
|
||||
* -----
|
||||
* pg_dump -t referentiels_non_geo.odo_dependance_habitat rhomeo > /…/odo_dependance_habitat.copy.sql
|
||||
* pg_dump --inserts -t referentiels_non_geo.odo_dependance_habitat rhomeo > /…/odo_dependance_habitat.inserts.sql
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys) <samuel.andres at geomatys.com>
|
||||
*/
|
||||
public class OdonataHabitatReference implements Reference {
|
||||
|
||||
// META-INFORMATION : ATTRIBUTE NAMES
|
||||
// MUST BE CONSISTENT WITH CLASS ATTRIBUTES
|
||||
public static final String ATT_CD_NOM = "cd_nom";
|
||||
public static final String ATT_CD_REF = "cd_ref";
|
||||
public static final String ATT_ESPECE = "espece";
|
||||
public static final String ATT_ZBIO = "zbio";
|
||||
public static final String ATT_BIOGEO = "biogeo";
|
||||
public static final String ATT_HABITAT = "habitat";
|
||||
public static final String ATT_VALEUR = "valeur";
|
||||
|
||||
// Species attributes
|
||||
private int cd_nom;
|
||||
private int cd_ref;
|
||||
private String espece;
|
||||
|
||||
// biozone attributes
|
||||
private String zbio;
|
||||
private String biogeo;
|
||||
|
||||
// Habitat
|
||||
private String habitat;
|
||||
|
||||
// Value for a association between a species, a biozone and an habitat.
|
||||
private int valeur;
|
||||
|
||||
public int getCd_nom() {
|
||||
return cd_nom;
|
||||
}
|
||||
|
||||
public void setCd_nom(int cd_nom) {
|
||||
this.cd_nom = cd_nom;
|
||||
}
|
||||
|
||||
public int getCd_ref() {
|
||||
return cd_ref;
|
||||
}
|
||||
|
||||
public void setCd_ref(int cd_ref) {
|
||||
this.cd_ref = cd_ref;
|
||||
}
|
||||
|
||||
public String getEspece() {
|
||||
return espece;
|
||||
}
|
||||
|
||||
public void setEspece(String espece) {
|
||||
this.espece = espece;
|
||||
}
|
||||
|
||||
public String getZbio() {
|
||||
return zbio;
|
||||
}
|
||||
|
||||
public void setZbio(String zbio) {
|
||||
this.zbio = zbio;
|
||||
}
|
||||
|
||||
public String getBiogeo() {
|
||||
return biogeo;
|
||||
}
|
||||
|
||||
public void setBiogeo(String biogeo) {
|
||||
this.biogeo = biogeo;
|
||||
}
|
||||
|
||||
public String getHabitat() {
|
||||
return habitat;
|
||||
}
|
||||
|
||||
public void setHabitat(String habitat) {
|
||||
if (habitat != null && habitat.startsWith("0"))
|
||||
habitat = habitat.substring(1);
|
||||
this.habitat = habitat;
|
||||
}
|
||||
|
||||
public int getValeur() {
|
||||
return valeur;
|
||||
}
|
||||
|
||||
public void setValeur(int valeur) {
|
||||
this.valeur = valeur;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 59 * hash + this.cd_nom; // same cd_nom => same cd_ref and same espece (interpretation)
|
||||
hash = 59 * hash + Objects.hashCode(this.zbio); // same zbio => same biogeo (interpretation)
|
||||
hash = 59 * hash + Objects.hashCode(this.habitat);
|
||||
hash = 61 * hash + this.valeur;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final OdonataHabitatReference other = (OdonataHabitatReference) obj;
|
||||
if (this.cd_nom != other.cd_nom) {
|
||||
return false;
|
||||
} // same cd_nom => same cd_ref and same espece (interpretation)
|
||||
if (!Objects.equals(this.zbio, other.zbio)) {
|
||||
return false;
|
||||
} // same zbio => same biogeo (interpretation)
|
||||
if (!Objects.equals(this.habitat, other.habitat)) {
|
||||
return false;
|
||||
}
|
||||
if (this.valeur != other.valeur) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder(Integer.toString(cd_nom)).append('|').append(cd_ref).append('|').append(espece).append('|').append(habitat).append('|').append(valeur).toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.ReferenceDescription;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys) <samuel.andres at geomatys.com>
|
||||
*/
|
||||
@Component
|
||||
public class OdonataHabitatReferenceDescription implements ReferenceDescription<OdonataHabitatReference> {
|
||||
|
||||
public static final String ODONATA_HABITAT_DESCRIPTION_NAME = "odo_dependance_habitat";
|
||||
|
||||
@Override
|
||||
public Class<OdonataHabitatReference> getReferenceType() {
|
||||
return OdonataHabitatReference.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return ODONATA_HABITAT_DESCRIPTION_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAlias() {
|
||||
return Collections.singleton("Liste des affinités des odonates par habitat odonatologique");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemarks() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,245 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Reference;
|
||||
|
||||
/**
|
||||
* Orthopterans indicator reference representation.
|
||||
*
|
||||
* Colonne | Type | Modificateurs
|
||||
* -------------------+------------------------+---------------
|
||||
* cd_nom | integer | non NULL
|
||||
* cd_ref | integer |
|
||||
* lb_nom | character varying(255) |
|
||||
* pres_lr | integer |
|
||||
* pres_ra | integer |
|
||||
* pres_paca | integer |
|
||||
* hs_code | integer |
|
||||
* hs_val | integer |
|
||||
* dm_code | integer |
|
||||
* dm_val | integer |
|
||||
* mediterraneen1_ml | integer |
|
||||
* mediterraneen1_ma | integer |
|
||||
* mediterraneen2_ma | integer |
|
||||
* mediterraneen2_tb | integer |
|
||||
* alpin_ma | integer |
|
||||
* alpin_tb | integer |
|
||||
* continental_ma | integer |
|
||||
* continental_tb | integer |
|
||||
*
|
||||
* (Source : base issue du script RhoMéO_Geomatys.backup)
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*/
|
||||
public class OrthopteraIndicatorReference implements Reference {
|
||||
|
||||
/**
|
||||
* CD_REF of the reference taxon.
|
||||
*/
|
||||
private int cd_ref;
|
||||
|
||||
private int mediterraneen1_ml;// Pourquoi pas booleen ?
|
||||
private int mediterraneen1_ma;// Pourquoi pas booleen ?
|
||||
private int mediterraneen2_ma;// Pourquoi pas booleen ?
|
||||
private int mediterraneen2_tb;// Pourquoi pas booleen ?
|
||||
private int alpin_ma;// Pourquoi pas booleen ?
|
||||
private int alpin_tb;// Pourquoi pas booleen ?
|
||||
private int continental_ma;// Pourquoi pas booleen ?
|
||||
private int continental_tb;// Pourquoi pas booleen ?
|
||||
|
||||
/**
|
||||
* Name of the taxon.
|
||||
*/
|
||||
private String lb_nom;
|
||||
|
||||
private int hs_code;
|
||||
|
||||
/**
|
||||
* Environment humidity
|
||||
*/
|
||||
private int hs_val;
|
||||
|
||||
private int dm_code;
|
||||
|
||||
/**
|
||||
* Sedimentary dynamics
|
||||
*/
|
||||
private int dm_val;
|
||||
|
||||
public int getCd_ref() {
|
||||
return cd_ref;
|
||||
}
|
||||
|
||||
public void setCd_ref(int cd_ref) {
|
||||
this.cd_ref = cd_ref;
|
||||
}
|
||||
|
||||
public int getMediterraneen1_ml() {
|
||||
return mediterraneen1_ml;
|
||||
}
|
||||
|
||||
public void setMediterraneen1_ml(int mediterraneen1_ml) {
|
||||
this.mediterraneen1_ml = mediterraneen1_ml;
|
||||
}
|
||||
|
||||
public int getMediterraneen1_ma() {
|
||||
return mediterraneen1_ma;
|
||||
}
|
||||
|
||||
public void setMediterraneen1_ma(int mediterraneen1_ma) {
|
||||
this.mediterraneen1_ma = mediterraneen1_ma;
|
||||
}
|
||||
|
||||
public int getMediterraneen2_ma() {
|
||||
return mediterraneen2_ma;
|
||||
}
|
||||
|
||||
public void setMediterraneen2_ma(int mediterraneen2_ma) {
|
||||
this.mediterraneen2_ma = mediterraneen2_ma;
|
||||
}
|
||||
|
||||
public int getMediterraneen2_tb() {
|
||||
return mediterraneen2_tb;
|
||||
}
|
||||
|
||||
public void setMediterraneen2_tb(int mediterraneen2_tb) {
|
||||
this.mediterraneen2_tb = mediterraneen2_tb;
|
||||
}
|
||||
|
||||
public int getAlpin_ma() {
|
||||
return alpin_ma;
|
||||
}
|
||||
|
||||
public void setAlpin_ma(int alpin_ma) {
|
||||
this.alpin_ma = alpin_ma;
|
||||
}
|
||||
|
||||
public int getAlpin_tb() {
|
||||
return alpin_tb;
|
||||
}
|
||||
|
||||
public void setAlpin_tb(int alpin_tb) {
|
||||
this.alpin_tb = alpin_tb;
|
||||
}
|
||||
|
||||
public int getContinental_ma() {
|
||||
return continental_ma;
|
||||
}
|
||||
|
||||
public void setContinental_ma(int continental_ma) {
|
||||
this.continental_ma = continental_ma;
|
||||
}
|
||||
|
||||
public int getContinental_tb() {
|
||||
return continental_tb;
|
||||
}
|
||||
|
||||
public void setContinental_tb(int continental_tb) {
|
||||
this.continental_tb = continental_tb;
|
||||
}
|
||||
|
||||
public String getLb_nom() {
|
||||
return lb_nom;
|
||||
}
|
||||
|
||||
public void setLb_nom(String lb_nom) {
|
||||
this.lb_nom = lb_nom;
|
||||
}
|
||||
|
||||
public int getHs_code() {
|
||||
return hs_code;
|
||||
}
|
||||
|
||||
public void setHs_code(int hs_code) {
|
||||
this.hs_code = hs_code;
|
||||
}
|
||||
|
||||
public int getHs_val() {
|
||||
return hs_val;
|
||||
}
|
||||
|
||||
public void setHs_val(int hs_val) {
|
||||
this.hs_val = hs_val;
|
||||
}
|
||||
|
||||
public int getDm_code() {
|
||||
return dm_code;
|
||||
}
|
||||
|
||||
public void setDm_code(int dm_code) {
|
||||
this.dm_code = dm_code;
|
||||
}
|
||||
|
||||
public int getDm_val() {
|
||||
return dm_val;
|
||||
}
|
||||
|
||||
public void setDm_val(int dm_val) {
|
||||
this.dm_val = dm_val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return cd_ref;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final OrthopteraIndicatorReference other = (OrthopteraIndicatorReference) obj;
|
||||
return getCd_ref() == other.getCd_ref()
|
||||
&& getHs_val() == other.getHs_val()
|
||||
&& getDm_val() == other.getDm_val();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder().append(cd_ref).append(' ').append(lb_nom).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.ReferenceDescription;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys) <samuel.andres at geomatys.com>
|
||||
*/
|
||||
@Component
|
||||
public class OrthopteraIndicatorReferenceDescription implements ReferenceDescription<OrthopteraIndicatorReference> {
|
||||
|
||||
public static final String ORTHOPTERA_INDICATOR_DESCRIPTION_NAME = "ortho_indicateurs";
|
||||
|
||||
@Override
|
||||
public Class<OrthopteraIndicatorReference> getReferenceType() {
|
||||
return OrthopteraIndicatorReference.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return ORTHOPTERA_INDICATOR_DESCRIPTION_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAlias() {
|
||||
return Collections.singleton("Liste des valeurs indicatrices des orthoptères");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemarks() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,202 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Reference;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Taxref taxonomic referential representation.
|
||||
*
|
||||
*
|
||||
* Colonne | Type | Modificateurs
|
||||
* --------------+----------------------+---------------
|
||||
* regne | text |
|
||||
* phylum | text |
|
||||
* classe | text |
|
||||
* ordre | text |
|
||||
* famille | text |
|
||||
* cd_nom | character varying(6) | non NULL
|
||||
* cd_taxsup | character varying(6) |
|
||||
* cd_ref | character varying(6) |
|
||||
* rang | text |
|
||||
* lb_nom | text |
|
||||
* lb_auteur | text |
|
||||
* nom_complet | text |
|
||||
* nom_valide | text |
|
||||
* nom_vern | text |
|
||||
* nom_vern_eng | text |
|
||||
* habitat | text |
|
||||
* fr | text |
|
||||
* gf | text |
|
||||
* mar | text |
|
||||
* gua | text |
|
||||
* sm | text |
|
||||
* sb | text |
|
||||
* spm | text |
|
||||
* may | text |
|
||||
* epa | text |
|
||||
* reu | text |
|
||||
* taaf | text |
|
||||
* pf | text |
|
||||
* nc | text |
|
||||
* wf | text |
|
||||
* cli | text |
|
||||
* aphia_id | text |
|
||||
*
|
||||
* (Source : base issue du script RhoMéO_Geomatys.backup)
|
||||
*
|
||||
* @author Samuel Andrés
|
||||
*
|
||||
* @see TaxrefDescription
|
||||
*/
|
||||
public class Taxref implements Reference {
|
||||
|
||||
// META-INFORMATION : ATTRIBUTE NAMES
|
||||
// MUST BE CONSISTENT WITH CLASS ATTRIBUTES
|
||||
public static final String ATT_CD_NOM = "cd_nom";
|
||||
public static final String ATT_CD_TAXSUP = "cd_taxsup";
|
||||
public static final String ATT_CD_REF = "cd_ref";
|
||||
public static final String ATT_RANG = "rang";
|
||||
public static final String ATT_NOM_COMPLET = "nomComplet";
|
||||
|
||||
// Other constants
|
||||
public static final String RANG_SSES = "SSES";
|
||||
|
||||
/**
|
||||
* Primary key.
|
||||
*/
|
||||
private int cd_nom;
|
||||
|
||||
private int cd_taxsup;
|
||||
|
||||
private int cd_ref;
|
||||
|
||||
private String rang;
|
||||
|
||||
private String lb_nom;
|
||||
|
||||
private String ordre;
|
||||
|
||||
private String classe;
|
||||
|
||||
public int getCd_nom() {
|
||||
return cd_nom;
|
||||
}
|
||||
|
||||
public void setCd_nom(int cd_nom) {
|
||||
this.cd_nom = cd_nom;
|
||||
}
|
||||
|
||||
public int getCd_taxsup() {
|
||||
return cd_taxsup;
|
||||
}
|
||||
|
||||
public void setCd_taxsup(int cd_taxsup) {
|
||||
this.cd_taxsup = cd_taxsup;
|
||||
}
|
||||
|
||||
public int getCd_ref() {
|
||||
return cd_ref;
|
||||
}
|
||||
|
||||
public void setCd_ref(int cd_ref) {
|
||||
this.cd_ref = cd_ref;
|
||||
}
|
||||
|
||||
public String getRang() {
|
||||
return rang;
|
||||
}
|
||||
|
||||
public void setRang(String rang) {
|
||||
this.rang = rang;
|
||||
}
|
||||
|
||||
public String getLb_nom() {
|
||||
return lb_nom;
|
||||
}
|
||||
|
||||
public void setLb_nom(String nomComplet) {
|
||||
this.lb_nom = nomComplet;
|
||||
}
|
||||
|
||||
public String getOrdre() {
|
||||
return ordre;
|
||||
}
|
||||
|
||||
public void setOrdre(String ordre) {
|
||||
this.ordre = ordre;
|
||||
}
|
||||
|
||||
public String getClasse() {
|
||||
return classe;
|
||||
}
|
||||
|
||||
public void setClasse(String classe) {
|
||||
this.classe = classe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return cd_nom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Taxref other = (Taxref) obj;
|
||||
if (!Objects.equals(this.cd_nom, other.cd_nom)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return lb_nom;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.reference;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.ReferenceDescription;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Description of the {@link Taxref} reference type.
|
||||
*
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public class TaxrefDescription implements ReferenceDescription<Taxref> {
|
||||
|
||||
private static final String TAXREF_DESCRIPTION_NAME = "taxref";
|
||||
|
||||
@Override
|
||||
public Class<Taxref> getReferenceType() {
|
||||
return Taxref.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return TAXREF_DESCRIPTION_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAlias() {
|
||||
return Collections.singletonList("Référentiel taxonomique");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemarks() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.site;
|
||||
|
||||
/**
|
||||
* Exception to launch when trying to use the same key for several items in the same collection.
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public class DuplicatedKeyException extends Exception {
|
||||
|
||||
public DuplicatedKeyException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public DuplicatedKeyException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.site;
|
||||
|
||||
import fr.cenra.rhomeo.api.IdentifiedObject;
|
||||
import javafx.collections.ObservableList;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
|
||||
|
||||
/**
|
||||
* Generic data access methods all project repositories should have.
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
* @param <I>
|
||||
*/
|
||||
public interface RhomeoRepository<I extends IdentifiedObject> {
|
||||
/**
|
||||
* Find the item for the given key.
|
||||
*
|
||||
* @param key An item key
|
||||
* @return The matching item, or {@code null} if not found.
|
||||
*/
|
||||
I findOne(@NotBlank String key);
|
||||
|
||||
/**
|
||||
* Create an item in the data source if the item key is not already present in the store,
|
||||
* otherwise throws {@link DuplicatedKeyException}.
|
||||
*
|
||||
* @param object The new item to create, should not be {@code null}
|
||||
* @throws DuplicatedKeyException if an object already exists with the same key
|
||||
*/
|
||||
void create(@NotNull I object) throws DuplicatedKeyException;
|
||||
|
||||
/**
|
||||
* Find all items in the data source.
|
||||
*
|
||||
* @return A list of items stored, eventually an empty list, never {@code null}
|
||||
*/
|
||||
ObservableList<I> findAll();
|
||||
|
||||
/**
|
||||
* Update an existing item in the data source. Its key should be the same in the
|
||||
* given object and in the stored version in order to know which item has to be updated.
|
||||
* If the given object key is not known in the store, then do nothing.
|
||||
*
|
||||
* @param object Item to update, with new values. Should not be {@code null}.
|
||||
*/
|
||||
void update(@NotNull I object);
|
||||
|
||||
/**
|
||||
* Update an existing item in the data source. The given object may have a new key specified,
|
||||
* so use the old key parameter to know which item should be updated.
|
||||
*
|
||||
* @param object Item to update, with new values. Should not be {@code null}.
|
||||
* @param oldKey Existing item key to update.
|
||||
* @throws DuplicatedKeyException if the given key in the object parameter is already used.
|
||||
*/
|
||||
void update(@NotNull I object, String oldKey) throws DuplicatedKeyException;
|
||||
|
||||
/**
|
||||
* Delete an existing item in the data source.
|
||||
*
|
||||
* @param key Key of the item to delete.
|
||||
*/
|
||||
void delete(@NotBlank String key);
|
||||
}
|
||||
229
core/src/main/java/fr/cenra/rhomeo/core/data/site/SiteImpl.java
Normal file
229
core/src/main/java/fr/cenra/rhomeo/core/data/site/SiteImpl.java
Normal file
@ -0,0 +1,229 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.site;
|
||||
|
||||
import com.vividsolutions.jts.geom.MultiPolygon;
|
||||
import fr.cenra.rhomeo.api.InternationalResource;
|
||||
import fr.cenra.rhomeo.api.annotations.RefersTo;
|
||||
import fr.cenra.rhomeo.api.data.Site;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import fr.cenra.rhomeo.core.list.HumidZoneType;
|
||||
import fr.cenra.rhomeo.core.list.OdonateZoneBio;
|
||||
import fr.cenra.rhomeo.core.list.OrthoptereZoneBio;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* POJO representing a site. No intelligence in here.
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public class SiteImpl implements Site, Cloneable, InternationalResource {
|
||||
|
||||
private MultiPolygon geometry;
|
||||
private String countyCode;
|
||||
private String referent;
|
||||
private String organization;
|
||||
private String zoneType;
|
||||
private String odonateType;
|
||||
private String orthoptereType;
|
||||
private String name;
|
||||
private String remarks;
|
||||
|
||||
private SiteImpl() {}
|
||||
|
||||
public SiteImpl(MultiPolygon geometry) {
|
||||
this.geometry = geometry;
|
||||
}
|
||||
|
||||
public SiteImpl(MultiPolygon geometry, String countyCode, String referent, String organization, String zoneType,
|
||||
String odonateType, String orthoptereType, String name, String remarks) {
|
||||
this.geometry = geometry;
|
||||
this.countyCode = countyCode;
|
||||
this.referent = referent;
|
||||
this.organization = organization;
|
||||
this.zoneType = zoneType;
|
||||
this.odonateType = odonateType;
|
||||
this.orthoptereType = orthoptereType;
|
||||
this.name = name;
|
||||
this.remarks = remarks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiPolygon getGeometry() {
|
||||
return geometry;
|
||||
}
|
||||
|
||||
public void setGeometry(MultiPolygon geometry) {
|
||||
this.geometry = geometry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCountyCode() {
|
||||
return countyCode;
|
||||
}
|
||||
|
||||
public void setCountyCode(final String county) {
|
||||
this.countyCode = county;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferent() {
|
||||
return referent;
|
||||
}
|
||||
|
||||
public void setReferent(String referent) {
|
||||
this.referent = referent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOrganization() {
|
||||
return organization;
|
||||
}
|
||||
|
||||
public void setOrganization(String organization) {
|
||||
this.organization = organization;
|
||||
}
|
||||
|
||||
@RefersTo(type = HumidZoneType.class, property = "code")
|
||||
@Override
|
||||
public String getZoneType() {
|
||||
return zoneType;
|
||||
}
|
||||
|
||||
public void setZoneType(String zoneType) {
|
||||
this.zoneType = zoneType;
|
||||
}
|
||||
|
||||
@RefersTo(type = OdonateZoneBio.class, property = "code")
|
||||
@Override
|
||||
public String getOdonateType() {
|
||||
return odonateType;
|
||||
}
|
||||
|
||||
public void setOdonateType(String odonateType) {
|
||||
this.odonateType = odonateType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SiteImpl clone() {
|
||||
final SiteImpl newSite = new SiteImpl(geometry);
|
||||
newSite.setCountyCode(countyCode);
|
||||
newSite.setName(name);
|
||||
newSite.setOdonateType(odonateType);
|
||||
newSite.setOrthoptereType(orthoptereType);
|
||||
newSite.setOrganization(organization);
|
||||
newSite.setReferent(referent);
|
||||
newSite.setRemarks(remarks);
|
||||
newSite.setZoneType(zoneType);
|
||||
|
||||
return newSite;
|
||||
}
|
||||
|
||||
@RefersTo(type= OrthoptereZoneBio.class, property = "code")
|
||||
@Override
|
||||
public String getOrthoptereType() {
|
||||
return orthoptereType;
|
||||
}
|
||||
|
||||
public void setOrthoptereType(String orthoptereType) {
|
||||
this.orthoptereType = orthoptereType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemarks() {
|
||||
return remarks;
|
||||
}
|
||||
|
||||
public void setRemarks(String remarks) {
|
||||
this.remarks = remarks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getAlias() {
|
||||
return Collections.singleton(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null)
|
||||
return false;
|
||||
if (getClass() != o.getClass())
|
||||
return false;
|
||||
final SiteImpl other = (SiteImpl) o;
|
||||
|
||||
return Objects.equals(this.geometry, other.geometry) &&
|
||||
RhomeoCore.equivalent(this.countyCode, other.countyCode) &&
|
||||
RhomeoCore.equivalent(this.referent, other.referent) &&
|
||||
RhomeoCore.equivalent(this.organization, other.organization) &&
|
||||
RhomeoCore.equivalent(this.zoneType, other.zoneType) &&
|
||||
RhomeoCore.equivalent(this.odonateType, other.odonateType) &&
|
||||
RhomeoCore.equivalent(this.orthoptereType, other.orthoptereType) &&
|
||||
RhomeoCore.equivalent(this.name, other.name) &&
|
||||
RhomeoCore.equivalent(this.remarks, other.remarks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = geometry.hashCode();
|
||||
result = 31 * result + name.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Site o) {
|
||||
return o == null ? -1 : getName().compareTo(o.getName());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.site;
|
||||
|
||||
import fr.cenra.rhomeo.api.data.Site;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
/**
|
||||
* For spring injection.
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public interface SiteRepository extends RhomeoRepository<Site>, AutoCloseable {
|
||||
|
||||
ObservableList<String> findNames();
|
||||
}
|
||||
@ -0,0 +1,483 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.data.site;
|
||||
|
||||
import com.vividsolutions.jts.geom.MultiPolygon;
|
||||
import fr.cenra.rhomeo.api.data.Site;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import static fr.cenra.rhomeo.core.RhomeoCore.SITES;
|
||||
import static fr.cenra.rhomeo.core.RhomeoCore.SITES_SHP_PATH;
|
||||
import fr.cenra.rhomeo.core.RhomeoRuntimeException;
|
||||
import fr.cenra.rhomeo.core.data.site.SiteImpl;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javax.annotation.PreDestroy;
|
||||
import org.apache.sis.storage.DataStoreException;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
import org.apache.sis.util.collection.Cache;
|
||||
import org.apache.sis.util.iso.Names;
|
||||
import org.geotoolkit.data.FeatureCollection;
|
||||
import org.geotoolkit.data.FeatureIterator;
|
||||
import org.geotoolkit.data.FeatureReader;
|
||||
import org.geotoolkit.data.FeatureWriter;
|
||||
import org.geotoolkit.data.query.Query;
|
||||
import org.geotoolkit.data.query.QueryBuilder;
|
||||
import org.geotoolkit.data.shapefile.ShapefileFeatureStore;
|
||||
import org.geotoolkit.data.shapefile.ShapefileFeatureStoreFactory;
|
||||
import org.geotoolkit.factory.FactoryFinder;
|
||||
import org.geotoolkit.factory.Hints;
|
||||
import org.geotoolkit.feature.Feature;
|
||||
import org.geotoolkit.feature.FeatureBuilder;
|
||||
import org.geotoolkit.feature.FeatureTypeBuilder;
|
||||
import org.geotoolkit.feature.type.FeatureType;
|
||||
import org.geotoolkit.parameter.Parameters;
|
||||
import org.opengis.filter.Filter;
|
||||
import org.opengis.filter.FilterFactory2;
|
||||
import org.opengis.parameter.ParameterValueGroup;
|
||||
import org.opengis.util.FactoryException;
|
||||
import org.opengis.util.LocalName;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
|
||||
/**
|
||||
* Access point to sites stored in the file system.
|
||||
* An {@linkplain ObservableList observable list} can be followed for listening
|
||||
* changes via the {@link #findAll()} method.
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
@Repository
|
||||
@Validated
|
||||
public class SiteRepositoryImpl implements SiteRepository {
|
||||
|
||||
private static final LocalName NAME = Names.createLocalName(null, ":", SITES);
|
||||
|
||||
private static FeatureType SITE_TYPE;
|
||||
|
||||
private final FilterFactory2 ff;
|
||||
|
||||
/**
|
||||
* Cache result of {@link #findNames() ()} method, to avoid reading the
|
||||
* shapefile each time a site is updated, created or deleted.
|
||||
*/
|
||||
private WeakReference<ObservableList<String>> allNames;
|
||||
|
||||
/**
|
||||
* Cache loaded sites, to ensure their uniqueness in memory.
|
||||
*/
|
||||
private final Cache<String, Site> cache;
|
||||
|
||||
/**
|
||||
* Feature store to use.
|
||||
*/
|
||||
private final ShapefileFeatureStore store;
|
||||
|
||||
/**
|
||||
* Get or create the {@linkplain #store feature store}, creating all folders needed
|
||||
* if necessary.
|
||||
* @throws java.lang.Exception If an error occurs while initializing shapefile.
|
||||
*/
|
||||
public SiteRepositoryImpl() throws Exception {
|
||||
Files.createDirectories(RhomeoCore.SITES_PATH);
|
||||
|
||||
final ParameterValueGroup parameters = ShapefileFeatureStoreFactory.PARAMETERS_DESCRIPTOR.createValue();
|
||||
Parameters.getOrCreate(ShapefileFeatureStoreFactory.PATH, parameters)
|
||||
.setValue(SITES_SHP_PATH.toUri());
|
||||
Parameters.getOrCreate(ShapefileFeatureStoreFactory.NAMESPACE, parameters)
|
||||
.setValue("no namespace");
|
||||
|
||||
final ShapefileFeatureStoreFactory fact = new ShapefileFeatureStoreFactory();
|
||||
|
||||
if (Files.exists(SITES_SHP_PATH)) {
|
||||
store = (ShapefileFeatureStore) fact.open(parameters);
|
||||
} else {
|
||||
store = (ShapefileFeatureStore) fact.create(parameters);
|
||||
store.createFeatureType(NAME, getSiteType());
|
||||
}
|
||||
|
||||
// Empty or corrupted file
|
||||
if (store.getName() == null || !store.getName().equals(NAME)) {
|
||||
store.createFeatureType(NAME, getSiteType());
|
||||
}
|
||||
|
||||
final Hints hints = new Hints();
|
||||
hints.put(Hints.FILTER_FACTORY, FilterFactory2.class);
|
||||
ff = (FilterFactory2) FactoryFinder.getFilterFactory(hints);
|
||||
|
||||
cache = new Cache(4, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Cached data, or null if cache has not been initialized yet.
|
||||
*/
|
||||
private synchronized ObservableList<String> getCachedNames() {
|
||||
return allNames == null ? null : allNames.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new filter which keeps only sites whose name is equal to given one.
|
||||
* @param nameValue The name to filter against.
|
||||
* @return A new filter.
|
||||
*/
|
||||
private Filter newNameFilter(final String nameValue) {
|
||||
return ff.equals(ff.property(RhomeoCore.FT_PROPERTIES.NAME.name()), ff.literal(nameValue));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param name The name to filter against.
|
||||
* @return A collection of sites whose names are equal to given one.
|
||||
*/
|
||||
private FeatureCollection filteredByName(final String name) {
|
||||
ArgumentChecks.ensureNonEmpty("Name to search", name.trim());
|
||||
return store.createSession(false).getFeatureCollection(
|
||||
QueryBuilder.filtered(this.NAME, newNameFilter(name))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param siteName A name to find sites for.
|
||||
* @return True if at least one site with the same name already exists.
|
||||
*/
|
||||
private synchronized boolean exists(final String siteName) {
|
||||
ArgumentChecks.ensureNonEmpty("Name to search", siteName.trim());
|
||||
// Do not use cache here, because if an existing site name has been modified,
|
||||
// it would appear in cache.
|
||||
return !filteredByName(siteName).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized Site findOne(final String name) {
|
||||
if (name == null || name.isEmpty())
|
||||
return null;
|
||||
|
||||
try {
|
||||
return cache.getOrCreate(name, () -> {
|
||||
final FeatureCollection col = filteredByName(name);
|
||||
if (col.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try (final FeatureIterator it = col.iterator()) {
|
||||
return toSite(it.next());
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new RhomeoRuntimeException("Cannot load site named ".concat(name), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized void create(final Site site) throws DuplicatedKeyException {
|
||||
ArgumentChecks.ensureNonNull("Site", site);
|
||||
|
||||
if (exists(site.getName())) {
|
||||
throw new DuplicatedKeyException();
|
||||
}
|
||||
|
||||
try {
|
||||
final Feature toAdd = toFeature(site);
|
||||
store.addFeatures(NAME, Collections.singleton(toAdd));
|
||||
} catch (DataStoreException e) {
|
||||
throw new RhomeoRuntimeException(e);
|
||||
}
|
||||
|
||||
ObservableList<String> cached = getCachedNames();
|
||||
if (cached != null) {
|
||||
cached.add(site.getName());
|
||||
Collections.sort(cached);
|
||||
}
|
||||
|
||||
cache.put(site.getName(), site);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized ObservableList<Site> findAll() {
|
||||
throw new UnsupportedOperationException("Cannot load full site list in memory !");
|
||||
}
|
||||
|
||||
public synchronized ObservableList<String> findNames() {
|
||||
ObservableList<String> result = getCachedNames();
|
||||
if (result == null) {
|
||||
final List<String> sites = new ArrayList<>();
|
||||
final Query query;
|
||||
try {
|
||||
final QueryBuilder builder = new QueryBuilder(store.getName());
|
||||
builder.setProperties(new String[]{RhomeoCore.FT_PROPERTIES.NAME.name()});
|
||||
query = builder.buildQuery();
|
||||
try (final FeatureReader reader = store.getFeatureReader(query)) {
|
||||
while (reader.hasNext()) {
|
||||
sites.add(reader.next().getPropertyValue(RhomeoCore.FT_PROPERTIES.NAME.name()).toString());
|
||||
}
|
||||
}
|
||||
} catch (DataStoreException ex) {
|
||||
throw new RhomeoRuntimeException(ex);
|
||||
}
|
||||
Collections.sort(sites);
|
||||
result = FXCollections.observableList(sites);
|
||||
allNames = new WeakReference<>(result);
|
||||
}
|
||||
|
||||
return FXCollections.unmodifiableObservableList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the first encountered feature matching given filter.
|
||||
*
|
||||
* @param filter
|
||||
* @param site
|
||||
* @throws DataStoreException
|
||||
*/
|
||||
private synchronized void updateFeature(final Filter filter, final Site site) throws DataStoreException {
|
||||
// There is a bug in the shp method getFeatureWriter(name, filter), it never uses the filter parameter!
|
||||
// Consequently we have to test each filter afterwards, via filter.evaluate(feature)
|
||||
boolean found = false;
|
||||
try(final FeatureWriter writer = store.getFeatureWriter(NAME, Filter.INCLUDE)) {
|
||||
while (writer.hasNext()) {
|
||||
final Feature f = writer.next();
|
||||
if (filter.evaluate(f)) {
|
||||
toFeature(f, site);
|
||||
writer.write();
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// If we've got until here, no element has been found for given filter.
|
||||
throw new IllegalArgumentException("Cannot update unexisting site !");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void update(final Site site) {
|
||||
try {
|
||||
update(site, null);
|
||||
} catch (DuplicatedKeyException ex) {
|
||||
throw new RhomeoRuntimeException(ex); // should not happen, as key is not modified.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized void update(final Site site, String oldName) throws DuplicatedKeyException {
|
||||
ArgumentChecks.ensureNonNull("Site", site);
|
||||
|
||||
// Defines if we need to sort the sites list in cache or not.
|
||||
// If user updated the site name, then it is required to ensure keeping this list sorted.
|
||||
boolean needsToSort = false;
|
||||
if (oldName == null || oldName.trim().isEmpty() || oldName.equals(site.getName())) {
|
||||
oldName = site.getName();
|
||||
} else {
|
||||
// Here we want to rename the current site name, and its position in the list might be impacted.
|
||||
needsToSort = true;
|
||||
}
|
||||
|
||||
ArgumentChecks.ensureNonNull("Name to update", oldName);
|
||||
if (!oldName.equals(site.getName()) && exists(site.getName())) {
|
||||
throw new DuplicatedKeyException("Cannot change site name because another one already has the same name !");
|
||||
}
|
||||
|
||||
// Persist change
|
||||
try {
|
||||
// Ok not already used key, we can update the matching feature
|
||||
updateFeature(newNameFilter(oldName), site);
|
||||
} catch (Exception e) {
|
||||
throw new RhomeoRuntimeException(e);
|
||||
}
|
||||
|
||||
// update caches
|
||||
if (needsToSort) {
|
||||
final ObservableList<String> cached = getCachedNames();
|
||||
if (cached != null)
|
||||
cached.set(cached.indexOf(oldName), site.getName());
|
||||
Collections.sort(cached);
|
||||
}
|
||||
|
||||
if (needsToSort) {
|
||||
cache.remove(oldName);
|
||||
cache.put(site.getName(), site);
|
||||
} else {
|
||||
cache.replace(oldName, site);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public synchronized void delete(final String name) {
|
||||
ArgumentChecks.ensureNonEmpty("Site name", name.trim());
|
||||
// There is a bug in the shp method getFeatureWriter(name, filter), it never uses the filter parameter!
|
||||
// Consequently we have to test each filter afterwards, via filter.evaluate(feature)
|
||||
final Filter filter = newNameFilter(name);
|
||||
try (final FeatureWriter writer = store.getFeatureWriter(this.NAME, Filter.INCLUDE)) {
|
||||
while (writer.hasNext()) {
|
||||
final Feature f = writer.next();
|
||||
if (filter.evaluate(f)) {
|
||||
writer.remove();
|
||||
}
|
||||
}
|
||||
} catch (DataStoreException e) {
|
||||
throw new RhomeoRuntimeException(e);
|
||||
}
|
||||
|
||||
ObservableList<String> cached = getCachedNames();
|
||||
if (cached != null) {
|
||||
cached.removeAll(Collections.singleton(name));
|
||||
}
|
||||
|
||||
cache.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@PreDestroy
|
||||
@Override
|
||||
public synchronized void close() throws Exception {
|
||||
allNames = null;
|
||||
store.close();
|
||||
}
|
||||
|
||||
public static final FeatureType getSiteType() {
|
||||
if (SITE_TYPE == null) {
|
||||
final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
|
||||
ftb.setName(NAME);
|
||||
try {
|
||||
ftb.add(RhomeoCore.FT_PROPERTIES.the_geom.name(), MultiPolygon.class, RhomeoCore.getSiteCRS());
|
||||
} catch (FactoryException ex) {
|
||||
throw new RhomeoRuntimeException(ex);
|
||||
}
|
||||
ftb.add(RhomeoCore.FT_PROPERTIES.NAME.name(), String.class);
|
||||
ftb.add(RhomeoCore.FT_PROPERTIES.REMARKS.name(), String.class);
|
||||
ftb.add(RhomeoCore.FT_PROPERTIES.COUNTY.name(), String.class);
|
||||
ftb.add(RhomeoCore.FT_PROPERTIES.REFERENT.name(), String.class);
|
||||
ftb.add(RhomeoCore.FT_PROPERTIES.ORG.name(), String.class);
|
||||
ftb.add(RhomeoCore.FT_PROPERTIES.TYPE.name(), String.class);
|
||||
ftb.add(RhomeoCore.FT_PROPERTIES.ODONATE.name(), String.class);
|
||||
ftb.add(RhomeoCore.FT_PROPERTIES.ORTHOPTERE.name(), String.class);
|
||||
ftb.setDefaultGeometry(RhomeoCore.FT_PROPERTIES.the_geom.name());
|
||||
SITE_TYPE = ftb.buildFeatureType();
|
||||
}
|
||||
|
||||
return SITE_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link Site} into a {@link Feature}.
|
||||
*
|
||||
* @param site Site to convert.
|
||||
* @return A new feature matching this site, never {@code null}
|
||||
* @throws DataStoreException
|
||||
*/
|
||||
public static Feature toFeature(final Site site) throws DataStoreException {
|
||||
final FeatureBuilder sfb = new FeatureBuilder(getSiteType());
|
||||
sfb.setPropertyValue(RhomeoCore.FT_PROPERTIES.the_geom.name(), site.getGeometry());
|
||||
sfb.setPropertyValue(RhomeoCore.FT_PROPERTIES.COUNTY.name(), site.getCountyCode());
|
||||
sfb.setPropertyValue(RhomeoCore.FT_PROPERTIES.NAME.name(), site.getName());
|
||||
sfb.setPropertyValue(RhomeoCore.FT_PROPERTIES.ODONATE.name(), site.getOdonateType());
|
||||
sfb.setPropertyValue(RhomeoCore.FT_PROPERTIES.ORTHOPTERE.name(), site.getOrthoptereType());
|
||||
sfb.setPropertyValue(RhomeoCore.FT_PROPERTIES.ORG.name(), site.getOrganization());
|
||||
sfb.setPropertyValue(RhomeoCore.FT_PROPERTIES.REFERENT.name(), site.getReferent());
|
||||
sfb.setPropertyValue(RhomeoCore.FT_PROPERTIES.REMARKS.name(), site.getRemarks());
|
||||
sfb.setPropertyValue(RhomeoCore.FT_PROPERTIES.TYPE.name(), site.getZoneType());
|
||||
return sfb.buildFeature(site.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply site values into an existing feature.
|
||||
*
|
||||
* @param feature existing feature to update
|
||||
* @param site new values to extract
|
||||
* @throws DataStoreException
|
||||
*/
|
||||
public static void toFeature(final Feature feature, final Site site) throws DataStoreException {
|
||||
feature.setPropertyValue(RhomeoCore.FT_PROPERTIES.the_geom.name(), site.getGeometry());
|
||||
feature.setPropertyValue(RhomeoCore.FT_PROPERTIES.COUNTY.name(), site.getCountyCode());
|
||||
feature.setPropertyValue(RhomeoCore.FT_PROPERTIES.NAME.name(), site.getName());
|
||||
feature.setPropertyValue(RhomeoCore.FT_PROPERTIES.ODONATE.name(), site.getOdonateType());
|
||||
feature.setPropertyValue(RhomeoCore.FT_PROPERTIES.ORTHOPTERE.name(), site.getOrthoptereType());
|
||||
feature.setPropertyValue(RhomeoCore.FT_PROPERTIES.ORG.name(), site.getOrganization());
|
||||
feature.setPropertyValue(RhomeoCore.FT_PROPERTIES.REFERENT.name(), site.getReferent());
|
||||
feature.setPropertyValue(RhomeoCore.FT_PROPERTIES.REMARKS.name(), site.getRemarks());
|
||||
feature.setPropertyValue(RhomeoCore.FT_PROPERTIES.TYPE.name(), site.getZoneType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link Feature} into a {@link Site}.
|
||||
*
|
||||
* @param feature Feature to convert into a site.
|
||||
* @return A new instance of site, never {@code null}
|
||||
*/
|
||||
public static Site toSite(final Feature feature) {
|
||||
final SiteImpl newSite = new SiteImpl((MultiPolygon)feature.getProperty(RhomeoCore.FT_PROPERTIES.the_geom.name()).getValue());
|
||||
newSite.setCountyCode(feature.getProperty(RhomeoCore.FT_PROPERTIES.COUNTY.name()).getValue().toString());
|
||||
newSite.setName(feature.getProperty(RhomeoCore.FT_PROPERTIES.NAME.name()).getValue().toString());
|
||||
newSite.setOdonateType(feature.getProperty(RhomeoCore.FT_PROPERTIES.ODONATE.name()).getValue().toString());
|
||||
newSite.setOrthoptereType(feature.getProperty(RhomeoCore.FT_PROPERTIES.ORTHOPTERE.name()).getValue().toString());
|
||||
newSite.setOrganization(feature.getProperty(RhomeoCore.FT_PROPERTIES.ORG.name()).getValue().toString());
|
||||
newSite.setReferent(feature.getProperty(RhomeoCore.FT_PROPERTIES.REFERENT.name()).getValue().toString());
|
||||
newSite.setRemarks(feature.getProperty(RhomeoCore.FT_PROPERTIES.REMARKS.name()).getValue().toString());
|
||||
newSite.setZoneType(feature.getProperty(RhomeoCore.FT_PROPERTIES.TYPE.name()).getValue().toString());
|
||||
return newSite;
|
||||
}
|
||||
}
|
||||
49
core/src/main/java/fr/cenra/rhomeo/core/list/CodeValue.java
Normal file
49
core/src/main/java/fr/cenra/rhomeo/core/list/CodeValue.java
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.list;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface CodeValue {
|
||||
|
||||
Object getCode();
|
||||
Object getValue();
|
||||
}
|
||||
103
core/src/main/java/fr/cenra/rhomeo/core/list/HumidZoneType.java
Normal file
103
core/src/main/java/fr/cenra/rhomeo/core/list/HumidZoneType.java
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.list;
|
||||
|
||||
/**
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public enum HumidZoneType implements CodeValue {
|
||||
|
||||
GRANDS_ESTUAIRES ("1", "Grands estuaires"), // Indicateurs : 1, 2, 3, 5, 6, 8, 12, 13
|
||||
BAIES_ESTUAIRES ("2", "Baies et estuaires moyens plats"), // Indicateurs : 1, 2, 3, 5, 6, 8, 12, 13
|
||||
MARAIS_LAGUNES ("3.1", "Marais et lagunes côtiers - lagunes"), // Indicateurs : 1, 2, 3, 5, 6, 8, 9, 10, 11, 12, 13
|
||||
MARAIS_LAGUNES_PERI_LAGUN ("3.2", "Marais et lagunes côtiers - péri-lagunaire"), // Indicateurs : 1, 2, 3, 5, 6, 8, 9, 10, 11, 12, 13
|
||||
MARAIS_LAGUNES_PERI_LAGUN_EAU("3.3", "Marais et lagunes côtiers - péri-lagunaire avec rapport d'eau"), // Indicateurs : 1, 2, 3, 5, 6, 8, 9, 10, 11, 12, 13
|
||||
MARAIS_SAUMATRES ("4", "Marais saumâtres aménagés"), // Indicateurs : 1, 2, 3, 6, 8, 9, 10, 11, 12, 13
|
||||
BORDURES_COURS_EAU ("5", "Bordures de cours d'eau"), // Indicateurs : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
PLAINES_ALLUVIALES ("6", "Plaines alluviales"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
ZH_BAS_FOND_ALTITUDE ("7.1", "Zones humides de bas-fonds en tête de BV - altitude"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13
|
||||
ZH_BAS_FOND_TOURB_ACIDE ("7.2", "Zones humides de bas-fonds en tête de BV - tourbière acide"), // Indicateurs : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
ZH_BAS_FOND_TOURB_ALCALINE ("7.3", "Zones humides de bas-fonds en tête de BV - tourbière alcaline"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
ZH_BAS_FOND_PENTES ("7.4", "Zones humides de bas-fonds en tête de BV - pentes et sources"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
ZH_BAS_FOND_COMBES ("7.5", "Zones humides de bas-fonds en tête de BV - combes et bordure de ruisseau"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
REGIONS_ETANGS ("8", "Régions d'étangs"), // Indicateurs : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
BORDURES_PLAN_EAU_ACIDE ("9.1", "Bordures de plan d'eau (lac) - ZH acide"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
BORDURES_PLAN_EAU_ALCALINE ("9.2", "Bordures de plan d'eau (lac) - ZH alcaline"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
MARAIS_LANDES_TOURB ("10.1", "Marais et landes humides de plaine - tourbière de plaine"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
MARAIS_LANDES_PRAIRIES ("10.2", "Marais et landes humides de plaine - prairies humides"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
MARAIS_LANDES_PRES ("10.3", "Marais et landes humides de plaine - Prés salés continentaux"), // Indicateurs : 1, 2, 3, 6, 8, 9, 10, 11, 12, 13
|
||||
ZH_PONCT_MARE_SAUMATRE ("11.11", "Zones humides ponctuelles - Mare temporaire saumâtre"), // Indicateurs : 1, 2, 3, 6, 8, 9, 10, 11, 12, 13
|
||||
ZH_PONCT_MARE_ALCALINE ("11.12", "Zones humides ponctuelles - Mare temporaire alcaline"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
ZH_PONCT_MARE_ACIDE ("11.13", "Zones humides ponctuelles - Mare temporaire acide"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
ZH_PONCT_MARE_PERMANENTE ("11.2", "Zones humides ponctuelles - Mare permanente"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
MARAIS_AMENAGES_AGRICOLE ("12", "Marais aménagés dans un but agricole"), // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
ZH_ARTIFICELLES ("13", "Zones humides artificielles"); // Indicateurs : 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13
|
||||
|
||||
private final String code;
|
||||
private final String value;
|
||||
|
||||
HumidZoneType(final String code, final String value) {
|
||||
this.code = code;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static HumidZoneType getByCode(final String code) {
|
||||
for (final HumidZoneType candid : values()) {
|
||||
if (candid.getCode().equals(code)) {
|
||||
return candid;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return code +" "+ value;
|
||||
}
|
||||
}
|
||||
130
core/src/main/java/fr/cenra/rhomeo/core/list/OdonateZoneBio.java
Normal file
130
core/src/main/java/fr/cenra/rhomeo/core/list/OdonateZoneBio.java
Normal file
@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.list;
|
||||
|
||||
import fr.cenra.rhomeo.core.data.reference.OdonataHabitatReference;
|
||||
|
||||
/**
|
||||
* L_zone_bio_odonate.
|
||||
*
|
||||
* id_zone_bio_odo nom_zone_bio_odo
|
||||
* -------------------------------------
|
||||
* 1 Alpin
|
||||
* 2 Continental
|
||||
* 3 Méditerranéen occidental
|
||||
* 4 Méditerranéen oriental
|
||||
* 5 Pyrénéen
|
||||
*
|
||||
* (Source : Champs_et_Listes.xlsx)
|
||||
*
|
||||
* We add the column "zbio" to join {@link OdonataHabitatReference} and a new
|
||||
* entry to represent 'zglobal' value.
|
||||
*
|
||||
* <code>select distinct zbio, biogeo from odo_dependance_habitat;</code>
|
||||
*
|
||||
* zbio | biogeo
|
||||
*--------------------------+--------------------------
|
||||
* mediterraneen oriental | Méditerranéen oriental
|
||||
* pyreneen | pyreneen
|
||||
* continental | Continental
|
||||
* alpin | Alpin
|
||||
* mediterraneen occidental | Méditerranéen occidental
|
||||
* zglobal | Z Global
|
||||
*
|
||||
* (Source : RhoMéO_Geomatys.backup)
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
* @author Samuel Andrés (Geomatys)
|
||||
*/
|
||||
public enum OdonateZoneBio implements CodeValue {
|
||||
ALPIN ("1", "Alpin", "alpin"),
|
||||
CONTINENTAL ("2", "Continental", "continental"),
|
||||
MED_OCCIDENTAL("3", "Méditerranéen occidental", "mediterraneen occidental"),
|
||||
MED_ORIENTAL ("4", "Méditerranéen oriental", "mediterraneen oriental"),
|
||||
PYRENEEN ("5", "Pyrénéen", "pyreneen"),
|
||||
ZGLOBAL ("", "Z Global", "zglobal");
|
||||
|
||||
private final String code;
|
||||
private final String value;
|
||||
private final String zbio;
|
||||
|
||||
|
||||
OdonateZoneBio(final String code, final String value, final String zbio) {
|
||||
this.code = code;
|
||||
this.value = value;
|
||||
this.zbio = zbio;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getZbio() {
|
||||
return zbio;
|
||||
}
|
||||
|
||||
public static OdonateZoneBio getByCode(final String code) {
|
||||
for (final OdonateZoneBio candid : values()) {
|
||||
if (candid.getCode().equals(code)) {
|
||||
return candid;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static OdonateZoneBio getByZbio(final String code) {
|
||||
for (final OdonateZoneBio candid : values()) {
|
||||
if (candid.getZbio().equals(code)) {
|
||||
return candid;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return code +" "+ value;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.list;
|
||||
|
||||
/**
|
||||
* L_zone_bio_orthoptere.
|
||||
*
|
||||
* id_zone_bio_ortho nom_zone_bio_ortho
|
||||
* ---------------------------------------
|
||||
* 1 Alpin_marais_alluvial
|
||||
* 2 Alpin_tourbière
|
||||
* 3 Mediterranen1_marais_alluvial
|
||||
* 4 Mediterranen1_marais_littoral
|
||||
* 5 Mediterranen2_tourbière
|
||||
* 6 Mediterranen2_marais_alluvial
|
||||
*
|
||||
* (Source : Champs_et_Listes.xlsx)
|
||||
*
|
||||
* @author Cédric Briançon (Geomatys)
|
||||
*/
|
||||
public enum OrthoptereZoneBio implements CodeValue {
|
||||
|
||||
ALPIN_MARAIS_ALLUVIAL("1", "Alpin_marais_alluvial"),
|
||||
ALPIN_TOURBIERE ("2", "Alpin_tourbière"),
|
||||
MED1_MARAIS_ALLUVIAL ("3", "Mediterranen1_marais_alluvial"),
|
||||
MED1_MARAIS_LITTORAL ("4", "Mediterranen1_marais_littoral"),
|
||||
MED2_TOURBIERE ("5", "Mediterranen2_tourbière"),
|
||||
MED2_MARAIS_ALLUVIAL ("6", "Mediterranen2_marais_alluvial");
|
||||
|
||||
private final String code;
|
||||
private final String value;
|
||||
|
||||
OrthoptereZoneBio(final String code, final String value) {
|
||||
this.code = code;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static OrthoptereZoneBio getByCode(final String code) {
|
||||
for (final OrthoptereZoneBio candid : values()) {
|
||||
if (candid.getCode().equals(code)) {
|
||||
return candid;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return code +" "+ value;
|
||||
}
|
||||
}
|
||||
76
core/src/main/java/fr/cenra/rhomeo/core/list/VonPost.java
Normal file
76
core/src/main/java/fr/cenra/rhomeo/core/list/VonPost.java
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.list;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public enum VonPost implements CodeValue {
|
||||
H1 ("Eau limpide"),
|
||||
H2 ("eau peu colorée"),
|
||||
H3 ("eau trouble pâle"),
|
||||
H4 ("eau trouble foncée"),
|
||||
H5 ("eau trouble et particules"),
|
||||
H6 ("1/3 du matériel passe entre les doigts"),
|
||||
H7 ("1/2 du matériel passe entre les doigts"),
|
||||
H8 ("2/3 du matériel passe entre les doigts"),
|
||||
H9 ("Presque tout le matériel"),
|
||||
H10("Tout le matériel");
|
||||
|
||||
private final String value;
|
||||
private VonPost(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder(name()).append(" : ").append(value).toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,206 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.preferences.ftp;
|
||||
|
||||
import fr.cenra.rhomeo.core.util.EncryptionResult;
|
||||
import fr.cenra.rhomeo.core.util.SecretGenerator;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.prefs.Preferences;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
|
||||
/**
|
||||
* Holds connection information over a single FTP service. The service is defined
|
||||
* by its host name, but also by a login, password and optionally a root directory.
|
||||
*
|
||||
* NOTE : If, for some reason, security context cannot initialize, passwords become
|
||||
* unavailable.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class FTPAccess {
|
||||
|
||||
private static enum PROPERTIES {
|
||||
ADRESS,
|
||||
PORT,
|
||||
LOGIN,
|
||||
PASSWORD,
|
||||
WORKING_DIR
|
||||
}
|
||||
|
||||
private final Preferences node;
|
||||
|
||||
/**
|
||||
* Encryption manager. Can be null if an error occurred at initialisation. In
|
||||
* this case, no password will be read or written.
|
||||
*/
|
||||
private final SecretGenerator cipher;
|
||||
|
||||
protected FTPAccess(@NotNull final Preferences infoContainer) {
|
||||
this.node = infoContainer;
|
||||
cipher = SecretGenerator.getInstance().orElse(null);
|
||||
}
|
||||
|
||||
private String getProperty(final PROPERTIES p) {
|
||||
return node.get(p.name(), null);
|
||||
}
|
||||
|
||||
private void setProperty(final PROPERTIES p, final String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
node.remove(p.name());
|
||||
} else {
|
||||
node.put(p.name(), value);
|
||||
}
|
||||
}
|
||||
|
||||
public String getAdress() {
|
||||
return getProperty(PROPERTIES.ADRESS);
|
||||
}
|
||||
|
||||
public void setAdress(final String newAdress) {
|
||||
setProperty(PROPERTIES.ADRESS, newAdress);
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return node.getInt(PROPERTIES.PORT.name(), 21);
|
||||
}
|
||||
|
||||
public void setPort(final int port) {
|
||||
node.putInt(PROPERTIES.PORT.name(), port);
|
||||
}
|
||||
|
||||
public String getLogin() {
|
||||
return getProperty(PROPERTIES.LOGIN);
|
||||
}
|
||||
|
||||
public void setLogin(final String newLogin) {
|
||||
setProperty(PROPERTIES.LOGIN, newLogin);
|
||||
}
|
||||
|
||||
|
||||
public String getWorkingDir() {
|
||||
return getProperty(PROPERTIES.WORKING_DIR);
|
||||
}
|
||||
|
||||
public void setWorkingDir(final String newDir) {
|
||||
setProperty(PROPERTIES.WORKING_DIR, newDir);
|
||||
}
|
||||
|
||||
public synchronized String getPassword() throws GeneralSecurityException {
|
||||
final String tmpValue = getProperty(PROPERTIES.PASSWORD);
|
||||
if (tmpValue == null || tmpValue.isEmpty()) { // No pw stored.
|
||||
return "";
|
||||
}
|
||||
|
||||
if (cipher == null) {
|
||||
throw new GeneralSecurityException("no security manager available. Passwords cannot be read or written from preferences.");
|
||||
}
|
||||
|
||||
byte[] sk = node.getByteArray("ftp_access_skey", null);
|
||||
byte[] sr = node.getByteArray("ftp_access_sran", null);
|
||||
if (sk == null || sr == null) {
|
||||
throw new GeneralSecurityException("no security manager available. Passwords cannot be read or written from preferences.");
|
||||
}
|
||||
|
||||
return cipher.decrypt(tmpValue, sk, sr);
|
||||
}
|
||||
|
||||
public synchronized void setPassword(final String newPassword) throws GeneralSecurityException {
|
||||
if (cipher == null) {
|
||||
throw new GeneralSecurityException("no security manager available. Passwords cannot be read or written from preferences.");
|
||||
}
|
||||
|
||||
// Empty value, no encryption needed.
|
||||
if (newPassword == null || newPassword.isEmpty()) {
|
||||
setProperty(PROPERTIES.PASSWORD, "");
|
||||
return;
|
||||
}
|
||||
|
||||
final EncryptionResult encrypted = cipher.encrypt(newPassword);
|
||||
setProperty(PROPERTIES.PASSWORD, encrypted.output);
|
||||
|
||||
node.putByteArray("ftp_access_skey", encrypted.getKey());
|
||||
node.putByteArray("ftp_access_sran", encrypted.getSecureRandom());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new connection over the FTP service provided by holded information.
|
||||
* The provided {@link FTPClient} must be closed using {@link FTPClient#disconnect() }
|
||||
* once you've finished your work.
|
||||
*
|
||||
* @return A client to exchange data with FTP service which contains
|
||||
* reference files.
|
||||
*
|
||||
* @throws IOException If we cannot connect to distant service.
|
||||
* @throws java.security.GeneralSecurityException If an authentication is
|
||||
* required, but we cannot access to password.
|
||||
*/
|
||||
public FTPClient createClient() throws IOException, GeneralSecurityException {
|
||||
return createClient(getAdress(), getPort(), getWorkingDir(), getLogin(), getPassword());
|
||||
}
|
||||
|
||||
public static FTPClient createClient(final String adress, final int port, final String workDir, final String login, final String password) throws IOException, GeneralSecurityException {
|
||||
if (adress == null) {
|
||||
throw new IllegalStateException("No adress configured for FTP access !");
|
||||
}
|
||||
|
||||
final FTPClient client = new FTPClient();
|
||||
client.enterLocalActiveMode();
|
||||
if (port < 1) {
|
||||
client.connect(adress);
|
||||
} else {
|
||||
client.connect(adress, port);
|
||||
}
|
||||
|
||||
if (login != null) {
|
||||
if (!client.login(login, password)) {
|
||||
throw new GeneralSecurityException("Unable to authenticate with the login "+ login);
|
||||
}
|
||||
}
|
||||
|
||||
if (workDir != null) {
|
||||
if (!client.changeWorkingDirectory(workDir)) {
|
||||
throw new IOException("Unable to change of working directory to:"+ workDir);
|
||||
}
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.preferences.ftp;
|
||||
|
||||
import fr.cenra.rhomeo.api.preferences.PreferenceGroup;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public interface FTPPreferences extends PreferenceGroup<Object> {
|
||||
|
||||
public static enum ACCESS_POINTS {
|
||||
REFERENCES("Références"),
|
||||
RESULTS("Résultats");
|
||||
|
||||
private final String title;
|
||||
|
||||
ACCESS_POINTS(final String value) {
|
||||
this.title = value;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Give all information about a specific FTP end point.
|
||||
*
|
||||
* @param ap The FTP service to retrieve.
|
||||
*
|
||||
* @return an object capable to open a connection over the queried FTP service.
|
||||
*/
|
||||
@NotNull
|
||||
FTPAccess getAccess(@NotNull final ACCESS_POINTS ap);
|
||||
}
|
||||
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.preferences.ftp;
|
||||
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import fr.cenra.rhomeo.core.preferences.net.NetPreferences;
|
||||
import fr.cenra.rhomeo.core.util.SecretGenerator;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.prefs.Preferences;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
* Holds preferences over FTP connections. You can retrieve information about a
|
||||
* specific FTP connection by using {@link #getAccess(fr.cenra.rhomeo.core.preferences.ftp.FTPPreferences.ACCESS_POINTS)
|
||||
* }.
|
||||
*
|
||||
* Known connections are listed in {@link ACCESS_POINTS}.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
@Qualifier(FTPPreferencesImpl.NAME)
|
||||
@Validated
|
||||
public class FTPPreferencesImpl implements FTPPreferences {
|
||||
|
||||
public static final String NAME = "FTPPreferencesImpl";
|
||||
|
||||
private final Preferences root;
|
||||
|
||||
public FTPPreferencesImpl() {
|
||||
root = Preferences.userNodeForPackage(FTPPreferencesImpl.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* DO NOT USE IT !
|
||||
*
|
||||
* @param key DO NOT USE IT !
|
||||
* @return DO NOT USE IT !
|
||||
*/
|
||||
@Override
|
||||
public String getPreference(Object key) {
|
||||
throw new UnsupportedOperationException("No value stored on root.");
|
||||
}
|
||||
|
||||
/**
|
||||
* DO NOT USE IT !
|
||||
*
|
||||
* @param key DO NOT USE IT !
|
||||
* @param value DO NOT USE IT !
|
||||
*/
|
||||
@Override
|
||||
public void setPreference(Object key, String value) {
|
||||
throw new UnsupportedOperationException("No value stored on root.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List getKeys() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give all information about a specific FTP end point.
|
||||
*
|
||||
* @param ap The FTP service to retrieve.
|
||||
*
|
||||
* @return an object capable to open a connection over the queried FTP
|
||||
* service.
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public FTPAccess getAccess(@NotNull final ACCESS_POINTS ap) {
|
||||
ArgumentChecks.ensureNonNull("Input access point", ap);
|
||||
return new FTPAccess(root.node(ap.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* If no FTP account has been parameterised, a default one is set for result
|
||||
* publication and reference data.
|
||||
*/
|
||||
@PostConstruct
|
||||
private void checkDefaultAccesses() {
|
||||
FTPAccess results = getAccess(FTPPreferences.ACCESS_POINTS.RESULTS);
|
||||
if (setDefaultAccess(results)) {
|
||||
results.setWorkingDir("results");
|
||||
}
|
||||
|
||||
FTPAccess references = getAccess(FTPPreferences.ACCESS_POINTS.REFERENCES);
|
||||
if (setDefaultAccess(references)) {
|
||||
references.setWorkingDir("references");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean setDefaultAccess(final FTPAccess access) {
|
||||
if ((access.getAdress() == null || access.getAdress().trim().isEmpty())
|
||||
&& (access.getLogin() == null || access.getLogin().trim().isEmpty())
|
||||
&& (access.getWorkingDir() == null || access.getWorkingDir().trim().isEmpty())) {
|
||||
|
||||
access.setAdress("constellation.cenra-outils.org");
|
||||
access.setLogin("rhomeoftp");
|
||||
final SecretGenerator gen = SecretGenerator.getInstance().orElse(null);
|
||||
if (gen == null)
|
||||
return false;
|
||||
|
||||
try {
|
||||
access.setPassword(gen.decrypt("4Iru5sD2uzixbWHhu7R72s658w/l3yCz", getDefaultKey(), getDefaultSR()));
|
||||
return true;
|
||||
} catch (IOException | GeneralSecurityException ex) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, null, ex);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private byte[] getDefaultKey() throws IOException {
|
||||
final byte[] buf = new byte[16];
|
||||
int read = 0;
|
||||
try (final InputStream stream = NetPreferences.class.getResourceAsStream("defaultKey")) {
|
||||
do {
|
||||
read += stream.read(buf, read, buf.length - read);
|
||||
} while (read < buf.length - 1);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
private byte[] getDefaultSR() throws IOException {
|
||||
final byte[] buf = new byte[8];
|
||||
int read = 0;
|
||||
try (final InputStream stream = NetPreferences.class.getResourceAsStream("defaultSR")) {
|
||||
do {
|
||||
read += stream.read(buf, read, 8 - read);
|
||||
} while (read < 7);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.preferences.net;
|
||||
|
||||
import fr.cenra.rhomeo.api.preferences.InternationalPreferenceKey;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class NetKey implements InternationalPreferenceKey {
|
||||
|
||||
private final String keyId;
|
||||
private final String defaultValue;
|
||||
|
||||
public NetKey(final String netKey) {
|
||||
this(netKey, null);
|
||||
}
|
||||
|
||||
public NetKey(final String netKey, final String defaultValue) {
|
||||
ArgumentChecks.ensureNonNull("Key", netKey);
|
||||
this.keyId = netKey;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return keyId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return keyId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,172 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.preferences.net;
|
||||
|
||||
import fr.cenra.rhomeo.api.preferences.UserPackagePreferenceGroup;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import fr.cenra.rhomeo.core.RhomeoRuntimeException;
|
||||
import fr.cenra.rhomeo.core.util.EncryptionResult;
|
||||
import fr.cenra.rhomeo.core.util.SecretGenerator;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public class NetPreferences extends UserPackagePreferenceGroup<NetKey> {
|
||||
|
||||
public static final NetKey UPDATE_URL = new NetKey("update_url", "http://updates-bao.cenra-outils.org/updates/update.json");
|
||||
public static final NetKey UPDATE_USER = new NetKey("update_user", "rhomeo");
|
||||
public static final NetKey UPDATE_PASSWORD = new PassNetKey("update_pass", null);
|
||||
public static final NetKey WFS_URL = new NetKey("wfs_url", "http://constellation.cenra-outils.org/WS/wfs/referential");
|
||||
|
||||
private static final List<NetKey> KEYS = Collections.unmodifiableList(Arrays.asList(new NetKey[] {
|
||||
UPDATE_URL, UPDATE_USER, UPDATE_PASSWORD, WFS_URL
|
||||
}));
|
||||
|
||||
private static final String UPDATE_KEY_PREF = "net_update_pass_key";
|
||||
private static final String UPDATE_SR_PREF = "net_update_pass_sr";
|
||||
|
||||
private final SecretGenerator gen;
|
||||
|
||||
public NetPreferences() {
|
||||
gen = SecretGenerator.getInstance().orElse(null);
|
||||
// Default values for password and secret key.
|
||||
if (getPreference(UPDATE_PASSWORD) == null) {
|
||||
prefs.put(UPDATE_PASSWORD.getKey(), "4Iru5sD2uzixbWHhu7R72s658w/l3yCz");
|
||||
try {
|
||||
final byte[] buf = new byte[16];
|
||||
int read = 0;
|
||||
try (final InputStream stream = NetPreferences.class.getResourceAsStream("defaultKey")) {
|
||||
do {
|
||||
read += stream.read(buf, read, buf.length - read);
|
||||
} while (read < buf.length -1);
|
||||
prefs.putByteArray(UPDATE_KEY_PREF, buf);
|
||||
}
|
||||
read = 0;
|
||||
try (final InputStream stream = NetPreferences.class.getResourceAsStream("defaultSR")) {
|
||||
do {
|
||||
read += stream.read(buf, read, 8 - read);
|
||||
} while (read < 7);
|
||||
prefs.putByteArray(UPDATE_SR_PREF, Arrays.copyOf(buf, 8));
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
RhomeoCore.LOGGER.log(Level.FINE, "cannot set default values", ex);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NetKey> getKeys() {
|
||||
return KEYS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPreference(NetKey key, String value) {
|
||||
if (UPDATE_PASSWORD.equals(key) && value != null && !(value = value.trim()).isEmpty()) {
|
||||
if (gen != null) {
|
||||
try {
|
||||
EncryptionResult encrypted = gen.encrypt(value);
|
||||
prefs.putByteArray(UPDATE_KEY_PREF, encrypted.getKey());
|
||||
prefs.putByteArray(UPDATE_SR_PREF, encrypted.getSecureRandom());
|
||||
value = encrypted.getOutput();
|
||||
} catch (GeneralSecurityException ex) {
|
||||
throw new RhomeoRuntimeException(ex);
|
||||
}
|
||||
} else {
|
||||
throw new RhomeoRuntimeException("no security manager available. Passwords cannot be written into preferences.");
|
||||
}
|
||||
}
|
||||
super.setPreference(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public URL getUpdateURL() throws MalformedURLException {
|
||||
return new URL(getPreference(UPDATE_URL));
|
||||
}
|
||||
|
||||
public URLConnection openConnection(final URL toReach) throws GeneralSecurityException, IOException {
|
||||
final URL updateURL = getUpdateURL();
|
||||
String user = getPreference(UPDATE_USER);
|
||||
if (toReach.getHost().equals(updateURL.getHost()) && toReach.getUserInfo() == null && user != null && !(user = user.trim()).isEmpty()) {
|
||||
final String pass = getPreference(UPDATE_PASSWORD);
|
||||
URLConnection con = toReach.openConnection();
|
||||
String dpw = null;
|
||||
if (pass !=null && !pass.isEmpty()) {
|
||||
final byte[] key = prefs.getByteArray(UPDATE_KEY_PREF, null);
|
||||
final byte[] sr = prefs.getByteArray(UPDATE_SR_PREF, null);
|
||||
if (key == null && sr == null) { // No encryption parameter
|
||||
dpw = pass;
|
||||
} else if (gen == null) { // No cipher
|
||||
throw new RhomeoRuntimeException("no security manager available. Passwords cannot be read from preferences.");
|
||||
} else {
|
||||
dpw = gen.decrypt(pass, key, sr);
|
||||
}
|
||||
}
|
||||
final StringBuilder authInfo = new StringBuilder(user);
|
||||
if (dpw != null) {
|
||||
authInfo.append(':').append(dpw);
|
||||
}
|
||||
final String b64 = Base64.getEncoder().withoutPadding().encodeToString(
|
||||
authInfo.toString().getBytes()
|
||||
);
|
||||
con.addRequestProperty("Authorization", "Basic ".concat(b64));
|
||||
return con;
|
||||
} else {
|
||||
return toReach.openConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.preferences.net;
|
||||
|
||||
import fr.cenra.rhomeo.api.preferences.PasswordKey;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class PassNetKey extends NetKey implements PasswordKey {
|
||||
|
||||
public PassNetKey(String netKey) {
|
||||
super(netKey);
|
||||
}
|
||||
|
||||
public PassNetKey(String netKey, String defaultValue) {
|
||||
super(netKey, defaultValue);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,341 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.result;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import fr.cenra.rhomeo.api.data.Site;
|
||||
import fr.cenra.rhomeo.api.process.Indicator;
|
||||
import fr.cenra.rhomeo.api.result.DashboardResultItem;
|
||||
import fr.cenra.rhomeo.api.result.Index;
|
||||
import fr.cenra.rhomeo.core.RhomeoCore;
|
||||
import fr.cenra.rhomeo.core.RhomeoRuntimeException;
|
||||
import fr.cenra.rhomeo.core.Session;
|
||||
import fr.cenra.rhomeo.core.util.ExportUtils;
|
||||
import fr.cenra.rhomeo.core.util.GeometryUtils;
|
||||
import fr.cenra.rhomeo.core.data.site.SiteRepository;
|
||||
import fr.cenra.rhomeo.core.util.SerializableDataContext;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.sis.storage.DataStoreException;
|
||||
import org.apache.sis.util.collection.IntegerList;
|
||||
import org.geotoolkit.nio.IOUtilities;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Component in charge of storing indicator results locally.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public class ResultStorage {
|
||||
|
||||
@Autowired
|
||||
private ResultWriter writer;
|
||||
|
||||
@Autowired
|
||||
private Session session;
|
||||
|
||||
@Autowired
|
||||
private SiteRepository siteRepo;
|
||||
|
||||
@Autowired
|
||||
private ResultWriter resultWriter;
|
||||
|
||||
final String[] expectedFiles = new String[]{ExportUtils.METADATA_JSON, ResultWriter.RESULT_FILE_NAME, ResultWriter.ADDITIONAL_RESULT_FILE_NAME};
|
||||
|
||||
private ResultStorage() {
|
||||
Arrays.sort(expectedFiles);
|
||||
}
|
||||
|
||||
public void store() throws IOException, IntrospectionException {
|
||||
if (session.getResults() == null || session.getResults().isEmpty() || session.getDataContext() == null)
|
||||
return;
|
||||
|
||||
final String sha1 = GeometryUtils.getSha1(session.getDataContext().getSite().getGeometry());
|
||||
final Path root = RhomeoCore.RESULT_PATH.resolve(sha1);
|
||||
Files.createDirectories(root);
|
||||
|
||||
/* Sort results by indicator and year, as publication / export via dashboard
|
||||
* has to be able to export results only for a specific indicator at a
|
||||
* specific year. We iterate on indices and not on the tracking points
|
||||
* related to process context, because some protocols appear to use no
|
||||
* tracking point at all.
|
||||
*/
|
||||
final IntegerList years = new IntegerList(10, Short.MAX_VALUE);
|
||||
for (final Index i : session.getResults()) {
|
||||
if (years.occurrence(i.getYear()) < 1)
|
||||
years.add(i.getYear());
|
||||
}
|
||||
|
||||
for (final Indicator indic : session.getProcessContext().getIndicators()) {
|
||||
final Path indicPath = root.resolve(indic.getName());
|
||||
Files.createDirectories(indicPath);
|
||||
for (final int year : years) {
|
||||
final Path yearPath = indicPath.resolve(Integer.toString(year));
|
||||
IOUtilities.deleteRecursively(yearPath);
|
||||
Files.createDirectory(yearPath);
|
||||
writer.prepareWriting(yearPath)
|
||||
.writeMetadataJSON()
|
||||
.writeResults((i) -> i.getYear() == year && i.getSpi().getIndicator().equals(indic));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the result storage manager that a site had its name changed.
|
||||
* @param oldSiteName
|
||||
* @param newSiteName
|
||||
* @throws IOException
|
||||
*/
|
||||
// public void siteNameChanged(final String oldSiteName, final String newSiteName) throws IOException {
|
||||
// final Base64.Encoder encoder = Base64.getEncoder().withoutPadding();
|
||||
// String oldName = encoder.encodeToString(oldSiteName.getBytes(StandardCharsets.UTF_8));
|
||||
// final Path oldPath = RhomeoCore.RESULT_PATH.resolve(oldName);
|
||||
// if (!Files.exists(oldPath))
|
||||
// return; // Nothing to move
|
||||
//
|
||||
// final String newName = encoder.encodeToString(newSiteName.getBytes(StandardCharsets.UTF_8));
|
||||
// Files.move(oldPath, RhomeoCore.RESULT_PATH.resolve(newName));
|
||||
// }
|
||||
|
||||
/**
|
||||
* Remove results associated to the input site, If any. Otherwise, do nothing.
|
||||
* @param siteName Name of the site to delete results for.
|
||||
*
|
||||
* @throws IOException If an error occurs while deleting files.
|
||||
*/
|
||||
public void deleteIfExists(String siteName) throws IOException {
|
||||
if (siteName == null || (siteName = siteName.trim()).isEmpty())
|
||||
return;
|
||||
deleteIfExists(siteRepo.findOne(siteName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove results associated to the input site, If any. Otherwise, do nothing.
|
||||
* @param site The site to delete results for.
|
||||
*
|
||||
* @throws IOException If an error occurs while deleting files.
|
||||
*/
|
||||
public void deleteIfExists(final Site site) throws IOException {
|
||||
if (site == null)
|
||||
return;
|
||||
final String sha1 = GeometryUtils.getSha1(site.getGeometry());
|
||||
IOUtilities.deleteRecursively(RhomeoCore.RESULT_PATH.resolve(sha1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the results associated to the input dashboard item in the FTP pointed
|
||||
* by given client.
|
||||
*
|
||||
* Note : All files are uploaded on the current working directory of the FTP client.
|
||||
*
|
||||
* @param target Dashboard item to upload results for.
|
||||
* @param ftp Connection to the FTP.
|
||||
* @return true if we succeeded
|
||||
* @throws IOException
|
||||
*/
|
||||
public boolean publish(final DashboardResultItem target, final FTPClient ftp) throws IOException {
|
||||
Optional<Path> directory = getDirectory(target);
|
||||
if (!directory.isPresent())
|
||||
return false;
|
||||
|
||||
final Path root = directory.get();
|
||||
try {
|
||||
Files.list(root).forEach(p -> {
|
||||
final String fileName = p.getFileName().toString();
|
||||
if (Files.isRegularFile(p) && Arrays.binarySearch(expectedFiles, fileName) >= 0) {
|
||||
|
||||
try (final InputStream stream = Files.newInputStream(p)) {
|
||||
ftp.storeFile(fileName, stream);
|
||||
} catch (IOException e) {
|
||||
throw new RhomeoRuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (RhomeoRuntimeException e) {
|
||||
if (e.getCause() instanceof IOException) {
|
||||
throw (IOException) e.getCause();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish results currently contained in the session into the current
|
||||
* working directory of the input client.
|
||||
*
|
||||
* @param ftpSupplier Provides an FTP client positioned in the directory we
|
||||
* want to send data to. The FTP CLient is closed internally.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws DataStoreException
|
||||
* @throws IntrospectionException
|
||||
*/
|
||||
public void publish(final Supplier<FTPClient> ftpSupplier) throws IOException, DataStoreException, IntrospectionException {
|
||||
Path tmpDir = Files.createTempDirectory("results");
|
||||
try {
|
||||
resultWriter.prepareWriting(tmpDir).writeMetadataJSON().writeResults().writeAdditionalValues();
|
||||
|
||||
final FTPClient ftp = ftpSupplier.get();
|
||||
try {
|
||||
Files.list(tmpDir).forEach(p -> {
|
||||
final String fileName = p.getFileName().toString();
|
||||
if (Files.isRegularFile(p)) {
|
||||
|
||||
try (final InputStream stream = Files.newInputStream(p)) {
|
||||
if (!ftp.storeFile(fileName, stream))
|
||||
throw new RhomeoRuntimeException("A file cannot be copied via FTP : ".concat(fileName));
|
||||
} catch (IOException e) {
|
||||
throw new RhomeoRuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
ftp.disconnect();
|
||||
}
|
||||
|
||||
} catch (RhomeoRuntimeException e) {
|
||||
if (e.getCause() instanceof IOException) {
|
||||
throw (IOException) e.getCause();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
// If the task fails, it does not halt publication process.
|
||||
try {
|
||||
IOUtilities.deleteRecursively(tmpDir);
|
||||
} catch (Exception e) {
|
||||
RhomeoCore.LOGGER.log(Level.WARNING, "Cannot clear temporary data", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a path to the CSV file containing main indices related to the
|
||||
* given dashboard item.
|
||||
* @param item
|
||||
* @return A path to the requested results, or an empty optional if there's
|
||||
* no result available, or they're not accessible.
|
||||
* @throws java.io.IOException If an error occurs while checking result path.
|
||||
*/
|
||||
public Optional<Path> getMainResults(final DashboardResultItem item) throws IOException {
|
||||
Optional<Path> directory = getDirectory(item);
|
||||
if (directory.isPresent()) {
|
||||
|
||||
final Path root = directory.get();
|
||||
// Read main results
|
||||
Path results = root.resolve(ResultWriter.RESULT_FILE_NAME);
|
||||
if (Files.isReadable(results)) {
|
||||
return Optional.of(results);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a path to the CSV file containing additional indices related to
|
||||
* the given dashboard item.
|
||||
* @param item
|
||||
* @return A path to the requested results, or an empty optional if there's
|
||||
* no result available, or they're not accessible.
|
||||
* @throws java.io.IOException If an error occurs while checking result path.
|
||||
*/
|
||||
public Optional<Path> getAdditionalResults(final DashboardResultItem item) throws IOException {
|
||||
Optional<Path> directory = getDirectory(item);
|
||||
if (directory.isPresent()) {
|
||||
|
||||
final Path root = directory.get();
|
||||
// Read main results
|
||||
Path results = root.resolve(ResultWriter.ADDITIONAL_RESULT_FILE_NAME);
|
||||
if (Files.isReadable(results)) {
|
||||
return Optional.of(results);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public Optional<SerializableDataContext> readMetadata(final DashboardResultItem item) throws IOException {
|
||||
Optional<Path> directory = getDirectory(item);
|
||||
if (directory.isPresent()) {
|
||||
|
||||
final Path root = directory.get();
|
||||
// Read main results
|
||||
Path results = root.resolve(ExportUtils.METADATA_JSON);
|
||||
if (Files.isReadable(results)) {
|
||||
try (final BufferedReader reader = Files.newBufferedReader(results, StandardCharsets.UTF_8)) {
|
||||
return Optional.of(new ObjectMapper().readValue(reader, SerializableDataContext.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Optional<Path> getDirectory(final DashboardResultItem target) throws IOException {
|
||||
if (target.getSite() == null || target.getSite().isEmpty()
|
||||
|| target.getIndicator() == null || target.getIndicator().isEmpty())
|
||||
return Optional.empty();
|
||||
|
||||
final Site site = siteRepo.findOne(target.getSite());
|
||||
if (site == null)
|
||||
return Optional.empty();
|
||||
|
||||
final String sha1 = GeometryUtils.getSha1(site.getGeometry());
|
||||
final Path root = RhomeoCore.RESULT_PATH.resolve(sha1).resolve(target.getIndicator()).resolve(Integer.toString(target.getYear()));
|
||||
if (!Files.isDirectory(root) || !Files.list(root).findAny().isPresent())
|
||||
return Optional.empty();
|
||||
|
||||
return Optional.of(root);
|
||||
}
|
||||
}
|
||||
281
core/src/main/java/fr/cenra/rhomeo/core/result/ResultWriter.java
Normal file
281
core/src/main/java/fr/cenra/rhomeo/core/result/ResultWriter.java
Normal file
@ -0,0 +1,281 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.result;
|
||||
|
||||
import fr.cenra.rhomeo.api.Version;
|
||||
import fr.cenra.rhomeo.api.data.DataContext;
|
||||
import fr.cenra.rhomeo.api.data.Dataset;
|
||||
import fr.cenra.rhomeo.api.data.Reference;
|
||||
import fr.cenra.rhomeo.api.data.ReferenceDescription;
|
||||
import fr.cenra.rhomeo.api.data.TrackingPoint;
|
||||
import fr.cenra.rhomeo.api.data.Warning;
|
||||
import fr.cenra.rhomeo.api.process.Indicator;
|
||||
import fr.cenra.rhomeo.api.result.AdditionalValue;
|
||||
import fr.cenra.rhomeo.api.result.AdditionalValueMapper;
|
||||
import fr.cenra.rhomeo.api.result.Index;
|
||||
import fr.cenra.rhomeo.api.result.TrackingPointIndex;
|
||||
import fr.cenra.rhomeo.core.CSVEncoder;
|
||||
import fr.cenra.rhomeo.core.Session;
|
||||
import fr.cenra.rhomeo.core.util.ExportUtils;
|
||||
import fr.cenra.rhomeo.core.util.SerializableDataContext;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validator;
|
||||
import org.apache.sis.storage.DataStoreException;
|
||||
import org.apache.sis.util.ArgumentChecks;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public class ResultWriter {
|
||||
|
||||
static final String ADDITIONAL_RESULT_FILE_NAME = "additionalResults.csv";
|
||||
static final String RESULT_FILE_NAME = "results.csv";
|
||||
|
||||
@Autowired
|
||||
Session session;
|
||||
|
||||
@Autowired(required = false)
|
||||
Set<AdditionalValueMapper> avMappers;
|
||||
|
||||
public WritingContext prepareWriting(final Path root) throws IOException {
|
||||
return new WritingContext(root, session, avMappers);
|
||||
}
|
||||
|
||||
/**
|
||||
* An object independent from {@link Session} variations, designed to write
|
||||
* a snapshot of results stored in session at a precise time (creation of
|
||||
* an instance of this class).
|
||||
*/
|
||||
public static class WritingContext {
|
||||
final Path root;
|
||||
final DataContext dataContext;
|
||||
final Map<ReferenceDescription, Version> referenceVersions;
|
||||
final Set<Indicator> indicators;
|
||||
final Set<TrackingPoint> trackingPoints;
|
||||
final List<Index> indices;
|
||||
final Validator validator;
|
||||
final Dataset ds;
|
||||
|
||||
final Set<AdditionalValue> additional;
|
||||
final Set<AdditionalValueMapper> mappers;
|
||||
|
||||
private WritingContext(final Path root, final Session session, final Set<AdditionalValueMapper> avMappers) throws IOException {
|
||||
ArgumentChecks.ensureNonNull("Root path", root);
|
||||
ArgumentChecks.ensureNonNull("Session", session);
|
||||
if (!Files.isDirectory(root)) {
|
||||
Files.createDirectories(root);
|
||||
}
|
||||
this.root = root;
|
||||
|
||||
final DataContext dc = session.getDataContext();
|
||||
ArgumentChecks.ensureNonNull("Data context", dc);
|
||||
ArgumentChecks.ensureNonNull("Site", dc.getSite());
|
||||
ArgumentChecks.ensureNonNull("Protocol", dc.getProtocol());
|
||||
dataContext = dc;
|
||||
|
||||
referenceVersions = new HashMap<>();
|
||||
if (dc.getReferences() != null) {
|
||||
for (final Map.Entry<Class<Reference>, Version> entry : dc.getReferences().entrySet()) {
|
||||
for (final ReferenceDescription refDescriptor : dc.getProtocol().getReferenceTypes()) {
|
||||
if (refDescriptor.getReferenceType().equals(entry.getKey()))
|
||||
referenceVersions.put(refDescriptor, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indicators = new HashSet<>(session.getProcessContext().getIndicators());
|
||||
|
||||
trackingPoints = new HashSet<>(session.getProcessContext().getTrackingPoints());
|
||||
|
||||
indices = new ArrayList<>(session.getResults());
|
||||
// #40 : Sort results.
|
||||
indices.sort(new IndexComparator());
|
||||
|
||||
validator = session.getBean(Validator.class);
|
||||
|
||||
ds = session.getDataset();
|
||||
|
||||
mappers = avMappers;
|
||||
if (mappers == null || mappers.isEmpty()) // If no writer is available, there's no need to keep a reference of additional values.
|
||||
additional = Collections.EMPTY_SET;
|
||||
else additional = session.getAdditionalValues();
|
||||
}
|
||||
|
||||
public WritingContext writeSite() throws IOException, DataStoreException {
|
||||
ExportUtils.writeGeoJson(dataContext.getSite(), root);
|
||||
return this;
|
||||
}
|
||||
|
||||
public WritingContext writeMetadataJSON() throws IOException {
|
||||
ExportUtils.writeMetadata(SerializableDataContext.fromDataContext(dataContext), root);
|
||||
return this;
|
||||
}
|
||||
|
||||
public WritingContext writeMetadataText() throws IOException {
|
||||
final Set<ConstraintViolation<Dataset>> datasetErrors = validator.validate(ds);
|
||||
datasetErrors.removeIf(cv -> cv.getConstraintDescriptor().getPayload().contains(Warning.class));
|
||||
|
||||
ExportUtils.writeMetadataText(root.resolve("metadata.txt"), dataContext.getSite(), dataContext.getProtocol(), referenceVersions, indicators, dataContext.getUserData(), datasetErrors);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all results in CSV files (results.csv for main ones,
|
||||
* additionalResults.csv for others).
|
||||
*
|
||||
* @return This context.
|
||||
* @throws IOException
|
||||
* @throws IntrospectionException
|
||||
*/
|
||||
public WritingContext writeResults() throws IOException, IntrospectionException {
|
||||
return writeResults(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write results accepted by given predicate in CSV files (results.csv
|
||||
* for main ones, additionalResults.csv for others).
|
||||
*
|
||||
* @param filter A predicate to filter results.
|
||||
* @return This context.
|
||||
* @throws IOException
|
||||
* @throws IntrospectionException
|
||||
*/
|
||||
public WritingContext writeResults(final Predicate<Index> filter) throws IOException, IntrospectionException {
|
||||
final ArrayList<SimpleLocationIndex> mainResults = new ArrayList();
|
||||
final ArrayList<SimpleLocationIndex> additionalResults = new ArrayList();
|
||||
|
||||
boolean primaryHasLocation = false;
|
||||
boolean additionalHasLocation = false;
|
||||
for (final Index i : indices) {
|
||||
if (filter != null && !filter.test(i))
|
||||
continue;
|
||||
|
||||
boolean isPrimary = i.getSpi().isPrimary();
|
||||
if (isPrimary) {
|
||||
mainResults.add(new SimpleLocationIndex(i));
|
||||
if (i instanceof TrackingPointIndex)
|
||||
primaryHasLocation = true;
|
||||
} else {
|
||||
additionalResults.add(new SimpleLocationIndex(i));
|
||||
if (i instanceof TrackingPointIndex)
|
||||
additionalHasLocation = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Write main results
|
||||
if (!mainResults.isEmpty()) {
|
||||
final Path mainResultPath = root.resolve(RESULT_FILE_NAME);
|
||||
Files.deleteIfExists(mainResultPath);
|
||||
new CSVEncoder(
|
||||
mainResultPath,
|
||||
primaryHasLocation ? SimpleLocationIndex.class : SimpleYearIndex.class,
|
||||
StandardCharsets.UTF_8
|
||||
).encode(mainResults, true);
|
||||
}
|
||||
|
||||
// Write additional results.
|
||||
if (!additionalResults.isEmpty()) {
|
||||
final Path additionalResultPath = root.resolve(ADDITIONAL_RESULT_FILE_NAME);
|
||||
Files.deleteIfExists(additionalResultPath);
|
||||
new CSVEncoder(
|
||||
additionalResultPath,
|
||||
additionalHasLocation ? SimpleLocationIndex.class : SimpleYearIndex.class,
|
||||
StandardCharsets.UTF_8
|
||||
).encode(additionalResults, true);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void writeAdditionalValues() throws IOException {
|
||||
if (mappers == null || mappers.isEmpty())
|
||||
return;
|
||||
for (final AdditionalValueMapper mapper : mappers)
|
||||
if (mapper.writeValues(root, additional))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort index by type, year, eventually tracking point, and finally by value.
|
||||
*/
|
||||
private static class IndexComparator implements Comparator<Index> {
|
||||
|
||||
@Override
|
||||
public int compare(Index o1, Index o2) {
|
||||
|
||||
int comparison = o1.getSpi().compareTo(o2.getSpi());
|
||||
if (comparison == 0) {
|
||||
comparison = o1.getYear() - o2.getYear();
|
||||
if (comparison == 0) {
|
||||
if (o1 instanceof TrackingPointIndex) {
|
||||
if (o2 instanceof TrackingPointIndex) {
|
||||
comparison = ((TrackingPointIndex) o1).getPoint().getName().compareTo(((TrackingPointIndex) o2).getPoint().getName());
|
||||
} else {
|
||||
comparison = 1;
|
||||
}
|
||||
} else if (o2 instanceof TrackingPointIndex) {
|
||||
comparison = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return comparison == 0 ? Double.compare(o1.getValue().doubleValue(), o2.getValue().doubleValue()) : comparison;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.result;
|
||||
|
||||
import fr.cenra.rhomeo.api.result.Index;
|
||||
import fr.cenra.rhomeo.api.result.TrackingPointIndex;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class SimpleLocationIndex extends SimpleYearIndex {
|
||||
|
||||
private String location;
|
||||
|
||||
public SimpleLocationIndex(){}
|
||||
|
||||
public SimpleLocationIndex(Index source) {
|
||||
super(source);
|
||||
if (source instanceof TrackingPointIndex)
|
||||
location = ((TrackingPointIndex)source).getPoint().getName();
|
||||
else location = null;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(final String location){this.location=location;}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleLocationIndex{" + "name=" + name + ", year=" + year + ", location=" + location + ", value=" + value +'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.result;
|
||||
|
||||
import fr.cenra.rhomeo.api.result.Index;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
public class SimpleYearIndex {
|
||||
|
||||
protected String name;
|
||||
protected int year;
|
||||
protected Number value;
|
||||
|
||||
public SimpleYearIndex(){}
|
||||
|
||||
protected SimpleYearIndex(final Index source) {
|
||||
name = source.getSpi().getTitle();
|
||||
year = source.getYear();
|
||||
value = source.getValue();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public Number getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setName(final String name){this.name=name;}
|
||||
public void setYear(final int year){this.year=year;}
|
||||
public void setValue(final Number value){this.value=value;}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleYearIndex{" + "name=" + name + ", year=" + year + ", value=" + value + '}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,282 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.state;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import fr.cenra.rhomeo.api.data.DataContext;
|
||||
import fr.cenra.rhomeo.api.data.Dataset;
|
||||
import fr.cenra.rhomeo.api.data.Statement;
|
||||
import fr.cenra.rhomeo.core.CSVDecoder;
|
||||
import fr.cenra.rhomeo.core.CSVEncoder;
|
||||
import fr.cenra.rhomeo.core.Session;
|
||||
import fr.cenra.rhomeo.core.WorkflowStep;
|
||||
import fr.cenra.rhomeo.core.util.SerializableDataContext;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.Observable;
|
||||
import javax.annotation.PreDestroy;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Listens given dataset and data context over time, to save them on change.
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
class DatasetManager implements StepStateManager {
|
||||
|
||||
private static final String CONTEXT_FILE = "context.json";
|
||||
private static final String DATASET_FILE = "dataset.csv";
|
||||
|
||||
@Autowired
|
||||
private Session session;
|
||||
|
||||
@Autowired
|
||||
private StateManager manager;
|
||||
|
||||
private Path target;
|
||||
private DataContext context;
|
||||
private Dataset dataset;
|
||||
|
||||
private final ObjectMapper jsonMapper;
|
||||
|
||||
private final InvalidationListener datasetListener;
|
||||
private final InvalidationListener contextListener;
|
||||
|
||||
private StateManager.Trigger contextTrigger;
|
||||
private StateManager.Trigger datasetTrigger;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public DatasetManager() {
|
||||
jsonMapper = new ObjectMapper();
|
||||
contextListener = this::contextChanged;
|
||||
datasetListener = this::datasetChanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkflowStep getStep() {
|
||||
return WorkflowStep.DATASET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setBackupFolder(Path toWriteInto) {
|
||||
target = toWriteInto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void startSaving() {
|
||||
if (session.getDataContext() == context && session.getDataset() == dataset)
|
||||
return; // Already listening on changes.
|
||||
|
||||
if (context != null || dataset != null)
|
||||
stopSaving();
|
||||
|
||||
context = session.getDataContext();
|
||||
context.getReferences().addListener(contextListener);
|
||||
contextTrigger = manager.prepareTask(this::writeContext, "Data context state");
|
||||
// If data context does not exists, we create it now
|
||||
if (target != null && !Files.exists(target.resolve(CONTEXT_FILE))) {
|
||||
contextChanged(null);
|
||||
}
|
||||
|
||||
dataset = session.getDataset();
|
||||
dataset.getItems().addListener(datasetListener);
|
||||
datasetTrigger = manager.prepareTask(this::writeDataset, "Dataset state");
|
||||
// If dataset does not exists, we create it now
|
||||
if (target != null && !Files.exists(target.resolve(DATASET_FILE))) {
|
||||
datasetChanged(null);
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
@Override
|
||||
public synchronized void stopSaving() {
|
||||
if (dataset != null) {
|
||||
datasetTrigger.close();
|
||||
dataset.getItems().removeListener(datasetListener);
|
||||
datasetTrigger = null;
|
||||
dataset = null;
|
||||
}
|
||||
|
||||
if (context != null) {
|
||||
contextTrigger.close();
|
||||
context.getReferences().removeListener(contextListener);
|
||||
contextTrigger = null;
|
||||
context = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreStep() {
|
||||
if (dataset != null || context != null) {
|
||||
throw new IllegalStateException("Cannot restore dataset while backup is running !");
|
||||
}
|
||||
|
||||
if (target == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* We start restoration with data context, as no dataset can be
|
||||
* initialized without it. The dataset is read once we're sure we've
|
||||
* loaded a valid context.
|
||||
*/
|
||||
try {
|
||||
final SerializableDataContext ctx = readContext();
|
||||
if (ctx == null || !ctx.restoreDataContext(session))
|
||||
return false;
|
||||
|
||||
final List<? extends Statement> data = readDataset();
|
||||
if (data != null) {
|
||||
session.getDataset().getItems().addAll(data);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
StateManager.LOGGER.log(Level.WARNING, "Cannot restore dataset from folder ".concat(target.toString()), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return A data context loaded from backup folder. Null if no context is
|
||||
* available.
|
||||
* @throws IOException If a backup file is present, but something goes wrong
|
||||
* at reading.
|
||||
*/
|
||||
private SerializableDataContext readContext() throws IOException {
|
||||
final Path ctxFile = target.resolve(CONTEXT_FILE);
|
||||
if (Files.isReadable(ctxFile)) {
|
||||
try (final BufferedReader reader = Files.newBufferedReader(ctxFile, StandardCharsets.UTF_8)) {
|
||||
return jsonMapper.readValue(reader, SerializableDataContext.class);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return A dataset loaded from backup folder. Null if none is available.
|
||||
* @throws IntrospectionException If a backup file is present, but something
|
||||
* goes wrong at reading.
|
||||
* @throws IOException If a backup file is present, but something goes wrong
|
||||
* at reading.
|
||||
* @throws ReflectiveOperationException If an error happens with the read
|
||||
* datatype.
|
||||
*/
|
||||
private List<? extends Statement> readDataset() throws IntrospectionException, IOException, ReflectiveOperationException {
|
||||
final Path datafile = target.resolve(DATASET_FILE);
|
||||
if (Files.isReadable(datafile)) {
|
||||
return new CSVDecoder(datafile, session.getDataContext().getProtocol().getDataType(), StandardCharsets.UTF_8).decode();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws IntrospectionException
|
||||
*/
|
||||
private boolean writeDataset() throws IOException, IntrospectionException {
|
||||
final Path tmpFile = Files.createTempFile("tmpDataset", ".csv");
|
||||
new CSVEncoder(tmpFile, context.getProtocol().getDataType(), StandardCharsets.UTF_8).encode(dataset.getItems(), true);
|
||||
|
||||
Files.move(tmpFile, target.resolve(DATASET_FILE), StandardCopyOption.REPLACE_EXISTING);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save current data context. First, we write it in a temporary file. We replace
|
||||
* the backup only once we're sure the context has been successfully written.
|
||||
* @throws IOException
|
||||
*/
|
||||
private boolean writeContext() throws IOException {
|
||||
final Path tmpFile = Files.createTempFile("tmpContext", ".json");
|
||||
// Prepare a serializable object.
|
||||
final SerializableDataContext ctx = SerializableDataContext.fromDataContext(context);
|
||||
try (final BufferedWriter writer = Files.newBufferedWriter(tmpFile, StandardCharsets.UTF_8)) {
|
||||
jsonMapper.writeValue(writer, ctx);
|
||||
}
|
||||
|
||||
Files.move(tmpFile, target.resolve(CONTEXT_FILE), StandardCopyOption.REPLACE_EXISTING);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify writer that we want it to store the current context state. We both
|
||||
* set trigger value and notify it, so if the writer is waiting, it will
|
||||
* be notified, and if it is already running, it will immediately be aware
|
||||
* that a new saving is required.
|
||||
*
|
||||
* @param obs
|
||||
*/
|
||||
private void contextChanged(final Observable obs) {
|
||||
contextTrigger.arm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify writer that we want it to store the current dataset state. We both
|
||||
* set trigger value and notify it, so if the writer is waiting, it will
|
||||
* be notified, and if it is already running, it will immediately be aware
|
||||
* that a new saving is required.
|
||||
*
|
||||
* @param obs
|
||||
*/
|
||||
private void datasetChanged(final Observable obs) {
|
||||
datasetTrigger.arm();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,305 @@
|
||||
/**
|
||||
* Copyright © CENRA (2016)
|
||||
*
|
||||
* remi.clement@espaces-naturels.fr
|
||||
*
|
||||
* This software is a multi-platform and portable application based on
|
||||
* the scientifical toolbox to monitor wetlands. With this toolbox it’s
|
||||
* possible to calculate indicators «RhoMéO» to monitor quality,
|
||||
* fonctionalities and urban and agricultural pressures of wetlands.
|
||||
* Indicators are calculated using naturalist data entered and/or imported,
|
||||
* and geographic data downloaded from a geographic server.
|
||||
*
|
||||
* This software is governed by the CeCILL license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use,
|
||||
* modify and/ or redistribute the software under the terms of the CeCILL
|
||||
* license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
* "http://www.cecill.info".
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy,
|
||||
* modify and redistribute granted by the license, users are provided only
|
||||
* with a limited warranty and the software's author, the holder of the
|
||||
* economic rights, and the successive licensors have only limited
|
||||
* liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated
|
||||
* with loading, using, modifying and/or developing or reproducing the
|
||||
* software by the user in light of its specific status of free software,
|
||||
* that may mean that it is complicated to manipulate, and that also
|
||||
* therefore means that it is reserved for developers and experienced
|
||||
* professionals having in-depth computer knowledge. Users are therefore
|
||||
* encouraged to load and test the software's suitability as regards their
|
||||
* requirements in conditions enabling the security of their systems and/or
|
||||
* data to be ensured and, more generally, to use and operate it in the
|
||||
* same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL license and that you accept its terms.
|
||||
*/
|
||||
package fr.cenra.rhomeo.core.state;
|
||||
|
||||
import fr.cenra.rhomeo.api.process.Indicator;
|
||||
import fr.cenra.rhomeo.api.process.ProcessContext;
|
||||
import fr.cenra.rhomeo.core.Session;
|
||||
import fr.cenra.rhomeo.core.WorkflowStep;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.logging.Level;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.MapChangeListener;
|
||||
import javafx.collections.SetChangeListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexis Manin (Geomatys)
|
||||
*/
|
||||
@Component
|
||||
public class ProcessManager implements StepStateManager {
|
||||
|
||||
private static final String INDICATOR_FILE = "indicators.txt";
|
||||
private static final String FILTER_FILE = "filter";
|
||||
private static final String USER_DATA_FILE = "userData";
|
||||
|
||||
@Autowired
|
||||
private Session session;
|
||||
|
||||
@Autowired
|
||||
private StateManager manager;
|
||||
|
||||
private Path target;
|
||||
|
||||
private ProcessContext ctx;
|
||||
|
||||
private StateManager.Trigger indicatorTrigger;
|
||||
private StateManager.Trigger filterTrigger;
|
||||
private StateManager.Trigger userDataTrigger;
|
||||
|
||||
private final SetChangeListener<Indicator> indicatorListener = this::indicatorsChanged;
|
||||
private final ChangeListener<Predicate> filterListener = this::filterChanged;
|
||||
private final MapChangeListener userDataListener = this::userDataChanged;
|
||||
|
||||
@Override
|
||||
public void setBackupFolder(Path toWriteInto) {
|
||||
target = toWriteInto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkflowStep getStep() {
|
||||
return WorkflowStep.PROCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startSaving() {
|
||||
if (ctx != null)
|
||||
stopSaving();
|
||||
|
||||
ctx = session.getProcessContext();
|
||||
|
||||
// Submit backup tasks.
|
||||
filterTrigger = manager.prepareTask(this::writeFilter, "Process context filter");
|
||||
indicatorTrigger = manager.prepareTask(this::writeIndicators, "Process context indicators");
|
||||
userDataTrigger = manager.prepareTask(this::writeUserData, "Process context indicators");
|
||||
|
||||
// Force writing process context in current state.
|
||||
filterTrigger.arm();
|
||||
indicatorTrigger.arm();
|
||||
userDataTrigger.arm();
|
||||
|
||||
// listens on process context change.
|
||||
ctx.filterProperty().addListener(filterListener);
|
||||
ctx.getIndicators().addListener(indicatorListener);
|
||||
ctx.getDataCtx().getUserData().addListener(userDataListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopSaving() {
|
||||
if (ctx != null) {
|
||||
ctx.filterProperty().removeListener(filterListener);
|
||||
filterTrigger.close();
|
||||
filterTrigger = null;
|
||||
|
||||
ctx.getIndicators().removeListener(indicatorListener);
|
||||
indicatorTrigger.close();
|
||||
indicatorTrigger = null;
|
||||
|
||||
ctx.getDataCtx().getUserData().removeListener(userDataListener);
|
||||
userDataTrigger.close();
|
||||
userDataTrigger = null;
|
||||
|
||||
ctx = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreStep() {
|
||||
final ProcessContext ctx = readProcessContext();
|
||||
if (ctx != null) {
|
||||
session.setProcessContext(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ProcessContext readProcessContext() {
|
||||
// Cannot restore process context if no data has been prepared before hand.
|
||||
if (target == null || session.getDataContext() == null || session.getDataset() == null)
|
||||
return null;
|
||||
|
||||
final Predicate filter;
|
||||
final Collection<Indicator> indics;
|
||||
final Map userData;
|
||||
try {
|
||||
filter = readFilter();
|
||||
indics = readIndicators();
|
||||
userData = readUserData();
|
||||
} catch (Exception e) {
|
||||
StateManager.LOGGER.log(Level.WARNING, "Cannot restore process context.", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
final boolean noIndic = indics == null || indics.isEmpty();
|
||||
final boolean noUserData = userData == null || userData.isEmpty();
|
||||
if (filter == null && noIndic && noUserData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ProcessContext context = new ProcessContext(session.getDataset(), session.getDataContext());
|
||||
if (filter != null) {
|
||||
context.setFilter(filter);
|
||||
}
|
||||
if (!noIndic) {
|
||||
context.getIndicators().addAll(indics);
|
||||
}
|
||||
if (!noUserData) {
|
||||
context.getDataCtx().getUserData().putAll(userData);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Tracking points saved in backup file.
|
||||
*/
|
||||
private Predicate readFilter() throws IOException, ClassNotFoundException {
|
||||
final Path file;
|
||||
if (target == null || !Files.isReadable((file = target.resolve(FILTER_FILE))))
|
||||
return null;
|
||||
|
||||
try (final InputStream source = Files.newInputStream(file);
|
||||
final ObjectInputStream input = new ObjectInputStream(source)) {
|
||||
final Object read = input.readObject();
|
||||
if (read instanceof Predicate)
|
||||
return (Predicate) read;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Collection<Indicator> readIndicators() throws IOException {
|
||||
final Path file;
|
||||
if (target == null || !Files.isReadable((file = target.resolve(INDICATOR_FILE))))
|
||||
return null;
|
||||
|
||||
final HashSet<Indicator> indicators = new HashSet<>();
|
||||
try (final BufferedReader r = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
|
||||
r.lines().forEach(line -> {
|
||||
final Optional<Indicator> optIndicator = session.getIndicators().stream()
|
||||
.filter(indicator -> line.equals(indicator.getName()))
|
||||
.findFirst();
|
||||
optIndicator.ifPresent(indicators::add);
|
||||
});
|
||||
}
|
||||
|
||||
return indicators;
|
||||
}
|
||||
|
||||
private Map readUserData() throws IOException, ClassNotFoundException {
|
||||
final Path file;
|
||||
if (target == null || !Files.isReadable((file = target.resolve(USER_DATA_FILE))))
|
||||
return null;
|
||||
|
||||
try (final InputStream source = Files.newInputStream(file);
|
||||
final ObjectInputStream input = new ObjectInputStream(source)) {
|
||||
final Object read = input.readObject();
|
||||
if (read instanceof Map)
|
||||
return (Map) read;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean writeFilter() throws IOException, IntrospectionException {
|
||||
if (ctx.getFilter() == null)
|
||||
return false;
|
||||
|
||||
final Path tmpFile = Files.createTempFile(target, FILTER_FILE, ".tmp");
|
||||
try (final OutputStream destination = Files.newOutputStream(tmpFile);
|
||||
final ObjectOutputStream output = new ObjectOutputStream(destination)) {
|
||||
output.writeObject(ctx.getFilter());
|
||||
}
|
||||
Files.move(tmpFile, target.resolve(FILTER_FILE), StandardCopyOption.REPLACE_EXISTING);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean writeIndicators() throws IOException {
|
||||
if (ctx.getIndicators().isEmpty())
|
||||
return false;
|
||||
|
||||
final Path tmpFile = Files.createTempFile(target, INDICATOR_FILE, ".tmp");
|
||||
try (final BufferedWriter w = Files.newBufferedWriter(tmpFile, StandardCharsets.UTF_8)) {
|
||||
for (final Indicator i : ctx.getIndicators()) {
|
||||
w.write(i.getName());
|
||||
w.newLine();
|
||||
}
|
||||
}
|
||||
Files.move(tmpFile, target.resolve(INDICATOR_FILE), StandardCopyOption.REPLACE_EXISTING);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean writeUserData() throws IOException {
|
||||
// Defensive copy. Moreover, Serialization does not work with observable map.
|
||||
final Map<String, Object> userData = new HashMap(ctx.getDataCtx().getUserData());
|
||||
if (userData.isEmpty())
|
||||
return false;
|
||||
|
||||
final Path tmpFile = Files.createTempFile(target, USER_DATA_FILE, ".tmp");
|
||||
try (final OutputStream destination = Files.newOutputStream(tmpFile);
|
||||
final ObjectOutputStream output = new ObjectOutputStream(destination)) {
|
||||
output.writeObject(userData);
|
||||
}
|
||||
|
||||
Files.move(tmpFile, target.resolve(USER_DATA_FILE), StandardCopyOption.REPLACE_EXISTING);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void filterChanged(final ObservableValue<? extends Predicate> obs, Predicate oldValue, Predicate newValue) {
|
||||
filterTrigger.arm();
|
||||
}
|
||||
|
||||
private void indicatorsChanged(final SetChangeListener.Change c) {
|
||||
indicatorTrigger.arm();
|
||||
}
|
||||
|
||||
private void userDataChanged(final MapChangeListener.Change c) {
|
||||
userDataTrigger.arm();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user