Package azkaban.workflow.flow

Source Code of azkaban.workflow.flow.SugiyamaLayout$Node

/*
* Copyright 2010 LinkedIn, Inc
*
* 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 azkaban.workflow.flow;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import azkaban.workflow.Flow;
import azkaban.workflow.flow.FlowNode;

public class SugiyamaLayout extends DagLayout {
  HashMap<Integer, ArrayList<Node>> levelMap = new HashMap<Integer, ArrayList<Node>>();
  LinkedHashMap<String, JobNode> nodesMap = new LinkedHashMap<String, JobNode>();
 
  public static final float LEVEL_HEIGHT = 120;
  public static final float LEVEL_WIDTH = 80;
  public static final float LEVEL_WIDTH_ADJUSTMENT = 5;
 
  public SugiyamaLayout(Flow flow) {
    super(flow);
  }
 
  public void setLayout() {
    nodesMap.clear();
    int longestWord = 0;
    for(FlowNode flowNode : flow.getFlowNodes()) {
      longestWord = Math.max(flowNode.getAlias().length(), longestWord);
      nodesMap.put(flowNode.getAlias(), new JobNode(flowNode));
    }
   
    for(JobNode jobNode : nodesMap.values()) {
      layerNodes(jobNode);
    }
   
    // Re-arrange top down!
    int size = levelMap.size();
    ArrayList<Node> list = levelMap.get(0);
    float count = 0;
    for (Node node: list) {
      node.setPosition(count);
      count +=1;
    }
    for (int i = 1; i < size; ++i) {
      //barycenterMethodUncross(levelMap.get(i), true);
      barycenterMethodUncross(levelMap.get(i));
   
   
    float widthAdjustment = LEVEL_WIDTH + longestWord*LEVEL_WIDTH_ADJUSTMENT;
    // Adjust level
    for (Map.Entry<Integer, ArrayList<Node>> entry: levelMap.entrySet()) {
      ArrayList<Node> nodes = entry.getValue();
      Integer level = entry.getKey();
     
      float offset = -((float)nodes.size()/2);
      for (Node node: nodes) {
        if (node instanceof JobNode) {
          FlowNode flowNode = ((JobNode) node).getFlowNode();
          flowNode.setPosition(offset*widthAdjustment, level*LEVEL_HEIGHT);
        }

        offset += 1;
      }
     
    }
   
    flow.setLayedOut(true);
  }
 
  private void uncrossLayer(ArrayList<Node> free, boolean topDown) {
    // Using median method
    if (topDown) {
      for (Node node: free) {
        float median = getMedian(node.getDependencies());
        System.out.println("getMedian " + median);
        node.setPosition(median);
      }
    }
    else {
      for (Node node: free) {
        float median = getMedian(node.getDependents());
        //System.out.println("getMedian " + median);
        node.setPosition(median);
      }
    }
   
    Collections.sort(free);
  }
 
  private void barycenterMethodUncross(ArrayList<Node> free) {
    int numOnLevel = free.size();
    for (Node node: free) {
      float average = findAverage(node.getDependencies());
      node.setPosition(average);
      node.setNumOnLevel( numOnLevel );
    }
 
    Collections.sort(free);
    reorder(free);
  }
 
  private void reorder(ArrayList<Node> nodes) {
    int count = 1;
    for (int i = 0; i < nodes.size(); ++i) {
      Node node = nodes.get(i);
      node.setPosition(i);
    }
  }
 
  private float findAverage(List<Node> nodes) {
    float sum = 0;
    for (Node node : nodes) {
      sum += node.getPosition();
    }
   
    return sum/(nodes.size());
  }
 
  private float getMedian(List<Node> dependents) {
    int length = dependents.size();
    if (length == 0) {
      return 0;
    }
   
    float[] position = new float[length];
    int i = 0;
    for (Node dep: dependents) {
      position[i] = dep.getPosition();
      ++i;
    }
   
    Arrays.sort(position);
    int index = position.length / 2;
    if ((length % 2) == 1) {
      return position[index];
    }
    else {
      return (position[index-1] + position[index])/2;
    }
  }
 
  private void layerNodes(JobNode node) {
    FlowNode flowNode = node.getFlowNode();
    int level = node.getLevel();

    ArrayList<Node> levelList = levelMap.get(level);
    if (levelList == null) {
      levelList = new ArrayList<Node>();
      levelMap.put(level, levelList);
    }
   
    levelList.add(node);
   
    for (String dep : flowNode.getDependents() ) {
      JobNode depNode = nodesMap.get(dep);
      if (depNode.getLevel() - node.getLevel() > 1) {
        addDummyNodes(node, depNode);
      }
      else {
        depNode.addDependecy(node);
        node.addDependent(depNode);
      }
    }
  }
 
  private void addDummyNodes(JobNode from, JobNode to) {
    int fromLevel = from.getLevel();
    int toLevel = to.getLevel();
   
    Node fromNode = from;
    for (int i = fromLevel+1; i < toLevel; ++i) {
      DummyNode dummyNode = new DummyNode(i);
     
      ArrayList<Node> levelList = levelMap.get(i);
      if (levelList == null) {
        levelList = new ArrayList<Node>();
        levelMap.put(i, levelList);
      }
      levelList.add(dummyNode);
     
      dummyNode.addDependecy(fromNode);
      fromNode.addDependent(dummyNode);
      fromNode = dummyNode;
    }
   
    to.addDependecy(from);
    fromNode.addDependent(to);
  }
 
  private class Node implements Comparable {
    private List<Node> dependents = new ArrayList<Node>();
    private List<Node> dependencies = new ArrayList<Node>();
    private float position = 0;
    private int numOnLevel = 0;
   
    public void addDependent(Node dependent) {
      dependents.add(dependent);
    }
   
    public void addDependecy(Node dependency) {
      dependencies.add(dependency);
    }
   
    public List<Node> getDependencies() {
      return dependencies;
    }
   
    public List<Node> getDependents() {
      return dependents;
    }
   
    public float getPosition() {
      return position;
    }
   
    private void setPosition(float pos) {
      position = pos;
    }

    @Override
    public int compareTo(Object arg0) {
      // TODO Auto-generated method stub
      Node other = (Node)arg0;
      Float pos = position;
     
      int comp = pos.compareTo(other.position);
      if ( comp == 0) {
        // Move larger # one to center.
        //int midpos = numOnLevel / 2;
       
       
//        // First priority... # of out nodes.
//        if (this.dependents.size() > other.dependents.size()) {
//          return 1;
//        }
//        else if (this.dependents.size() < other.dependents.size()) {
//          return -1;
//        }
//       
//        // Second priority... # of out nodes
//        if (this.dependencies.size() > other.dependencies.size()) {
//          return 1;
//        }
//        else if (this.dependencies.size() < other.dependencies.size()) {
//          return -1;
//        }
//       
//        if (this instanceof DummyNode) {
//          if (arg0 instanceof DummyNode) {
//            return 0;
//          }
//          return -1;
//        }
//        else if (arg0 instanceof DummyNode){
//          return 1;
//        }
      }
     
      return comp;
    }

    public void setNumOnLevel(int numOnLevel) {
      this.numOnLevel = numOnLevel;
    }

    public int getNumOnLevel() {
      return numOnLevel;
    }
   
  }
 
  private class JobNode extends Node {
    private FlowNode flowNode;
    public JobNode(FlowNode flowNode) {
      this.flowNode = flowNode;
    }
   
    public FlowNode getFlowNode() {
      return flowNode;
    }
   
    public int getLevel() {
      return flowNode.getLevel();
    }
  }
 
  private class DummyNode extends Node {
    private int level = 0;
    public DummyNode(int level) {
      this.level = level;
    }
  }
 
  public class LayoutData {
    final FlowNode flowNode;
    public LayoutData(FlowNode flow) {
      flowNode = flow;
    }
  }
}
TOP

Related Classes of azkaban.workflow.flow.SugiyamaLayout$Node

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.