/*******************************************************************************
* Copyright (c) 2016 BREDEX GmbH.
* 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:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.client.core.businessprocess;
import java.util.Set;
import org.eclipse.jubula.client.core.model.IComponentNamePO;
import org.eclipse.jubula.toolkit.common.xml.businessprocess.ComponentBuilder;
import org.eclipse.jubula.tools.internal.xml.businessmodell.CompSystem;
import org.eclipse.jubula.tools.internal.xml.businessmodell.Component;
/**
* Class containing all type-related methods for Component Names
* @author BREDEX GmbH
*/
public class CompNameTypeManager {
/** Private constructor */
private CompNameTypeManager() {
// empty constructor
}
/**
* Calculates the type of two types
* @param type1 the first type
* @param type2 the second type
* @return the determined type or null if the types are not compatible
*/
public static String calcUsageType(String type1, String type2) {
if (type1 == null || type2 == null) {
return ComponentNamesBP.UNKNOWN_COMPONENT_TYPE;
}
CompSystem compSystem = ComponentBuilder.getInstance().getCompSystem();
Component comp1 = getMostConcreteVisibleAncestor(
compSystem.findComponent(type1), compSystem);
Component comp2 = getMostConcreteVisibleAncestor(
compSystem.findComponent(type2), compSystem);
if (comp1 == null || comp2 == null) {
return ComponentNamesBP.UNKNOWN_COMPONENT_TYPE;
}
Component moreConcrete = getMoreConcreteComponent(comp1, comp2, true);
if (moreConcrete == null) {
return ComponentNamesBP.UNKNOWN_COMPONENT_TYPE;
}
String compType = moreConcrete.getType();
moreConcrete = getMostConcreteVisibleAncestor(
moreConcrete, compSystem);
// Use the most concrete visible type, if one is available
if (moreConcrete != null) {
compType = moreConcrete.getType();
}
if (compType != null) {
return compType;
}
return ComponentNamesBP.UNKNOWN_COMPONENT_TYPE;
}
/**
* Returns the most abstract Component Type
* @return the most abstract Component Type
*/
public static String getMostAbstractType() {
return ComponentBuilder.getInstance().getCompSystem()
.getMostAbstractComponent().getType();
}
/**
* Determines if the first type realize the second
* @param first the first type
* @param second the second type
* @return whether the first type realizes the second
*/
public static boolean doesFirstTypeRealizeSecond(
String first, String second) {
if (first == null || second == null) {
return false;
}
if (first.equals(second)) {
return true;
}
CompSystem compSystem = ComponentBuilder.getInstance().getCompSystem();
Component comp1 = compSystem.getComponentForType(first);
if (comp1 == null) {
return false;
}
return comp1.isRealizing(second);
}
/**
* @param comp1 a Component
* @param comp2 a Component
* @param isFirstCall caller should set this to true always!
* @return the more concrete Component or null if the given Components are
* incompatible.
*/
private static Component getMoreConcreteComponent(Component comp1,
Component comp2, boolean isFirstCall) {
if (comp1 == null || comp2 == null) {
return null;
}
if (comp1.equals(comp2)) {
return comp1;
}
final String comp2Type = comp2.getType();
for (Component realizer : comp1.getAllRealizers()) {
if (realizer.getType().equals(comp2Type)) {
return realizer;
}
}
// if comp2 is not more concrete than comp1, try inverted search:
return isFirstCall ? getMoreConcreteComponent(comp2, comp1, false)
: null;
}
/**
* Find the most concrete visible ancestor of the given component.
*
* @param component The component for which to find the most concrete
* visible ancestor.
* @param compSystem The component system to use to perform the search.
* @return the most concrete, visible ancestor of <code>component</code>,
* which may be <code>component</code> itself.
* Returns <code>null</code> if <code>component</code> and
* its ancestors are all invisible.
*/
private static Component getMostConcreteVisibleAncestor(Component component,
CompSystem compSystem) {
Component comp = component;
while (comp != null
&& !comp.isVisible()) {
Set<Component> realized = comp.getAllRealized();
comp = compSystem.getMostConcrete(
realized.toArray(new Component [realized.size()]));
}
return comp;
}
/**
* Returns the most concrete visible ancestor type
* @param type the type
* @return the ancestor type
*/
public static String getMostConcreteVisibleAncestorType(String type) {
if (type == null) {
return ComponentNamesBP.UNKNOWN_COMPONENT_TYPE;
}
CompSystem compSystem = ComponentBuilder.getInstance().getCompSystem();
Component comp = compSystem.findComponent(type);
if (comp == null) {
return ComponentNamesBP.UNKNOWN_COMPONENT_TYPE;
}
Component ancestor = getMostConcreteVisibleAncestor(comp, compSystem);
return ancestor == null ? ComponentNamesBP.UNKNOWN_COMPONENT_TYPE
: ancestor.getType();
}
/**
* Decides whether a component name may have a new usage
* If it says NO, then it definitely can't, but otherwise it is not sure it can
* @param cN the Component Name
* @param type the type
* @return NO, if type is independent of the usage type of the component name
* or if the usage type and the real type of the component name differ, and
* the real type does not realize the given type
*/
public static boolean mayBeCompatible(IComponentNamePO cN,
String type) {
if (cN.getComponentType() == null) {
return false;
}
return (doesFirstTypeRealizeSecond(type, cN.getUsageType())
|| doesFirstTypeRealizeSecond(cN.getUsageType(), type))
&& (cN.getComponentType().equals(cN.getUsageType())
|| doesFirstTypeRealizeSecond(cN.getComponentType(), type));
}
}