Added ability to transparently unpack artifacts via an IArtifactUnpacker interface This allows handlers that receive an object that is not the artifact itself, but, e.g., a wrapper from which the actual artifact can be derived.
diff --git a/org.eclipse.capra.core/src/org/eclipse/capra/core/handlers/AbstractArtifactHandler.java b/org.eclipse.capra.core/src/org/eclipse/capra/core/handlers/AbstractArtifactHandler.java index bb19459..be9899a 100644 --- a/org.eclipse.capra.core/src/org/eclipse/capra/core/handlers/AbstractArtifactHandler.java +++ b/org.eclipse.capra.core/src/org/eclipse/capra/core/handlers/AbstractArtifactHandler.java
@@ -16,8 +16,26 @@ public abstract class AbstractArtifactHandler<T> implements IArtifactHandler<T> { + private Object unpack(Object artifact) { + Object result = artifact; + if (IArtifactUnpacker.class.isAssignableFrom(this.getClass())) { + try { + result = IArtifactUnpacker.class.cast(this).unpack(artifact); + } catch (ClassCastException ex) { + /* + * Deliberately do nothing. This is not uncommon when trying to + * find the right handler. In such cases, canHandleArtifact() is + * called on all handlers, but for most the artifact can not be + * casted. + */ + } + } + return result; + } + @Override public <R> Optional<R> withCastedHandler(Object artifact, BiFunction<IArtifactHandler<T>, T, R> handleFunction) { + artifact = unpack(artifact); if (canHandleArtifact(artifact)) { @SuppressWarnings("unchecked") T a = (T) artifact; @@ -30,12 +48,13 @@ @Override public <R> R withCastedHandlerUnchecked(Object artifact, BiFunction<IArtifactHandler<T>, T, R> handleFunction) { return withCastedHandler(artifact, handleFunction).orElseThrow( - () -> new IllegalArgumentException("withCastedHanderUnchecked called with unhandleble artifact." - + " Artifact: " + artifact + ", handler: " + this)); + () -> new IllegalArgumentException("withCastedHanderUnchecked called with unhandleble artifact." + + " Artifact: " + artifact + ", handler: " + this)); } @Override public boolean canHandleArtifact(Object artifact) { + artifact = unpack(artifact); try { Class<?> genericType = ((Class<?>) ((ParameterizedType) this.getClass().getGenericSuperclass()) .getActualTypeArguments()[0]);
diff --git a/org.eclipse.capra.core/src/org/eclipse/capra/core/handlers/IArtifactUnpacker.java b/org.eclipse.capra.core/src/org/eclipse/capra/core/handlers/IArtifactUnpacker.java new file mode 100644 index 0000000..43a3d92 --- /dev/null +++ b/org.eclipse.capra.core/src/org/eclipse/capra/core/handlers/IArtifactUnpacker.java
@@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2017 Chalmers | University of Gothenburg, rt-labs and others. + * 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: + * Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation + *******************************************************************************/ +package org.eclipse.capra.core.handlers; + +/** + * Defines functions to unpack the artifact from a surrounding container. This + * can be helpful if the artifact is wrapped by another class and Eclipse calls + * the methods of an {@link IArtifactHandler} with the wrapper instead of the + * actual object the wrapper is able to handle. + * + * @param <T> + * the type of the container + * @param <K> + * the type of the artifact + */ +public interface IArtifactUnpacker<T, K> { + + /** + * Unpacks an artifact from a container. + * + * @param container + * the container containing the artifact + * @return an artifact unpacked from the container + */ + K unpack(T container); + +}