public CommandType getCommandType() { return CommandType.of(aggregateType, commandName); }
public CommandTypeInfo getCommandTypeInfo() { return CommandTypeInfo.of(tupleSchema, resultType); }
private void populateArgsFromTuple(Command command, Object[] args) { IntStream.range(0, tupleKeys.length).forEach(i -> args[i + 2] = command.getParameters().get(tupleKeys[i])); }
/** * Convert the supplied {@link Command} into a {@link CommandJson} object suitable for JSON serialisation. * @param command The {@link Command} to convert. * @param objectMapper The {@link ObjectMapper} to use to convert the {@link Command}'s parameters into JSON nodes. * @return The converted {@link CommandJson}. */ public static CommandJson of(Command command, ObjectMapper objectMapper) { Function<Object, JsonNode> serialiser = objectMapper::valueToTree; return of( command.getAggregateId().getType(), command.getAggregateId().getId(), command.getCommandName().getName(), command.getCommandName().getVersion(), command.getCommandTimestamp().getTimestamp().toEpochMilli(), command.getCommandTimestamp().getStreamId(), command.getProcessingId().map(UUID::toString).orElse(""), command.getParameters().serialise(serialiser) ); }
/** * Convert this {@link CommandJson} to an {@link Command}, using the supplied {@link CommandTypeMatcher} and * {@link ObjectMapper}. * @param typeMatcher The {@link CommandTypeMatcher} to use to resolve {@link CommandType}s to * {@link com.opencredo.concursus.domain.commands.CommandTypeInfo}. * @param objectMapper The {@link ObjectMapper} to use to deserialise event parameters. * @return The converted {@link Command}, iff the {@link CommandTypeMatcher} matches its type. */ public Optional<Command> toCommand(CommandTypeMatcher typeMatcher, ObjectMapper objectMapper) { CommandType commandType = getCommandType(); BiFunction<JsonNode, Type, Object> deserialiser = makeDeserialiser(objectMapper); return typeMatcher.match(commandType).map(typeInfo -> commandType.makeCommand( aggregateId, StreamTimestamp.of(streamId, Instant.ofEpochMilli(commandTimestamp)), typeInfo.getTupleSchema().deserialise(deserialiser, parameters), typeInfo.getReturnType() )) .map(command -> processingId.isEmpty() ? command : command.processed(UUID.fromString(processingId)) ); }
public Object[] mapCommand(Command command) { checkNotNull(command, "command must not be null"); Object[] args = new Object[tupleKeys.length + 2]; args[0] = command.getCommandTimestamp(); args[1] = command.getAggregateId().getId(); populateArgsFromTuple(command, args); return args; }
public static CommandMethodMapping forMethod(Method method, String aggregateType) { checkNotNull(method, "method must not be null"); final VersionedName commandName = getCommandName(method); ParameterArgs parameterArgs = ParameterArgs.forMethod(method, 2); TupleSchema schema = parameterArgs.getTupleSchema(CommandType.of(aggregateType, commandName).toString()); TupleKey[] tupleKeys = parameterArgs.getTupleKeys(schema); return new CommandMethodMapping( aggregateType, commandName, schema, tupleKeys, method.getGenericReturnType()); }
@Override public CompletableFuture<Optional<Object>> apply(Command command) { String json = serialise(command); return inChannel.apply(json).thenApply(deserialiseTo(command.getResultType())); }
@Override public CompletableFuture<?> apply(Object o, Command command) { CommandDispatcher dispatcher = dispatcherMap.get(command.getCommandType()); return dispatcher.apply(o, command); }
public Command mapArguments(Object[] args) { checkNotNull(args, "args must not be null"); checkArgument(args.length == tupleKeys.length + 2, "Expected %s args, received %s", tupleKeys.length +2, args.length); checkArgument(args[0] instanceof StreamTimestamp, "first argument %s is not a StreamTimestamp", args[0]); checkArgument(args[1] instanceof String, "second argument %s is not a String", args[0]); return Command.of( AggregateId.of(aggregateType, (String) args[1]), (StreamTimestamp) args[0], commandName, makeTupleFromArgs(args), resultType ); }
private static CommandInterfaceInfo forInterfaceUncached(Class<?> iface) { checkNotNull(iface, "iface must not be null"); checkArgument(iface.isInterface(), "iface must be interface"); checkArgument(iface.isAnnotationPresent(HandlesCommandsFor.class), "Interface %s is not annotated with @HandlesCommandsFor", iface); String aggregateType = iface.getAnnotation(HandlesCommandsFor.class).value(); Map<Method, CommandMethodMapping> commandMappers = getCommandMappers(iface, aggregateType); Map<CommandType, CommandTypeInfo> typeInfoMap = commandMappers.values().stream().collect(Collectors.toMap( CommandMethodMapping::getCommandType, CommandMethodMapping::getCommandTypeInfo )); MultiTypeCommandDispatcher commandDispatcher = CommandDispatchers.dispatchingCommandsByType(commandMappers); return new CommandInterfaceInfo(typeInfoMap, commandMappers, CommandTypeMatcher.matchingAgainst(typeInfoMap), commandDispatcher); }
@JsonIgnore public CommandType getCommandType() { return CommandType.of(aggregateType, VersionedName.of(name, version)); } }