initial commit of version 2

This commit is contained in:
Andreas Billmann
2015-03-23 21:50:58 +01:00
commit 6a4c1ace4f
58 changed files with 5327 additions and 0 deletions

76
.gitignore vendored Normal file
View File

@@ -0,0 +1,76 @@
# Created by .ignore support plugin (hsz.mobi)
### Java template
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Gradle template
.gradle
build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties

17
README.md Normal file
View File

@@ -0,0 +1,17 @@
GeoFroggerFX
============
GeoFroggerFX is a JavaFX desktop application to manage geocaching gpx files.
Webpage of the project: [http://www.geofroggerfx.de](http://www.geofroggerfx.de)
This is the second try after a complete rewrite.
Requirements
------------
- JDK8
Building and run with Gradle
----------------------------
* Set your environment variable JAVA_HOME to the directory that contains the JDK1.8
* gradlew run

26
build.gradle Normal file
View File

@@ -0,0 +1,26 @@
apply plugin: 'java'
apply plugin: 'groovy'
apply plugin:'application'
apply plugin: 'idea'
sourceCompatibility = 1.8
version = '1.0'
mainClassName = 'de.geofroggerfx.ui.GeoFroggerFX'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.0'
compile group: 'org.springframework', name:'spring-context', version: '4.1.5.RELEASE'
compile group: 'org.springframework', name:'spring-jdbc', version: '4.1.5.RELEASE'
compile group: 'org.codehaus.woodstox', name: 'woodstox-core-asl', version: '4.4.1'
compile group: 'org.codehaus.woodstox', name: 'stax2-api', version: '4.0.0'
compile group: 'com.h2database', name: 'h2', version: '1.4.186'
compile group: 'de.jensd', name: 'fontawesomefx', version: '8.2'
compile group: 'org.controlsfx', name: 'controlsfx', version: '8.20.8'
compile group: 'com.lynden', name: 'GMapsFX', version: '1.1.1'
}

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Mon Mar 09 19:47:19 CET 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip

164
gradlew vendored Normal file
View File

@@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

25
license.txt Normal file
View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2013-2015 Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

View File

@@ -0,0 +1,97 @@
import de.geofroggerfx.plugins.Plugin
import javafx.collections.FXCollections
import javafx.scene.chart.PieChart
import javafx.scene.control.ButtonType
import javafx.scene.control.Dialog
import javafx.scene.control.ScrollPane
import javafx.scene.layout.VBox
import static javafx.scene.chart.PieChart.Data
class BasicListStatisticsPlugin implements Plugin {
private difficultyTerrainValues = ['1', '1.5', '2', '2.5', '3', '3.5', '4', '4.5', '5']
final String name = "Basic List Statistic"
final String version = "0.0.2"
@Override
void run(final Map context) {
showDialog(createContent(context.cacheService))
}
/**
* creates the statistic charts to show
* @param sessionContext context with the cache list in it
* @return
*/
private javafx.scene.Node createContent(cacheService) {
// get the cache list from service
def cacheList = cacheService.getAllCaches()
// create a vbox as layout container
VBox contenPane = new VBox()
// groovy maps for selecting the statistic numbers
def typeStats = [:]
def difficultyStats = [:]
def terrainStats = [:]
// iterate over all the caches and count the data
for (def cache in cacheList) {
incrementStats(typeStats, cache.type)
incrementStats(difficultyStats, cache.difficulty)
incrementStats(terrainStats, cache.terrain)
}
// create javafx chart
def typeData = FXCollections.observableArrayList()
typeStats.each() { key, value -> typeData.add(new Data(key.toString() + ' (' + value + ')', value as double)) }
def typeChart = new PieChart(typeData);
typeChart.setTitle("Spreading of cache types in list.");
// create javafx chart
def difficultyData = FXCollections.observableArrayList()
difficultyTerrainValues.each {
def value = difficultyStats[it]
if (value) difficultyData.add(new Data(it + ' (' + value + ')', value))
}
def difficultyChart = new PieChart(difficultyData);
difficultyChart.setTitle("Spreading of difficulties in list.");
// create javafx chart
def terrainData = FXCollections.observableArrayList()
difficultyTerrainValues.each {
def value = terrainStats[it]
if (value) terrainData.add(new Data(it + ' (' + value + ')', value))
}
def terrainChart = new PieChart(terrainData);
terrainChart.setTitle("Spreading of terrain in list.");
// add charts to layout container
contenPane.children.addAll(typeChart, difficultyChart, terrainChart)
// return the layout container
def scrollPane = new ScrollPane(contenPane)
scrollPane.minWidth = 600
scrollPane.minHeight = 450
scrollPane
}
private void incrementStats(map, key) {
map[key] = map[key] ? map[key] + 1 : 1
}
private void showDialog(content) {
Dialog dialog = new Dialog()
dialog.resizableProperty().set(true)
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.CLOSE);
dialog.setTitle(name + " (" + version + ")")
dialog.setHeaderText("This example plugin shows some stats based on the current list.\nThese statistics are global statistics over all caches in list\nand not personalized statistics over own founds.")
dialog.getDialogPane().setContent(content)
dialog.setWidth(800)
dialog.setHeight(600)
dialog.show()
}
}

View File

@@ -0,0 +1,139 @@
import de.geofroggerfx.plugins.Plugin
import javafx.collections.FXCollections
import javafx.concurrent.Service
import javafx.concurrent.Task
import javafx.concurrent.WorkerStateEvent
import javafx.event.EventHandler
import javafx.scene.chart.PieChart
import javafx.scene.control.ButtonType
import javafx.scene.control.Dialog
import javafx.scene.control.ScrollPane
import javafx.scene.layout.Priority
import javafx.scene.layout.VBox
import static javafx.scene.chart.PieChart.Data
class OwnStatisticsPlugin implements Plugin {
private difficultyTerrainValues = ['1', '1.5', '2', '2.5', '3', '3.5', '4', '4.5', '5']
final String name = "Own Statistic"
final String version = "0.0.1"
final CalculateService service = new CalculateService();
OwnStatisticsPlugin() {
service.onSucceeded = {
showDialog(createContent(it.source.value))
} as EventHandler<WorkerStateEvent>;
}
@Override
void run(final Map context) {
calculateStats(context.cacheService)
}
/**
* creates the statistic charts to show
* @param sessionContext context with the cache list in it
* @return
*/
private void calculateStats(cacheService) {
// get the cache list from service
def cacheList = cacheService.getAllCaches()
service.cacheList = cacheList;
service.restart();
}
/**
* creates the statistic charts to show
* @param sessionContext context with the cache list in it
* @return
*/
private javafx.scene.Node createContent(result) {
// create a vbox as layout container
VBox contenPane = new VBox()
contenPane.prefWidth = 600
VBox.setVgrow(contenPane, Priority.ALWAYS);
// create javafx chart
def typeData = FXCollections.observableArrayList()
result.typeStats.each() { key, value -> typeData.add(new Data(key.toString() + ' (' + value + ')', value as double)) }
def typeChart = new PieChart(typeData);
typeChart.setTitle("Spreading of cache types found (${result.foundCount}).");
// create javafx chart
def difficultyData = FXCollections.observableArrayList()
difficultyTerrainValues.each {
def value = result.difficultyStats[it]
if (value) difficultyData.add(new Data(it + ' (' + value + ')', value))
}
def difficultyChart = new PieChart(difficultyData);
difficultyChart.setTitle("Spreading of difficulties found (${result.foundCount}).");
// create javafx chart
def terrainData = FXCollections.observableArrayList()
difficultyTerrainValues.each {
def value = result.terrainStats[it]
if (value) terrainData.add(new Data(it + ' (' + value + ')', value))
}
def terrainChart = new PieChart(terrainData);
terrainChart.setTitle("Spreading of terrain found (${result.foundCount}).");
// add charts to layout container
contenPane.children.addAll(typeChart, difficultyChart, terrainChart)
// return the layout container
def scrollPane = new ScrollPane(contenPane)
scrollPane.minWidth = 640
scrollPane.minHeight = 450
scrollPane
}
private void showDialog(content) {
Dialog dialog = new Dialog()
dialog.resizableProperty().set(true)
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.CLOSE);
dialog.setTitle(name + " (" + version + ")")
dialog.setHeaderText("This example plugin shows some stats based on the current list.\nThese statistics are found statistics, based on all found caches in the list.")
dialog.getDialogPane().setContent(content)
dialog.setWidth(800)
dialog.setHeight(600)
dialog.show()
}
}
class CalculateService extends Service {
def cacheList
@Override
protected Task createTask() {
return new Task() {
@Override
protected LinkedHashMap call() throws Exception {
def typeStats = [:]
def difficultyStats = [:]
def terrainStats = [:]
def foundCount = 0
for (def cache in cacheList) {
if (cache.found) {
foundCount++
incrementStats(typeStats, cache.type)
incrementStats(difficultyStats, cache.difficulty)
incrementStats(terrainStats, cache.terrain)
}
}
['foundCount': foundCount, 'typeStats': typeStats, 'difficultyStats': difficultyStats, 'terrainStats': terrainStats]
}
};
}
private void incrementStats(map, key) {
map[key] = map[key] ? map[key] + 1 : 1
}
}

2
settings.gradle Normal file
View File

