Package de.scoopgmbh.copper.monitoring.client.ui.adaptermonitoring.result.animation

Source Code of de.scoopgmbh.copper.monitoring.client.ui.adaptermonitoring.result.animation.AdapterAnimationCreator$TimeValuePair

/*
* Copyright 2002-2013 SCOOP Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.scoopgmbh.copper.monitoring.client.ui.adaptermonitoring.result.animation;

import java.util.*;

import com.google.common.base.Optional;

import de.scoopgmbh.copper.monitoring.client.ui.adaptermonitoring.result.AdapterCallRowModel;
import de.scoopgmbh.copper.monitoring.client.ui.adaptermonitoring.result.AdapterLaunchRowModel;
import de.scoopgmbh.copper.monitoring.client.ui.adaptermonitoring.result.AdapterNotifyRowModel;
import javafx.animation.Animation.Status;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontSmoothingType;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.util.Duration;

public class AdapterAnimationCreator {
 
  public long FADEDURATION=300;
  public long MOVEDURATION=1600;
  public long DEFAULT_TOTAL_ANNIMATION_TIME=FADEDURATION+MOVEDURATION+FADEDURATION;
 

  private long min;
 
    public long getMin() {
    return min;
  }
  public void setMin(long min) {
    this.min = min;
  }
 
  Pane animationPane;
  Timeline timeline;
  private ArrayList<AnimationPartBase> animations;
 
  public AdapterAnimationCreator(Pane animationPane, Timeline timeline) {
    super();
    this.animationPane = animationPane;
    this.timeline = timeline;
  }
 
 
  private Optional<AnimationPartBase> searchAnimationRunningAt(String id, long startTime, long endTime){
    AnimationPartBase result=null;
    for (AnimationPartBase animation: animations){
      if (animation.id.equals(id) && !(endTime<animation.startTime || startTime>animation.endTime)){
        result=animation;
        break;
      }
    }
    return Optional.fromNullable(result);
  }
 
  private List<AnimationPartBase> searchAnimationWithType(Class<? extends AnimationPartBase> clazz, long startTime, long endTime){
    List<AnimationPartBase> result=new ArrayList<AnimationPartBase>();
    for (AnimationPartBase animation: animations){
      if (animation.getClass()==clazz && !(endTime<animation.startTime || startTime>animation.endTime)){
        result.add(animation);
      }
    }
    return result;
  }
 
  private void addAdapterAnimation(String adapterName, long time){
    Optional<AnimationPartBase> animationOpt =  searchAnimationRunningAt(adapterName, time, time + DEFAULT_TOTAL_ANNIMATION_TIME);
    if (animationOpt.isPresent()){
      animationOpt.get().endTime=time+DEFAULT_TOTAL_ANNIMATION_TIME;
    } else {
      Optional<Double> ypos = getFreeYslot(time, time+DEFAULT_TOTAL_ANNIMATION_TIME, AdapterAnimation.ADAPTER_HEIGHT+20,false,Arrays.<Class<? extends AnimationPartBase>>asList(AdapterAnimation.class));
      if (ypos.isPresent()){
        double xpos = animationPane.getWidth()/2- AdapterAnimation.ADAPTER_WIDTH/2;
       
        animations.add(new AdapterAnimation(new AnimationPartParameter(time, time + DEFAULT_TOTAL_ANNIMATION_TIME, adapterName,
                        xpos,
                        ypos.get(),
                        xpos,
                        ypos.get())));
      }
    }
  }
 
  private Optional<Double> getFreeYslot(long starttime, long endtime,  double slotHeight, boolean useEndPos, List<Class<? extends AnimationPartBase>>  types){
    final List<AnimationPartBase> foundAnimations = new ArrayList<AnimationPartBase>();
    for (Class<? extends AnimationPartBase> type: types){
      foundAnimations.addAll(searchAnimationWithType(type, starttime, endtime));
    }
    for (int i=0;i<20;i++){
      double ypos = 65+(slotHeight)*i;
      boolean posInlist=false;
      for (AnimationPartBase animation: foundAnimations){
        if (useEndPos){
          if (Math.abs(animation.endy-ypos)<0.0001){
            posInlist=true;
          }
        } else {
          if (Math.abs(animation.starty-ypos)<0.0001){
            posInlist=true;
          }
        }
      }
      if (!posInlist){
        return Optional.of(ypos);
      }
    }
    return Optional.absent();
  }

 
  private void addNotifyEventAnimation(long time, String id, String adapterId){
    Optional<Double> ypos = getFreeYslot(time,time+DEFAULT_TOTAL_ANNIMATION_TIME,60,true,Arrays.<Class<? extends AnimationPartBase>>asList(NotifyAnimation.class,LaunchAnimation.class));
    if (ypos.isPresent()){
      Optional<AnimationPartBase> adapterAnimation =  searchAnimationRunningAt(adapterId, time, time + DEFAULT_TOTAL_ANNIMATION_TIME);
      if (adapterAnimation.isPresent()){
        animations.add(new NotifyAnimation(createOutputParameter(time, id, ypos, adapterAnimation)));
      }
    }
  }
  private AnimationPartParameter createOutputParameter(long time, String id, Optional<Double> ypos,
      Optional<AnimationPartBase> adapterAnimation) {
    return new AnimationPartParameter(time, time+DEFAULT_TOTAL_ANNIMATION_TIME,id,
        adapterAnimation.get().startx+ AdapterAnimation.ADAPTER_WIDTH/2- EventAnimationBase.EVENT_WIDTH/2,
        adapterAnimation.get().starty+ AdapterAnimation.ADAPTER_HEIGHT- EventAnimationBase.EVENT_HEIGHT-5,
        getAnimationPaneWidth()/2+ getAnimationPaneWidth()/4- EventAnimationBase.EVENT_WIDTH/2,
        ypos.get());
  }
 
  private void addLaunchEventAnimation(long time, String id, String adapterId){
    Optional<Double> ypos = getFreeYslot(time,time+DEFAULT_TOTAL_ANNIMATION_TIME,60,true,Arrays.<Class<? extends AnimationPartBase>>asList(NotifyAnimation.class,LaunchAnimation.class));
    if (ypos.isPresent()){
      Optional<AnimationPartBase> adapterAnimation =  searchAnimationRunningAt(adapterId, time, time + DEFAULT_TOTAL_ANNIMATION_TIME);
      if (adapterAnimation.isPresent()){
        animations.add(new LaunchAnimation(createOutputParameter(time, id, ypos, adapterAnimation)));
      }
    }
  }
 
  private void addCallEventAnimation(long time, String id, String adapterId, String workflowInstanceId){
    double ypos = searchAnimationRunningAt(workflowInstanceId, time, time + DEFAULT_TOTAL_ANNIMATION_TIME).get().starty+5;

    Optional<AnimationPartBase> adapterAnimation = searchAnimationRunningAt(adapterId, time, time + DEFAULT_TOTAL_ANNIMATION_TIME);
    Optional<AnimationPartBase> sameCallAnimation = searchAnimationRunningAt(id, time, time + 20);
    if (adapterAnimation.isPresent()){
      if (sameCallAnimation.isPresent()){
        ((CallAnimation)sameCallAnimation.get()).count++;
      } else {
        animations.add(new CallAnimation(new AnimationPartParameter(time, time + DEFAULT_TOTAL_ANNIMATION_TIME, id,
                        getAnimationPaneWidth() / 2 - getAnimationPaneWidth() / 4,
                        ypos,
                        adapterAnimation.get().startx + AdapterAnimation.ADAPTER_WIDTH / 2 - EventAnimationBase.EVENT_WIDTH / 2,
                        adapterAnimation.get().starty + 5)));
      }
    }
  }
 

  private class TimeValuePair<T>{
    long time;
    T value;
    public TimeValuePair(T value, long time) {
      super();
      this.time = time;
      this.value = value;
    }
  }
 
  public void create(
        ObservableList<AdapterCallRowModel> adapterInput,
        ObservableList<AdapterLaunchRowModel> adapterOutputLaunch,
        ObservableList<AdapterNotifyRowModel> adapterOutputNotify){

   
    animations = new ArrayList<AnimationPartBase>();

      min = Long.MAX_VALUE;
    for (final AdapterCallRowModel adapterCallRowModel: adapterInput){
      min = Math.min(min, adapterCallRowModel.timestamp.get().getTime()-DEFAULT_TOTAL_ANNIMATION_TIME);
    }
    for (final AdapterLaunchRowModel adapterLaunchRowModel: adapterOutputLaunch){
      min = Math.min(min, adapterLaunchRowModel.timestamp.get().getTime());
    }
    for (final AdapterNotifyRowModel adapterNotifyRowModel: adapterOutputNotify){
      min = Math.min(min, adapterNotifyRowModel.timestamp.get().getTime());
    }
   
   
   
    ArrayList<TimeValuePair<String>> timeAdapterPairs = new ArrayList<TimeValuePair<String>>();
    for (final AdapterCallRowModel adapterCallRowModel: adapterInput){
      final long time = adapterCallRowModel.timestamp.get().getTime()-DEFAULT_TOTAL_ANNIMATION_TIME;
      timeAdapterPairs.add(new TimeValuePair<String>(adapterCallRowModel.adapterName.get(),time));
      addWorkflowAnimation(adapterCallRowModel.workflowClassCaller.get(), adapterCallRowModel.workflowInstanceIdCaller.get(), time);
    }
    for (final AdapterLaunchRowModel adapterLaunchRowModel: adapterOutputLaunch){
      final long time = adapterLaunchRowModel.timestamp.get().getTime();
      timeAdapterPairs.add(new TimeValuePair<String>(adapterLaunchRowModel.adapterName.get(),time));
    }
    for (final AdapterNotifyRowModel adapterNotifyRowModel: adapterOutputNotify){
      final long time = adapterNotifyRowModel.timestamp.get().getTime();
      timeAdapterPairs.add(new TimeValuePair<String>(adapterNotifyRowModel.adapterName.get(),time));
    }
    Collections.sort(timeAdapterPairs, new Comparator<TimeValuePair<String>>(){
      @Override
      public int compare(TimeValuePair<String> o1, TimeValuePair<String> o2) {
        //TODO replace when switch to java 1.7 with: Long.compare(o1.time, o2.time);
        return Long.valueOf(o1.time).compareTo(Long.valueOf(o2.time));
      }
    });
    for (TimeValuePair<String> timeAdapterPair: timeAdapterPairs){
      addAdapterAnimation(timeAdapterPair.value, timeAdapterPair.time);
    }
   

   

    addStaticContent();
   
   
    for (final AdapterCallRowModel adapterCallRowModel: adapterInput){
      addCallEventAnimation(
                    adapterCallRowModel.timestamp.get().getTime() - DEFAULT_TOTAL_ANNIMATION_TIME,
                    adapterCallRowModel.method.get(),
                    adapterCallRowModel.adapterName.get(),
                    adapterCallRowModel.workflowInstanceIdCaller.get());
    }

   
    ArrayList<TimeValuePair<Object>> outputsSorted = new ArrayList<TimeValuePair<Object>>();
    for (final AdapterLaunchRowModel adapterLaunchRowModel: adapterOutputLaunch){
      outputsSorted.add(new TimeValuePair<Object>(adapterLaunchRowModel, adapterLaunchRowModel.timestamp.get().getTime()));
    }
    for (final AdapterNotifyRowModel adapterNotifyRowModel: adapterOutputNotify){
      outputsSorted.add(new TimeValuePair<Object>(adapterNotifyRowModel, adapterNotifyRowModel.timestamp.get().getTime()));
    }
    Collections.sort(outputsSorted, new Comparator<TimeValuePair<Object>>(){
      @Override
      public int compare(TimeValuePair<Object> o1, TimeValuePair<Object> o2) {
        //TODO replace when switch to java 1.7 with: Long.compare(o1.time, o2.time);
        return Long.valueOf(o1.time).compareTo(Long.valueOf(o2.time));
      }
    });
    for (TimeValuePair<Object> output: outputsSorted){
      if (output.value instanceof AdapterLaunchRowModel){
        AdapterLaunchRowModel adapterLaunchRowModel = (AdapterLaunchRowModel)output.value;
        addLaunchEventAnimation(
                        adapterLaunchRowModel.timestamp.get().getTime(),
                        adapterLaunchRowModel.workflowname.get(),
                        adapterLaunchRowModel.adapterName.get());
      }
      if (output.value instanceof AdapterNotifyRowModel){
        AdapterNotifyRowModel adapterNotifyRowModel = (AdapterNotifyRowModel)output.value;
        addNotifyEventAnimation(
                        adapterNotifyRowModel.timestamp.get().getTime(),
                        adapterNotifyRowModel.correlationId.get(),
                        adapterNotifyRowModel.adapterName.get());
      }
    }
   
   
   
   
   
    ArrayList<KeyFrame> keyFrames = new ArrayList<KeyFrame>();//Performance optimization adding single keyframes directly is too slow
    for (AnimationPartBase animation: animations){
      addAnimation(keyFrames, animation, min);
    }
    timeline.getKeyFrames().addAll(keyFrames);
    }
   
  private void addWorkflowAnimation(String workflowClass, String workflowInstanceId, long time) {
    Optional<AnimationPartBase> animationOpt = searchAnimationRunningAt(workflowInstanceId, time, time + DEFAULT_TOTAL_ANNIMATION_TIME);
    if (animationOpt.isPresent()){
      animationOpt.get().endTime=time+DEFAULT_TOTAL_ANNIMATION_TIME;
    } else {
      Optional<Double> ypos = getFreeYslot(time, time+DEFAULT_TOTAL_ANNIMATION_TIME, EventAnimationBase.EVENT_HEIGHT+15+35,false,Arrays.<Class<? extends AnimationPartBase>>asList(WorkflowAnimation.class));
      if (ypos.isPresent()){
        double xpos = animationPane.getWidth()/2- animationPane.getWidth()/4- WorkflowAnimation.WIDTH/2;
       
        animations.add(new WorkflowAnimation(workflowClass, new AnimationPartParameter(time, time + DEFAULT_TOTAL_ANNIMATION_TIME, workflowInstanceId,
                        xpos,
                        ypos.get(),
                        xpos,
                        ypos.get())));
      }
    }
  }
  private void createLegend(){
    VBox pane = new VBox();
//    pane.setScaleX(0.5);
//    pane.setScaleY(0.5);
    pane.getChildren().add(new Label("Legend"));
    pane.getChildren().add(createLegendEntry("adapter", AdapterAnimation.ADAPTER_COLOR));
    pane.getChildren().add(createLegendEntry("adapter method call", CallAnimation.ADAPTER_CALL_COLOR));
    pane.getChildren().add(createLegendEntry("notify correlation id ", NotifyAnimation.ADAPTER_NOTIFY_COLOR));
    pane.getChildren().add(createLegendEntry("workflow launch", LaunchAnimation.ADAPTER_LAUNCH_COLOR));
    pane.getChildren().add(createLegendEntry("workflow instance", WorkflowAnimation.WORKFLOW_COLOR));
    pane.setStyle("-fx-border-color: black; -fx-border-width: 1;");
    pane.setTranslateX(3);
    pane.setTranslateY(animationPane.getHeight()-150);
    animationPane.getChildren().add(pane);
   
  }
 
  private Node createLegendEntry(String text, Color color){
    HBox hbox = new HBox();
    hbox.setAlignment(Pos.CENTER_LEFT);
    hbox.setSpacing(3);
    hbox.getChildren().add(new Rectangle(15,15,color));
    hbox.getChildren().add(new Label(text));
    VBox.setMargin(hbox, new Insets(1.5,3,1.5,3));
    return hbox;
  }
   
    private void addStaticContent() {
      createLegend();
  
    final Text inputText = new Text("Input");
    inputText.setX(getAnimationPaneWidth()/2- getAnimationPaneWidth()/4-inputText.getBoundsInLocal().getWidth()/2);
    inputText.setY(20);
    inputText.setFont(Font.font(Font.getDefault().getName(), FontWeight.BOLD, Font.getDefault().getSize()));
    inputText.setFontSmoothingType(FontSmoothingType.LCD);
    animationPane.getChildren().add(inputText);
   
    final Text outputText = new Text("Output");
    outputText.setX(getAnimationPaneWidth()/2+ getAnimationPaneWidth()/4-outputText.getBoundsInLocal().getWidth()/2);
    outputText.setY(20);
    outputText.setFont(Font.font(Font.getDefault().getName(), FontWeight.BOLD, Font.getDefault().getSize()));
    outputText.setFontSmoothingType(FontSmoothingType.LCD);
    animationPane.getChildren().add(outputText);
   
    final Text adapterText = new Text("Adapter");
    adapterText.setX(getAnimationPaneWidth()/2-adapterText.getBoundsInLocal().getWidth()/2);
    adapterText.setTranslateY(20);
    adapterText.setFont(Font.font(Font.getDefault().getName(), FontWeight.BOLD, Font.getDefault().getSize()));
    adapterText.setFontSmoothingType(FontSmoothingType.LCD);
    animationPane.getChildren().add(adapterText);
   
    Line lineInput = new Line();
    lineInput.getStrokeDashArray().addAll(5d);
    lineInput.setCache(true);
    lineInput.startXProperty().set(getAnimationPaneWidth()/2- getAnimationPaneWidth()/8);
    lineInput.endXProperty().set(lineInput.startXProperty().get());
    lineInput.startYProperty().set(0);
    lineInput.endYProperty().bind(animationPane.heightProperty());
    animationPane.getChildren().add(lineInput);
   
    Line lineOutput = new Line();
    lineOutput.getStrokeDashArray().addAll(5d);
    lineOutput.setCache(true);
    lineOutput.startXProperty().set(getAnimationPaneWidth() / 2 + getAnimationPaneWidth() / 8);
    lineOutput.endXProperty().set(lineOutput.startXProperty().get());
    lineOutput.startYProperty().set(0);
    lineOutput.endYProperty().bind(animationPane.heightProperty());
    animationPane.getChildren().add(lineOutput);
   
  }

  private void addAnimation(ArrayList<KeyFrame> keyFrames, final AnimationPartBase annimation, long minTime){
    long startTimeMs = annimation.startTime-minTime;
    long endTimeMs = annimation.endTime-minTime;
   
    final Node node = annimation.createVisualRepresentation();
   
    KeyValue keyValueStartX = new KeyValue(node.translateXProperty(), annimation.startx);
    KeyValue keyValueStartY = new KeyValue(node.translateYProperty(), annimation.starty);
    KeyValue keyValueEndX = new KeyValue(node.translateXProperty(),annimation.endx);
    KeyValue keyValueEndY = new KeyValue(node.translateYProperty(), annimation.endy);
   

    KeyFrame keyFrame1 = new KeyFrame(Duration.millis(startTimeMs),
          new EventHandler<ActionEvent>(){
            @Override
            public void handle(ActionEvent event) {
              animationPane.getChildren().add(node);
            }
              },new KeyValue(node.opacityProperty(), 0));
    KeyFrame keyFrame2 = new KeyFrame(Duration.millis(startTimeMs), keyValueStartX, keyValueStartY);
    KeyFrame keyFrame3 = new KeyFrame(Duration.millis(startTimeMs+FADEDURATION),new KeyValue(node.opacityProperty(), 1));
    KeyFrame keyFrame4 = new KeyFrame(Duration.millis(startTimeMs+FADEDURATION), keyValueStartX, keyValueStartY);
    KeyFrame keyFrame5 = new KeyFrame(Duration.millis(endTimeMs-FADEDURATION),keyValueEndX,keyValueEndY);
    KeyFrame keyFrame6 = new KeyFrame(Duration.millis(endTimeMs-FADEDURATION), new KeyValue(node.opacityProperty(), 1));
    KeyFrame keyFrame7 = new KeyFrame(Duration.millis(endTimeMs),
        new EventHandler<ActionEvent>(){
          @Override
          public void handle(ActionEvent event) {
            animationPane.getChildren().remove(node);
          }
            },new KeyValue(node.opacityProperty(), 0));
   
   
    keyFrames.add(keyFrame1);
    keyFrames.add(keyFrame2);
    keyFrames.add(keyFrame3);
    keyFrames.add(keyFrame4);
    keyFrames.add(keyFrame5);
    keyFrames.add(keyFrame6);
    keyFrames.add(keyFrame7);
   
    timeline.statusProperty().addListener(new ChangeListener<Status>() {
      @Override
      public void changed(ObservableValue<? extends Status> observable, Status oldValue, Status newValue) {
        if (newValue==Status.STOPPED){//clean up when animation stopped
          animationPane.getChildren().remove(node);
        }
      }
    });
  }

  private double getAnimationPaneWidth(){
    return animationPane.getWidth();
  }

}
TOP

Related Classes of de.scoopgmbh.copper.monitoring.client.ui.adaptermonitoring.result.animation.AdapterAnimationCreator$TimeValuePair

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.