diff --git a/signals/base/src/main/java/org/eclipse/ditto/signals/base/AbstractAnnotationBasedJsonParsableFactory.java b/signals/base/src/main/java/org/eclipse/ditto/signals/base/AbstractAnnotationBasedJsonParsableFactory.java index 972824e0ec..1c04895f0c 100644 --- a/signals/base/src/main/java/org/eclipse/ditto/signals/base/AbstractAnnotationBasedJsonParsableFactory.java +++ b/signals/base/src/main/java/org/eclipse/ditto/signals/base/AbstractAnnotationBasedJsonParsableFactory.java @@ -14,8 +14,22 @@ import java.lang.annotation.Annotation; + /** + * Responsible to build an {@link AnnotationBasedJsonParsable} from a given annotation. + * + * @param The superclass of the class that should be parsed by an annotation based json parsable created by this + * factory. + * @param The type of the annotation that holds the information to build an annotation based json parsable. + */ public abstract class AbstractAnnotationBasedJsonParsableFactory { + /** + * Builds an {@link AnnotationBasedJsonParsable} from the given annotation. + * + * @param annotation the annotation that holds the information to build an annotation based json parsable. + * @param classToParse the class that should be deserialized. + * @return the annotation based json parsable. + */ AnnotationBasedJsonParsable fromAnnotation(final A annotation, final Class classToParse) { final String methodName = getMethodNameFor(annotation); final String key = getKeyFor(annotation); @@ -24,9 +38,28 @@ AnnotationBasedJsonParsable fromAnnotation(final A annotation, final Class(key, v1FallbackKey, classToParse, methodName); } + /** + * The fallback key for API v1 deserialization strategies. If there is no fallback required this method returns + * the same as {@link #getKeyFor(java.lang.annotation.Annotation)}. + * + * @param annotation the annotation that holds the information to build an annotation based json parsable. + * @return the fallback key for v1 deserialization strategies or the v2 key if no fallback is required. + */ protected abstract String getV1FallbackKeyFor(A annotation); + /** + * The key for v2 deserialization strategies. + * + * @param annotation the annotation that holds the information to build an annotation based json parsable. + * @return the key for v2 deserialization strategies. + */ protected abstract String getKeyFor(A annotation); + /** + * The name of the method used for deserialization. + * + * @param annotation the annotation that holds the information to build an annotation based json parsable. + * @return the name of the method used for deserialization. + */ protected abstract String getMethodNameFor(A annotation); } diff --git a/signals/base/src/main/java/org/eclipse/ditto/signals/base/AbstractGlobalJsonParsableRegistry.java b/signals/base/src/main/java/org/eclipse/ditto/signals/base/AbstractGlobalJsonParsableRegistry.java index e8cf7f37a8..542c1f001e 100644 --- a/signals/base/src/main/java/org/eclipse/ditto/signals/base/AbstractGlobalJsonParsableRegistry.java +++ b/signals/base/src/main/java/org/eclipse/ditto/signals/base/AbstractGlobalJsonParsableRegistry.java @@ -19,25 +19,51 @@ import org.atteo.classindex.ClassIndex; + /** + * Responsible for collecting all {@link AnnotationBasedJsonParsable} for subclasses of T. + * + * @param The superclass of all classes that should be deserialized by this registry. + * @param The type of the annotation that holds the information to build an annotation based json parsable. + */ public abstract class AbstractGlobalJsonParsableRegistry extends AbstractJsonParsableRegistry { + /** + * Creates a new instance. + * + * @param parsedClass the superclass of all classes that should be deserialized by this registry. + * @param annotationClass the type of the annotation that holds the information to build an annotation based + * json parsable. + * @param annotationBasedJsonParsableFactory the factory used to create {@link AnnotationBasedJsonParsable} + * based on a given annotation. + */ protected AbstractGlobalJsonParsableRegistry( final Class parsedClass, final Class annotationClass, - final AbstractAnnotationBasedJsonParsableFactory annotationBasedJsonParsableBuilder) { + final AbstractAnnotationBasedJsonParsableFactory annotationBasedJsonParsableFactory) { - super(initAnnotationBasedParseStrategies(parsedClass, annotationClass, annotationBasedJsonParsableBuilder)); + super(initAnnotationBasedParseStrategies(parsedClass, annotationClass, annotationBasedJsonParsableFactory)); } + /** + * Creates a new instance. + * + * @param parsedClass the superclass of all classes that should be deserialized by this registry. + * @param annotationClass the type of the annotation that holds the information to build an annotation based + * json parsable. + * @param annotationBasedJsonParsableFactory the factory used to create {@link AnnotationBasedJsonParsable} + * based on a given annotation. + * @param parseStrategies individual strategies that should be added to the annotation based strategies. + * Annotation based strategies will be overridden if they have the same key. + */ protected AbstractGlobalJsonParsableRegistry( final Class parsedClass, final Class annotationClass, - final AbstractAnnotationBasedJsonParsableFactory annotationBasedJsonParsableBuilder, + final AbstractAnnotationBasedJsonParsableFactory annotationBasedJsonParsableFactory, final Map> parseStrategies) { super(mergeParsingStrategies( - initAnnotationBasedParseStrategies(parsedClass, annotationClass, annotationBasedJsonParsableBuilder), + initAnnotationBasedParseStrategies(parsedClass, annotationClass, annotationBasedJsonParsableFactory), parseStrategies) ); } @@ -52,22 +78,24 @@ private static Map> mergeParsingStrategies( return mergedStrategies; } + @SuppressWarnings("unchecked") //Suppressed because the cast of cls is ensured by the two filters before. private static Map> initAnnotationBasedParseStrategies( final Class baseClass, final Class annotationClass, - final AbstractAnnotationBasedJsonParsableFactory annotationBasedJsonParsableBuilder) { + final AbstractAnnotationBasedJsonParsableFactory annotationBasedJsonParsableFactory) { final Map> parseRegistries = new HashMap<>(); final Iterable> annotatedClasses = ClassIndex.getAnnotated(annotationClass); StreamSupport.stream(annotatedClasses.spliterator(), false) .filter(baseClass::isAssignableFrom) + .filter(cls -> !baseClass.equals(cls)) .map(cls -> (Class) cls) .forEach(classToParse -> { final A fromJsonAnnotation = classToParse.getAnnotation(annotationClass); final AnnotationBasedJsonParsable strategy = - annotationBasedJsonParsableBuilder.fromAnnotation(fromJsonAnnotation, classToParse); + annotationBasedJsonParsableFactory.fromAnnotation(fromJsonAnnotation, classToParse); parseRegistries.put(strategy.getKey(), strategy); parseRegistries.put(strategy.getV1FallbackKey(), strategy); }); diff --git a/signals/base/src/main/java/org/eclipse/ditto/signals/base/AnnotationBasedJsonParsable.java b/signals/base/src/main/java/org/eclipse/ditto/signals/base/AnnotationBasedJsonParsable.java index 6778b331fa..a96042682c 100644 --- a/signals/base/src/main/java/org/eclipse/ditto/signals/base/AnnotationBasedJsonParsable.java +++ b/signals/base/src/main/java/org/eclipse/ditto/signals/base/AnnotationBasedJsonParsable.java @@ -18,9 +18,14 @@ import org.eclipse.ditto.json.JsonObject; import org.eclipse.ditto.json.JsonParseException; import org.eclipse.ditto.model.base.exceptions.DittoJsonException; - import org.eclipse.ditto.json.JsonParseException; + import org.eclipse.ditto.model.base.exceptions.DittoRuntimeException; import org.eclipse.ditto.model.base.headers.DittoHeaders; + /** + * Responsible for deserialization of a class of type T. + * + * @param the type of the class that should be deserialized. + */ final class AnnotationBasedJsonParsable implements JsonParsable { private static final Class JSON_OBJECT_PARAMETER = JsonObject.class; @@ -30,6 +35,15 @@ final class AnnotationBasedJsonParsable implements JsonParsable { private final String v1FallbackKey; private final Method parseMethod; + /** + * Creates a new instance. + * + * @param key the API v2 key for this strategy. + * @param v1FallbackKey the API v1 key for this strategy. + * @param parsedClass the class that should be deserialized. + * @param parsingMethodName the name of the method that should be called on the given class in order to + * deserialize. + */ AnnotationBasedJsonParsable(final String key, final String v1FallbackKey, final Class parsedClass, final String parsingMethodName) { @@ -49,10 +63,20 @@ final class AnnotationBasedJsonParsable implements JsonParsable { } } + /** + * The API v2 key for this strategy. + * + * @return the API v2 key for this strategy. + */ public String getKey() { return key; } + /** + * The API v1 key for this strategy. + * + * @return the API v1 key for this strategy. + */ public String getV1FallbackKey() { return v1FallbackKey; }