@@ -0,0 +1,2 @@
rootProject.name = 'GeoFroggerFX2'

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.application;
/**
* @author Andreas
*/
public class ProgressEvent {
public enum State {INITIALIZED, STARTED, RUNNING, FINISHED}
;
public static final double INDETERMINATE_PROGRESS = -1.0;
private final String module;
private final State state;
private final String message;
private final Double progress;
public ProgressEvent(String module, State state, String message) {
this(module, state, message, INDETERMINATE_PROGRESS);
}
public ProgressEvent(String module, State state, String message, Double progress) {
this.module = module;
this.state = state;
this.message = message;
this.progress = progress;
}
public String getModule() {
return module;
}
public State getState() {
return state;
}
public String getMessage() {
return message;
}
public Double getProgress() {
return progress;
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.application;
/**
* @author Andreas
*/
public interface ProgressListener {
void progress(ProgressEvent event);
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.application;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Andreas
*/
@Component
public class SessionContext {
public static final String CACHE_ENTRY_LIST = "CACHE_ENTRY_LIST";
public static final String CURRENT_CACHE = "CURRENT_CACHE";
private final Map<String, Object> map = new ConcurrentHashMap<>();
private final Map<String, List<SessionContextListener>> sessionListeners = new HashMap<>();
public void setData(String key, Object value) {
if (value == null && map.containsKey(key)) {
map.remove(key);
} else if (value != null) {
map.put(key, value);
}
fireSessionEvent(key);
}
public Object getData(String key) {
if (map.containsKey(key)) {
return map.get(key);
} else {
return null;
}
}
public void addListener(String key, SessionContextListener sessionListener) {
List<SessionContextListener> listenerList;
if (sessionListeners.containsKey(key)) {
listenerList = sessionListeners.get(key);
} else {
listenerList = new ArrayList<>();
sessionListeners.put(key, listenerList);
}
if (!listenerList.contains(sessionListener)) {
listenerList.add(sessionListener);
}
}
private void fireSessionEvent(String key) {
if (sessionListeners.containsKey(key)) {
sessionListeners.
get(key).
stream().
forEach(SessionContextListener::sessionContextChanged);
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.application;
/**
* @author Andreas
*/
public interface SessionContextListener {
void sessionContextChanged();
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.dao;
import de.geofroggerfx.model.Cache;
import de.geofroggerfx.model.CacheListEntry;
import java.util.List;
/**
* Created by Andreas on 11.03.2015.
*/
public interface CacheDAO {
void save(List<Cache> listOfCaches);
void update(Cache cache);
List<CacheListEntry> getAllCachEntriesSortBy(String name, String asc);
Cache getCacheForId(long id);
List<Cache> getAllCaches();
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.dao.jdbc;
import org.h2.jdbcx.JdbcDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
/**
* Created by Andreas on 11.03.2015.
*/
@Configuration
@PropertySource("classpath:/de/geofroggerfx/dao/jdbc/database.properties")
public class DataConfig {
@Autowired
private Environment env;
@Bean
public DataSource dataSource(){
JdbcDataSource dataSource = new JdbcDataSource();
dataSource.setURL(env.getProperty("jdbc.url"));
dataSource.setUser(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager(){
return new DataSourceTransactionManager(dataSource());
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.dao.jdbc;
/**
* Created by Andreas on 11.03.2015.
*/
public class JDBCUtils {
public static String generateSelectSQL(String table, String... columns) {
assert columns != null && columns.length > 0 : "columns must not be null or empty";
StringBuffer sql = new StringBuffer();
sql.append("SELECT ");
for (int columnCounter = 0; columnCounter < columns.length-1; columnCounter++) {
addCommaToValue(sql, columns[columnCounter]);
}
sql.append(columns[columns.length-1]);
sql.append(" FROM ").append(table);
return sql.toString();
}
public static String generateUpdateSQL(String table, String... columns) {
assert columns != null && columns.length > 0 : "columns must not be null or empty";
StringBuffer sql = new StringBuffer();
sql.append("UPDATE ").append(table).append(" SET ");
for (int columnCounter = 0; columnCounter < columns.length-1; columnCounter++) {
addCommaToValue(sql, columns[columnCounter]+"=? ");
}
sql.append(columns[columns.length-1]+"=? ");
sql.append(" WHERE ID = ?");
return sql.toString();
}
public static String generateInsertSQL(String table, String... columns) {
assert columns != null && columns.length > 0 : "columns must not be null or empty";
StringBuffer sql = new StringBuffer();
sql.append("INSERT INTO ").append(table).append("(");
for (int columnCounter = 0; columnCounter < columns.length-1; columnCounter++) {
addCommaToValue(sql, columns[columnCounter]);
}
sql.append(columns[columns.length-1]);
sql.append(") ");
sql.append("values(");
for (int columnCounter = 0; columnCounter < columns.length-1; columnCounter++) {
addCommaToValue(sql, "?");
}
sql.append("?");
sql.append(") ");
return sql.toString();
}
public static String generateInsertSQL(String table, String[] columns, Object[] values) {
assert columns != null && columns.length > 0 : "columns must not be null or empty";
StringBuffer sql = new StringBuffer();
sql.append("INSERT INTO ").append(table).append("(");
for (int columnCounter = 0; columnCounter < columns.length-1; columnCounter++) {
addCommaToValue(sql, columns[columnCounter]);
}
sql.append(columns[columns.length-1]);
sql.append(") ");
sql.append("values(");
for (int valuesCounter = 0; valuesCounter < values.length-1; valuesCounter++) {
addCommaToValue(sql, "'"+values[valuesCounter]+"'");
}
sql.append("'"+values[values.length-1]+"'");
sql.append(") ");
return sql.toString();
}
public static void addCommaToValue(StringBuffer sql, String value) {
sql.append(value);
sql.append(",");
}
}

View File

@@ -0,0 +1,327 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.dao.jdbc;
import de.geofroggerfx.dao.CacheDAO;
import de.geofroggerfx.model.Cache;
import de.geofroggerfx.model.CacheListEntry;
import de.geofroggerfx.model.Waypoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import static de.geofroggerfx.dao.jdbc.JDBCUtils.*;
import static de.geofroggerfx.model.Container.groundspeakStringToContainer;
import static de.geofroggerfx.model.Type.groundspeakStringToType;
/**
* Created by Andreas on 11.03.2015.
*/
@Repository
public class JdbcCacheDAO implements CacheDAO {
private static final Logger LOGGER = Logger.getLogger("JdbcCacheDAO");
private static final String CACHE_TABLE = "cache";
private static final String WAYPOINT_TABLE = "waypoint";
private String[] columnListCache = new String[] {
"id",
"name",
"placed_by",
"available",
"archived",
"found",
"difficulty",
"terrain",
"country",
"state",
"short_description",
"short_description_html",
"long_description",
"long_description_html",
"encoded_hints",
"container",
"type",
"user_id"};
private String[] columnListWaypoint = new String[] {
"name",
"cache_id",
"latitude",
"longitude",
"time",
"description",
"url",
"urlName",
"symbol",
"type"};
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataConfig(DataConfig dataConfig) {
this.jdbcTemplate = new JdbcTemplate(dataConfig.dataSource());
}
@Override
public void save(List<Cache> listOfCaches) {
deleteExistingCaches(listOfCaches);
batchInsertCaches(listOfCaches);
batchInsertWaypoints(listOfCaches);
}
@Override
public void update(Cache cache) {
String updateSQL = generateUpdateSQL(CACHE_TABLE, columnListCache);
jdbcTemplate.update(updateSQL, valuesFromCache(cache, cache.getId()));
updateSQL = generateUpdateSQL(WAYPOINT_TABLE, columnListWaypoint);
jdbcTemplate.update(updateSQL, valuesFromWaypoint(cache, cache.getMainWayPoint().getName()));
}
@Override
public List<CacheListEntry> getAllCachEntriesSortBy(String name, String asc) {
return this.jdbcTemplate.query(
"SELECT c.id, c.name AS name, c.name AS code, c.difficulty, c.terrain, c.type FROM "+CACHE_TABLE+" c ORDER BY "+name+" "+asc,
(rs, rowNum) -> {
return new CacheListEntry(
rs.getLong("id"),
rs.getString("name"),
rs.getString("code"),
rs.getString("difficulty"),
rs.getString("terrain"),
groundspeakStringToType(rs.getString("type")));
});
}
@Override
public Cache getCacheForId(long id) {
return this.jdbcTemplate.queryForObject(
generateSelectSQL(CACHE_TABLE, columnListCache) + " WHERE id=?",
new Object[]{id},
(rs, rowNum) -> {
Cache cache = getCacheFromResultSet(rs);
Waypoint waypoint = getWaypointForCacheId(cache.getId());
cache.setMainWayPoint(waypoint);
waypoint.setCache(cache);
return cache;
});
}
@Override
public List<Cache> getAllCaches() {
return this.jdbcTemplate.query(
generateSelectSQL(CACHE_TABLE, columnListCache),
(rs, rowNum) -> {
return getCacheFromResultSet(rs);
});
}
private void batchInsertCaches(List<Cache> listOfCaches) {
LOGGER.info("try to save " + listOfCaches.size() + " caches");
long startInsert = System.currentTimeMillis();
List<Object[]> batch = listOfCaches.parallelStream().map(this::valuesFromCache).collect(Collectors.toList());
try {
String insertSQL = generateInsertSQL(CACHE_TABLE, columnListCache);
int[] updateCounts = jdbcTemplate.batchUpdate(
insertSQL,
batch);
int updatedRows = 0;
for (int count:updateCounts) {
updatedRows += count;
}
LOGGER.info("batch inserted "+updatedRows+" caches");
} catch (Throwable e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
long endInsert = System.currentTimeMillis();
LOGGER.info("try to save " + listOfCaches.size() + " caches -> done in " + (endInsert - startInsert) + " ms");
}
private void deleteExistingCaches(List<Cache> listOfCaches) {
LOGGER.info("try to delete existing caches");
long startDelete = System.currentTimeMillis();
StringBuffer sb = new StringBuffer();
for (int current = 0; current < listOfCaches.size()-1; current++) {
addCommaToValue(sb, Long.toString(listOfCaches.get(current).getId()));
}
sb.append(listOfCaches.get(listOfCaches.size()-1).getId());
try {
int result = jdbcTemplate.update("DELETE FROM "+CACHE_TABLE+" WHERE id IN ("+sb.toString()+")");
LOGGER.info("deleted "+result+" caches");
} catch (Throwable e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
long endDelete = System.currentTimeMillis();
LOGGER.info("try to delete existing caches -> done in " + (endDelete - startDelete) + " ms");
}
private void batchInsertWaypoints(List<Cache> listOfCaches) {
LOGGER.info("try to save "+listOfCaches.size()+" waypoints");
long startInsert = System.currentTimeMillis();
List<Object[]> batch = listOfCaches.parallelStream().map(this::valuesFromWaypoint).collect(Collectors.toList());
try {
String insertSQL = generateInsertSQL(WAYPOINT_TABLE, columnListWaypoint);
int[] updateCounts = jdbcTemplate.batchUpdate(
insertSQL,
batch);
int updatedRows = 0;
for (int count:updateCounts) {
updatedRows += count;
}
LOGGER.info("batch inserted "+updatedRows+" waypoints");
} catch (Throwable e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
long endInsert = System.currentTimeMillis();
LOGGER.info("try to save "+listOfCaches.size()+" waypoints -> done in "+(endInsert-startInsert)+" ms");
}
private Waypoint getWaypointForCacheId(long cacheId) {
return this.jdbcTemplate.queryForObject(
generateSelectSQL(WAYPOINT_TABLE, columnListWaypoint) + " WHERE cache_id=?",
new Object[]{cacheId},
(rs, rowNum) -> {
return getWaypointFromResultSet(rs);
});
}
private Cache getCacheFromResultSet(ResultSet rs) throws SQLException {
Cache cache = new Cache();
cache.setId(rs.getLong("id"));
cache.setName(rs.getString("name"));
cache.setDifficulty(rs.getString("difficulty"));
cache.setTerrain(rs.getString("terrain"));
cache.setPlacedBy(rs.getString("placed_by"));
cache.setAvailable(rs.getBoolean("available"));
cache.setArchived(rs.getBoolean("archived"));
cache.setFound(rs.getBoolean("found"));
cache.setCountry(rs.getString("country"));
cache.setState(rs.getString("state"));
cache.setShortDescription(rs.getString("short_description"));
cache.setLongDescription(rs.getString("long_description"));
cache.setEncodedHints(rs.getString("encoded_hints"));
cache.setShortDescriptionHtml(rs.getBoolean("short_description_html"));
cache.setLongDescriptionHtml(rs.getBoolean("long_description_html"));
cache.setContainer(groundspeakStringToContainer(rs.getString("container")));
cache.setType(groundspeakStringToType(rs.getString("type")));
cache.setOwner(null);
return cache;
}
private Object[] valuesFromCache(Cache cache) {
return new Object[]{
cache.getId(),
cache.getName(),
cache.getPlacedBy(),
cache.getAvailable(),
cache.getArchived(),
cache.getFound(),
cache.getDifficulty(),
cache.getTerrain(),
cache.getCountry(),
cache.getState(),
cache.getShortDescription(),
cache.getShortDescriptionHtml(),
cache.getLongDescription(),
cache.getLongDescriptionHtml(),
cache.getEncodedHints(),
cache.getContainer().toGroundspeakString(),
cache.getType().toGroundspeakString(),
cache.getOwner() != null ? cache.getOwner().getId() : null };
}
private Waypoint getWaypointFromResultSet(ResultSet rs) throws SQLException {
Waypoint waypoint = new Waypoint();
waypoint.setName(rs.getString("name"));
waypoint.setLatitude(rs.getDouble("latitude"));
waypoint.setLongitude(rs.getDouble("longitude"));
waypoint.setTime(rs.getTimestamp("time"));
waypoint.setDescription(rs.getString("description"));
waypoint.setUrl(rs.getString("url"));
waypoint.setUrlName(rs.getString("urlName"));
waypoint.setSymbol(rs.getString("symbol"));
// waypoint.setType(WaypointType.rs.getString("description"));
return waypoint;
}
private Object[] valuesFromWaypoint(Cache cache) {
return new Object[]{
cache.getMainWayPoint().getName(),
cache.getId(),
cache.getMainWayPoint().getLatitude(),
cache.getMainWayPoint().getLongitude(),
cache.getMainWayPoint().getTime(),
cache.getMainWayPoint().getDescription(),
cache.getMainWayPoint().getUrl(),
cache.getMainWayPoint().getUrlName(),
cache.getMainWayPoint().getSymbol(),
null
};
/*
"name",
"cache_id",
"latitude",
"longitude",
"time",
"description",
"url",
"urlName",
"symbol",
"type"
*/
}
private Object[] valuesFromCache(Cache cache, long id) {
return Arrays.asList(valuesFromCache(cache), id).toArray();
}
private Object[] valuesFromWaypoint(Cache cache, String name) {
return Arrays.asList(valuesFromWaypoint(cache), name).toArray();
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.gpx;
import de.geofroggerfx.application.ProgressListener;
import de.geofroggerfx.model.Cache;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* TODO: describe the class
*
* @author Andreas Billmann
*/
public interface GPXReader {
List<Cache> load(File fileName) throws IOException;
void addListener(ProgressListener listener);
}

View File

@@ -0,0 +1,267 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.gpx;
import de.geofroggerfx.application.ProgressEvent;
import de.geofroggerfx.application.ProgressListener;
import de.geofroggerfx.model.*;
import org.springframework.stereotype.Service;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
/**
* @author Andreas Billmann
*/
@Service
public class GroundspeakGPXReader implements GPXReader {
private static final Logger LOGGER = Logger.getLogger(GroundspeakGPXReader.class.getName());
public static final String LAT = "lat";
public static final String LON = "lon";
public static final String TIME = "time";
public static final String NAME = "name";
public static final String DESC = "desc";
public static final String WPT = "wpt";
public static final String URL = "url";
public static final String URLNAME = "urlname";
public static final String SYM = "sym";
public static final String TYPE = "type";
public static final String CACHE = "cache";
public static final String GROUNDSPEAK = "groundspeak";
public static final String ID = "id";
public static final String AVAILABLE = "available";
public static final String ARCHIVED = "archived";
public static final String PLACED_BY = "placed_by";
public static final String OWNER = "owner";
public static final String CONTAINER = "container";
public static final String ATTRIBUTES = "attributes";
public static final String ATTRIBUTE = "attribute";
public static final String INC = "inc";
public static final String DIFFICULTY = "difficulty";
public static final String TERRAIN = "terrain";
public static final String COUNTRY = "country";
public static final String STATE = "state";
public static final String SHORT_DESCRIPTION = "short_description";
public static final String HTML = "html";
public static final String LONG_DESCRIPTION = "long_description";
public static final String ENCODED_HINTS = "encoded_hints";
public static final String LOGS = "logs";
public static final String LOG = "log";
public static final String DATE = "date";
public static final String FINDER = "finder";
public static final String ENCODED = "encoded";
public static final String TRAVELBUGS = "travelbugs";
public static final String TRAVELBUG = "travelbug";
public static final String TEXT = "text";
public static final String REF = "ref";
// 2011-12-03T10:15:30+01:00
private final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
private final List<ProgressListener> listeners = new ArrayList<>();
private final Map<Long, User> userCache = new HashMap<>();
@Override
public void addListener(ProgressListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
@Override
public List<Cache> load(File file) throws IOException {
fireEvent(new ProgressEvent("GPX Reader",
ProgressEvent.State.STARTED,
"Load File " + file.getName() + " started."));
List<Cache> modelList = new ArrayList<>();
long start = System.currentTimeMillis();
XMLInputFactory factory = XMLInputFactory.newInstance();
try (FileInputStream fis = new FileInputStream(file)) {
XMLStreamReader reader = factory.createXMLStreamReader(fis);
Waypoint waypoint = null;
Cache cache = null;
String currentLevel = null;
String startTag;
StringBuffer tagContent = new StringBuffer();
while(reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
tagContent = new StringBuffer();
startTag = reader.getLocalName();
switch (startTag) {
case WPT:
currentLevel = WPT;
waypoint = new Waypoint();
waypoint.setLatitude(Double.parseDouble(reader.getAttributeValue(0)));
waypoint.setLongitude(Double.parseDouble(reader.getAttributeValue(1)));
break;
case CACHE:
currentLevel = CACHE;
cache = new Cache();
cache.setMainWayPoint(waypoint);
waypoint.setCache(cache);
cache.setId(Long.parseLong(reader.getAttributeValue(0)));
cache.setAvailable(Boolean.parseBoolean(reader.getAttributeValue(1)));
cache.setArchived(Boolean.parseBoolean(reader.getAttributeValue(2)));
modelList.add(cache);
break;
case LOG:
currentLevel = LOG;
break;
case ATTRIBUTE:
cache.getAttributes().add(
Attribute.groundspeakAttributeToAttribute(
Long.parseLong(reader.getAttributeValue(0)),
Boolean.parseBoolean(reader.getAttributeValue(1))));
break;
case SHORT_DESCRIPTION:
cache.setShortDescriptionHtml(Boolean.parseBoolean(reader.getAttributeValue(0)));
break;
case LONG_DESCRIPTION:
cache.setLongDescriptionHtml(Boolean.parseBoolean(reader.getAttributeValue(0)));
break;
}
break;
case XMLStreamConstants.CHARACTERS:
tagContent.append(reader.getText().trim());
break;
case XMLStreamConstants.END_ELEMENT:
switch (reader.getLocalName()) {
case WPT:
currentLevel = null;
break;
case CACHE:
cache = null;
currentLevel = WPT;
break;
case LOG:
currentLevel = CACHE;
break;
case NAME:
if (WPT.equals(currentLevel)) {
waypoint.setName(tagContent.toString());
} else if (CACHE.equals(currentLevel)) {
cache.setName(tagContent.toString());
}
break;
case DESC:
if (WPT.equals(currentLevel)) {
waypoint.setDescription(tagContent.toString());
}
break;
case URL:
waypoint.setUrl(tagContent.toString());
break;
case URLNAME:
waypoint.setUrlName(tagContent.toString());
break;
case SYM:
waypoint.setSymbol(tagContent.toString());
break;
case TYPE:
if (CACHE.equals(currentLevel)) {
cache.setType(Type.groundspeakStringToType(tagContent.toString()));
}
break;
case PLACED_BY:
cache.setPlacedBy(tagContent.toString());
break;
case OWNER:
break;
case CONTAINER:
cache.setContainer(Container.groundspeakStringToContainer(tagContent.toString()));
break;
case ATTRIBUTES:
// do nothing
break;
case DIFFICULTY:
cache.setDifficulty(tagContent.toString());
break;
case TERRAIN:
cache.setTerrain(tagContent.toString());
break;
case COUNTRY:
cache.setCountry(tagContent.toString());
break;
case STATE:
cache.setState(tagContent.toString());
break;
case SHORT_DESCRIPTION:
cache.setShortDescription(tagContent.toString());
break;
case LONG_DESCRIPTION:
cache.setLongDescription(tagContent.toString());
break;
case ENCODED_HINTS:
cache.setEncodedHints(tagContent.toString());
break;
}
break;
}
}
} catch (Throwable e) {
e.printStackTrace();
throw new IOException(e.getMessage(), e);
}
long end = System.currentTimeMillis();
LOGGER.info(modelList.size()+" Caches geladen in "+(end-start)+"ms");
fireEvent(new ProgressEvent("GPX Reader",
ProgressEvent.State.FINISHED,
"Load File " + file.getName() + " finished."));
return modelList;
}
private void fireEvent(ProgressEvent event) {
listeners.stream().forEach((l) -> {
l.progress(event);
});
}
}

View File

@@ -0,0 +1,337 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.model;
import java.util.ArrayList;
import java.util.List;
/**
* @author Andreas Billmann
*/
public enum Attribute {
// id:1 text:Dogs
DOGS_TRUE(1),
DOGS_FALSE(-1),
// id:2 text:Access or parking fee
ACCESS_OR_PARKING_FEE_TRUE(2),
ACCESS_OR_PARKING_FEE_FALSE(-2),
// id:3 text:Climbing gear
CLIMBING_GEAR_TRUE(3),
CLIMBING_GEAR_FALSE(-3),
// id:4 text:Boat
BOAT_TRUE(4),
BOAT_FALSE(-4),
// id:5 text:Scuba gear
SCUBA_GEAR_TRUE(5),
SCUBA_GEAR_FALSE(-5),
// id:6 text:Recommended for kids
RECOMMENDED_FOR_KIDS_TRUE(6),
RECOMMENDED_FOR_KIDS_FALSE(-6),
// id:7 text:Takes less than an hour
TAKES_LESS_THAN_AN_HOUR_TRUE(7),
TAKES_LESS_THAN_AN_HOUR_FALSE(-7),
// id:8 text:Scenic view
SCENIC_VIEW_TRUE(8),
SCENIC_VIEW_FALSE(-8),
// id:9 text:Significant Hike
SIGNIFICANT_HIKE_TRUE(9),
SIGNIFICANT_HIKE_FALSE(-9),
// id:10 text:Difficult climbing
DIFFICULT_CLIMBING_TRUE(10),
DIFFICULT_CLIMBING_FALSE(-10),
// id:11 text:May require wading
MAY_REQUIRE_WADING_TRUE(11),
MAY_REQUIRE_WADING_FALSE(-11),
// id:12 text:May require swimming
MAY_REQUIRE_SWIMMING_TRUE(12),
MAY_REQUIRE_SWIMMING_FALSE(-12),
// id:13 text:Available at all times
AVAILABLE_AT_ALL_TIMES_TRUE(13),
AVAILABLE_AT_ALL_TIMES_FALSE(-13),
// id:14 text:Recommended at night
RECOMMENDED_AT_NIGHT_TRUE(14),
RECOMMENDED_AT_NIGHT_FALSE(-14),
// id:15 text:Available during winter
AVAILABLE_DURING_WINTER_TRUE(15),
AVAILABLE_DURING_WINTER_FALSE(-15),
// id:17 text:Poison plants
POISON_PLANTS_TRUE(17),
POISON_PLANTS_FALSE(-17),
// id:18 text:Dangerous Animals
DANGEROUS_ANIMALS_TRUE(18),
DANGEROUS_ANIMALS_FALSE(-18),
// id:19 text:Ticks
TICKS_TRUE(19),
TICKS_FALSE(-19),
// id:20 text:Abandoned mines
ABANDONED_MINES_TRUE(20),
ABANDONED_MINES_FALSE(-20),
// id:21 text:Cliff / falling rocks
CLIFF_FALLING_ROCKS_TRUE(21),
CLIFF_FALLING_ROCKS_FALSE(-21),
// id:22 text:Hunting
HUNTING_TRUE(22),
HUNTING_FALSE(-22),
// id:23 text:Dangerous area
DANGEROUS_AREA_TRUE(23),
DANGEROUS_AREA_FALSE(-23),
// id:24 text:Wheelchair accessible
WHEELCHAIR_ACCESSIBLE_TRUE(24),
WHEELCHAIR_ACCESSIBLE_FALSE(-24),
// id:25 text:Parking available
PARKING_AVAILABLE_TRUE(25),
PARKING_AVAILABLE_FALSE(-25),
// id:26 text:Public transportation
PUBLIC_TRANSPORTATION_TRUE(26),
PUBLIC_TRANSPORTATION_FALSE(-26),
// id:27 text:Drinking water nearby
DRINKING_WATER_NEARBY_TRUE(27),
DRINKING_WATER_NEARBY_FALSE(-27),
// id:28 text:Public restrooms nearby
PUBLIC_RESTROOMS_NEARBY_TRUE(28),
PUBLIC_RESTROOMS_NEARBY_FALSE(-28),
// id:29 text:Telephone nearby
TELEPHONE_NEARBY_TRUE(29),
TELEPHONE_NEARBY_FALSE(-29),
// id:30 text:Picnic tables nearby
PICNIC_TABLES_NEARBY_TRUE(30),
PICNIC_TABLES_NEARBY_FALSE(-30),
// id:31 text:Camping available
CAMPING_AVAILABLE_TRUE(31),
CAMPING_AVAILABLE_FALSE(-31),
// id:32 text:Bicycles
BICYCLES_TRUE(32),
BICYCLES_FALSE(-32),
// id:33 text:Motorcycles
MOTORCYCLES_TRUE(33),
MOTORCYCLES_FALSE(-33),
// id:34 text:Quads
QUADS_TRUE(34),
QUADS_FALSE(-34),
// id:35 text:Off-road vehicles
OFF_ROAD_VEHICLES_TRUE(35),
OFF_ROAD_VEHICLES_FALSE(-35),
// id:36 text:Snowmobiles
SNOWMOBILES_TRUE(36),
SNOWMOBILES_FALSE(-36),
// id:37 text:Horses
HORSES_TRUE(37),
HORSES_FALSE(-37),
// id:38 text:Campfires
CAMPFIRES_TRUE(38),
CAMPFIRES_FALSE(-38),
// id:39 text:Thorns
THORNS_TRUE(39),
THORNS_FALSE(-39),
// id:40 text:Stealth required
STEALTH_REQUIRED_TRUE(40),
STEALTH_REQUIRED_FALSE(-40),
// id:41 text:Stroller accessible
STROLLER_ACCESSIBLE_TRUE(41),
STROLLER_ACCESSIBLE_FALSE(-41),
// id:43 text:Watch for livestock
WATCH_FOR_LIVESTOCK_TRUE(43),
WATCH_FOR_LIVESTOCK_FALSE(-43),
// id:42 text:Needs maintenance
NEEDS_MAINTENANCE_TRUE(42),
NEEDS_MAINTENANCE_FALSE(-42),
// id:44 text:Flashlight required
FLASHLIGHT_REQUIRED_TRUE(44),
FLASHLIGHT_REQUIRED_FALSE(-44),
// id:45 text:Lost and Found Tour
LOST_AND_FOUND_TOUR_TRUE(45),
LOST_AND_FOUND_TOUR_FALSE(-45),
// id:46 text:Truck Driver/RV
TRUCK_DRIVER_RV_TRUE(46),
TRUCK_DRIVER_RV_FALSE(-46),
// id:47 text:Field Puzzle
FIELD_PUZZLE_TRUE(47),
FIELD_PUZZLE_FALSE(-47),
// id:48 text:UV Light Required
UV_LIGHT_REQUIRED_TRUE(48),
UV_LIGHT_REQUIRED_FALSE(-48),
// id:49 text:Snowshoes
SNOWSHOES_TRUE(49),
SNOWSHOES_FALSE(-49),
// id:50 text:Cross Country Skis
CROSS_COUNTRY_SKIS_TRUE(50),
CROSS_COUNTRY_SKIS_FALSE(-50),
// id:51 text:Special Tool Required
SPECIAL_TOOL_REQUIRED_TRUE(51),
SPECIAL_TOOL_REQUIRED_FALSE(-51),
// id:52 text:Night Cache
NIGHT_CACHE_TRUE(52),
NIGHT_CACHE_FALSE(-52),
// id:53 text:Park and Grab
PARK_AND_GRAB_TRUE(53),
PARK_AND_GRAB_FALSE(-53),
// id:54 text:Abandoned Structure
ABANDONED_STRUCTURE_TRUE(54),
ABANDONED_STRUCTURE_FALSE(-54),
// id:55 text:Short hike (less than 1km)
SHORT_HIKE_LESS_THAN_1KM_TRUE(55),
SHORT_HIKE_LESS_THAN_1KM_FALSE(-55),
// id:56 text:Medium hike (1km-10km)
MEDIUM_HIKE_1KM_10KM_TRUE(56),
MEDIUM_HIKE_1KM_10KM_FALSE(-56),
// id:57 text:Long Hike (+10km)
LONG_HIKE_10KM_TRUE(57),
LONG_HIKE_10KM_FALSE(-57),
// id:58 text:Fuel Nearby
FUEL_NEARBY_TRUE(58),
FUEL_NEARBY_FALSE(-58),
// id:59 text:Food Nearby
FOOD_NEARBY_TRUE(59),
FOOD_NEARBY_FALSE(-59),
// id:60 text:Wireless Beacon
WIRELESS_BEACON_TRUE(60),
WIRELESS_BEACON_FALSE(-60),
// id:61 text:Partnership cache
PARTNERSHIP_CACHE_TRUE(61),
PARTNERSHIP_CACHE_FALSE(-61),
// id:62 text:Seasonal Access
SEASONAL_ACCESS_TRUE(62),
SEASONAL_ACCESS_FALSE(-62),
// id:63 text:Tourist Friendly
TOURIST_FRIENDLY_TRUE(63),
TOURIST_FRIENDLY_FALSE(-63),
// id:64 text:Tree Climbing
TREE_CLIMBING_TRUE(64),
TREE_CLIMBING_FALSE(-64),
// id:65 text:Front Yard (Private Residence)
FRONT_YARD_PRIVATE_RESIDENCE_TRUE(65),
FRONT_YARD_PRIVATE_RESIDENCE_FALSE(-65),
// id:66 text:Teamwork Required
TEAMWORK_REQUIRED_TRUE(66),
TEAMWORK_REQUIRED_FALSE(-66),
// id:67 text:geotour
GEOTOUR_TRUE(67),
GEOTOUR_FALSE(-67);
private final static List<Long> attributes = new ArrayList<>();
private int id;
private Attribute(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public static Attribute groundspeakAttributeToAttribute(Long id, boolean inc) {
int idToCompare = id.intValue();
if (!inc) {
idToCompare = -idToCompare;
}
for (Attribute t : Attribute.values()) {
if (t.getId() == idToCompare) {
return t;
}
}
if (!attributes.contains(id)) {
attributes.add(id);
}
throw new IllegalArgumentException("unknown attribute id:" + id + " inc:" + inc);
}
}

View File

@@ -0,0 +1,317 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.model;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class Cache {
private LongProperty id = new SimpleLongProperty();
private BooleanProperty available = new SimpleBooleanProperty();
private BooleanProperty archived = new SimpleBooleanProperty();
private BooleanProperty found = new SimpleBooleanProperty();
private StringProperty name = new SimpleStringProperty();
private StringProperty placedBy = new SimpleStringProperty();
private ObjectProperty<User> owner = new SimpleObjectProperty<>();
private ObjectProperty<Type> type = new SimpleObjectProperty<>();
private ObjectProperty<Container> container = new SimpleObjectProperty<>();
private ObjectProperty<ObservableList<Attribute>> attributes = new SimpleObjectProperty<>(FXCollections.observableArrayList());
private StringProperty difficulty = new SimpleStringProperty();
private StringProperty terrain = new SimpleStringProperty();
private StringProperty country = new SimpleStringProperty();
private StringProperty state = new SimpleStringProperty();
private StringProperty shortDescription = new SimpleStringProperty();
private BooleanProperty shortDescriptionHtml = new SimpleBooleanProperty();
private StringProperty longDescription = new SimpleStringProperty();
private BooleanProperty longDescriptionHtml = new SimpleBooleanProperty();
private StringProperty encodedHints = new SimpleStringProperty();
private ObjectProperty<Waypoint> mainWayPoint = new SimpleObjectProperty<>();
public long getId() {
return id.get();
}
public LongProperty idProperty() {
return id;
}
public void setId(long id) {
this.id.set(id);
}
public boolean getAvailable() {
return available.get();
}
public BooleanProperty availableProperty() {
return available;
}
public void setAvailable(boolean available) {
this.available.set(available);
}
public boolean getArchived() {
return archived.get();
}
public BooleanProperty archivedProperty() {
return archived;
}
public void setArchived(boolean archived) {
this.archived.set(archived);
}
public boolean getFound() {
return found.get();
}
public BooleanProperty foundProperty() {
return found;
}
public void setFound(boolean found) {
this.found.set(found);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public String getPlacedBy() {
return placedBy.get();
}
public StringProperty placedByProperty() {
return placedBy;
}
public void setPlacedBy(String placedBy) {
this.placedBy.set(placedBy);
}
public User getOwner() {
return owner.get();
}
public ObjectProperty<User> ownerProperty() {
return owner;
}
public void setOwner(User owner) {
this.owner.set(owner);
}
public Type getType() {
return type.get();
}
public ObjectProperty<Type> typeProperty() {
return type;
}
public void setType(Type type) {
this.type.set(type);
}
public Container getContainer() {
return container.get();
}
public ObjectProperty<Container> containerProperty() {
return container;
}
public void setContainer(Container container) {
this.container.set(container);
}
public ObservableList<Attribute> getAttributes() {
return attributes.get();
}
public ObjectProperty<ObservableList<Attribute>> attributesProperty() {
return attributes;
}
public void setAttributes(ObservableList<Attribute> attributes) {
this.attributes.set(attributes);
}
public String getDifficulty() {
return difficulty.get();
}
public StringProperty difficultyProperty() {
return difficulty;
}
public void setDifficulty(String difficulty) {
this.difficulty.set(difficulty);
}
public String getTerrain() {
return terrain.get();
}
public StringProperty terrainProperty() {
return terrain;
}
public void setTerrain(String terrain) {
this.terrain.set(terrain);
}
public String getCountry() {
return country.get();
}
public StringProperty countryProperty() {
return country;
}
public void setCountry(String country) {
this.country.set(country);
}
public String getState() {
return state.get();
}
public StringProperty stateProperty() {
return state;
}
public void setState(String state) {
this.state.set(state);
}
public String getShortDescription() {
return shortDescription.get();
}
public StringProperty shortDescriptionProperty() {
return shortDescription;
}
public void setShortDescription(String shortDescription) {
this.shortDescription.set(shortDescription);
}
public boolean getShortDescriptionHtml() {
return shortDescriptionHtml.get();
}
public BooleanProperty shortDescriptionHtmlProperty() {
return shortDescriptionHtml;
}
public void setShortDescriptionHtml(boolean shortDescriptionHtml) {
this.shortDescriptionHtml.set(shortDescriptionHtml);
}
public String getLongDescription() {
return longDescription.get();
}
public StringProperty longDescriptionProperty() {
return longDescription;
}
public void setLongDescription(String longDescription) {
this.longDescription.set(longDescription);
}
public boolean getLongDescriptionHtml() {
return longDescriptionHtml.get();
}
public BooleanProperty longDescriptionHtmlProperty() {
return longDescriptionHtml;
}
public void setLongDescriptionHtml(boolean longDescriptionHtml) {
this.longDescriptionHtml.set(longDescriptionHtml);
}
public String getEncodedHints() {
return encodedHints.get();
}
public StringProperty encodedHintsProperty() {
return encodedHints;
}
public void setEncodedHints(String encodedHints) {
this.encodedHints.set(encodedHints);
}
public Waypoint getMainWayPoint() {
return mainWayPoint.get();
}
public ObjectProperty<Waypoint> mainWayPointProperty() {
return mainWayPoint;
}
public void setMainWayPoint(Waypoint mainWayPoint) {
this.mainWayPoint.set(mainWayPoint);
}
@Override
public String toString() {
return "Cache{" +
"name=" + name +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Cache cache = (Cache) o;
if (id != null ? !id.equals(cache.id) : cache.id != null) return false;
return true;
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.model;
import javafx.beans.property.*;
/**
* Created by Andreas on 10.03.2015.
*/
public class CacheListEntry {
private LongProperty id = new SimpleLongProperty();
private StringProperty name = new SimpleStringProperty();
private StringProperty difficulty = new SimpleStringProperty();
private StringProperty terrain = new SimpleStringProperty();
private StringProperty code = new SimpleStringProperty();
private ObjectProperty<Type> type = new SimpleObjectProperty<>();
public CacheListEntry(long id,
String name,
String code,
String difficulty,
String terrain,
Type type) {
this.id.setValue(id);
this.name.setValue(name);
this.code.setValue(code);
this.difficulty.setValue(difficulty);
this.terrain.setValue(terrain);
this.type.setValue(type);
}
public String getName() {
return name.get();
}
public ReadOnlyStringProperty nameProperty() {
return name;
}
public String getCode() {
return code.get();
}
public ReadOnlyStringProperty codeProperty() {
return code;
}
public long getId() {
return id.get();
}
public ReadOnlyLongProperty idProperty() {
return id;
}
public String getDifficulty() {
return difficulty.get();
}
public ReadOnlyStringProperty difficultyProperty() {
return difficulty;
}
public String getTerrain() {
return terrain.get();
}
public ReadOnlyStringProperty terrainProperty() {
return terrain;
}
public Type getType() {
return type.get();
}
public ReadOnlyObjectProperty<Type> typeProperty() {
return type;
}
@Override
public String toString() {
return "CacheListEntry{" +
"name=" + name +
'}';
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.model;
import groovy.lang.Closure;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
/**
* Created by Andreas Billmann on 22.02.2015.
*/
public enum Container {
SMALL("Small"),
MICRO("Micro"),
REGULAR("Regular"),
OTHER("Other"),
NOT_CHOSEN("Not chosen"),
LARGE("Large"),
VIRTUAL("Virtual");
private int id;
private String groundspeakString;
private Container(String groundspeakString) {
this.groundspeakString = groundspeakString;
}
public String toGroundspeakString() {
return groundspeakString;
}
public static Container groundspeakStringToContainer(String groundspeakString) {
for (Container t : Container.values()) {
if (t.toGroundspeakString().equals(groundspeakString)) {
return t;
}
}
throw new IllegalArgumentException("unknown container:" + groundspeakString);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.model;
import groovy.lang.Closure;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
/**
* Created by Andreas Billmann on 22.02.2015.
*/
public enum Type {
TRADITIONAL_CACHE("Traditional Cache"),
MULTI_CACHE("Multi-cache"),
UNKNOWN_CACHE("Unknown Cache"),
EARTH_CACHE("Earthcache"),
LETTERBOX("Letterbox Hybrid"),
EVENT("Event Cache"),
WHERIGO("Wherigo Cache"),
WEBCAM_CACHE("Webcam Cache"),
VIRTUAL_CACHE("Virtual Cache"),
CITO_EVENT("Cache In Trash Out Event"),
MEGA_EVENT("Mega-Event Cache"),
MYSTERY_CACHE("Mystery Cache");
private int id;
private String groundspeakString;
private Type(String groundspeakString) {
this.groundspeakString = groundspeakString;
}
public String toGroundspeakString() {
return groundspeakString;
}
public static Type groundspeakStringToType(String groundspeakString) {
for (Type t : Type.values()) {
if (t.toGroundspeakString().equals(groundspeakString)) {
return t;
}
}
throw new IllegalArgumentException("unknown type:" + groundspeakString);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.model;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
/**
* Created by Andreas Billmann on 22.02.2015.
*/
public class User {
private LongProperty id = new SimpleLongProperty();
private StringProperty name = new SimpleStringProperty();
public long getId() {
return id.get();
}
public LongProperty idProperty() {
return id;
}
public void setId(long id) {
this.id.set(id);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.model;
import javafx.beans.property.*;
import java.util.Date;
/**
* Created by Andreas Billmann on 22.02.2015.
*/
public class Waypoint {
private ObjectProperty<Cache> cache = new SimpleObjectProperty<>();
private DoubleProperty latitude = new SimpleDoubleProperty();
private DoubleProperty longitude = new SimpleDoubleProperty();
private StringProperty name = new SimpleStringProperty();
private ObjectProperty<Date> time = new SimpleObjectProperty<>();
private StringProperty description = new SimpleStringProperty();
private StringProperty url = new SimpleStringProperty();
private StringProperty urlName = new SimpleStringProperty();
private StringProperty symbol = new SimpleStringProperty();
private ObjectProperty<WaypointType> type = new SimpleObjectProperty<>();
public Cache getCache() {
return cache.get();
}
public ObjectProperty<Cache> cacheProperty() {
return cache;
}
public void setCache(Cache cache) {
this.cache.set(cache);
}
public double getLatitude() {
return latitude.get();
}
public DoubleProperty latitudeProperty() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude.set(latitude);
}
public double getLongitude() {
return longitude.get();
}
public DoubleProperty longitudeProperty() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude.set(longitude);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public Date getTime() {
return time.get();
}
public ObjectProperty<Date> timeProperty() {
return time;
}
public void setTime(Date time) {
this.time.set(time);
}
public String getDescription() {
return description.get();
}
public StringProperty descriptionProperty() {
return description;
}
public void setDescription(String description) {
this.description.set(description);
}
public String getUrl() {
return url.get();
}
public StringProperty urlProperty() {
return url;
}
public void setUrl(String url) {
this.url.set(url);
}
public String getUrlName() {
return urlName.get();
}
public StringProperty urlNameProperty() {
return urlName;
}
public void setUrlName(String urlName) {
this.urlName.set(urlName);
}
public String getSymbol() {
return symbol.get();
}
public StringProperty symbolProperty() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol.set(symbol);
}
public WaypointType getType() {
return type.get();
}
public ObjectProperty<WaypointType> typeProperty() {
return type;
}
public void setType(WaypointType type) {
this.type.set(type);
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.model;
/**
* Created by Andreas Billmann on 22.02.2015.
*/
public enum WaypointType {
}

View File

@@ -0,0 +1,31 @@
package de.geofroggerfx.plugins;
import java.util.Map;
/**
* This interface defines the method a plugin has to provide to be called correctly
*
* @author abi
*/
public interface Plugin {
/**
* @return name
*/
String getName();
/**
* @return version
*/
String getVersion();
/**
* Run the main method of the plugin. All the logic is done in this method.
* Every run method will get a context map, with all the services inside,
* to use them.
*
* @param context services and data
*/
void run(Map context);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.service;
import de.geofroggerfx.model.Cache;
import de.geofroggerfx.model.CacheListEntry;
import java.util.List;
/**
* Created by Andreas on 10.03.2015.
*/
public interface CacheService {
void storeCaches(List<Cache> cacheList);
List<CacheListEntry> getAllCacheEntriesSortBy(String name, String asc);
Cache getCacheForId(long id);
List<Cache> getAllCaches();
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.service;
import de.geofroggerfx.dao.CacheDAO;
import de.geofroggerfx.model.Cache;
import de.geofroggerfx.model.CacheListEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Created by Andreas on 10.03.2015.
*/
@Service
public class CacheServiceImpl implements CacheService {
@Autowired
private CacheDAO cacheDAO;
@Override
public void storeCaches(List<Cache> cacheList) {
cacheDAO.save(cacheList);
}
@Override
public List<CacheListEntry> getAllCacheEntriesSortBy(String name, String asc) {
return cacheDAO.getAllCachEntriesSortBy(name, asc);
}
@Override
public Cache getCacheForId(long id) {
return cacheDAO.getCacheForId(id);
}
@Override
public List<Cache> getAllCaches() {
return cacheDAO.getAllCaches();
}
}

View File

@@ -0,0 +1,19 @@
package de.geofroggerfx.service;
import de.geofroggerfx.plugins.Plugin;
import java.util.List;
/**
* TODO: class description
*
* @author abi
*/
public interface PluginService {
List<Plugin> getAllPlugins();
void executePlugin(Plugin plugin);
}

View File

@@ -0,0 +1,79 @@
package de.geofroggerfx.service;
import de.geofroggerfx.application.SessionContext;
import de.geofroggerfx.dao.jdbc.DataConfig;
import de.geofroggerfx.plugins.Plugin;
import groovy.lang.GroovyClassLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This service find, load and executes plugins based on the plugin interface.
*
* @author abi
*/
@Service
public class PluginServiceImpl implements PluginService {
private final GroovyClassLoader gcl = new GroovyClassLoader();
@Autowired
private CacheService cacheService;
@Autowired
private SessionContext sessionContext;
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataConfig(DataConfig dataConfig) {
this.jdbcTemplate = new JdbcTemplate(dataConfig.dataSource());
}
@Override
public List<Plugin> getAllPlugins() {
List<Plugin> plugins = new ArrayList<>();
try {
File file = new File("./plugins");
if (!file.exists()) {
throw new IllegalArgumentException("plugins folder does not exist");
}
File[] pluginFiles = file.listFiles((dir, name) -> name.endsWith("Plugin.groovy"));
for (File pluginFile : pluginFiles) {
Class clazz = gcl.parseClass(pluginFile);
for (Class interf : clazz.getInterfaces()) {
if (interf.equals(Plugin.class)) {
plugins.add((Plugin) clazz.newInstance());
break;
}
}
}
} catch (IOException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return plugins;
}
@Override
public void executePlugin(final Plugin plugin) {
Map<String, Object> context = new HashMap<>();
context.put("sessionContext", sessionContext);
context.put("cacheService", cacheService);
context.put("jdbcTemplate", jdbcTemplate);
plugin.run(context);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.ui;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import java.io.IOException;
import java.io.InputStream;
import java.util.ResourceBundle;
public abstract class FXMLController implements InitializingBean, Initializable {
protected Node view;
protected String fxmlFilePath;
protected String resourcePath;
public abstract void setFxmlFilePath(String filePath);
@Value("${resource.main}")
public void setResourceBundle(String resourcePath) {
this.resourcePath = resourcePath;
}
@Override
public void afterPropertiesSet() throws Exception {
loadFXML();
}
protected final void loadFXML() throws IOException {
try (InputStream fxmlStream = getClass().getResourceAsStream(fxmlFilePath)) {
FXMLLoader loader = new FXMLLoader();
loader.setResources(ResourceBundle.getBundle(this.resourcePath));
loader.setController(this);
this.view = (loader.load(fxmlStream));
} catch (Throwable t) {
t.printStackTrace();
}
}
public Node getView() {
return view;
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.ui;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.text.Font;
import javafx.stage.Stage;
//import org.scenicview.ScenicView;
import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
@Configuration
@ComponentScan("de.geofroggerfx")
@PropertySource(value = "classpath:/de/geofroggerfx/ui/application.properties")
public class GeoFroggerFX extends Application {
private AnnotationConfigApplicationContext appContext;
@Override
public void start(Stage primaryStage) throws Exception {
loadCustomFonts();
appContext = new AnnotationConfigApplicationContext(GeoFroggerFX.class);
String name = appContext.getEnvironment().getProperty("application.name");
String version = appContext.getEnvironment().getProperty("application.version");
GeoFroggerFXController geoFroggerFXController = appContext.getBean(GeoFroggerFXController.class);
Scene scene = new Scene((Parent) geoFroggerFXController.getView());
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (isScenicViewShortcutPressed(event)) {
// ScenicView.show(scene);
}
}
});
primaryStage.setScene(scene);
primaryStage.setTitle(String.format("%s %s", name, version));
primaryStage.show();
}
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Override
public void stop() throws Exception {
if (appContext != null) {
appContext.close();
}
super.stop();
}
public static void main(String[] args) {
launch(args);
}
private static boolean isScenicViewShortcutPressed(final KeyEvent keyEvent) {
return keyEvent.isAltDown() && keyEvent.isControlDown() && keyEvent.getCode().equals(KeyCode.V);
}
private void loadCustomFonts() {
Font.loadFont(GeoFroggerFX.class.getResource("/fonts/sofia/Sofia-Regular.otf").toExternalForm(), 24);
}
}

View File

@@ -0,0 +1,283 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.ui;
import de.geofroggerfx.application.ProgressEvent;
import de.geofroggerfx.application.SessionContext;
import de.geofroggerfx.gpx.GPXReader;
import de.geofroggerfx.model.Cache;
import de.geofroggerfx.model.CacheListEntry;
import de.geofroggerfx.plugins.Plugin;
import de.geofroggerfx.service.CacheService;
import de.geofroggerfx.service.PluginService;
import de.geofroggerfx.ui.details.DetailsController;
import de.geofroggerfx.ui.list.ListController;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.stage.FileChooser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import static de.geofroggerfx.application.SessionContext.*;
/**
* Created by Andreas on 09.03.2015.
*/
@Component
public class GeoFroggerFXController extends FXMLController {
private static final Logger LOGGER = Logger.getLogger(GeoFroggerFXController.class.getName());
@Autowired
private CacheService cacheService;
@Autowired
private SessionContext sessionContext;
@Autowired
private ListController listController;
@Autowired
private DetailsController detailsController;
@Autowired
private PluginService pluginService;
@Autowired
private GPXReader reader;
@FXML
private HBox cacheListContent;
@FXML
private AnchorPane cacheDetailsContent;
@FXML
private Label leftStatus;
@FXML
private ProgressBar progress;
@FXML
private Menu pluginsMenu;
private ResourceBundle resourceBundle;
private final LoadCachesFromFileService loadService = new LoadCachesFromFileService();
private final LoadCacheListsFromDatabaseService loadListsFromDBService = new LoadCacheListsFromDatabaseService();
@Value("${fxml.geofrogger.view}")
@Override
public void setFxmlFilePath(String filePath) {
this.fxmlFilePath = filePath;
}
@Override
public void initialize(URL location, ResourceBundle resources) {
this.resourceBundle = resources;
LOGGER.info("load all sub controller");
cacheListContent.getChildren().add(listController.getView());
cacheDetailsContent.getChildren().add(detailsController.getView());
LOGGER.info("add listeners");
reader.addListener((ProgressEvent event) -> updateStatus(event.getMessage(), event.getProgress()));
loadListsFromDBService.start();
List<Plugin> plugins = pluginService.getAllPlugins();
for (Plugin plugin: plugins) {
MenuItem menuItem = new MenuItem(plugin.getName()+" ("+plugin.getVersion()+")");
menuItem.setOnAction(actionEvent -> pluginService.executePlugin(plugin));
pluginsMenu.getItems().add(menuItem);
}
}
@FXML
public void importGpx(ActionEvent actionEvent) {
final FileChooser fileChooser = new FileChooser();
//Set extension filter
final FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("GPX files (*.gpx)", "*.gpx");
fileChooser.getExtensionFilters().add(extFilter);
//Show open file dialog
final File file = fileChooser.showOpenDialog(null);
loadService.setFile(file);
loadService.restart();
}
@FXML
public void showAboutDialog(ActionEvent actionEvent) {
// Dialog dialog = new Dialog(null, resourceBundle.getString("dialog.title.about"));
// dialog.setMasthead(MASTHEAD_TEXT);
// dialog.setContent(ABOUT_TEXT);
// dialog.setExpandableContent(new TextArea(LICENSE));
// dialog.show();
}
@FXML
public void showSettings(ActionEvent actionEvent) {
// mainPane.setCenter();
// FXMLLoader.load()
}
@FXML
public void newList(ActionEvent actionEvent) {
// final Optional<String> listNameOption = Dialogs.
// create().
// title(resourceBundle.getString("dialog.title.new_list")).
// message(resourceBundle.getString("dialog.label.listname")).
// showTextInput();
// if (hasValue(listNameOption)) {
// final String listName = listNameOption.get().trim();
// if (cacheService.doesCacheListNameExist(listName)) {
// Dialogs.
// create().
// message(resourceBundle.getString("dialog.msg.list.does.exist")).
// showError();
// } else {
// CacheList list = new CacheList();
// list.setName(listName);
// cacheService.storeCacheList(list);
// setCacheListInContext();
// }
// }
}
@FXML
public void deleteList(ActionEvent actionEvent) {
// final Optional<CacheList> listOption = Dialogs.
// create().
// title("dialog.title.delete_list").
// message("dialog.label.listname").
// showChoices(cacheService.getAllCacheLists());
//
// if (listOption.isPresent()) {
// cacheService.deleteCacheList(listOption.get());
// setCacheListInContext();
// }
}
@FXML
public void exit(ActionEvent actionEvent) {
Platform.exit();
}
private void updateStatus(String text, double progressValue) {
Platform.runLater(() -> {
leftStatus.setText(text);
progress.setProgress(progressValue);
});
}
private class LoadCachesFromFileService extends Service {
private final ObjectProperty<File> file = new SimpleObjectProperty();
public final void setFile(File value) {
file.set(value);
}
public final File getFile() {
return file.get();
}
public final ObjectProperty<File> fileProperty() {
return file;
}
@Override
protected Task createTask() {
return new Task() {
@Override
protected Void call() throws Exception {
try {
LOGGER.info("load from file "+file.get().getAbsolutePath());
final List<Cache> cacheList = reader.load(file.get());
LOGGER.info(cacheList.size()+" caches loaded");
if (!cacheList.isEmpty()) {
updateStatus(resourceBundle.getString("status.store.all.caches"), ProgressIndicator.INDETERMINATE_PROGRESS);
cacheService.storeCaches(cacheList);
updateStatus(resourceBundle.getString("status.all.caches.stored"), 0);
LOGGER.info("caches stored in database");
loadAllCacheEntries();
}
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, ex.getMessage() ,ex);
}
return null;
}
};
}
}
private class LoadCacheListsFromDatabaseService extends Service {
@Override
protected Task createTask() {
return new Task() {
@Override
protected Void call() throws Exception {
loadAllCacheEntries();
return null;
}
};
}
}
private void loadAllCacheEntries() {
updateStatus(resourceBundle.getString("status.load.caches.from.db"), ProgressIndicator.INDETERMINATE_PROGRESS);
sessionContext.setData(CACHE_ENTRY_LIST, cacheService.getAllCacheEntriesSortBy("name", "asc"));
updateStatus(resourceBundle.getString("status.all.caches.loaded"), 0);
}
}

View File

@@ -0,0 +1,334 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.ui;
import de.geofroggerfx.model.Attribute;
import de.geofroggerfx.model.Type;
import de.jensd.fx.glyphs.GlyphIcon;
import de.jensd.fx.glyphs.GlyphIcons;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcons;
import javafx.scene.text.Text;
import java.util.HashMap;
import java.util.Map;
import static de.geofroggerfx.model.Attribute.*;
import static de.geofroggerfx.model.Type.*;
import static de.geofroggerfx.ui.glyphs.GeofroggerGlyphsDude.createIcon;
import static de.jensd.fx.glyphs.fontawesome.FontAwesomeIcons.*;
import static de.jensd.fx.glyphs.weathericons.WeatherIcons.*;
/**
* @author Andreas
*/
public class GeocachingIcons {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cache attribute
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private static final Map<Attribute, GlyphIcons> attributeMap;
static {
attributeMap = new HashMap<>();
attributeMap.put(DOGS_TRUE, PAW);
attributeMap.put(DOGS_FALSE, PAW);
// attributeMap.put(ACCESS_OR_PARKING_FEE_TRUE,);
// attributeMap.put(ACCESS_OR_PARKING_FEE_FALSE, );
// attributeMap.put(CLIMBING_GEAR_TRUE,);
// attributeMap.put(CLIMBING_GEAR_FALSE,);
attributeMap.put(BOAT_TRUE, SHIP);
attributeMap.put(BOAT_FALSE, SHIP);
// attributeMap.put(SCUBA_GEAR_TRUE(5);
// attributeMap.put(SCUBA_GEAR_FALSE(-5);
attributeMap.put(RECOMMENDED_FOR_KIDS_TRUE, CHILD);
attributeMap.put(RECOMMENDED_FOR_KIDS_FALSE, CHILD);
attributeMap.put(TAKES_LESS_THAN_AN_HOUR_TRUE, TIME_1);
attributeMap.put(TAKES_LESS_THAN_AN_HOUR_FALSE, TIME_1);
attributeMap.put(SCENIC_VIEW_TRUE, EYE);
attributeMap.put(SCENIC_VIEW_FALSE, EYE);
// attributeMap.put(SIGNIFICANT_HIKE_TRUE(9);
// attributeMap.put(SIGNIFICANT_HIKE_FALSE(-9);
// attributeMap.put(DIFFICULT_CLIMBING_TRUE(10);
// attributeMap.put(DIFFICULT_CLIMBING_FALSE(-10);
// attributeMap.put(MAY_REQUIRE_WADING_TRUE(11);
// attributeMap.put(MAY_REQUIRE_WADING_FALSE(-11);
// attributeMap.put(MAY_REQUIRE_SWIMMING_TRUE(12);
// attributeMap.put(MAY_REQUIRE_SWIMMING_FALSE(-12);
attributeMap.put(AVAILABLE_AT_ALL_TIMES_TRUE, TIME_12);
attributeMap.put(AVAILABLE_AT_ALL_TIMES_FALSE, TIME_12);
attributeMap.put(RECOMMENDED_AT_NIGHT_TRUE, MOON_ALT);
attributeMap.put(RECOMMENDED_AT_NIGHT_FALSE, MOON_ALT);
attributeMap.put(AVAILABLE_DURING_WINTER_TRUE, SNOW);
attributeMap.put(AVAILABLE_DURING_WINTER_FALSE, SNOW);
// attributeMap.put(POISON_PLANTS_TRUE(17);
// attributeMap.put(POISON_PLANTS_FALSE(-17);
// attributeMap.put(DANGEROUS_ANIMALS_TRUE(18);
// attributeMap.put(DANGEROUS_ANIMALS_FALSE(-18);
// attributeMap.put(TICKS_TRUE(19);
// attributeMap.put(TICKS_FALSE(-19);
// attributeMap.put(ABANDONED_MINES_TRUE(20);
// attributeMap.put(ABANDONED_MINES_FALSE(-20);
attributeMap.put(CLIFF_FALLING_ROCKS_TRUE, METEOR);
attributeMap.put(CLIFF_FALLING_ROCKS_FALSE, METEOR);
// attributeMap.put(HUNTING_TRUE(22);
// attributeMap.put(HUNTING_FALSE(-22);
// attributeMap.put(DANGEROUS_AREA_TRUE(23);
// attributeMap.put(DANGEROUS_AREA_FALSE(-23);
attributeMap.put(WHEELCHAIR_ACCESSIBLE_TRUE, WHEELCHAIR);
attributeMap.put(WHEELCHAIR_ACCESSIBLE_FALSE, WHEELCHAIR);
// attributeMap.put(PARKING_AVAILABLE_TRUE(25);
// attributeMap.put(PARKING_AVAILABLE_FALSE(-25);
attributeMap.put(PUBLIC_TRANSPORTATION_TRUE, BUS);
attributeMap.put(PUBLIC_TRANSPORTATION_FALSE, BUS);
// attributeMap.put(DRINKING_WATER_NEARBY_TRUE(27);
// attributeMap.put(DRINKING_WATER_NEARBY_FALSE(-27);
// attributeMap.put(PUBLIC_RESTROOMS_NEARBY_TRUE(28);
// attributeMap.put(PUBLIC_RESTROOMS_NEARBY_FALSE(-28);
attributeMap.put(TELEPHONE_NEARBY_TRUE, PHONE);
attributeMap.put(TELEPHONE_NEARBY_FALSE, PHONE);
// attributeMap.put(PICNIC_TABLES_NEARBY_TRUE(30);
// attributeMap.put(PICNIC_TABLES_NEARBY_FALSE(-30);
// attributeMap.put(CAMPING_AVAILABLE_TRUE(31);
// attributeMap.put(CAMPING_AVAILABLE_FALSE(-31);
attributeMap.put(BICYCLES_TRUE, BICYCLE);
attributeMap.put(BICYCLES_FALSE, BICYCLE);
attributeMap.put(MOTORCYCLES_TRUE, MOTORCYCLE);
attributeMap.put(MOTORCYCLES_FALSE, MOTORCYCLE);
// attributeMap.put(QUADS_TRUE(34);
// attributeMap.put(QUADS_FALSE(-34);
// attributeMap.put(OFF_ROAD_VEHICLES_TRUE(35);
// attributeMap.put(OFF_ROAD_VEHICLES_FALSE(-35);
// attributeMap.put(SNOWMOBILES_TRUE(36);
// attributeMap.put(SNOWMOBILES_FALSE(-36);
// attributeMap.put(HORSES_TRUE(37);
// attributeMap.put(HORSES_FALSE(-37);
// attributeMap.put(CAMPFIRES_TRUE(38);
// attributeMap.put(CAMPFIRES_FALSE(-38);
// attributeMap.put(THORNS_TRUE(39);
// attributeMap.put(THORNS_FALSE(-39);
// attributeMap.put(STEALTH_REQUIRED_TRUE(40);
// attributeMap.put(STEALTH_REQUIRED_FALSE(-40);
// attributeMap.put(STROLLER_ACCESSIBLE_TRUE(41);
// attributeMap.put(STROLLER_ACCESSIBLE_FALSE(-41);
// attributeMap.put(WATCH_FOR_LIVESTOCK_TRUE(43);
// attributeMap.put(WATCH_FOR_LIVESTOCK_FALSE(-43);
// attributeMap.put(NEEDS_MAINTENANCE_TRUE(42);
// attributeMap.put(NEEDS_MAINTENANCE_FALSE(-42);
// attributeMap.put(FLASHLIGHT_REQUIRED_TRUE(44);
// attributeMap.put(FLASHLIGHT_REQUIRED_FALSE(-44);
// attributeMap.put(LOST_AND_FOUND_TOUR_TRUE(45);
// attributeMap.put(LOST_AND_FOUND_TOUR_FALSE(-45);
// attributeMap.put(TRUCK_DRIVER_RV_TRUE(46);
// attributeMap.put(TRUCK_DRIVER_RV_FALSE(-46);
// attributeMap.put(FIELD_PUZZLE_TRUE(47);
// attributeMap.put(FIELD_PUZZLE_FALSE(-47);
// attributeMap.put(UV_LIGHT_REQUIRED_TRUE(48);
// attributeMap.put(UV_LIGHT_REQUIRED_FALSE(-48);
// attributeMap.put(SNOWSHOES_TRUE(49);
// attributeMap.put(SNOWSHOES_FALSE(-49);
// attributeMap.put(CROSS_COUNTRY_SKIS_TRUE(50);
// attributeMap.put(CROSS_COUNTRY_SKIS_FALSE(-50);
// attributeMap.put(SPECIAL_TOOL_REQUIRED_TRUE(51);
// attributeMap.put(SPECIAL_TOOL_REQUIRED_FALSE(-51);
attributeMap.put(NIGHT_CACHE_TRUE, MOON_WANING_CRESCENT_2);
attributeMap.put(NIGHT_CACHE_FALSE, MOON_WANING_CRESCENT_2);
// attributeMap.put(PARK_AND_GRAB_TRUE(53);
// attributeMap.put(PARK_AND_GRAB_FALSE(-53);
// attributeMap.put(ABANDONED_STRUCTURE_TRUE(54);
// attributeMap.put(ABANDONED_STRUCTURE_FALSE(-54);
// attributeMap.put(SHORT_HIKE_LESS_THAN_1KM_TRUE(55);
// attributeMap.put(SHORT_HIKE_LESS_THAN_1KM_FALSE(-55);
// attributeMap.put(MEDIUM_HIKE_1KM_10KM_TRUE(56);
// attributeMap.put(MEDIUM_HIKE_1KM_10KM_FALSE(-56);
// attributeMap.put(LONG_HIKE_10KM_TRUE(57);
// attributeMap.put(LONG_HIKE_10KM_FALSE(-57);
// attributeMap.put(FUEL_NEARBY_TRUE(58);
// attributeMap.put(FUEL_NEARBY_FALSE(-58);
// attributeMap.put(FOOD_NEARBY_TRUE(59);
// attributeMap.put(FOOD_NEARBY_FALSE(-59);
// attributeMap.put(WIRELESS_BEACON_TRUE(60);
// attributeMap.put(WIRELESS_BEACON_FALSE(-60);
// attributeMap.put(PARTNERSHIP_CACHE_TRUE(61);
// attributeMap.put(PARTNERSHIP_CACHE_FALSE(-61);
attributeMap.put(SEASONAL_ACCESS_TRUE, THERMOMETER);
attributeMap.put(SEASONAL_ACCESS_FALSE, THERMOMETER);
// attributeMap.put(TOURIST_FRIENDLY_TRUE(63);
// attributeMap.put(TOURIST_FRIENDLY_FALSE(-63);
// attributeMap.put(TREE_CLIMBING_TRUE(64);
// attributeMap.put(TREE_CLIMBING_FALSE(-64);
// attributeMap.put(FRONT_YARD_PRIVATE_RESIDENCE_TRUE(65);
// attributeMap.put(FRONT_YARD_PRIVATE_RESIDENCE_FALSE(-65);
// attributeMap.put(TEAMWORK_REQUIRED_TRUE(66);
// attributeMap.put(TEAMWORK_REQUIRED_FALSE(-66);
// attributeMap.put(GEOTOUR_TRUE(67);
// attributeMap.put(GEOTOUR_FALSE(-67);
}
public static Text getIconAsText(Attribute attribute, String iconSize) {
return createIcon(getIcon(attribute), iconSize);
}
public static Text getIconAsText(Attribute attribute) {
return getIconAsText(attribute, GlyphIcon.DEFAULT_ICON_SIZE);
}
public static String getIconAsString(Attribute attribute) {
return getIcon(attribute).characterToString();
}
public static GlyphIcons getIcon(Attribute attribute) {
GlyphIcons iconName = attributeMap.get(attribute);
if (iconName == null) {
iconName = FontAwesomeIcons.BLANK;
}
return iconName;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cache type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private static final Map<Type, GlyphIcons> typeMap;
static {
typeMap = new HashMap<>();
typeMap.put(MULTI_CACHE, TAGS);
typeMap.put(TRADITIONAL_CACHE, TAG);
typeMap.put(UNKNOWN_CACHE, QUESTION);
typeMap.put(EARTH_CACHE, GLOBE);
typeMap.put(LETTERBOX, ENVELOPE);
typeMap.put(EVENT, CALENDAR);
typeMap.put(CITO_EVENT, CALENDAR);
typeMap.put(MEGA_EVENT, CALENDAR);
typeMap.put(WHERIGO, COMPASS);
typeMap.put(WEBCAM_CACHE, CAMERA);
typeMap.put(VIRTUAL_CACHE, LAPTOP);
}
public static Text getIconAsText(Type type, String iconSize) {
return createIcon(getIcon(type), iconSize);
}
public static Text getIconAsText(Type type) {
return getIconAsText(type, GlyphIcon.DEFAULT_ICON_SIZE);
}
public static String getIconAsString(Type type) {
return getIcon(type).characterToString();
}
public static GlyphIcons getIcon(Type type) {
GlyphIcons iconName = typeMap.get(type);
if (iconName == null) {
iconName = FontAwesomeIcons.BLANK;
}
return iconName;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// star icon
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static Text getStars(String value) {
return getStarsAsText(value, GlyphIcon.DEFAULT_ICON_SIZE);
}
public static String getStarsAsString(String value) {
StringBuffer stringBuffer = new StringBuffer();
switch (value) {
case "1":
stringBuffer.append(STAR.characterToString());
break;
case "1.5":
stringBuffer.append(STAR.characterToString())
.append(STAR_HALF.characterToString());
break;
case "2":
stringBuffer.append(STAR.characterToString())
.append(STAR.characterToString());
break;
case "2.5":
stringBuffer.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR_HALF.characterToString());
break;
case "3":
stringBuffer.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR.characterToString());
break;
case "3.5":
stringBuffer.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR_HALF.characterToString());
break;
case "4":
stringBuffer.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR.characterToString());
break;
case "4.5":
stringBuffer.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR_HALF.characterToString());
break;
case "5":
stringBuffer.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR.characterToString())
.append(STAR.characterToString());
break;
default:
stringBuffer.append(FontAwesomeIcons.BLANK.characterToString());
System.out.println(value);
}
return stringBuffer.toString();
}
public static Text getStarsAsText(String value, String iconSize) {
Text text = createIcon(FontAwesomeIcons.BLANK, iconSize);
text.setText(value);
return text;
}
}

View File

@@ -0,0 +1,158 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.ui.details;
import com.lynden.gmapsfx.GoogleMapView;
import com.lynden.gmapsfx.MapComponentInitializedListener;
import com.lynden.gmapsfx.javascript.object.*;
import de.geofroggerfx.application.SessionContext;
import de.geofroggerfx.application.SessionContextListener;
import de.geofroggerfx.model.Cache;
import de.geofroggerfx.ui.FXMLController;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.net.URL;
import java.util.ResourceBundle;
import static de.geofroggerfx.application.SessionContext.CURRENT_CACHE;
import static de.geofroggerfx.ui.GeocachingIcons.getStarsAsString;
/**
* Created by Andreas on 09.03.2015.
*/
@Component
public class DetailsController extends FXMLController {
@Autowired
private SessionContext sessionContext;
@FXML
private Label cacheName;
@FXML
private Text cacheDifficulty;
@FXML
private Text cacheTerrain;
@FXML
private VBox mainContent;
@FXML
private WebView description;
@FXML
private GoogleMapView mapView;
private GoogleMap map;
private Marker marker;
@Value("${fxml.geofrogger.details.view}")
@Override
public void setFxmlFilePath(String filePath) {
this.fxmlFilePath = filePath;
}
@Override
public void initialize(URL location, ResourceBundle resources) {
sessionContext.addListener(CURRENT_CACHE, new SessionContextListener() {
@Override
public void sessionContextChanged() {
fillContent();
}
});
mapView.addMapInializedListener(new MapComponentInitializedListener() {
@Override
public void mapInitialized() {
//Set the initial properties of the map.
MapOptions mapOptions = new MapOptions();
mapOptions.center(new LatLong(47.6097, -122.3331))
.mapType(MapTypeIdEnum.ROADMAP)
.overviewMapControl(false)
.panControl(false)
.rotateControl(false)
.scaleControl(false)
.streetViewControl(false)
.zoomControl(false)
.zoom(12);
map = mapView.createMap(mapOptions);
LatLong latLong = new LatLong(49.045458, 9.189835);
MarkerOptions options = new MarkerOptions();
options.position(latLong);
marker = new Marker(options);
map.addMarker(marker);
map.setCenter(latLong);
}
});
}
private void fillContent() {
Cache cache = (Cache) sessionContext.getData(CURRENT_CACHE);
cacheName.setText(cache.getName());
cacheDifficulty.setText(getStarsAsString(cache.getDifficulty()));
cacheTerrain.setText(getStarsAsString(cache.getTerrain()));
String shortDescription = cache.getShortDescription();
if (!cache.getLongDescriptionHtml()) {
shortDescription = shortDescription.replaceAll("\n","</br>");
}
String longDescription = cache.getLongDescription();
if (!cache.getLongDescriptionHtml()) {
longDescription = longDescription.replaceAll("\n","</br>");
}
String description = "<html><body><p>"+shortDescription+"</p><p>"+longDescription+"</p></body></html>";
final WebEngine webEngine = this.description.getEngine();
webEngine.loadContent(description);
LatLong latLong = new LatLong(cache.getMainWayPoint().getLatitude(), cache.getMainWayPoint().getLongitude());
MarkerOptions options = new MarkerOptions();
options.position(latLong);
options.title(cache.getMainWayPoint().getName());
map.removeMarker(marker);
marker.setTitle(cache.getMainWayPoint().getName());
marker = new Marker(options);
map.addMarker(marker);
map.setCenter(latLong);
mapView.requestLayout();
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.ui.glyphs;
import de.jensd.fx.glyphs.GlyphIcon;
import javafx.scene.text.Font;
public class ElusiveIcon extends GlyphIcon<ElusiveIcons> {
public final static String TTF_PATH = "/fonts/elusive/Elusive-Icons.ttf";
public final static String FONT_FAMILY = "\'Elusive-Icons\'";
static {
Font.loadFont(ElusiveIcon.class.getResource(TTF_PATH).toExternalForm(), 10.0);
}
@Override
public ElusiveIcons getDefaultGlyph() {
return ElusiveIcons.USER;
}
}

View File

@@ -0,0 +1,359 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.ui.glyphs;
import de.jensd.fx.glyphs.GlyphIcons;
public enum ElusiveIcons implements GlyphIcons {
ZOOM_OUT('\uE600'),
ZOOM_IN('\uE601'),
YOUTUBE('\uE602'),
WRENCH_ALT('\uE603'),
WRENCH('\uE604'),
WORDPRESS('\uE605'),
WHEELCHAIR('\uE606'),
WEBSITE_ALT('\uE607'),
WEBSITE('\uE608'),
WARNING_SIGN('\uE609'),
W3C('\uE60A'),
VOLUME_UP('\uE60B'),
VOLUME_OFF('\uE60C'),
VOLUME_DOWN('\uE60D'),
VKONTAKTE('\uE60E'),
VIMEO('\uE60F'),
VIEW_MODE('\uE610'),
VIDEO_CHAT('\uE611'),
VIDEO_ALT('\uE612'),
VIDEO('\uE613'),
VIADEO('\uE614'),
USER('\uE615'),
USD('\uE616'),
UPLOAD('\uE617'),
UNLOCK_ALT('\uE618'),
UNLOCK('\uE619'),
UNIVERSAL_ACCESS('\uE61A'),
TWITTER('\uE61B'),
TUMBLR('\uE61C'),
TRASH_ALT('\uE61D'),
TRASH('\uE61E'),
TORSO('\uE61F'),
TINT('\uE620'),
TIME_ALT('\uE621'),
TIME('\uE622'),
THUMBS_UP('\uE623'),
THUMBS_DOWN('\uE624'),
TH_LIST('\uE625'),
TH_LARGE('\uE626'),
TH('\uE627'),
TEXT_WIDTH('\uE628'),
TEXT_HEIGHT('\uE629'),
TASKS('\uE62A'),
TAGS('\uE62B'),
TAG('\uE62C'),
STUMBLEUPON('\uE62D'),
STOP_ALT('\uE62E'),
STOP('\uE62F'),
STEP_FORWARD('\uE630'),
STEP_BACKWARD('\uE631'),
STAR_EMPTY('\uE632'),
STAR_ALT('\uE633'),
STAR('\uE634'),
STACKOVERFLOW('\uE635'),
SPOTIFY('\uE636'),
SPEAKER('\uE637'),
SOUNDCLOUD('\uE638'),
SMILEY_ALT('\uE639'),
SMILEY('\uE63A'),
SLIDESHARE('\uE63B'),
SKYPE('\uE63C'),
SIGNAL('\uE63D'),
SHOPPING_CART_SIGN('\uE63E'),
SHOPPING_CART('\uE63F'),
SHARE_ALT('\uE640'),
SHARE('\uE641'),
SEARCH_ALT('\uE642'),
SEARCH('\uE643'),
SCREENSHOT('\uE644'),
SCREEN_ALT('\uE645'),
SCREEN('\uE646'),
SCISSORS('\uE647'),
RSS('\uE648'),
ROAD('\uE649'),
REVERSE_ALT('\uE64A'),
RETWEET('\uE64B'),
RETURN_KEY('\uE64C'),
RESIZE_VERTICAL('\uE64D'),
RESIZE_SMALL('\uE64E'),
RESIZE_HORIZONTAL('\uE64F'),
RESIZE_FULL('\uE650'),
REPEAT_ALT('\uE651'),
REPEAT('\uE652'),
REMOVE_SIGN('\uE653'),
REMOVE_CIRCLE('\uE654'),
REMOVE('\uE655'),
REFRESH('\uE656'),
REDDIT('\uE657'),
RECORD('\uE658'),
RANDOM('\uE659'),
QUOTES_ALT('\uE65A'),
QUOTES('\uE65B'),
QUESTION_SIGN('\uE65C'),
QUESTION('\uE65D'),
QRCODE('\uE65E'),
PUZZLE('\uE65F'),
PRINT('\uE660'),
PODCAST('\uE661'),
PLUS_SIGN('\uE662'),
PLUS('\uE663'),
PLAY_CIRCLE('\uE664'),
PLAY_ALT('\uE665'),
PLAY('\uE666'),
PLANE('\uE667'),
PINTEREST('\uE668'),
PICTURE('\uE669'),
PICASA('\uE66A'),
PHOTO_ALT('\uE66B'),
PHOTO('\uE66C'),
PHONE_ALT('\uE66D'),
PHONE('\uE66E'),
PERSON('\uE66F'),
PENCIL_ALT('\uE670'),
PENCIL('\uE671'),
PAUSE_ALT('\uE672'),
PAUSE('\uE673'),
PATH('\uE674'),
PAPER_CLIP_ALT('\uE675'),
PAPER_CLIP('\uE676'),
OPENSOURCE('\uE677'),
OK_SIGN('\uE678'),
OK_CIRCLE('\uE679'),
OK('\uE67A'),
OFF('\uE67B'),
NETWORK('\uE67C'),
MYSPACE('\uE67D'),
MUSIC('\uE67E'),
MOVE('\uE67F'),
MINUS_SIGN('\uE680'),
MINUS('\uE681'),
MIC_ALT('\uE682'),
MIC('\uE683'),
MAP_MARKER_ALT('\uE684'),
MAP_MARKER('\uE685'),
MALE('\uE686'),
MAGNET('\uE687'),
MAGIC('\uE688'),
LOCK_ALT('\uE689'),
LOCK('\uE68A'),
LIVEJOURNAL('\uE68B'),
LIST_ALT('\uE68C'),
LIST('\uE68D'),
LINKEDIN('\uE68E'),
LINK('\uE68F'),
LINES('\uE690'),
LEAF('\uE691'),
LASTFM('\uE692'),
LAPTOP_ALT('\uE693'),
LAPTOP('\uE694'),
KEY('\uE695'),
ITALIC('\uE696'),
IPHONE_HOME('\uE697'),
INSTAGRAM('\uE698'),
INFO_SIGN('\uE699'),
INDENT_RIGHT('\uE69A'),
INDENT_LEFT('\uE69B'),
INBOX_BOX('\uE69C'),
INBOX_ALT('\uE69D'),
INBOX('\uE69E'),
IDEA_ALT('\uE69F'),
IDEA('\uE6A0'),
HOURGLASS('\uE6A1'),
HOME_ALT('\uE6A2'),
HOME('\uE6A3'),
HEART_EMPTY('\uE6A4'),
HEART_ALT('\uE6A5'),
HEART('\uE6A6'),
HEARING_IMPAIRED('\uE6A7'),
HEADPHONES('\uE6A8'),
HDD('\uE6A9'),
HAND_UP('\uE6AA'),
HAND_RIGHT('\uE6AB'),
HAND_LEFT('\uE6AC'),
HAND_DOWN('\uE6AD'),
GUIDEDOG('\uE6AE'),
GROUP_ALT('\uE6AF'),
GROUP('\uE6B0'),
GRAPH_ALT('\uE6B1'),
GRAPH('\uE6B2'),
GOOGLEPLUS('\uE6B3'),
GLOBE_ALT('\uE6B4'),
GLOBE('\uE6B5'),
GLASSES('\uE6B6'),
GLASS('\uE6B7'),
GITHUB_TEXT('\uE6B8'),
GITHUB('\uE6B9'),
GIFT('\uE6BA'),
GBP('\uE6BB'),
FULLSCREEN('\uE6BC'),
FRIENDFEED_RECT('\uE6BD'),
FRIENDFEED('\uE6BE'),
FOURSQUARE('\uE6BF'),
FORWARD_ALT('\uE6C0'),
FORWARD('\uE6C1'),
FORK('\uE6C2'),
FONTSIZE('\uE6C3'),
FONT('\uE6C4'),
FOLDER_SIGN('\uE6C5'),
FOLDER_OPEN('\uE6C6'),
FOLDER_CLOSE('\uE6C7'),
FOLDER('\uE6C8'),
FLICKR('\uE6C9'),
FLAG_ALT('\uE6CA'),
FLAG('\uE6CB'),
FIRE('\uE6CC'),
FILTER('\uE6CD'),
FILM('\uE6CE'),
FILE_NEW_ALT('\uE6CF'),
FILE_NEW('\uE6D0'),
FILE_EDIT_ALT('\uE6D1'),
FILE_EDIT('\uE6D2'),
FILE_ALT('\uE6D3'),
FILE('\uE6D4'),
FEMALE('\uE6D5'),
FAST_FORWARD('\uE6D6'),
FAST_BACKWARD('\uE6D7'),
FACETIME_VIDEO('\uE6D8'),
FACEBOOK('\uE6D9'),
EYE_OPEN('\uE6DA'),
EYE_CLOSE('\uE6DB'),
EXCLAMATION_SIGN('\uE6DC'),
EUR('\uE6DD'),
ERROR_ALT('\uE6DE'),
ERROR('\uE6DF'),
ENVELOPE_ALT('\uE6E0'),
ENVELOPE('\uE6E1'),
EJECT('\uE6E2'),
EDIT('\uE6E3'),
DRIBBBLE('\uE6E4'),
DOWNLOAD_ALT('\uE6E5'),
DOWNLOAD('\uE6E6'),
DIGG('\uE6E7'),
DEVIANTART('\uE6E8'),
DELICIOUS('\uE6E9'),
DASHBOARD('\uE6EA'),
CSS('\uE6EB'),
CREDIT_CARD('\uE6EC'),
COMPASS_ALT('\uE6ED'),
COMPASS('\uE6EE'),
COMMENT_ALT('\uE6EF'),
COMMENT('\uE6F0'),
COGS('\uE6F1'),
COG_ALT('\uE6F2'),
COG('\uE6F3'),
CLOUD_ALT('\uE6F4'),
CLOUD('\uE6F5'),
CIRCLE_ARROW_UP('\uE6F6'),
CIRCLE_ARROW_RIGHT('\uE6F7'),
CIRCLE_ARROW_LEFT('\uE6F8'),
CIRCLE_ARROW_DOWN('\uE6F9'),
CHILD('\uE6FA'),
CHEVRON_UP('\uE6FB'),
CHEVRON_RIGHT('\uE6FC'),
CHEVRON_LEFT('\uE6FD'),
CHEVRON_DOWN('\uE6FE'),
CHECK_EMPTY('\uE6FF'),
CHECK('\uE700'),
CERTIFICATE('\uE701'),
CC('\uE702'),
CARET_UP('\uE703'),
CARET_RIGHT('\uE704'),
CARET_LEFT('\uE705'),
CARET_DOWN('\uE706'),
CAR('\uE707'),
CAMERA('\uE708'),
CALENDAR_SIGN('\uE709'),
CALENDAR('\uE70A'),
BULLHORN('\uE70B'),
BULB('\uE70C'),
BRUSH('\uE70D'),
BROOM('\uE70E'),
BRIEFCASE('\uE70F'),
BRAILLE('\uE710'),
BOOKMARK_EMPTY('\uE711'),
BOOKMARK('\uE712'),
BOOK('\uE713'),
BOLD('\uE714'),
BLOGGER('\uE715'),
BLIND('\uE716'),
BELL('\uE717'),
BEHANCE('\uE718'),
BARCODE('\uE719'),
BAN_CIRCLE('\uE71A'),
BACKWARD('\uE71B'),
ASL('\uE71C'),
ARROW_UP('\uE71D'),
ARROW_RIGHT('\uE71E'),
ARROW_LEFT('\uE71F'),
ARROW_DOWN('\uE720'),
ALIGN_RIGHT('\uE721'),
ALIGN_LEFT('\uE722'),
ALIGN_JUSTIFY('\uE723'),
ALIGN_CENTER('\uE724'),
ADULT('\uE725'),
ADJUST_ALT('\uE726'),
ADJUST('\uE727'),
ADDRESS_BOOK_ALT('\uE728'),
ADDRESS_BOOK('\uE729'),
ASTERISK('\uE72A');
private final char character;
private ElusiveIcons(char character) {
this.character = character;
}
@Override
public char getChar() {
return character;
}
@Override
public String unicodeToString() {
return String.format("\\u%04x", (int) character);
}
@Override
public String characterToString() {
return Character.toString(character);
}
@Override
public String getFontFamily() {
return ElusiveIcon.FONT_FAMILY;
}
}

View File

@@ -0,0 +1,14 @@
package de.geofroggerfx.ui.glyphs;
import de.jensd.fx.glyphs.GlyphsDude;
import javafx.scene.text.Font;
/**
* Created by Andreas on 23.03.2015.
*/
public class GeofroggerGlyphsDude extends GlyphsDude {
static {
Font.loadFont(GeofroggerGlyphsDude.class.getResource(ElusiveIcon.TTF_PATH).toExternalForm(), 10.0);
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.ui.list;
import de.geofroggerfx.model.CacheListEntry;
import de.geofroggerfx.ui.GeocachingIcons;
import de.jensd.fx.glyphs.GlyphsDude;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcons;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.text.Text;
/**
* Multi-Column-Row list cell to shows the most important data in a list.
*
* @author Andreas
*/
public class CacheListCell extends ListCell<CacheListEntry> {
private static final String YELLOW = ";-fx-fill: linear-gradient(#e8e474 0%, #edcf59 70%, #bfba26 85%);";
private static final String GRAY = ";-fx-fill: linear-gradient(#cccccc 0%, #999999 70%, #888888 85%);";
private final GridPane grid = new GridPane();
private final Text icon = GlyphsDude.createIcon(FontAwesomeIcons.BLANK, "20.0");
private final Label name = new Label();
private final Text difficultyStars = GlyphsDude.createIcon(FontAwesomeIcons.BLANK, "8.0");
private final Text terrainStars = GlyphsDude.createIcon(FontAwesomeIcons.BLANK, "8.0");
public CacheListCell() {
configureGrid();
configureIcon();
configureName();
configureDifficulty();
configureTerrain();
addControlsToGrid();
}
@Override
public void updateItem(CacheListEntry cache, boolean empty) {
super.updateItem(cache, empty);
if (empty) {
clearContent();
} else {
addContent(cache);
}
}
private void configureGrid() {
grid.setHgap(10);
grid.setVgap(4);
grid.setPadding(new Insets(0, 10, 0, 10));
ColumnConstraints column1 = new ColumnConstraints(32);
ColumnConstraints column2 = new ColumnConstraints(USE_COMPUTED_SIZE , USE_COMPUTED_SIZE, Double.MAX_VALUE);
column2.setHgrow(Priority.NEVER);
ColumnConstraints column3 = new ColumnConstraints(30 , 50 , Double.MAX_VALUE);
column3.setHgrow(Priority.ALWAYS);
column3.setFillWidth(true);
ColumnConstraints column4 = new ColumnConstraints(USE_COMPUTED_SIZE , USE_COMPUTED_SIZE , Double.MAX_VALUE);
column4.setHgrow(Priority.NEVER);
ColumnConstraints column5 = new ColumnConstraints(30 , 50 , Double.MAX_VALUE);
column5.setHgrow(Priority.ALWAYS);
column5.setFillWidth(true);
grid.getColumnConstraints().addAll(column1, column2, column3, column4, column5);
}
private void configureIcon() {
icon.setStyle(icon.getStyle()+ GRAY);
}
private void configureName() {
name.setStyle("-fx-font-weight: bold;");
}
private void configureDifficulty() {
difficultyStars.setStyle(difficultyStars.getStyle() + YELLOW);
}
private void configureTerrain() {
terrainStars.setStyle(difficultyStars.getStyle() + YELLOW);
}
private void addControlsToGrid() {
grid.add(icon, 0, 0, 1, 2);
grid.add(name, 1, 0, 4, 1);
grid.add(new Label("Difficulty:"), 1, 1);
grid.add(difficultyStars, 2, 1);
grid.add(new Label("Terrain:"), 3, 1);
grid.add(terrainStars, 4, 1);
}
private void clearContent() {
setText(null);
setGraphic(null);
}
private void addContent(CacheListEntry cache) {
setIcon(cache);
setCacheName(cache);
setDifficulty(cache);
setTerrain(cache);
setGraphic(grid);
}
private void setCacheName(CacheListEntry cache) {
name.setText(cache.getName());
}
private void setIcon(CacheListEntry cache) {
icon.setText(GeocachingIcons.getIconAsString(cache.getType()));
}
private void setDifficulty(CacheListEntry cache) {
difficultyStars.setText(GeocachingIcons.getStarsAsString(cache.getDifficulty()));
}
private void setTerrain(CacheListEntry cache) {
terrainStars.setText(GeocachingIcons.getStarsAsString(cache.getTerrain()));
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) Andreas Billmann <abi@geofroggerfx.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.geofroggerfx.ui.list;
import de.geofroggerfx.application.SessionContext;
import de.geofroggerfx.model.Cache;
import de.geofroggerfx.model.CacheListEntry;
import de.geofroggerfx.service.CacheService;
import de.geofroggerfx.ui.FXMLController;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import static de.geofroggerfx.application.SessionContext.CACHE_ENTRY_LIST;
import static de.geofroggerfx.application.SessionContext.CURRENT_CACHE;
/**
* Created by Andreas on 09.03.2015.
*/
@Component
public class ListController extends FXMLController {
@Autowired
private SessionContext sessionContext;
@Autowired
private CacheService cacheService;
@FXML
ListView cacheListView;
@Value("${fxml.geofrogger.list.view}")
@Override
public void setFxmlFilePath(String filePath) {
this.fxmlFilePath = filePath;
}
@Override
public void initialize(URL location, ResourceBundle resources) {
setCellFactory();
sessionContext.addListener(CACHE_ENTRY_LIST, () -> Platform.runLater(this::resetCacheList));
cacheListView.getSelectionModel().selectedItemProperty().addListener(
(InvalidationListener) observable -> setSelectedCacheIntoSession()
);
}
private void resetCacheList() {
List<Cache> caches = (List<Cache>) sessionContext.getData(CACHE_ENTRY_LIST);
cacheListView.getItems().setAll(caches);
}
@SuppressWarnings("unchecked")
private void setCellFactory() {
cacheListView.setCellFactory(param -> new CacheListCell());
}
private void setSelectedCacheIntoSession() {
CacheListEntry entry = (CacheListEntry) cacheListView.getSelectionModel().getSelectedItem();
Cache cache = null;
if (entry != null) {
cache = cacheService.getCacheForId(entry.getId());
}
sessionContext.setData(CURRENT_CACHE, cache);
}
}

View File

@@ -0,0 +1,3 @@
jdbc.url=jdbc:h2:file:C:/billmann/projects/GeoFroggerFX2/geofroggerfx
jdbc.username = sa
jdbc.password = sa

View File

@@ -0,0 +1,40 @@
CREATE TABLE cache (
id INT PRIMARY KEY,
name VARCHAR (255),
placed_by VARCHAR (255),
available BOOLEAN,
archived BOOLEAN,
found BOOLEAN,
difficulty VARCHAR (255),
terrain VARCHAR (255),
country VARCHAR (255),
state VARCHAR (255),
short_description VARCHAR(2147483647),
short_description_html BOOLEAN,
long_description VARCHAR(2147483647),
long_description_html BOOLEAN,
encoded_hints VARCHAR(2147483647),
container VARCHAR (255),
type VARCHAR (255),
user_id INT
);
CREATE TABLE waypoint (
name VARCHAR (255) PRIMARY KEY ,
cache_id INT,
latitude DOUBLE,
longitude DOUBLE,
time TIMESTAMP,
description VARCHAR (255),
url VARCHAR (255),
urlName VARCHAR (255),
symbol VARCHAR (255),
type VARCHAR (255),
FOREIGN KEY(cache_id) REFERENCES cache(id) ON DELETE CASCADE
);
CREATE TABLE version (
version INT
);
INSERT INTO version(version) values(1);

View File

@@ -0,0 +1,10 @@
application.name = GeoFroggerFX
application.version = 2.0
# fxml views
fxml.geofrogger.view = /de/geofroggerfx/ui/geofroggerfx.fxml
fxml.geofrogger.list.view = /de/geofroggerfx/ui/list/list.fxml
fxml.geofrogger.details.view = /de/geofroggerfx/ui/details/details.fxml
# resources
resource.main = de.geofroggerfx.ui.geofrogger

View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.web.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.text.*?>
<?import de.jensd.fx.glyphs.fontawesome.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.effect.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.effect.DropShadow?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<?import java.net.URL?>
<?import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon?>
<?import com.lynden.gmapsfx.GoogleMapView?>
<BorderPane layoutX="10.0" layoutY="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="600" minWidth="400"
style="-fx-background-color: #ffffff;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/8.0.40"
xmlns:fx="http://javafx.com/fxml/1">
<right>
<VBox minWidth="200.0" prefHeight="200.0" spacing="8.0" BorderPane.alignment="CENTER">
<children>
<TitledPane animated="false" collapsible="false" text="Attributes">
<content>
<FlowPane hgap="4.0" prefWidth="200.0" vgap="4.0">
<children>
<FontAwesomeIcon glyphName="CAR" size="1.6em"/>
<FontAwesomeIcon glyphName="CHILD" size="1.6em"/>
<FontAwesomeIcon glyphName="WHEELCHAIR" size="1.6em"/>
</children>
<opaqueInsets>
<Insets/>
</opaqueInsets>
</FlowPane>
</content>
</TitledPane>
<TitledPane animated="false" collapsible="false" text="Logs">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<GridPane hgap="4.0" vgap="4.0" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="NEVER" minWidth="10.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" vgrow="NEVER"/>
</rowConstraints>
<children>
<FontAwesomeIcon glyphName="EXTERNAL_LINK" size="1.2em" GridPane.columnIndex="1"
GridPane.halignment="RIGHT" GridPane.rowIndex="2"
GridPane.valignment="BOTTOM"/>
<Label alignment="TOP_LEFT"
text="Bei einer Spontan-Tour mit den Hoppels haben wir heute nun zum 2. Mal den Geisterkäfer besucht.Immer wieder nett [;)]. Die Zeit hinterlässt immer mehr ihre Spuren.Nach kurzer Suche war das Final gefunden und der Rest schnell erledigt.Auch wir danken für's reloaden [8D].Viele Grüße - die Jedi-Ritter"
wrapText="true" GridPane.columnIndex="1"/>
<FontAwesomeIcon glyphName="CHECK" size="1.2em" GridPane.valignment="TOP"/>
<FontAwesomeIcon glyphName="TIMES" size="1.2em" GridPane.rowIndex="1"
GridPane.valignment="TOP"/>
<Label alignment="TOP_LEFT"
text="Hier war ich doch schon mal...Nach einer gefühlten Ewigkeit die Dose dann doch noch gefunden.DFDC"
wrapText="true" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
</children>
</GridPane>
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane animated="false" collapsible="false" prefHeight="200.0" prefWidth="200.0" text="Trackables">
<content>
<ListView prefHeight="200.0" prefWidth="200.0"/>
</content>
</TitledPane>
<TitledPane animated="false" collapsible="false" prefHeight="200.0" prefWidth="200.0" text="Map">
<content>
<GoogleMapView fx:id="mapView" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="NEVER"/>
</content>
</TitledPane>
</children>
<BorderPane.margin>
<Insets left="8.0" right="8.0"/>
</BorderPane.margin>
</VBox>
</right>
<top>
<GridPane BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="NEVER" minWidth="60.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<ColumnConstraints hgrow="NEVER" minWidth="60.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="50.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<Label fx:id="cacheName" styleClass="cache-h1" text="Cache-Name" GridPane.columnSpan="4"/>
<Label text="Difficulty:" GridPane.rowIndex="1"/>
<FontAwesomeIcon fx:id="cacheDifficulty" glyphName="BLANK"
glyphStyle="-fx-fill: linear-gradient(#e8e474 0%, #edcf59 70%, #bfba26 85%);"
size="16.0" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label text="Terrain:" GridPane.columnIndex="2" GridPane.rowIndex="1"/>
<FontAwesomeIcon fx:id="cacheTerrain" glyphName="BLANK"
glyphStyle="-fx-fill: linear-gradient(#e8e474 0%, #edcf59 70%, #bfba26 85%);"
size="16.0" GridPane.columnIndex="3" GridPane.rowIndex="1"/>
</children>
</GridPane>
</top>
<center>
<ScrollPane fitToHeight="true" fitToWidth="true" minWidth="400.0" prefHeight="200.0" prefWidth="400.0"
style="-fx-background-color: #ffffff;" BorderPane.alignment="CENTER">
<content>
<VBox fx:id="mainContent" style="-fx-background-color: #ffffff;" spacing="10">
<children>
<WebView fx:id="description" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS"/>
</children>
</VBox>
</content>
</ScrollPane>
</center>
<padding>
<Insets bottom="16.0" left="16.0" right="16.0" top="16.0"/>
</padding>
<effect>
<DropShadow/>
</effect>
<stylesheets>
<URL value="@/de/geofroggerfx/ui/geofroggerfx.css"/>
</stylesheets>
</BorderPane>

View File

@@ -0,0 +1,52 @@
menu.title.import.gpx = Importiere GPX
menu.title.file = Datei
menu.title.quit = Beenden
menu.title.help = Hilfe
menu.title.settings = Einstellungen
menu.title.about = \u00dcber GeoFroggerFX
menu.title.plugins = Plugins
menu.title.list = Listen
menu.title.list.new = Liste anlegen
menu.title.list.delete = Liste l\u00F6schen
menu.title.sort = Sortieren
menu.title.filter = Filtern
label.text.cache.list=Liste:
label.text.cache.list.count=Anzahl:
label.text.name=Name:
label.text.difficulty=Schwierigkeit:
label.text.terrain=Gel\u00E4nde
label.text.placedBy=Platziert von:
label.text.owner=Betreut von:
label.text.date=Datum:
label.text.type=Typ:
label.text.container=Gr\u00F6\u00dfe:
label.text.shortdescription=Kurze Beschreibung:
label.text.htmldescription=HTML Beschreibung
label.text.longdescription=Lange Beschreibung:
tab.text.descriptions=Beschreibungen
tab.text.general=Allgemein
sort.cache.name = GC Code
sort.cache.type = Art
sort.cache.difficulty = Schwierigkeitsgrad
sort.cache.terrain = Gel\u00E4nde
sort.cache.placedBy = Platziert von
sort.cache.owner = Betreut von
dialog.title.about = &#220;ber
dialog.title.new_list = Neue Liste
dialog.label.listname = Name der Liste:
dialog.msg.list.does.exist = Diese Liste existiert schon!
dialog.title.delete_list = Liste l&#246;schen
all.caches = Alle Caches
status.load.all.caches.from.db = Lade alle Caches von der Datenbank.
status.all.cache.lists.loaded = Alle Listen geladen.
status.load.caches.from.db = Lade Caches von der Datenbank.
status.all.caches.loaded = Alle Caches geladen.
status.store.all.caches = Speichere Caches in Datenbank.
status.all.caches.stored = Alle Caches in der Datenbank gespeichert.

View File

@@ -0,0 +1,53 @@
menu.title.import.gpx = Import GPX
menu.title.file = File
menu.title.quit = Quit
menu.title.help = Help
menu.title.settings = Settings
menu.title.about = About GeoFroggerFX
menu.title.plugins = Plugins
menu.title.list = Lists
menu.title.list.new = New list
menu.title.list.delete = Delete list
menu.title.sort = Sort
menu.title.filter = Filter
label.text.cache.list=List:
label.text.cache.list.count=Number:
label.text.name=Name:
label.text.difficulty=Difficulty:
label.text.terrain=Terrain:
label.text.placedBy=Placed By:
label.text.owner=Owner:
label.text.date=Date:
label.text.type=Type:
label.text.container=Container:
label.text.shortdescription=Short description:
label.text.htmldescription=HTML Description
label.text.longdescription=Long description:
tab.text.descriptions=Descriptions
tab.text.general=General
sort.cache.name = GC Code
sort.cache.type = Type
sort.cache.difficulty = Difficulty
sort.cache.terrain = Terrain
sort.cache.placedBy = Placed by
sort.cache.owner = Owner
dialog.title.about = About
dialog.title.new_list = New list
dialog.label.listname = Name of list:
dialog.msg.list.does.exist = List does already exist!
dialog.title.delete_list = Delete list
all.caches = All caches
status.load.all.caches.from.db = Load cache lists from database.
status.all.cache.lists.loaded = All cache lists loaded.
status.load.caches.from.db = Load caches from database.
status.all.caches.loaded = All caches loaded.
status.store.all.caches = Store caches in database.
status.all.caches.stored = All caches are stored in database.

View File

@@ -0,0 +1,4 @@
.cache-h1 {
-fx-font-size: 24pt;
-fx-font-family: "Sofia-Regular";
}

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.Color?>
<?import javafx.scene.text.Font?>
<?import java.net.URL?>
<VBox prefHeight="800.0" prefWidth="1280.0" minHeight="600.0" minWidth="800.0" xmlns:fx="http://javafx.com/fxml" >
<children>
<MenuBar VBox.vgrow="NEVER">
<menus>
<Menu mnemonicParsing="false" text="%menu.title.file">
<items>
<MenuItem mnemonicParsing="false" onAction="#importGpx" text="%menu.title.import.gpx"/>
<SeparatorMenuItem mnemonicParsing="false"/>
<MenuItem mnemonicParsing="false" onAction="#exit" text="%menu.title.quit"/>
</items>
</Menu>
<Menu mnemonicParsing="false" text="%menu.title.list">
<items>
<MenuItem mnemonicParsing="false" onAction="#newList" text="%menu.title.list.new"/>
<MenuItem mnemonicParsing="false" onAction="#deleteList" text="%menu.title.list.delete"/>
</items>
</Menu>
<Menu fx:id="pluginsMenu" mnemonicParsing="false" text="%menu.title.plugins"/>
<Menu mnemonicParsing="false" text="%menu.title.help">
<items>
<MenuItem mnemonicParsing="false" onAction="#showSettings" text="%menu.title.settings"/>
<MenuItem mnemonicParsing="false" onAction="#showAboutDialog" text="%menu.title.about"/>
</items>
</Menu>
</menus>
</MenuBar>
<BorderPane fx:id="mainPane" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
<center>
<SplitPane fx:id="contentPane" dividerPositions="0.3779342723004695" focusTraversable="true" prefHeight="-1.0" prefWidth="-1.0"
VBox.vgrow="ALWAYS">
<items>
<HBox fx:id="cacheListContent" maxWidth="400" minWidth="300"/>
<AnchorPane fx:id="cacheDetailsContent" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="400" minWidth="600" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: #cccccc;">
<padding>
<Insets bottom="16.0" left="32.0" right="32.0" top="16.0" />
</padding>
</AnchorPane>
</items>
</SplitPane>
</center>
</BorderPane>
<HBox id="HBox" alignment="CENTER_LEFT" spacing="5.0" VBox.vgrow="NEVER">
<children>
<Pane prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="ALWAYS"/>
<Label fx:id="leftStatus" maxHeight="1.7976931348623157E308" maxWidth="-1.0" text="" HBox.hgrow="ALWAYS">
<font>
<Font size="11.0" fx:id="x3"/>
</font>
<textFill>
<Color blue="0.625" green="0.625" red="0.625" fx:id="x4"/>
</textFill>
</Label>
<ProgressBar fx:id="progress" prefWidth="300.0" progress="0" HBox.hgrow="ALWAYS"/>
</children>
<padding>
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0"/>
</padding>
</HBox>
</children>
<stylesheets>
<URL value="@/de/geofroggerfx/ui/geofroggerfx.css"/>
</stylesheets>
</VBox>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import java.net.URL?>
<?import javafx.geometry.Insets?>
<VBox id="AnchorPane2" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" HBox.hgrow="ALWAYS">
<children>
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="-1.0" styleClass="cache-header" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label alignment="CENTER_LEFT" prefWidth="-1.0" style="&#10;" text="%label.text.cache.list" textAlignment="LEFT" textFill="BLACK" wrapText="false">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin></Label>
<ComboBox fx:id="cacheListComboBox" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" HBox.hgrow="ALWAYS">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin></ComboBox>
<MenuButton fx:id="menuIcon" minHeight="16.0" />
</children>
<padding>
<Insets left="16.0" right="16.0" />
</padding>
</HBox>
<ListView fx:id="cacheListView" VBox.vgrow="ALWAYS" />
</children>
<stylesheets>
<URL value="@/de/geofroggerfx/ui/geofroggerfx.css"/>
</stylesheets>
</VBox>

Binary file not shown.

View File

@@ -0,0 +1,86 @@
SIL OPEN FONT LICENSE
Version 1.1 - 26 February 2007
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting — in part or in whole — any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@@ -0,0 +1,10 @@
Elusive-Iconfont
================
The Elusive Iconfont is an icons webfont, optimized for use with twitter's bootstrap.
For examples & usage see http://shoestrap.org/downloads/elusive-icons-webfont/
Licence: [SIL](http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL)
https://github.com/reduxframework/elusive-iconfont

View File

@@ -0,0 +1,94 @@
Copyright (c) 2011 by LatinoType Limitada (luciano@latinotype.com),
with Reserved Font Names &quot;Sofia&quot;
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
&quot;Font Software&quot; refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
&quot;Reserved Font Name&quot; refers to any names specified as such after the
copyright statement(s).
&quot;Original Version&quot; refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
&quot;Modified Version&quot; refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
&quot;Author&quot; refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION &amp; CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.