Skip to content

Commit

Permalink
Diminish duplication among all 3 child entity impls
Browse files Browse the repository at this point in the history
-Extend from the AbstractChildEntityDefinition in the
AggregateMemberAnnotatedChildEntityDefinition
-Introduce the extractChildEntityModel()
-Drop the resolveType() and resolveGenericType() in favor of the
extractChildEntityModel()
-Create the commandHandlerRoutingKeys in the
createCommandTargetResolvers() rather then passing it, as it's only a
requirement for the map and iterable impls
-Add dummy javadoc to fill in later

[#388]
  • Loading branch information
smcvb committed Nov 23, 2017
1 parent e3f2ac7 commit 41f3823
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,17 @@ public <T> Optional<ChildEntity<T>> createChildDefinition(Field field, EntityMod
if (attributes == null || fieldIsOfType(field)) {
return Optional.empty();
}
EntityModel<Object> childEntityModel = declaringEntity.modelOf(resolveType(attributes, field));
EntityModel<Object> childEntityModel = extractChildEntityModel(declaringEntity, attributes, field);

Boolean forwardEvents = (Boolean) attributes.get("forwardEvents");
ForwardingMode eventForwardingMode = (ForwardingMode) attributes.get("eventForwardingMode");
Map<String, Property<Object>> commandHandlerRoutingKeys =
extractCommandHandlerRoutingKeys(field, childEntityModel);

return Optional.of(new AnnotatedChildEntity<>(
childEntityModel,
(Boolean) attributes.get("forwardCommands"),
eventForwardingMode(forwardEvents, eventForwardingMode),
(String) attributes.get("eventRoutingKey"),
(msg, parent) -> createCommandTargetResolvers(msg,
parent,
commandHandlerRoutingKeys,
field,
childEntityModel),
(msg, parent) -> createCommandTargetResolvers(msg, parent, field, childEntityModel),
(msg, parent) -> createEventTargetResolvers(field, parent)
));
}
Expand All @@ -71,6 +65,17 @@ public <T> Optional<ChildEntity<T>> createChildDefinition(Field field, EntityMod
*/
protected abstract boolean fieldIsOfType(Field field);

/**
* @param declaringEntity
* @param attributes
* @param field
* @param <T>
* @return
*/
protected abstract <T> EntityModel<Object> extractChildEntityModel(EntityModel<T> declaringEntity,
Map<String, Object> attributes,
Field field);

/**
* Resolves the type of the Child Entity, either by pulling it from the {@link org.axonframework.commandhandling.model.AggregateMember}
* its attributes, or by resolving it him self through the {@link AbstractChildEntityDefinition#resolveType(Map,
Expand All @@ -82,25 +87,25 @@ public <T> Optional<ChildEntity<T>> createChildDefinition(Field field, EntityMod
* @param field a {@link java.lang.reflect.Field} denoting the Child Entity to resolve the type of.
* @return the type as a {@link java.lang.Class} of the Child Entity.
*/
private Class<?> resolveType(Map<String, Object> attributes, Field field) {
Class<?> entityType = (Class<?>) attributes.get("type");
if (Void.class.equals(entityType)) {
entityType = resolveGenericType(field).orElseThrow(() -> new AxonConfigurationException(format(
"Unable to resolve entity type of field [%s]. Please provide type explicitly in @AggregateMember annotation.",
field.toGenericString()
)));
}

return entityType;
}
// private Class<?> resolveType(Map<String, Object> attributes, Field field) {
// Class<?> entityType = (Class<?>) attributes.get("type");
// if (Void.class.equals(entityType)) {
// entityType = resolveGenericType(field).orElseThrow(() -> new AxonConfigurationException(format(
// "Unable to resolve entity type of field [%s]. Please provide type explicitly in @AggregateMember annotation.",
// field.toGenericString()
// )));
// }
//
// return entityType;
// }

/**
* Resolves the generic type of a {@link java.lang.reflect.Field} Child Entity.
*
* @param field a {@link java.lang.reflect.Field} denoting the Child Entity to resolve the type of.
* @return the type as a {@link java.lang.Class} of the given {@code field}.
*/
protected abstract Optional<Class<?>> resolveGenericType(Field field);
// protected abstract Optional<Class<?>> resolveGenericType(Field field);

/**
* Retrieves the routing keys of every command handler on the given {@code childEntityModel} to be able to correctly
Expand All @@ -113,8 +118,9 @@ private Class<?> resolveType(Map<String, Object> attributes, Field field) {
* @return a {@link java.util.Map} of key/value types {@link java.lang.String}/{@link
* org.axonframework.common.property.Property} from Command Message name to routing key.
*/
private Map<String, Property<Object>> extractCommandHandlerRoutingKeys(Field field,
EntityModel<Object> childEntityModel) {
@SuppressWarnings("WeakerAccess")
protected Map<String, Property<Object>> extractCommandHandlerRoutingKeys(Field field,
EntityModel<Object> childEntityModel) {
return childEntityModel.commandHandlers()
.values()
.stream()
Expand Down Expand Up @@ -171,15 +177,13 @@ private ForwardingMode eventForwardingMode(Boolean forwardEvents, ForwardingMode
/**
* @param msg
* @param parent
* @param commandHandlerRoutingKeys
* @param field
* @param childEntityModel
* @param <T>
* @return
*/
protected abstract <T> Object createCommandTargetResolvers(CommandMessage<?> msg,
T parent,
Map<String, Property<Object>> commandHandlerRoutingKeys,
Field field,
EntityModel<Object> childEntityModel);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@

import org.axonframework.commandhandling.CommandMessage;
import org.axonframework.commandhandling.model.AggregateMember;
import org.axonframework.common.AxonConfigurationException;
import org.axonframework.common.ReflectionUtils;
import org.axonframework.common.property.Property;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.StreamSupport;

import static java.lang.String.format;
import static org.axonframework.common.ReflectionUtils.resolveGenericType;

/**
* Implementation of a {@link AbstractChildEntityDefinition} that is used to detect Collections of entities
* (field type assignable to {@link Iterable}) annotated with {@link AggregateMember}. If such a field is found a {@link
Expand All @@ -34,24 +37,38 @@
public class AggregateMemberAnnotatedChildEntityCollectionDefinition extends AbstractChildEntityDefinition {

@Override
protected Optional<Class<?>> resolveGenericType(Field field) {
return ReflectionUtils.resolveGenericType(field, 0);
protected boolean fieldIsOfType(Field field) {
return !Iterable.class.isAssignableFrom(field.getType());
}

@Override
protected boolean fieldIsOfType(Field field) {
return !Iterable.class.isAssignableFrom(field.getType());
protected <T> EntityModel<Object> extractChildEntityModel(EntityModel<T> declaringEntity,
Map<String, Object> attributes,
Field field) {
Class<?> entityType = (Class<?>) attributes.get("type");
if (Void.class.equals(entityType)) {
entityType = resolveGenericType(field, 0).orElseThrow(
() -> new AxonConfigurationException(format(
"Unable to resolve entity type of field [%s]. Please provide type explicitly in @AggregateMember annotation.",
field.toGenericString()
)));
}

return declaringEntity.modelOf(entityType);
}

@Override
protected <T> Object createCommandTargetResolvers(CommandMessage<?> msg,
T parent,
Map<String, Property<Object>> commandHandlerRoutingKeys,
Field field,
EntityModel<Object> childEntityModel) {
Map<String, Property<Object>> commandHandlerRoutingKeys =
extractCommandHandlerRoutingKeys(field, childEntityModel);

Object routingValue = commandHandlerRoutingKeys.get(msg.getCommandName())
.getValue(msg.getPayload());
Iterable<?> iterable = ReflectionUtils.getFieldValue(field, parent);

return StreamSupport.stream(iterable.spliterator(), false)
.filter(i -> Objects.equals(routingValue, childEntityModel.getIdentifier(i)))
.findFirst()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,53 +15,42 @@

package org.axonframework.commandhandling.model.inspection;

import org.axonframework.commandhandling.CommandMessage;
import org.axonframework.commandhandling.model.AggregateMember;
import org.axonframework.commandhandling.model.ForwardingMode;
import org.axonframework.common.ReflectionUtils;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Optional;

import static java.util.Collections.emptyList;
import static java.util.Collections.singleton;
import static org.axonframework.common.annotation.AnnotationUtils.findAnnotationAttributes;

/**
* Implementation of a {@link ChildEntityDefinition} that is used to detect single entities annotated with
* {@link AggregateMember}. If such a field is found a {@link ChildEntity} is created that delegates to the entity.
*/
public class AggregateMemberAnnotatedChildEntityDefinition implements ChildEntityDefinition {
public class AggregateMemberAnnotatedChildEntityDefinition extends AbstractChildEntityDefinition {

@Override
@SuppressWarnings("unchecked")
public <T> Optional<ChildEntity<T>> createChildDefinition(Field field, EntityModel<T> declaringEntity) {
Map<String, Object> attributes = findAnnotationAttributes(field, AggregateMember.class).orElse(null);
if (attributes == null
|| Iterable.class.isAssignableFrom(field.getType())
|| Map.class.isAssignableFrom(field.getType())) {
return Optional.empty();
}

EntityModel entityModel = declaringEntity.modelOf(field.getType());
protected boolean fieldIsOfType(Field field) {
return Iterable.class.isAssignableFrom(field.getType()) || Map.class.isAssignableFrom(field.getType());
}

Boolean forwardEvents = (Boolean) attributes.get("forwardEvents");
ForwardingMode eventForwardingMode = (ForwardingMode) attributes.get("eventForwardingMode");
@Override
protected <T> EntityModel<Object> extractChildEntityModel(EntityModel<T> declaringEntity,
Map<String, Object> attributes, Field field) {
return declaringEntity.modelOf(field.getType());
}

return Optional.of(new AnnotatedChildEntity<>(
entityModel,
(Boolean) attributes.get("forwardCommands"),
eventForwardingMode(forwardEvents, eventForwardingMode),
(String) attributes.get("eventRoutingKey"),
(msg, parent) -> ReflectionUtils.getFieldValue(field, parent),
(msg, parent) -> {
Object fieldVal = ReflectionUtils.getFieldValue(field, parent);
return fieldVal == null ? emptyList() : singleton(fieldVal);
}
));
@Override
protected <T> Object createCommandTargetResolvers(CommandMessage<?> msg, T parent,
Field field, EntityModel<Object> childEntityModel) {
return ReflectionUtils.getFieldValue(field, parent);
}

private ForwardingMode eventForwardingMode(Boolean forwardEvents, ForwardingMode eventForwardingMode) {
return !forwardEvents ? ForwardingMode.NONE : eventForwardingMode;
@Override
protected <T> Iterable<Object> createEventTargetResolvers(Field field, T parent) {
Object fieldVal = ReflectionUtils.getFieldValue(field, parent);
return fieldVal == null ? emptyList() : singleton(fieldVal);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@

import org.axonframework.commandhandling.CommandMessage;
import org.axonframework.commandhandling.model.AggregateMember;
import org.axonframework.common.AxonConfigurationException;
import org.axonframework.common.ReflectionUtils;
import org.axonframework.common.property.Property;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;

import static java.lang.String.format;
import static org.axonframework.common.ReflectionUtils.resolveGenericType;

/**
* Implementation of a {@link AbstractChildEntityDefinition} that is used to detect Maps with entities as
Expand All @@ -33,24 +36,38 @@
public class AggregateMemberAnnotatedChildEntityMapDefinition extends AbstractChildEntityDefinition {

@Override
protected Optional<Class<?>> resolveGenericType(Field field) {
return ReflectionUtils.resolveGenericType(field, 1);
protected boolean fieldIsOfType(Field field) {
return !Map.class.isAssignableFrom(field.getType());
}

@Override
protected boolean fieldIsOfType(Field field) {
return !Map.class.isAssignableFrom(field.getType());
protected <T> EntityModel<Object> extractChildEntityModel(EntityModel<T> declaringEntity,
Map<String, Object> attributes,
Field field) {
Class<?> entityType = (Class<?>) attributes.get("type");
if (Void.class.equals(entityType)) {
entityType = resolveGenericType(field, 1).orElseThrow(
() -> new AxonConfigurationException(format(
"Unable to resolve entity type of field [%s]. Please provide type explicitly in @AggregateMember annotation.",
field.toGenericString()
)));
}

return declaringEntity.modelOf(entityType);
}

@Override
protected <T> Object createCommandTargetResolvers(CommandMessage<?> msg,
T parent,
Map<String, Property<Object>> commandHandlerRoutingKeys,
Field field,
EntityModel<Object> childEntityModel) {
Map<String, Property<Object>> commandHandlerRoutingKeys =
extractCommandHandlerRoutingKeys(field, childEntityModel);

Object routingValue = commandHandlerRoutingKeys.get(msg.getCommandName())
.getValue(msg.getPayload());
Map<?, ?> fieldValue = ReflectionUtils.getFieldValue(field, parent);

return fieldValue == null ? null : fieldValue.get(routingValue);
}

Expand Down

0 comments on commit 41f3823

Please sign in to comment.