Skip to content

Commit

Permalink
Complete assembler DSL use cases
Browse files Browse the repository at this point in the history
Add use cases with lists for dto, aggregate and tuple.
Delete the AssemblerContext which was passed between
DSL elements. This last change also fixed some bugs.
  • Loading branch information
pith committed Apr 21, 2015
1 parent 35274f7 commit 295d4c0
Show file tree
Hide file tree
Showing 28 changed files with 1,011 additions and 381 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class AssemblerDslWithTupleIT {
public void testAssembleFromFactory() {
Recipe recipe = new Recipe("customer1", "luke", "order1", "light saber");

Pair<Order, Customer> orderCustomerPair = fluently.assemble().dto(recipe).<Pair<Order, Customer>>to(Order.class, Customer.class).fromFactory();
Pair<Order, Customer> orderCustomerPair = fluently.assemble().dto(recipe).to(Order.class, Customer.class).fromFactory();

Assertions.assertThat(orderCustomerPair.getValue0()).isNotNull();
Assertions.assertThat(orderCustomerPair.getValue0().getEntityId()).isEqualTo("order1");
Expand All @@ -71,7 +71,7 @@ public void testAssembleFromRepository() {

Pair<Order, Customer> orderCustomerPair = null;
try {
orderCustomerPair = fluently.assemble().dto(recipe).<Pair<Order, Customer>>to(Order.class, Customer.class).fromRepository().orFail();
orderCustomerPair = fluently.assemble().dto(recipe).to(Order.class, Customer.class).fromRepository().orFail();
} catch (AggregateNotFoundException e) {
fail();
}
Expand All @@ -86,8 +86,9 @@ public void testAssembleFromRepository() {
@Test
@Ignore
public void testAssembleFromRepositoryOrFail() {
Recipe recipe = new Recipe("customer1", "luke", "order1", "light saber");
try {
fluently.assemble().dto(new OrderDto("1", "light saber")).to(Order.class).fromRepository().orFail();
fluently.assemble().dto(recipe).to(Order.class, Customer.class).fromRepository().orFail();
fail();
} catch (AggregateNotFoundException e) {
Assertions.assertThat(e).isNotNull();
Expand All @@ -97,15 +98,16 @@ public void testAssembleFromRepositoryOrFail() {
@Test
@Ignore
public void testAssembleFromRepositoryOrFactory() {
OrderDto dto = new OrderDto("1", "light saber", PRICE);
Recipe recipe = new Recipe("customer1", "luke", "order1", "light saber");

Order aggregateRoot = fluently.assemble().dto(dto).to(Order.class).fromRepository().thenFromFactory();
Pair<Order, Customer> orderCustomerPair = fluently.assemble().dto(recipe).to(Order.class, Customer.class).fromRepository().thenFromFactory();

Assertions.assertThat(aggregateRoot).isNotNull();
Assertions.assertThat(aggregateRoot.getEntityId()).isEqualTo("1");
Assertions.assertThat(aggregateRoot.getProduct()).isEqualTo("light saber");
// the customer name is not part of the factory parameters, but so it should be set by the assembler
Assertions.assertThat(aggregateRoot.getPrice()).isEqualTo(PRICE);
Assertions.assertThat(orderCustomerPair.getValue0()).isNotNull();
Assertions.assertThat(orderCustomerPair.getValue0().getEntityId()).isEqualTo("order1");
Assertions.assertThat(orderCustomerPair.getValue0().getProduct()).isEqualTo("light saber");
// the customer name is not part of the factory parameters, so it is set by the assembler
Assertions.assertThat(orderCustomerPair.getValue1().getEntityId()).isEqualTo("customer1");
Assertions.assertThat(orderCustomerPair.getValue1().getName()).isEqualTo("luke");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ protected A doLoad(K id) {
return null;
}


@Override
protected void doDelete(K id) {

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,49 +10,47 @@
package org.seedstack.business.core.interfaces.assembler.dsl;

import org.seedstack.business.api.domain.AggregateRoot;
import org.seedstack.business.api.domain.GenericFactory;
import org.seedstack.business.api.domain.Repository;
import org.seedstack.business.api.interfaces.assembler.Assembler;
import org.seedstack.business.api.interfaces.assembler.dsl.AggAssemblerWithRepoAndFactProvider;
import org.seedstack.business.api.interfaces.assembler.dsl.AggAssemblerWithRepoProvider;
import org.seedstack.business.api.interfaces.assembler.dsl.AggregateNotFoundException;
import org.seedstack.business.api.interfaces.assembler.resolver.ParameterHolder;

/**
* @author Pierre Thirouin <pierre.thirouin@ext.mpsa.com>
*/
public class AggAssemblerWithRepoProviderImpl<A extends AggregateRoot<?>> extends BaseAggAssemblerWithRepoProviderImpl implements AggAssemblerWithRepoProvider<A>, AggAssemblerWithRepoAndFactProvider<A> {
public class AggAssemblerWithRepoProviderImpl<A extends AggregateRoot<?>> extends BaseAggAssemblerWithRepoProviderImpl<A> implements AggAssemblerWithRepoProvider<A>, AggAssemblerWithRepoAndFactProvider<A> {

public AggAssemblerWithRepoProviderImpl(InternalRegistry registry, AssemblerContext assemblerContext) {
super(registry, assemblerContext);
private final Class<A> aggregateClass;
private final Object dto;

public AggAssemblerWithRepoProviderImpl(InternalRegistry registry, Class<A> aggregateClass, Object dto) {
super(registry);
this.aggregateClass = aggregateClass;
this.dto = dto;
}

// --------------------------- AggAssemblerWithRepoProvider

@Override
public AggAssemblerWithRepoAndFactProvider<A> fromRepository() {
assemblerContext.setRepository(registry.repositoryOf(assemblerContext.getAggregateClass()));
// Just redirect to the expected DSL path
return this;
}

@SuppressWarnings("unchecked")
@Override
public A fromFactory() {
GenericFactory<A> genericFactory = (GenericFactory<A>) registry.genericFactoryOf(assemblerContext.getAggregateClass());
ParameterHolder parameterHolder = dtoInfoResolver.resolveAggregate(assemblerContext.getDto());
A aggregateRoot = (A) getAggregateFromFactory(genericFactory, assemblerContext.getAggregateClass(), parameterHolder.parameters());
return assembleWithDto(aggregateRoot);
return fromFactory(aggregateClass,dto);
}

/**
* Loads an aggregate roots from a repository.
*
* @param key the aggregate roots identity
* @param <A> the aggregate root type
* @return the loaded aggregate root
*/
protected <A> A loadFromRepo(Object key) {
Repository repository = assemblerContext.getRepository();
protected A loadFromRepo(Object key) {
Repository repository = registry.repositoryOf(aggregateClass);
//noinspection unchecked
return (A) repository.load(key);
}
Expand All @@ -61,43 +59,29 @@ protected <A> A loadFromRepo(Object key) {

@Override
public A orFail() throws AggregateNotFoundException {
Object id = resolveId(assemblerContext.getDto(), assemblerContext.getAggregateClass());
Object id = resolveId(dto, aggregateClass);
A a = loadFromRepo(id);

if (a == null) {
throw new AggregateNotFoundException(String.format("Unable to load aggregate %s for id: %s", assemblerContext.getAggregateClass(), id));
throw new AggregateNotFoundException(String.format("Unable to load aggregate %s for id: %s", aggregateClass, id));
}

return assembleWithDto(a);
return assembleWithDto(a, dto);
}

@Override
public A thenFromFactory() {
// load from the repository
Object id = resolveId(assemblerContext.getDto(), assemblerContext.getAggregateClass());
Object id = resolveId(dto, aggregateClass);
A a = loadFromRepo(id);

if (a != null) {
// then assemble the dto in the previously created aggregate root
return assembleWithDto(a);
return assembleWithDto(a, dto);
} else {
// otherwise fallback on the factory
return fromFactory();
}
}

/**
* Assemble one or a tuple of aggregate root from a dto.
*
* @param aggregateRoots the aggregate root(s) to assemble
* @param <T> type of aggregate root(s). It could be a {@code Tuple} or an {@code AggregateRoot}
* @return the assembled aggregate root(s)
*/
protected <T> T assembleWithDto(T aggregateRoots) {
Assembler assembler = registry.assemblerOf(assemblerContext.getAggregateClass(), assemblerContext.getDto().getClass());
//noinspection unchecked
assembler.mergeAggregateWithDto(aggregateRoots, assemblerContext.getDto());
return aggregateRoots;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
* Copyright (c) 2013-2015 by The SeedStack authors. All rights reserved.
*
* This file is part of SeedStack, An enterprise-oriented full development stack.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.business.core.interfaces.assembler.dsl;

import com.google.common.collect.Lists;
import org.javatuples.*;
import org.seedstack.business.api.domain.AggregateRoot;
import org.seedstack.business.api.interfaces.assembler.Assembler;
import org.seedstack.business.api.interfaces.assembler.dsl.AggsAssemblerProvider;
import org.seedstack.business.api.interfaces.assembler.dsl.AggsAssemblerWithRepoProvider;
import org.seedstack.business.api.interfaces.assembler.dsl.TupleAggsAssemblerWithRepoProvider;

import java.util.ArrayList;
import java.util.List;

/**
* @author Pierre Thirouin <pierre.thirouin@ext.mpsa.com>
*/
public class AggsAssemblerProviderImpl<D> implements AggsAssemblerProvider<D> {

private InternalRegistry registry;
private final List<D> dtos;

public AggsAssemblerProviderImpl(InternalRegistry registry, List<D> dtos) {
this.registry = registry;
this.dtos = dtos;
}

@Override
public <A extends AggregateRoot<?>> AggsAssemblerWithRepoProvider<A> to(Class<A> aggregateRootClass) {
return new AggsAssemblerWithRepoProviderImpl<A>(registry, aggregateRootClass, dtos);
}

@Override
public <A1 extends AggregateRoot<?>, A2 extends AggregateRoot<?>>
TupleAggsAssemblerWithRepoProvider<Pair<A1, A2>> to(Class<A1> first, Class<A2> second) {
return new TupleAggsAssemblerWithRepoProviderImpl<Pair<A1, A2>>(registry, Lists.newArrayList(first, second), dtos);
}

@Override
public <A1 extends AggregateRoot<?>, A2 extends AggregateRoot<?>, A3 extends AggregateRoot<?>>
TupleAggsAssemblerWithRepoProvider<Triplet<A1, A2, A3>> to(Class<A1> first, Class<A2> second, Class<A3> third) {
return new TupleAggsAssemblerWithRepoProviderImpl<Triplet<A1, A2, A3>>(registry, Lists.newArrayList(first, second, third), dtos);
}

@Override
public <A1 extends AggregateRoot<?>, A2 extends AggregateRoot<?>, A3 extends AggregateRoot<?>, A4 extends AggregateRoot<?>>
TupleAggsAssemblerWithRepoProvider<Quartet<A1, A2, A3, A4>> to(Class<A1> first, Class<A2> second, Class<A3> third, Class<A4> fourth) {
return new TupleAggsAssemblerWithRepoProviderImpl<Quartet<A1, A2, A3, A4>>(registry, Lists.newArrayList(first, second, third, fourth), dtos);
}

@Override
public <A1 extends AggregateRoot<?>, A2 extends AggregateRoot<?>, A3 extends AggregateRoot<?>, A4 extends AggregateRoot<?>, A5 extends AggregateRoot<?>>
TupleAggsAssemblerWithRepoProvider<Quintet<A1, A2, A3, A4, A5>> to(Class<A1> first, Class<A2> second, Class<A3> third, Class<A4> fourth, Class<A5> fifth) {
return new TupleAggsAssemblerWithRepoProviderImpl<Quintet<A1, A2, A3, A4, A5>>(registry, Lists.newArrayList(first, second, third, fourth, fifth), dtos);
}

@Override
public <A1 extends AggregateRoot<?>, A2 extends AggregateRoot<?>, A3 extends AggregateRoot<?>, A4 extends AggregateRoot<?>, A5 extends AggregateRoot<?>, A6 extends AggregateRoot<?>>
TupleAggsAssemblerWithRepoProvider<Sextet<A1, A2, A3, A4, A5, A6>> to(Class<A1> first, Class<A2> second, Class<A3> third, Class<A4> fourth, Class<A5> fifth, Class<A6> sixth) {
return new TupleAggsAssemblerWithRepoProviderImpl<Sextet<A1, A2, A3, A4, A5, A6>>(registry, Lists.newArrayList(first, second, third, fourth, fifth, sixth), dtos);
}

@Override
public <A1 extends AggregateRoot<?>, A2 extends AggregateRoot<?>, A3 extends AggregateRoot<?>, A4 extends AggregateRoot<?>, A5 extends AggregateRoot<?>, A6 extends AggregateRoot<?>, A7 extends AggregateRoot<?>>
TupleAggsAssemblerWithRepoProvider<Septet<A1, A2, A3, A4, A5, A6, A7>> to(Class<A1> first, Class<A2> second, Class<A3> third, Class<A4> fourth, Class<A5> fifth, Class<A6> sixth, Class<A7> seventh) {
return new TupleAggsAssemblerWithRepoProviderImpl<Septet<A1, A2, A3, A4, A5, A6, A7>>(registry, Lists.newArrayList(first, second, third, fourth, fifth, sixth, seventh), dtos);
}

@Override
public <A1 extends AggregateRoot<?>, A2 extends AggregateRoot<?>, A3 extends AggregateRoot<?>, A4 extends AggregateRoot<?>, A5 extends AggregateRoot<?>, A6 extends AggregateRoot<?>, A7 extends AggregateRoot<?>, A8 extends AggregateRoot<?>>
TupleAggsAssemblerWithRepoProvider<Octet<A1, A2, A3, A4, A5, A6, A7, A8>> to(Class<A1> first, Class<A2> second, Class<A3> third, Class<A4> fourth, Class<A5> fifth, Class<A6> sixth, Class<A7> seventh, Class<A8> eighth) {
return new TupleAggsAssemblerWithRepoProviderImpl<Octet<A1, A2, A3, A4, A5, A6, A7, A8>>(registry, Lists.newArrayList(first, second, third, fourth, fifth, sixth, seventh, eighth), dtos);
}

@Override
public <A1 extends AggregateRoot<?>, A2 extends AggregateRoot<?>, A3 extends AggregateRoot<?>, A4 extends AggregateRoot<?>, A5 extends AggregateRoot<?>, A6 extends AggregateRoot<?>, A7 extends AggregateRoot<?>, A8 extends AggregateRoot<?>, A9 extends AggregateRoot<?>>
TupleAggsAssemblerWithRepoProvider<Ennead<A1, A2, A3, A4, A5, A6, A7, A8, A9>> to(Class<A1> first, Class<A2> second, Class<A3> third, Class<A4> fourth, Class<A5> fifth, Class<A6> sixth, Class<A7> seventh, Class<A8> eighth, Class<A9> ninth) {
return new TupleAggsAssemblerWithRepoProviderImpl<Ennead<A1, A2, A3, A4, A5, A6, A7, A8, A9>>(registry, Lists.newArrayList(first, second, third, fourth, fifth, sixth, seventh, eighth, ninth), dtos);
}

@Override
public <A1 extends AggregateRoot<?>, A2 extends AggregateRoot<?>, A3 extends AggregateRoot<?>, A4 extends AggregateRoot<?>, A5 extends AggregateRoot<?>, A6 extends AggregateRoot<?>, A7 extends AggregateRoot<?>, A8 extends AggregateRoot<?>, A9 extends AggregateRoot<?>, A10 extends AggregateRoot<?>>
TupleAggsAssemblerWithRepoProvider<Decade<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>> to(Class<A1> first, Class<A2> second, Class<A3> third, Class<A4> fourth, Class<A5> fifth, Class<A6> sixth, Class<A7> seventh, Class<A8> eighth, Class<A9> ninth, Class<A10> tenth) {
return new TupleAggsAssemblerWithRepoProviderImpl<Decade<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>>(registry, Lists.newArrayList(first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth), dtos);
}

// -----------------------------------------------------------------------------------------------------------------

@Override
public TupleAggsAssemblerWithRepoProvider<Tuple> to(Tuple aggregateRootClassTuple) {
List<Class<? extends AggregateRoot<?>>> aggregateRootClasses = new ArrayList<Class<? extends AggregateRoot<?>>>();
for (Object aggregateRootClass : aggregateRootClassTuple) {
if (aggregateRootClass instanceof Class) {
aggregateRootClasses.add((Class<? extends AggregateRoot<?>>) aggregateRootClass);
}
}

return new TupleAggsAssemblerWithRepoProviderImpl<Tuple>(registry, aggregateRootClasses, dtos);
}

@Override
public <A extends AggregateRoot<?>> List<A> to(List<A> aggregateRoots) {
if (aggregateRoots != null && dtos != null) {
if (aggregateRoots.size() != dtos.size()) {
throw new IllegalArgumentException("The list of dto should have the same size as the list of aggregate");
}
Assembler assembler = registry.assemblerOf((Class<? extends AggregateRoot<?>>) aggregateRoots.get(0).getClass(), dtos.get(0).getClass());
for (int i = 0; i < aggregateRoots.size(); i++) {
assembler.mergeAggregateWithDto(aggregateRoots.get(i), dtos.get(i));
}
}
return aggregateRoots;
}

}
Loading

0 comments on commit 295d4c0

Please sign in to comment.