This is a time line for control over the events of some containers in a train station.
It gets all the data to build the time line by getting a JSON from a database via REST service. The app resets every minute to refresh the results and every dot representing a container has some info in a tooltip activated by hovering the mouse.
The app needs 3 external libraries:
- commons-io-2.4.jar
- guava-18.0.jar
- json-simple-1.1.1.jar
There is also a webstart test version online, please use Firefox if you want to try it out: http://www.abaxomol.com/dist/ContenedoresChart.html
ContenedoresChart.java
public class ContenedoresChart extends Application {
DrawDots drawDots = new DrawDots();
static DotsArrays dotsArrays = new DotsArrays();
final static NumberAxis xAxis = new NumberAxis();
final static CategoryAxis yAxis = new CategoryAxis();
final static LineChart<Number, String> sc = new
LineChart<>(xAxis,yAxis);
static String fullJSON = "";
@Override
public void start(Stage primaryStage) {
NumberAxis xAxis = new NumberAxis();
CategoryAxis yAxis = new CategoryAxis();
LineChart<Number, String> sc = new
LineChart<>(xAxis,yAxis);
Get_JSON_String.getJSONString();
primaryStage.setTitle("Ferroservicios");
DateFormatter.dateFormatter(xAxis);
xAxis.setLabel("Fecha");
yAxis.setLabel("Contenedores");
sc.setTitle("Eventos de Contenedores");
SeparateContenedores.loadDots(sc);
//sc.setLegendVisible(false);
SetTooltip.setTooltip();
SetTooltip.setSeriesStyle(sc);
LegendItems.setItems(sc);
LegendItems.setTransparent();
Legend legend = (Legend)sc.lookup(".chart-legend");
legend.getItems().removeIf(item->item.getText().equals("hide"));
Scene scene = new Scene(sc, 1200, 1000);
//primaryStage.setMaximized(true);
primaryStage.setScene(scene);
primaryStage.show();
LegendItems.setLegendStyle(sc);
SetRefreshRate.setRefreshRate(primaryStage, 60);
}
public static void main(String[] args) {
launch(args);
}
}
DateFormatter.java
public class DateFormatter {
static String date1 = "";
static String date2 = "";
static String date3 = "";
static String date4 = "";
static String date5 = "";
static String date6 = "";
static String date7 = "";
public static void dateFormatter(NumberAxis xAxis){
loadDates();
xAxis.setLowerBound(0.0);
xAxis.setUpperBound(7.4);
xAxis.setAutoRanging(false);
xAxis.setTickUnit(1);
xAxis.setTickLabelFormatter(new StringConverter<Number>() {
@Override
public String toString(Number n) {
if (n.equals(1.00)) return date1;
if (n.equals(2.00)) return date2;
if (n.equals(3.00)) return date3;
if (n.equals(4.00)) return date4;
if (n.equals(5.00)) return date5;
if (n.equals(6.00)) return date6;
if (n.equals(7.00)) return date7;
return "";
}
@Override
public Number fromString(String string) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
});
}
public static void loadDates(){
try {
JSONParser parser = new JSONParser();
String urlJSON = ContenedoresChart.fullJSON;
JSONObject JSON_obj = (JSONObject) JSONValue.parseWithException(urlJSON);
//set the value of the dates
JSONObject namesArray = (JSONObject) JSON_obj.get("dates");
date1 = String.valueOf(namesArray.get("date1"));
date2 = String.valueOf(namesArray.get("date2"));
date3 = String.valueOf(namesArray.get("date3"));
date4 = String.valueOf(namesArray.get("date4"));
date5 = String.valueOf(namesArray.get("date5"));
date6 = String.valueOf(namesArray.get("date6"));
date7 = String.valueOf(namesArray.get("date7"));
} catch (ParseException e) {
//ErrorHandling.showException();
}
}
}
DotsArray.java
public class DotsArrays {
static JSON_Reader reader = new JSON_Reader();
static ArrayList<ArrayList<XYChart.Data>> arrayOfContainers = new ArrayList<>();
public static void loadDots(){
SeparateContenedores.loadNames();
arrayOfContainers.clear();
for(int x=0; x<SeparateContenedores.arrayOfNames.size(); x++){
ArrayList<XYChart.Data> contenedor = new ArrayList<>();
arrayOfContainers.add(contenedor);
reader.setDots(contenedor,SeparateContenedores.arrayOfNames.get(x));
}
}
}
DrawDots.java
public class DrawDots {
public static ListMultimap<String, String> dataMap = ArrayListMultimap.create();
public static void drawJSONdots(ArrayList<XYChart.Data> dotArray, XYChart.Series series){
for(int x = 0; x<dotArray.size();x++){
series.getData().add(dotArray.get(x));
}
}
public static void hackTooltipStartTiming(Tooltip tooltip) {
try {
Field fieldBehavior = tooltip.getClass().getDeclaredField("BEHAVIOR");
fieldBehavior.setAccessible(true);
Object objBehavior = fieldBehavior.get(tooltip);
Field fieldTimer = objBehavior.getClass().getDeclaredField("activationTimer");
fieldTimer.setAccessible(true);
Timeline objTimer = (Timeline) fieldTimer.get(objBehavior);
objTimer.getKeyFrames().clear();
objTimer.getKeyFrames().add(new KeyFrame(new Duration(100)));
} catch (Exception e) {
e.printStackTrace();
}
}
}
ErrorHandling.java
public class ErrorHandling {
public static Alert showException(){
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error JSON");
alert.setHeaderText("Error en el archivo JSON");
alert.setContentText("No se pudo obtener el archivo JSON");
Exception ex = new FileNotFoundException("Could not retrieve JSON text");
// Create expandable Exception.
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
String exceptionText = sw.toString();
Label label = new Label("The exception stacktrace was:");
TextArea textArea = new TextArea(exceptionText);
textArea.setEditable(false);
textArea.setWrapText(true);
textArea.setMaxWidth(Double.MAX_VALUE);
textArea.setMaxHeight(Double.MAX_VALUE);
GridPane.setVgrow(textArea, Priority.ALWAYS);
GridPane.setHgrow(textArea, Priority.ALWAYS);
GridPane expContent = new GridPane();
expContent.setMaxWidth(Double.MAX_VALUE);
expContent.add(label, 0, 0);
expContent.add(textArea, 0, 1);
// Set expandable Exception into the dialog pane.
alert.getDialogPane().setExpandableContent(expContent);
alert.showAndWait();
return alert;
}
}
Get_JSON_String.java
public class Get_JSON_String {
public static void getJSONString(){
try{
ContenedoresChart.fullJSON = IOUtils.toString(new URL("http://mic.abaxomol.com:8080/apex/mic_ferro.JSON_CONTAINERS_TIMELINE_PARM?p_dias_atras=3&p_id_consignatario=1088"));
} catch (IOException e) {
e.printStackTrace();
ErrorHandling.showException();
}
}
}
JSON_Reader.java
public class JSON_Reader {
static String nombre;
static String fecha;
static String hora;
public static void setDots(ArrayList<XYChart.Data> dotsArrayList, String name){
Integer numOfEvents;
try {
JSONParser parser = new JSONParser();
// get the data
String urlJSON = ContenedoresChart.fullJSON;
JSONObject JSON_obj = (JSONObject) JSONValue.parseWithException(urlJSON);
JSONArray dayArray = (JSONArray) JSON_obj.get(name);
// get the object of the loop
JSONObject numOfEventsJSON = (JSONObject) dayArray.get(0);
numOfEvents = Integer.parseInt(String.valueOf(numOfEventsJSON.get("numEventos")));
if (numOfEvents.equals(1)) {
JSONObject contenedorArray = (JSONObject) dayArray.get(1);
Double fecha = Double.parseDouble((String.valueOf(contenedorArray.get("fecha"))));
String hora = String.valueOf(contenedorArray.get("hora"));
String nombre = String.valueOf(contenedorArray.get("nombre"));
String id = String.valueOf(contenedorArray.get("ID"));
String confirmado = String.valueOf(contenedorArray.get("confirmado"));
String tipo_evento = String.valueOf(contenedorArray.get("tipo_evento"));
String vacio_lleno = String.valueOf(contenedorArray.get("vacio_lleno"));
String extraValue = ("Nombre: "+nombre+"\n"
+"ID: "+id+"\n"
+"Fecha y Hora: "+hora+"\n"
+"Confirmado: "+confirmado+"\n"
+"Tipo de Evento: "+tipo_evento+"\n"
+"Vacio/Lleno: "+vacio_lleno);
XYChart.Data contenedor = new XYChart.Data(fecha, nombre);
dotsArrayList.add(contenedor);
LegendItems.nombre = nombre;
contenedor.setExtraValue(extraValue);
} else {
for(int x = 1; x<=numOfEvents; x++){
JSONObject contenedorArray = (JSONObject) dayArray.get(x);
Double fecha = Double.parseDouble((String.valueOf(contenedorArray.get("fecha"))));
String hora = String.valueOf(contenedorArray.get("hora"));
String nombre = String.valueOf(contenedorArray.get("nombre"));
String id = String.valueOf(contenedorArray.get("ID"));
String confirmado = String.valueOf(contenedorArray.get("confirmado"));
String tipo_evento = String.valueOf(contenedorArray.get("tipo_evento"));
String vacio_lleno = String.valueOf(contenedorArray.get("vacio_lleno"));
String extraValue = ("Nombre: "+nombre+"\n"
+"ID: "+id+"\n"
+"Fecha y Hora: "+hora+"\n"
+"Confirmado: "+confirmado+"\n"
+"Tipo de Evento: "+tipo_evento+"\n"
+"Vacio/Lleno: "+vacio_lleno);
XYChart.Data contenedor = new XYChart.Data(fecha, nombre);
dotsArrayList.add(contenedor);
LegendItems.nombre = nombre;
contenedor.setExtraValue(extraValue);
}
}
} catch (ParseException e) {
e.printStackTrace();
System.out.println("hubo un problema con el json");
}
}
public static Integer getNumberOfContainers(){
Integer numberOfContainers = 0;
try {
JSONParser parser = new JSONParser();
// get the data
String urlJSON = ContenedoresChart.fullJSON;
JSONObject JSON_obj = (JSONObject) JSONValue.parseWithException(urlJSON);
numberOfContainers = Integer.parseInt(String.valueOf(JSON_obj.get("numberofcontainers")));
} catch (ParseException e) {
e.printStackTrace();
System.out.println("hubo un problema con el json");
}
return numberOfContainers;
}
}
LegendItems.java
public class LegendItems {
static String nombre = "";
static XYChart.Series vacio_series = new XYChart.Series();
static XYChart.Series lleno_series = new XYChart.Series();
public static void setItems(LineChart<Number, String> sc){
vacio_series.setName("Contenedor Vacio");
vacio_series.getData().add(new XYChart.Data(-1, nombre));
sc.getData().add(vacio_series);
lleno_series.setName("Contenedor Lleno");
lleno_series.getData().add(new XYChart.Data(-1, nombre));
sc.getData().add(lleno_series);
}
public static void setTransparent(){
lleno_series.getNode().setVisible(false);
vacio_series.getNode().setVisible(false);
}
public static void setLegendStyle(LineChart<Number, String> chart){
Set<Node> items = chart.lookupAll("Label.chart-legend-item");
int i = 0;
// these colors came from caspian.css .default-color0..4.chart-pie
Color[] colors = {Color.web("#808080")};
for (Node item : items) {
Label label = (Label) item;
final Rectangle rectangle = new Rectangle(13, 13, colors[0]);
final Circle circle = new Circle(10, 10, 7);
final Glow niceEffect = new Glow();
niceEffect.setInput(new Reflection());
circle.setEffect(niceEffect);
circle.setFill(colors[0]);
rectangle.setEffect(niceEffect);
if(i == 0){
label.setGraphic(circle);
} else {label.setGraphic(rectangle);}
i++;
}
}
}
SeparateContenedores.java
public class SeparateContenedores {
static ArrayList<String> arrayOfNames = new ArrayList<>();
static int numberOfContainers = 0;
public static void loadNames(){
try {
ContainerNames.loadNames();
JSONParser parser = new JSONParser();
//set the value of number of containers
String urlJSON = ContenedoresChart.fullJSON;
JSONObject JSON_obj = (JSONObject) JSONValue.parseWithException(urlJSON);
numberOfContainers = Integer.parseInt((String.valueOf(JSON_obj.get("numberofcontainers"))));
//set the value of the names of containers
JSONObject namesArray = (JSONObject) JSON_obj.get("namesofcontainers");
arrayOfNames.clear();
for(int x=0; x<namesArray.size(); x++){
arrayOfNames.add(String.valueOf(namesArray.get(ContainerNames.names.get(x))));
}
} catch (ParseException e) {
e.printStackTrace();
System.out.println("hubo un problema con el json");
}
}
public static void loadDots(LineChart<Number, String> sc){
loadNames();
DotsArrays.loadDots();
for(int x=0; x<DotsArrays.arrayOfContainers.size(); x++){
XYChart.Series series = new XYChart.Series();
series.setName("hide");
DrawDots.drawJSONdots(DotsArrays.arrayOfContainers.get(x),series);
sc.getData().add(series);
}
}
}
ContainerNames.java
public class ContainerNames {
static ArrayList<String> names = new ArrayList<>();
public static void loadNames(){
names.clear();
for(int x=1; x<=JSON_Reader.getNumberOfContainers(); x++){
names.add("container"+x);
}
}
}
SetRefreshRate.java
public static void setRefreshRate(Stage primaryStage, int segundos){
Task task = new Task<Void>() {
@Override
public Void call() throws Exception {
int i = 0;
while (true) {
final int finalI = i;
Platform.runLater(new Runnable() {
@Override
public void run() {
NumberAxis xAxis = new NumberAxis();
CategoryAxis yAxis = new CategoryAxis();
LineChart<Number, String> sc = new
LineChart<>(xAxis,yAxis);
Get_JSON_String.getJSONString();
primaryStage.setTitle("Ferroservicios");
DateFormatter.dateFormatter(xAxis);
xAxis.setLabel("Fecha");
yAxis.setLabel("Contenedores");
sc.setTitle("Eventos de Contenedores");
SeparateContenedores.loadDots(sc);
//sc.setLegendVisible(false);
SetTooltip.setTooltip();
SetTooltip.setSeriesStyle(sc);
LegendItems.setItems(sc);
LegendItems.setTransparent();
Legend legend = (Legend)sc.lookup(".chart-legend");
legend.getItems().removeIf(item->item.getText().equals("hide"));
Scene scene = new Scene(sc, 800, 600);
if(finalI > 2){
primaryStage.close();
primaryStage.setMaximized(true);
primaryStage.setScene(scene);
primaryStage.show();
LegendItems.setLegendStyle(sc);
}
}
});
i++;
Thread.sleep(segundos*1000);
}
}
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
}
}
SetTooltip.java
public class SetTooltip {
public static void setTooltipProperties(ArrayList<XYChart.Data> array){
for(int x = 0; x<array.size();x++){
StringBuilder sb = new StringBuilder();
Tooltip tooltip = new Tooltip();
tooltip.setMaxWidth(300);
tooltip.setWrapText(true);
hackTooltipStartTiming(tooltip);
tooltip.setText(array.get(x).getExtraValue().toString());
Tooltip.install(array.get(x).getNode(), tooltip);
boolean confirmado = array.get(x).getExtraValue().toString().contains("Confirmado: SI");
boolean vacio_lleno = array.get(x).getExtraValue().toString().contains("Vacio/Lleno: LLENO");
/*if(array.get(x).getExtraValue().toString().contains("Confirmado: SI")){
array.get(x).getNode().setStyle("-fx-background-color: #a9e200, #95c604;");
}
else {array.get(x).getNode().setStyle("-fx-background-color: #f1003c, #ae0000;\n" + "-fx-background-radius: 0;");}*/
sb.append(createConfirmadoStyleString(confirmado));
sb.append(createVacioLlenoStyleString(vacio_lleno));
array.get(x).getNode().setStyle(sb.toString());
//System.out.println(sb.toString());
}
}
public static String createConfirmadoStyleString(boolean confirmado){
StringBuilder sb = new StringBuilder();
if(confirmado){
sb.append("-fx-background-color: #a9e200, #95c604;\n");
} else {sb.append("-fx-background-color: #f1003c, #ae0000;\n");}
String cssStyle = sb.toString();
return cssStyle;
}
public static String createVacioLlenoStyleString(boolean vacio_lleno){
StringBuilder sb = new StringBuilder();
if(vacio_lleno){
sb.append("-fx-background-radius: 0;\n -fx-padding: 5px;");
}
String cssStyle = sb.toString();
return cssStyle;
}
public static void setTooltip(){
for(int x=0; x<DotsArrays.arrayOfContainers.size(); x++){
setTooltipProperties(DotsArrays.arrayOfContainers.get(x));
}
}
public static void setSeriesStyle(LineChart<Number, String> sc){
Set<Node> nodes = sc.lookupAll((".chart-series-line")); // series0 is the style class for first series
for (Node n : nodes) {
n.setStyle("-fx-stroke: black;\n" +
" -fx-stroke-width: 1px;\n" +
" -fx-effect: dropshadow( two-pass-box , rgba(0,0,0,0.3) , 8, 0.0 , 0 , 3 );");
}
}
}