/*
* Copyright (c) 2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.carbon.bpel.ui.bpel2svg;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Manage the whole layout of the SVG graph
*/
public class LayoutManager {
// Variables
// Properties
private int svgWidth = 2800;
private int svgHeight = 3000;
private int xSpacing = 50;
private int ySpacing = 70;
private boolean includeAssigns = true;
private boolean showSequenceBoxes = true;
private boolean verticalLayout = false;
private boolean addCompositeActivityOpacity = false;
private boolean addIconOpacity = false;
private boolean addSimpleActivityOpacity = true;
private String iconOpacity = "0.25";
private String opacity = "0.50";
private String simpleActivityOpacity = "0.251";
private String compositeActivityOpacity = "0.10";
private int startIconDim = 50;
private int endIconDim = 50;
//Get Icon Width
private int iconWidth = 100;
private Map<ActivityInterface, ArrayList<ActivityInterface>> linkAdjacencyList;
private Set<ActivityInterface> rootLinks;
private int correctionCumulation = 0;
private int hieghestCorrectionCumulation = 0;
/**
* Gets the width of the SVG graph
*
* @return width of the SVG graph
*/
public int getSvgWidth() {
return svgWidth;
}
/**
* Sets the width of the SVG graph
*
* @param svgWidth width of the SVG graph
*/
public void setSvgWidth(int svgWidth) {
this.svgWidth = svgWidth;
}
/**
* Gets the height of the SVG graph
*
* @return height of the SVG graph
*/
public int getSvgHeight() {
return svgHeight;
}
/**
* Sets the height of the SVG graph
*
* @param svgHeight height of the SVG graph
*/
public void setSvgHeight(int svgHeight) {
this.svgHeight = svgHeight;
}
/**
* Gets the xSpacing which is added to the width of the activities when setting the dimensions
*
* @return xSpacing "50"
*/
public int getXSpacing() {
return xSpacing;
}
/**
* Sets the xSpacing which is added to the width of the activities when setting the dimensions
*
* @param xSpacing "50"
*/
public void setXSpacing(int xSpacing) {
this.xSpacing = xSpacing;
}
/**
* Gets the ySpacing which is added to the height of the activities when setting the dimensions
*
* @return ySpacing "70"
*/
public int getYSpacing() {
return ySpacing;
}
/**
* Sets the ySpacing which is added to the height of the activities when setting the dimensions
*
* @param ySpacing "70"
*/
public void setYSpacing(int ySpacing) {
this.ySpacing = ySpacing;
}
/**
* Gets the boolean value to include the assign activities
*
* @return boolean value to include the assign activities->true/false
*/
public boolean isIncludeAssigns() {
return includeAssigns;
}
/**
* Sets the boolean value to include the assign activities
*
* @param includeAssigns boolean value to include the assign activities
*/
public void setIncludeAssigns(boolean includeAssigns) {
this.includeAssigns = includeAssigns;
}
/**
* Gets the boolean value to show the Sequence box
*
* @return boolean value to show the the Sequence box->true/false
*/
public boolean isShowSequenceBoxes() {
return showSequenceBoxes;
}
/**
* Sets the boolean value to show the Sequence box
*
* @param showSequenceBoxes boolean value to show the the Sequence box->true/false
*/
public void setShowSequenceBoxes(boolean showSequenceBoxes) {
this.showSequenceBoxes = showSequenceBoxes;
}
/**
* Gets the boolean value to select the vertical layout
*
* @return boolean value to select the vertical layout -> true/false
*/
public boolean isVerticalLayout() {
return verticalLayout;
}
/**
* Sets the boolean value to select the vertical layout
*
* @param verticalLayout boolean value to select the vertical layout
*/
public void setVerticalLayout(boolean verticalLayout) {
this.verticalLayout = verticalLayout;
}
/**
* Gets true/false to add opacity to composite activity icons e.g:like IF, ELSE IF activities
*
* @return true/false
*/
public boolean isAddCompositeActivityOpacity() {
return addCompositeActivityOpacity;
}
/**
* Sets true/false to add opacity to composite activity icons
*
* @param addCompositeActivityOpacity boolean value to add opacity to composite activity icons
*/
public void setAddCompositeActivityOpacity(boolean addCompositeActivityOpacity) {
this.addCompositeActivityOpacity = addCompositeActivityOpacity;
}
/**
* Gets true/false to add opacity to activity icons
*
* @return true/false
*/
public boolean isAddIconOpacity() {
return addIconOpacity;
}
/**
* Sets true/false to add opacity to activity icons
*
* @param addIconOpacity boolean value to add opacity to activity icons
*/
public void setAddIconOpacity(boolean addIconOpacity) {
this.addIconOpacity = addIconOpacity;
}
/**
* Gets true/false to add opacity to simple activity icons e.g:like ASSIGN, THROW activities
*
* @return true/false
*/
public boolean isAddSimpleActivityOpacity() {
return addSimpleActivityOpacity;
}
/**
* Sets true/false to add opacity to simple activity icons
*
* @param addSimpleActivityOpacity boolean value to add opacity to simple activity icons
*/
public void setAddSimpleActivityOpacity(boolean addSimpleActivityOpacity) {
this.addSimpleActivityOpacity = addSimpleActivityOpacity;
}
/**
* Gets the icon opacity amount for composite activities
*
* @return String with the opacity "0.10"
*/
public String getCompositeActivityOpacity() {
return compositeActivityOpacity;
}
/**
* Sets the icon opacity amount for composite activities
*
* @param compositeActivityOpacity icon opacity amount for composite activities
*/
public void setCompositeActivityOpacity(String compositeActivityOpacity) {
this.compositeActivityOpacity = compositeActivityOpacity;
}
/**
* Gets the icon opacity amount for activities
*
* @return String with the opacity "0.25"
*/
public String getIconOpacity() {
return iconOpacity;
}
/**
* Sets the icon opacity amount for activities
*
* @param iconOpacity icon opacity amount for activities
*/
public void setIconOpacity(String iconOpacity) {
this.iconOpacity = iconOpacity;
}
/**
* Gets the icon opacity amount
*
* @return String with the opacity "0.5"
*/
public String getOpacity() {
return opacity;
}
/**
* Sets the icon opacity amount
*
* @param opacity icon opacity
*/
public void setOpacity(String opacity) {
this.opacity = opacity;
}
/**
* Gets the icon opacity amount for simple activities
*
* @return String with the opacity "0.251"
*/
public String getSimpleActivityOpacity() {
return simpleActivityOpacity;
}
/**
* Sets the icon opacity amount for simple activities
*
* @param simpleActivityOpacity icon opacity amount for simple activities
*/
public void setSimpleActivityOpacity(String simpleActivityOpacity) {
this.simpleActivityOpacity = simpleActivityOpacity;
}
/**
* Gets the dimensions of the start icon of the activity
*
* @return dimensions of the start icon of the activity
*/
public int getStartIconDim() {
return startIconDim;
}
/**
* Sets the dimensions of the start icon of the activity
*
* @param startIconDim dimensions of the start icon of the activity
*/
public void setStartIconDim(int startIconDim) {
this.startIconDim = startIconDim;
}
// Methods
/**
* Gets the dimensions of the end icon of the activity
*
* @return dimensions of the end icon of the activity
*/
public int getEndIconDim() {
return endIconDim;
}
/**
* Sets the dimensions of the end icon of the activity
*
* @param endIconDim dimensions of the end icon of the activity
*/
public void setEndIconDim(int endIconDim) {
this.endIconDim = endIconDim;
}
/**
* Gets the width of the rectangle/image holder which holds the activity icon
*
* @return icon width i.e. width of the rectangle/image holder which holds the activity icon
*/
public int getIconWidth() {
return iconWidth;
}
/**
* Sets the width of the rectangle/image holder which holds the activity icon
*
* @param iconWidth width of the rectangle/image holder which holds the activity icon
*/
public void setIconWidth(int iconWidth) {
this.iconWidth = endIconDim;
}
/**
* Layout the SVG
* Get the dimensions i.e. width and height of the root activity, set the links of the process if there are any
*
* @param rootActivity
*/
public void layoutSVG(ActivityInterface rootActivity) {
rootActivity.getDimensions();
layoutLinks(rootActivity);
rootActivity.layout(0, 0);
}
/**
* Get the Link Adjacency List for a process (Map which contains the Source and Target activities for links )
*
* @param links
* @return
*/
private Map<ActivityInterface, ArrayList<ActivityInterface>> getLinkAdjacencyList(Map<String, Link> links) {
Map<ActivityInterface, ArrayList<ActivityInterface>> linkAdjacencyList =
new HashMap<ActivityInterface, ArrayList<ActivityInterface>>();
//Checks whether they are any links in the bpel process
if (links != null && !links.isEmpty()) {
//Returns a set view of the mappings contained in the links map
Set linksSet = links.entrySet();
//Iterates through each element in the set
Iterator linksIterator = linksSet.iterator();
while (linksIterator.hasNext()) {
Map.Entry<String, Link> link = (Map.Entry<String, Link>) linksIterator.next();
//Gets the Source/Start activity of the link
ActivityInterface startActivity = link.getValue().getSource();
//Gets the Target/End activity of the link
ActivityInterface endActivity = link.getValue().getTarget();
//Checks whether the AdjacencyList contains the Source/Start activity of the link(key)
if (linkAdjacencyList.containsKey(startActivity)) {
//Get the Source/Start activity(key) and append the Target/End activity(value)
linkAdjacencyList.get(startActivity).add(endActivity);
} else {
//If the AdjacencyList doesn't contain the Source/Start activity of the link
ArrayList<ActivityInterface> tmpArrayList = new ArrayList<ActivityInterface>();
//Add the Target/End activity to the temp arraylist
tmpArrayList.add(endActivity);
//Include the Source/Start activity and the temp arraylist which contains the Target/End activity
linkAdjacencyList.put(startActivity, tmpArrayList);
}
}
}
return linkAdjacencyList;
}
/**
* Set the yTop position of the Target activities
*
* @param source
* @param children
*/
private void setCorrectionY(ActivityInterface source, ArrayList<ActivityInterface> children) {
//Checks whether the source contains any target activities
if (children != null && !children.isEmpty()) {
//Iterate through the target activities of the Source
for (ActivityInterface target : children) {
int whereTargetShouldBe = source.getStartIconHeight() + 40;
//Checks whether the target is null
if (target != null) {
//Gets the yTop position of the Target activity
int whereTargetIs = target.getStartIconYTop();
//Calculate the actual yTop position of the Target activity
// int correction = whereTargetShouldBe - whereTargetIs;
if (whereTargetIs < whereTargetShouldBe) {
//Set the correct yTop position of the target activity
target.setCorrectionY(target.getStartIconYTop());
int relativeCorrection = whereTargetShouldBe - source.getStartIconYTop();
correctionCumulation += relativeCorrection;
setCorrectionY(target, linkAdjacencyList.get(target));
correctionCumulation -= relativeCorrection;
}
}
}
} else {
if (hieghestCorrectionCumulation < correctionCumulation) {
hieghestCorrectionCumulation = correctionCumulation;
}
}
}
/**
* Sets the layout of the links in the process
*
* @param rootActivity root Activity of the process
*/
private void layoutLinks(ActivityInterface rootActivity) {
//Get the links in a process
Map<String, Link> links = rootActivity.getLinks();
//Checks whether the list with the links is empty or null i.e. whether the process has any links
if (links != null && !links.isEmpty()) {
//Get details of the links from the linkAdjacencyList
linkAdjacencyList = getLinkAdjacencyList(links);
//Get a list of activities which are only SOURCE activities and not TARGET activities
rootLinks = rootActivity.getLinkRoots();
//Iterate through the activities which are only SOURCE activities
for (ActivityInterface root : rootLinks) {
correctionCumulation = 0;
/*
* root- iterated activity which is only a SOURCE activity
* get(root) ---> the value to which the activity is mapped, or
* {@code null} if this map contains no mapping for the activity
* */
setCorrectionY(root, linkAdjacencyList.get(root));
}
ActivityInterface tempParent = rootLinks.iterator().next().getParent();
//Iterate through the parent activities of the SOURCE activities
while (tempParent != null) {
//Get the height of the parent activity
int tempHeight = tempParent.getDimensions().getHeight();
//Set the height of the parent activity by adding the hieghestCorrectionCumulation to the activity
// height
tempParent.getDimensions().setHeight(tempHeight + hieghestCorrectionCumulation);
tempParent = tempParent.getParent();
}
//Removes all of the activities from this set. The set will be empty
rootLinks.clear();
}
}
}