use of spoon.reflect.meta.RoleHandler in project spoon by INRIA.
the class RoleHandlerHelper method getRoleHandlers.
/**
* @param targetClass a Class whose handlers we are looking for
* @return all {@link RoleHandler}s available for the `targetClass`
*/
public static List<RoleHandler> getRoleHandlers(Class<? extends CtElement> targetClass) {
List<RoleHandler> handlers = roleHandlersByClass.get(targetClass);
if (handlers == null) {
List<RoleHandler> modifiableHandlers = new ArrayList<>();
for (CtRole role : CtRole.values()) {
RoleHandler roleHandler = getOptionalRoleHandler(targetClass, role);
if (roleHandler != null) {
modifiableHandlers.add(roleHandler);
}
}
handlers = Collections.unmodifiableList(modifiableHandlers);
roleHandlersByClass.put(targetClass, handlers);
}
return handlers;
}
use of spoon.reflect.meta.RoleHandler in project spoon by INRIA.
the class MetaModelTest method checkRoleHandlersOfType.
private void checkRoleHandlersOfType(CtType iface) {
Class ifaceClass = iface.getActualClass();
// contract: check that for each Spoon model interface we have correct list of Role handlers
List<RoleHandler> roleHandlersOfIFace = new ArrayList<>(RoleHandlerHelper.getRoleHandlers(ifaceClass));
Set<RoleHandler> allRoleHandlers = new HashSet<>();
RoleHandlerHelper.forEachRoleHandler(rh -> allRoleHandlers.add(rh));
for (CtRole role : CtRole.values()) {
RoleHandler rh = RoleHandlerHelper.getOptionalRoleHandler(ifaceClass, role);
if (rh != null) {
assertTrue("RoleHandler for role " + role + " is missing for " + ifaceClass, roleHandlersOfIFace.remove(rh));
assertTrue("RoleHandler " + rh + " is not accessible by RoleHandlerHelper#forEachRoleHandler()", allRoleHandlers.contains(rh));
}
}
assertTrue("There are unexpected RoleHandlers " + roleHandlersOfIFace + " for " + ifaceClass, roleHandlersOfIFace.isEmpty());
}
use of spoon.reflect.meta.RoleHandler in project spoon by INRIA.
the class MetaModelTest method elementAnnotationRoleHandlerTest.
@Test
public void elementAnnotationRoleHandlerTest() {
Launcher launcher = new Launcher();
Factory factory = launcher.getFactory();
CtClass<?> type = (CtClass) factory.Core().create(CtClass.class);
CtAnnotation<?> annotation = factory.Annotation().annotate(type, Parameter.class, "value", "abc");
// check contract of low level RoleHandler
RoleHandler roleHandler = RoleHandlerHelper.getRoleHandler(type.getClass(), CtRole.ANNOTATION);
assertNotNull(roleHandler);
assertEquals(CtElement.class, roleHandler.getTargetType());
assertSame(CtRole.ANNOTATION, roleHandler.getRole());
assertSame(ContainerKind.LIST, roleHandler.getContainerKind());
assertEquals(CtAnnotation.class, roleHandler.getValueClass());
// check getting value using role handler
List<CtAnnotation<?>> value = roleHandler.getValue(type);
assertEquals(1, value.size());
assertSame(annotation, value.get(0));
// check we have got direct readonly List
try {
value.remove(annotation);
fail();
} catch (Exception e) {
this.getClass();
}
// check setValueByRole
roleHandler.setValue(type, Collections.emptyList());
value = roleHandler.getValue(type);
assertEquals(0, value.size());
roleHandler.setValue(type, Collections.singletonList(annotation));
value = roleHandler.getValue(type);
assertEquals(1, value.size());
assertSame(annotation, value.get(0));
try {
// contract value must be a list of annotation. One annotation is not actually OK. This contract might be changed in future
roleHandler.setValue(type, annotation);
fail();
} catch (ClassCastException e) {
// OK
}
}
use of spoon.reflect.meta.RoleHandler in project spoon by INRIA.
the class CtRolePathElement method getElements.
@Override
public Collection<CtElement> getElements(Collection<CtElement> roots) {
Collection<CtElement> matchs = new LinkedList<>();
for (CtElement root : roots) {
RoleHandler roleHandler = RoleHandlerHelper.getOptionalRoleHandler(root.getClass(), getRole());
if (roleHandler != null) {
switch(roleHandler.getContainerKind()) {
case SINGLE:
if (roleHandler.getValue(root) != null) {
matchs.add(roleHandler.getValue(root));
}
break;
case LIST:
if (getArguments().containsKey("index")) {
int index = Integer.parseInt(getArguments().get("index"));
if (index < roleHandler.asList(root).size()) {
matchs.add((CtElement) roleHandler.asList(root).get(index));
}
} else {
matchs.addAll(roleHandler.asList(root));
}
break;
case SET:
if (getArguments().containsKey("name")) {
String name = getArguments().get("name");
try {
CtElement match = getFromSet(roleHandler.asSet(root), name);
if (match != null) {
matchs.add(match);
}
} catch (CtPathException e) {
// System.err.println("[ERROR] Element not found for name: " + name);
// No element found for name.
}
} else {
matchs.addAll(roleHandler.asSet(root));
}
break;
case MAP:
if (getArguments().containsKey("key")) {
String name = getArguments().get("key");
if (roleHandler.asMap(root).containsKey(name)) {
matchs.add((CtElement) roleHandler.asMap(root).get(name));
}
} else {
Map<String, CtElement> map = roleHandler.asMap(root);
matchs.addAll(map.values());
}
break;
}
}
}
return matchs;
}
use of spoon.reflect.meta.RoleHandler in project spoon by INRIA.
the class CtElementPathBuilder method fromElement.
/**
* Build path to a CtElement el, from one of its parent.
*
* @throws CtPathException is thrown when root is not a parent of el.
*
* @param el : the element to which the CtPath leads to
* @param root : Starting point of the CtPath
* @return CtPath from root to el
*/
public CtPath fromElement(CtElement el, CtElement root) throws CtPathException {
CtPathImpl path = new CtPathImpl();
CtElement cur = el;
while (cur != root) {
CtElement parent = cur.getParent();
CtRole role = cur.getRoleInParent();
if (role == null) {
throw new CtPathException();
}
RoleHandler roleHandler = RoleHandlerHelper.getOptionalRoleHandler(parent.getClass(), role);
if (roleHandler == null) {
throw new CtPathException();
}
CtPathElement pathElement = new CtRolePathElement(role);
switch(roleHandler.getContainerKind()) {
case SINGLE:
break;
case LIST:
// Element needs to be differentiated from its brothers
List list = roleHandler.asList(parent);
// Assumes that List's order is deterministic.
// Can't be replaced by list.indexOf(cur)
// Because objects must be the same (and not just equals)
int index = 0;
for (Object o : list) {
if (o == cur) {
break;
}
index++;
}
pathElement.addArgument("index", index + "");
break;
case SET:
String name;
if (cur instanceof CtNamedElement) {
name = ((CtNamedElement) cur).getSimpleName();
} else if (cur instanceof CtReference) {
name = ((CtReference) cur).getSimpleName();
} else {
throw new CtPathException();
}
pathElement.addArgument("name", name);
break;
case MAP:
Map map = roleHandler.asMap(parent);
String key = null;
for (Object o : map.keySet()) {
if (map.get(o) == cur) {
key = (String) o;
break;
}
}
if (key == null) {
throw new CtPathException();
} else {
pathElement.addArgument("key", key);
}
break;
}
cur = parent;
path.addFirst(pathElement);
}
return path;
}
Aggregations