Skip to content
Snippets Groups Projects
Commit 2e3ab4a7 authored by Alexander Diewald's avatar Alexander Diewald
Browse files

Exploration: Add utility methods for solution visualization.

* Introduce utility methods to transform a ExplorationSolutionSet to a DataSetCollection and subsequent methods.
* Move some reflection utility classes from the exploration.alg plugin to the exploration plugin.
refs 2935
parent 1a27847d
No related branches found
No related tags found
No related merge requests found
Opt4JExplorationSolutionSet.java fd1ca946198990604ea7a521e9d0335bef4ad8e1 RED
Opt4JExplorerBackend.java b647535f92ebdf1e428757f6fe1e918964feb4f2 RED
Opt4JSingleExplorationSolution.java 6086e36a5b48b9f3ea68b6e50e2ac20758942d0a RED
Opt4JSingleExplorationSolution.java 5b9e6ccdb887605faaa4d2a8b17b8fa1350fbafd RED
......@@ -15,7 +15,7 @@
+--------------------------------------------------------------------------*/
package org.fortiss.af3.exploration.alg.dse.backend.opt4j;
import static org.fortiss.af3.exploration.alg.util.ExplorationAlgUtils.getSubstitutionTypeOfGenericIface;
import static org.fortiss.af3.exploration.util.ExplorationUtils.getReturnTypeOf;
import java.util.Map;
import java.util.Map.Entry;
......@@ -51,8 +51,7 @@ public class Opt4JSingleExplorationSolution extends SolutionQuantification {
// Determine the ExplorationTarget class to identify the correct return value type.
Objective objective = problemModule.getObjectiveOf(targetAssoc.getValue());
ExplorationTarget<?> concreteExpTarget = targetAssoc.getKey();
Class<?> expectedResultType =
getSubstitutionTypeOfGenericIface(concreteExpTarget, ExplorationTarget.class);
Class<?> expectedResultType = getReturnTypeOf(concreteExpTarget);
// FIXME: throw an exception here.
assert (expectedResultType != null) : "Could not determine the result type of the exploration target " +
concreteExpTarget.getName() +
......
AF3Utils.java ae4bb78f77989e3a5689bfff80298c1bdeccdb3a RED
DesignSpaceExplorationModelElementFactory.java 9dc330973f132c4b936e4dc7ee8407614faf2ff6 RED
ExplorationAlgDebugUtils.java ff9feee46a3d00dd21d007a53f71f2de1ce10a94 RED
ExplorationAlgUtils.java 5915fd72f26cf5d7ef49e62a8e304a63da71d8dc RED
ExplorationAlgUtils.java 1deb317ed1d276e778fb64d207a1784a4919518b RED
ExplorationEcoreUtils.java 48ed07aec3cd93e66d37abc10d50636d591f1c71 RED
GraphUtils.java a1cec037a4d54bcf196dc5eebddc72b033993d6f RED
TransformationUtils.java b077f7a695cecd66bfdb5c265e8875900bee137c RED
......@@ -23,10 +23,7 @@ import static org.fortiss.tooling.kernel.utils.EcoreUtils.getParentsWithType;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
......@@ -35,8 +32,6 @@ import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
import java.util.function.Predicate;
import org.conqat.lib.commons.reflect.ReflectionUtils;
import org.eclipse.emf.common.util.BasicEList;
......@@ -681,157 +676,6 @@ public class ExplorationAlgUtils {
return getSuperClassOfImplementingInterface(goal, IProblemDimension.class);
}
/**
* Given an object that directly or indirectly inherits from the given interface, this method
* returns the substitution class type of the generic parameter of the given interface.
* <p>
* <b>NOTE:</b> This method works only for interfaces that have a single generic type parameter.
* <p>
* This method makes no assumptions about the location of the substitution in the class
* hierarchy.
* <p>
* <p>
* This method first identifies the path from the given object's class to the given interface in
* the class hierarchy. This path is then traversed and each found generic substitution is
* examined whether it substitutes the generic of the given interface.
*
* @param object
* Object for which the substitution type defined in the given class shall be found.
* @param interfaceClass
* Interface defining or redefining the generic type of interest.
* @return Class type substituting the generic parameter of the given interface.
*/
public static Class<?> getSubstitutionTypeOfGenericIface(Object object,
Class<?> interfaceClass) {
// First, identify the "hierarchy path" from the given object to the target interface.
LinkedList<Class<?>> inheritancePath = getClassPathToIface(object, interfaceClass);
Stack<Type> paramTypeStack = new Stack<>();
LinkedList<Class<?>> hierTraversalList = new LinkedList<>();
hierTraversalList.addAll(inheritancePath);
Type currParamRawType = null;
Predicate<Class<?>> targetIfaceFound = t -> t != null && t.isAssignableFrom(interfaceClass);
// Outer loop: Inspect the "hierarchy path".
do {
Class<?> hierStackElem = hierTraversalList.poll();
Type[] genTypes = hierStackElem.getGenericInterfaces();
LinkedList<Type> typesToTraverse = new LinkedList<>();
typesToTraverse.addAll(Arrays.asList(genTypes));
// Inner loop: Inspect a single generic substitution.
while(!typesToTraverse.isEmpty() &&
!targetIfaceFound.test((Class<?>)currParamRawType)) {
Type currTraversedType = typesToTraverse.poll();
paramTypeStack.add(currTraversedType);
// Skip non-parameterized types (like other interfaces): Would be a wrong path.
if(currTraversedType instanceof ParameterizedType) {
currParamRawType = ((ParameterizedType)currTraversedType).getRawType();
// Only follow the "path" of this generic parameter if it matches the previously
// identified path to the given interface.
if(inheritancePath.contains(currParamRawType)) {
Collection<Type> matchedTypes = processParentParamerType(currParamRawType);
typesToTraverse.addAll(0, matchedTypes);
}
} else {
// Otherwise, remove the current parameter type from the "path" stack: It would
// lead to the generic of the interface.
paramTypeStack.pop();
}
}
if(!targetIfaceFound.test((Class<?>)currParamRawType)) {
// This generic substitution was not the right one --> clean the "path".
paramTypeStack.clear();
}
} while(!hierTraversalList.isEmpty() && !targetIfaceFound.test((Class<?>)currParamRawType));
// Return the class of the substituting parameter type.
if(targetIfaceFound.test((Class<?>)currParamRawType)) {
// get(0): The above if clause implicitly guarantees the existence of one element.
Type paramType = paramTypeStack.get(0);
if(paramType instanceof ParameterizedType) {
Type actParamType = ((ParameterizedType)paramType).getActualTypeArguments()[0];
if(actParamType instanceof Class<?>) {
return (Class<?>)actParamType;
} else if(actParamType instanceof ParameterizedType) {
return (Class<?>)((ParameterizedType)actParamType).getRawType();
}
}
}
return null;
}
/** Collects and returns all parent interface that are parameterized by the given type. */
private static Collection<Type> processParentParamerType(Type rawType) {
Collection<Type> matchingTypes = new ArrayList<>();
Type[] typeParams = ((Class<?>)rawType).getGenericInterfaces();
Collection<Type> xT = Arrays.asList(((Class<?>)rawType).getTypeParameters());
for(Type parentType : typeParams) {
if(parentType instanceof ParameterizedType) {
Type[] typeArgs = ((ParameterizedType)parentType).getActualTypeArguments();
if(typeArgs.length == 1 && xT.contains(typeArgs[0])) {
matchingTypes.add(parentType);
}
}
}
return matchingTypes;
}
/**
* Determines the path in the class hierarchy from the given object's class to the interface. It
* returns a list view on the identified path.
* <p>
* <b>NOTE:</b> The given object's class must be always below the given interface's class in the
* class hierarchy. Although this property is enforced if the second class is an interface, it
* is specifically noted here since normal classes and interface cannot be differentiated here.
*
* @param object
* Object inheriting from {@code interfaceClass}.
* @param interfaceClass
* Interface forming the top of the stack and defining the end of the path.
* @return Path between the given object's class and the given interface as a linked list.
*/
private static LinkedList<Class<?>> getClassPathToIface(Object object,
Class<?> interfaceClass) {
LinkedList<Class<?>> traversalList = new LinkedList<>();
Stack<Class<?>> hierarchyBrachStack = new Stack<>();
LinkedList<Class<?>> ifacesTraversalList = new LinkedList<>();
ifacesTraversalList.addAll(Arrays.asList(object.getClass().getInterfaces()));
while(!ifacesTraversalList.isEmpty()) {
Class<?> currIface = ifacesTraversalList.poll();
traversalList.add(currIface);
if(currIface.equals(interfaceClass)) {
break;
}
Class<?>[] parentIfaces = currIface.getInterfaces();
if(parentIfaces.length > 0) {
// Add candidate paths to the classes to traverse. If multiple candidate paths are
// found, remember the branch point.
// Note: always insert the parent interface at the top of the traversal list.
ifacesTraversalList.addAll(0, Arrays.asList(parentIfaces));
if(parentIfaces.length > 1) {
hierarchyBrachStack.add(currIface);
}
} else {
// No more parent classes: Remove invalid path fragment from the stack (does not
// lead to the target interface).
int lastBranchIdx = 1;
if(!hierarchyBrachStack.isEmpty()) {
Class<?> lastHierBranch = hierarchyBrachStack.lastElement();
traversalList.indexOf(lastHierBranch);
}
List<Class<?>> rmFromTravStrack = new ArrayList<>();
rmFromTravStrack.addAll(traversalList.subList(lastBranchIdx, traversalList.size()));
traversalList.removeAll(rmFromTravStrack);
}
}
return traversalList;
}
/**
* Returns the typed key from the map which is the best match for the given
* class. The best match is defined by the first match occurring in a breath
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment