There are several possible ways to run Calliope. Below we provide instructions for installation of any software dependencies.
To start the Calliope GUI you will need to install a couple of software dependencies.
JavaFX comes bundled with Java 8. We recommended that you use the latest Java 8.
Note: If you are using OpenJDK instead of Oracle's JDK, you will also need OpenJFX.
If you're installing Java 8 onto a Mac OS X, you'll need to set the alias:
alias j8="export JAVA_HOME=`/usr/libexec/java_home -v 1.8`; java -version"
j8
ExifTool must be accessible in your system $PATH
environment variable. Calliope will run without ExifTool so you can check if you have successfully installed ExifTool by launching Calliope and going to the settings tab. If the text at the bottom reads ExifTool Installation Status: Found
you are good to go. If the text at the bottom reads ExifTool Installation Status: Not Found
follow the instructions at the bottom of the settings tab to install ExifTool on your system. If you attempt to import images without having ExifTool installed you will be prompted to install ExifTool first.
We have hosted a pre-built Java JAR image on CyVerse. After you've installed Java 8 and ExifTool, you can download the program and run it from a command line:
java -jar Calliope-1.5-SNAPSHOT-jar-with-dependencies.jar
The latest version of the build is also hosted on the Docker Hub. By running with Docker, you can avoid installing Java 8 on your system.
git pull cyverse-gis/calliope:latest
docker run -it -p 9200:9200 cyverse-gis/calliope:latest
The code is hosted on GitHub, and can be pulled and built from source.
git clone https://github.com/cyverse-gis/suas-metadata
cd suas-metadata/Calliope
mvn -U compile package
The CyVerse infrastructure is heavily used by Calliope to both store data and authenticate users. In order to use Calliope, you will need a CyVerse account. Please register for a free account before trying to log into Calliope.
After registering you can open Calliope where you should be prompted with a login screen.
At this point you can enter your CyVerse account username and password into the respective fields. If you would like Calliope to remember your username in the future you can check the box. If you have not yet registered for an account click on the blue 'Register' text. If you have trouble logging in and would like to change your password click on 'Forgot Password'.
All Source Code is maintained on GitHub
Calliope is built using the standard MVC design pattern.
In this design pattern, the model is created first with complete independence from the view or controller. The model tends to be made up of simple classes that make up the data of the program and functions to manipulate that data. Any database connections or network threads are managed by the model.
The view is completely independent from the model, but is linked or 'bound' to the controller. The view is made up of FXML and CSS files that define each user interface component. Each FXML file begins with a component that has an fx:controller="x.y.z"
attribute that defines the controller the FXML file is bound to. Any actions done to the UI are forwarded to the controller through action listeners.
The controller is dependent on both the model and controller. Any UI components such as text fields and labels are represented in the controller as fields. The controller contains method definitions that represent action listeners for actions that are fired from the view. The controller contains an important public void initialize() {}
method that is automatically called upon UI creation. This method is used to initialize any UI fields and setup data bindings to the model.
Calliope makes use of dependency injection to link a FXML file to its controller. This is automatically performed by JavaFX, so you won't need to do anything special. FXML elements with the tag
tell JavaFX to 'dependency inject' this element into the field private X abc;
found in the controller. If this field is not present an error will arise.
The singleton design pattern ensures only one instance of an object is ever created. This is used to ensure one publicly accessible data model is available to all controller files without needing to pass object references around. This data can be accessed with: CalliopeData.getInstance()...
. While this makes referencing the data model very easy, it can be dangerous. A publicly accessible data model is typically frowned upon in traditional object oriented programming and is not the best design decision, but it does work for now. In the future this should be refactored to pass references around to each individual file.
The observer design pattern is seen in JavaFX as data bindings. The model (as previously described in MVC) stores its variables as properties instead of primitive types. As an example, a person's name would be stored using a StringProperty
instead of a String
. A property has the ability to notify listeners of any changes. These properties are bound to the view through the controller and vice versa. When the model changes the view will automatically reflect the changes, and when the view updates the model will also reflect those changes.
Model classes are found in: /src/main/java/model
This object contains all data used by Calliope. This data contains the list of sites, list of collections, currently imported images, CyVerse connection manager, ElasticSearch connection manager, threaded executor, and much more. To access the data model from anywhere in the program use CalliopeData.getInstance()
. Any additional classes that need a single instance and a global presence should be added to this class.
This class contains all method definitions for connecting to the ElasticSearch index. It lets users authenticate their account, index images, and perform metadata queries. Any logic that interfaces with ElasticSearch should be found in this file or at least in the /elasticsearch/
package.
This class contains all method definitions for connecting to CyVerse using Jargon. It lets users authenticate their account, upload images, download files, and much more. Any logic that interfaces with iRODS or the CyVerse datastore should be found in this file or at least in the /cyverse/
package.
This interface defines a set of methods used for interacting with different data sources. This should be implemented if adding support for more data sources such as Amazon S3 or Google Drive. To add a data source add the following line to CalliopeData.java
private void addDefaultDataSources()
{
...
this.dataSources.add(new MyDataSource());
...
}
This interface is implemented by ImageEntry.java
and ImageDirectory.java
. Both these classes are used in the tree of files on the right side on the import tab. ImageEntryies are the programmatic form of an image file, while ImageDirectoryies are the programmatic form of a directory. ImageDirectories
contain a list of sub-directories and files while ImageEntry
contain image metadata and an icon. This interface may be extended for custom image and directory implementations for use in new data sources. See Data Sources for info on how to add new data sources.
This class contains all things related to threading. It contains 3 different threading executors, the BackgroundExecutor
, ImmediateExecutor
, and QueuedExecutor
.
BackgroundExecutor
: This executor has 25 available threads all running at once which can receive tasks without user knowledge. No progress is displayed to the user. This should be used when performing tasks such as loading icons.
ImmediateExecutor
: This does the same thing as the background executor, but the task message and progress is displayed to the user in the Collections tab. Task progress is shown in the center column at the bottom. This should be used for performing uploads (to a data source).
QueuedExecutor
: This is used for any operation that must be done in a specific order. Any tasks added to this executor are guaranteed to run in the order they are added. This executor is used for doing tasks such as importing images, and logging in. Progress is displayed to the user at the bottom of the central pane in the import tab.
This class contains a list of settings to be displayed in the settings tab. All settings contain properties with getters and setters which are bound to the settings tab.
This utility class allows for easy FXML document loading. Just call FXMLLoaderUtils.loadFXML()
with the path of FXML file to load. As an example, to load the FXML file to render the sites list, we do:
FXMLLoaderUtils.loadFXML("importView/SiteListEntry.fxml")
A library used for its high quality UI controls. This project relys heavily on the 'DateTimePicker' which allows for users to easily pick a date and/or time without having to type it in a special format.
One of the most important libraries in this project that provides helper classes for creating data bindings. In vanilla JavaFX it is challenging to create a listener that listens for changes in sub-properties of an object and this library makes that much easier with EasyBind.monadic()
.
ControlsFX arguably contains the highest quality set of controls ever for JavaFX. Calliope specifically makes use of the PropertySheet
, TaskProgressView
, NotificationPane
, HyperlinkLabel
, StatusBar
, Validators
, and much more.
This library provides utility classes that allow for advanced string manipulation, number parsing, and exception parsing. It is used to format exceptions in popups and parsing strings into numbers.
Much like Apache Commons Lang, this library provides utility classes for manipulating IO streams and files. It is used to retrieve file extensions and copy input streams to files.
An optional dependency that is required for apache commons configuration manager.
Much like the other Apache Commons libraries, this one assists in the creation of TAR files as well as the extraction of KMZ files. This library lets us optimize uploads by 'tarring' images first.
Once again another Apache Commons library, this time for managing and parsing configuration files. These are used to keep private details like passwords out of the code and in separate files.
A utility library by Google to help serialize Java objects into JSON and vice versa. This is incredibly useful when working with ElasticSearch which heavily makes use of JSON.
An addon to Gson that allows for cleaner serialization and deserialization of JavaFX properties.
Arguably the most important library in this list, Jargon is a Java implementation of the iRODS protocol which allows for connection to CyVerse's iRODS-based Data Store. This allows users to authenticate and then upload and download images.
This library allows users to connect to an ElasticSearch index which enables fast queries and efficient data indexing. We are using OpenDistro, an Amazon product that builds security features into the ES and Kibana platforms
A utility library used by ElasticSearch to print out errors and warnings. These are turned off by Calliope, but can be useful when debugging.
This library allows Java to parse and import KML files. These contain shape and boundary information of NEON sites ready to be drawn on the map.
A fantastic Java interface to the ExifTool software used to read image file's metadata. This library starts the ExifTool process and keeps it alive while running multiple images through it.
An advanced imaging library provided by Oracle to enable swing's ImageIO class to parse ".tif" image files. These can then be converted into JavaFX image files.
used by ElasticSearch for geo-queries.
used by ElasticSearch for geo-queries.
Another simple logging library used as a dependency to disable library logging.
Intended successor to Log4j used to log information. This is used by the Jargon library and also disabled to remove debug messages.
Advanced map rendering library for JavaFX that supports multiple tile providers and the addition of JavaFX nodes on the map.