/*******************************************************************************
* Copyright (c) 2010-2015 Henshin developers. All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* TU Berlin, University of Luxembourg, SES S.A.
*******************************************************************************/
/**
*
*/
package de.tub.tfs.henshin.editor.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.henshin.model.And;
import org.eclipse.emf.henshin.model.BinaryFormula;
import org.eclipse.emf.henshin.model.Formula;
import org.eclipse.emf.henshin.model.Graph;
import org.eclipse.emf.henshin.model.NestedCondition;
import org.eclipse.emf.henshin.model.Not;
import org.eclipse.emf.henshin.model.Or;
import org.eclipse.emf.henshin.model.Rule;
import org.eclipse.emf.henshin.model.UnaryFormula;
import org.eclipse.gef.EditPart;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import de.tub.tfs.henshin.editor.editparts.graph.tree.GraphTreeEditPart;
import de.tub.tfs.henshin.editor.editparts.rule.tree.LhsRhsTreeEditPart;
import de.tub.tfs.henshin.editor.ui.condition.ConditionView;
import de.tub.tfs.henshin.editor.ui.rule.RuleView;
/**
* A helper class to calculate something in formula.
*
* @author Angeline Warning
*/
public class FormulaUtil {
/**
* If the given parent and child formula are not {@code null}, then checks
* if the child formula is the left child of the parent formula.
*
* @param parentFormula
* Parent formula.
* @param childFormula
* Child formula
* @return {@code true} if the given child formula is the child formula of
* the given parent formula on the left side.
*/
public static boolean isLeftChild(final BinaryFormula parentFormula,
final Formula childFormula) {
return parentFormula != null && childFormula != null
&& parentFormula.getLeft() == childFormula;
}
/**
* If the given parent and child formula are not {@code null}, then checks
* if the child formula is the right child of the parent formula.
*
* @param parentFormula
* Parent formula.
* @param childFormula
* Child formula
* @return {@code true} if the given child formula is the child formula of
* the given parent formula on the right side.
*/
public static boolean isRightChild(final BinaryFormula parentFormula,
final Formula childFormula) {
return parentFormula != null && childFormula != null
&& parentFormula.getRight() == childFormula;
}
/**
* Calculates the depth of the given {@code formula}
*
* @param formula
* A formula whose depth is calculated.
* @return Formula's depth.
*/
public static int getDepth(final Formula formula) {
int depth = 0;
if (formula != null) {
if (formula instanceof NestedCondition) {
depth += 1;
} else if (formula instanceof UnaryFormula) {
depth++;
depth += getDepth(((UnaryFormula) formula).getChild());
} else if (formula instanceof BinaryFormula) {
depth++;
depth += Math.max(
getDepth(((BinaryFormula) formula).getLeft()),
getDepth(((BinaryFormula) formula).getRight()));
}
}
return depth;
}
/**
* Calculates the width of the given {@code formula}
*
* @param formula
* A formula whose width is calculated.
* @return Formula's width.
*/
public static int getWidth(final Formula formula) {
int width = 0;
if (formula != null) {
if (formula instanceof NestedCondition) {
width = 1;
} else if (formula instanceof UnaryFormula) {
width = 1;
int childWidth = getWidth(((UnaryFormula) formula).getChild());
if (childWidth > 1) {
width = Math.max(width, childWidth);
}
} else if (formula instanceof BinaryFormula) {
width = 2;
int leftWidth = getWidth(((BinaryFormula) formula).getLeft());
int rightWidth = getWidth(((BinaryFormula) formula).getRight());
if (leftWidth > 1 || rightWidth > 1) {
width = 2 * Math.max(leftWidth, rightWidth);
}
}
}
return width;
}
/**
* Returns the string representation of the given {@code formula}.
*
* @param formula
* A formula whose string representation is calculated.
* @return String representation of the given {@code formula} or
* "Unknown formula type!" if the formula type is unidentified.
*/
public static String getText(Formula formula) {
if (formula == null) {
return null;
}
String text = "Unknown formula type!";
if (formula instanceof NestedCondition) {
Graph conclusion = ((NestedCondition) formula).getConclusion();
if (conclusion != null) {
text = conclusion.getName();
}
} else if (formula instanceof Not) {
text = "NOT";
} else if (formula instanceof And) {
text = "AND";
} else if (formula instanceof Or) {
text = "OR";
}
return text;
}
/**
* Finds out the premise of the given {@code formula}.
*
* @param formula
* A formula whose premise is found out.
* @return Premise of the given {@code formula} or {@code null} if such
* premise doesn't exist.
*/
public static Graph getPremise(Formula formula) {
if (formula != null) {
EObject parent = formula.eContainer();
while (parent != null && !(parent instanceof Graph)) {
parent = parent.eContainer();
}
if (parent != null && parent instanceof Graph) {
return (Graph) parent;
}
}
return null;
}
/**
* Checks, if the given {@code formula} is valid. Valid means: If the given
* {@code formula} is an unary formula, then this formula has to have a
* child. If the given {@code formula} is a binary formula, then this
* formula has to have a left and right child.
*
* @param formula
* A formula to check.
* @return {@code true} if the given formula is valid, {@code false}
* otherwise.
*/
public static boolean isValid(Formula formula) {
boolean valid = false;
if (formula != null) {
if (formula instanceof NestedCondition) {
valid = true;
} else if (formula instanceof UnaryFormula) {
valid = ((UnaryFormula) formula).getChild() != null;
} else if (formula instanceof BinaryFormula) {
valid = ((BinaryFormula) formula).getLeft() != null
&& ((BinaryFormula) formula).getRight() != null;
}
}
return valid;
}
/**
* Finds opened condition views which represent the given {@code formula} as
* a model or child model. If such views are found, then returns it.
* Otherwise, returns an empty list.
*
* @return Opened condition views represent the given {@code formula} or an
* empty list if such views can't be found.
*/
public static List<ConditionView> getOpenedConditionViews(Formula formula) {
final List<ConditionView> conditionViews = new ArrayList<ConditionView>();
final IWorkbench workbench = PlatformUI.getWorkbench();
final IWorkbenchPage page = workbench.getActiveWorkbenchWindow()
.getActivePage();
if (page != null) {
final IViewReference[] viewReferences = page.getViewReferences();
for (int i = 0; i < viewReferences.length; i++) {
final IViewPart viewPart = viewReferences[i].getView(false);
if (viewPart instanceof ConditionView) {
final ConditionView currentView = (ConditionView) viewPart;
final Formula viewModel = currentView.getCastedModel();
if (contains(formula, viewModel)) {
conditionViews.add(currentView);
}
}
}
}
return conditionViews;
}
/**
* Finds opened condition view which represent the given {@code formula} as
* a model. If such view is found, then returns it. Otherwise, returns an
* empty list.
*
* @return Opened condition view represent the given {@code formula} or an
* empty list if such view can't be found.
*/
public static ConditionView getOpenedConditionView(Formula formula) {
final IWorkbench workbench = PlatformUI.getWorkbench();
final IWorkbenchPage page = workbench.getActiveWorkbenchWindow()
.getActivePage();
if (page != null) {
final IViewReference[] viewReferences = page.getViewReferences();
for (int i = 0; i < viewReferences.length; i++) {
final IViewPart viewPart = viewReferences[i].getView(false);
if (viewPart instanceof ConditionView) {
final ConditionView currentView = (ConditionView) viewPart;
final Formula viewModel = currentView.getCastedModel();
if (formula == viewModel) {
return (ConditionView) viewPart;
}
}
}
}
return null;
}
/**
* Contains.
*
* @param formula
* the formula
* @param toFind
* the to find
* @return true, if successful
*/
private static boolean contains(Formula formula, Formula toFind) {
if (formula == toFind) {
return true;
} else if (formula instanceof NestedCondition) {
return contains(((NestedCondition) formula).getConclusion()
.getFormula(), toFind);
} else if (formula instanceof UnaryFormula) {
return contains(((UnaryFormula) formula).getChild(), toFind);
} else if (formula instanceof BinaryFormula) {
return contains(((BinaryFormula) formula).getLeft(), toFind)
|| contains(((BinaryFormula) formula).getRight(), toFind);
}
return false;
}
/**
* Finds condition and rule views which show the given {@code formula}. If
* such views are found, then returns it. Otherwise, returns an empty list.
*
* @return Condition or rule view that show the given {@code formula} or an
* empty list if such views can't be found.
*/
public static List<IViewPart> getViewsShowing(Formula formula) {
final List<IViewPart> views = new ArrayList<IViewPart>();
final IWorkbench workbench = PlatformUI.getWorkbench();
final IWorkbenchPage page = workbench.getActiveWorkbenchWindow()
.getActivePage();
if (page != null) {
final IViewReference[] viewReferences = page.getViewReferences();
for (int i = 0; i < viewReferences.length; i++) {
final IViewPart viewPart = viewReferences[i].getView(true);
if (viewPart instanceof ConditionView) {
final ConditionView currentView = (ConditionView) viewPart;
final Formula viewModel = currentView.getCastedModel();
if (contains(viewModel, formula)) {
views.add(currentView);
}
} else if (viewPart instanceof RuleView) {
final RuleView currentView = (RuleView) viewPart;
final Rule viewModel = currentView.getCastedModel();
if (contains(viewModel.getLhs().getFormula(), formula)) {
views.add(currentView);
}
}
}
}
return views;
}
/**
* Finds all opened views. If such views are found, then returns it.
* Otherwise, returns an empty list.
*
* @return All opened views or an empty list if no view is opened.
*/
public static List<IViewPart> getViewsShowing() {
final List<IViewPart> views = new ArrayList<IViewPart>();
final IWorkbench workbench = PlatformUI.getWorkbench();
final IWorkbenchPage page = workbench.getActiveWorkbenchWindow()
.getActivePage();
if (page != null) {
final IViewReference[] viewReferences = page.getViewReferences();
for (int i = 0; i < viewReferences.length; i++) {
final IViewPart viewPart = viewReferences[i].getView(true);
views.add(viewPart);
}
}
return views;
}
public static EditPart getPremiseEditPart(final EditPart formulaEditPart) {
if (formulaEditPart != null) {
EditPart parentEditPart = formulaEditPart.getParent();
while (parentEditPart != null
&& (!(parentEditPart instanceof LhsRhsTreeEditPart) && !(parentEditPart instanceof GraphTreeEditPart))) {
parentEditPart = parentEditPart.getParent();
}
if (parentEditPart != null
&& (parentEditPart instanceof LhsRhsTreeEditPart || parentEditPart instanceof GraphTreeEditPart)) {
return parentEditPart;
}
}
return null;
}
/**
* Gets the distinct name of AC's conclusion.
*
* @param ac
* application condition whose conclusion name is generated.
* @return A distinct name of AC's conclusion within the root formula.
*/
public static String getDistinctACName(final NestedCondition ac) {
if (ac != null) {
final Formula root = getRootFormula(ac);
final Set<String> forbiddenNames = ModelUtil.getExistNames(root,
null);
// Generates a distinct name
final String nameBase = "AC";
int i = 0;
String distinctName;
do {
distinctName = nameBase + i++;
} while (forbiddenNames.contains(distinctName));
return distinctName;
}
return null;
}
private static Formula getRootFormula(final NestedCondition ac) {
EObject rootFormula = ac.eContainer();
while (rootFormula.eContainer() != null
&& rootFormula.eContainer() instanceof Formula) {
rootFormula = rootFormula.eContainer();
}
if (rootFormula != null && rootFormula instanceof Formula) {
return (Formula) rootFormula;
}
return ac;
}
/**
* Finds a condition view that showing the deleted formula and closes it.
*/
public static void closeConditionViewsShowing(final Formula formula) {
final IWorkbench workbench = PlatformUI.getWorkbench();
final List<ConditionView> conditionViews = FormulaUtil
.getOpenedConditionViews(formula);
final IWorkbenchPage page = workbench.getActiveWorkbenchWindow()
.getActivePage();
for (final ConditionView conditionView : conditionViews) {
page.hideView(conditionView);
}
}
/**
* Close the given view.
*
* @param view
* View to close.
*/
public static void closeView(ConditionView view) {
if (view != null) {
final IWorkbench workbench = PlatformUI.getWorkbench();
final IWorkbenchPage page = workbench.getActiveWorkbenchWindow()
.getActivePage();
page.hideView(view);
}
}
/**
* @param formula
* Formula to check.
* @return {@code true} if the given formula has at least one child.
*/
public static boolean hasChild(Formula formula) {
if (formula instanceof UnaryFormula) {
return ((UnaryFormula) formula).getChild() != null;
} else if (formula instanceof BinaryFormula) {
return ((BinaryFormula) formula).getLeft() != null
|| ((BinaryFormula) formula).getRight() != null;
}
return false;
}
}