Repository: deltaspike Updated Branches: refs/heads/master 900d57084 -> 3175cb266
DELTASPIKE-606 Improve simplified DTO mapping Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/3175cb26 Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/3175cb26 Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/3175cb26 Branch: refs/heads/master Commit: 3175cb2669b47df33702676184e240834ee99d61 Parents: b0233a2 Author: Thomas Hug <[email protected]> Authored: Mon May 26 07:15:29 2014 -0700 Committer: Thomas Hug <[email protected]> Committed: Mon May 26 07:41:58 2014 -0700 ---------------------------------------------------------------------- .../api/mapping/SimpleQueryInOutMapperBase.java | 65 +++++++++++++++++++- .../mapping/SimpleQueryInOutMapperBaseTest.java | 26 ++++++-- .../impl/handler/CdiQueryInvocationContext.java | 2 +- .../data/impl/handler/QueryHandler.java | 2 +- .../deltaspike/data/impl/util/QueryUtils.java | 18 ------ .../data/impl/audit/TimestampsProviderTest.java | 4 +- .../data/impl/mapping/MappedRepositoryTest.java | 49 ++++++++++++++- .../deltaspike/data/test/domain/Simple.java | 2 +- .../test/service/SimpleMappedDtoRepository.java | 32 ++++++++++ .../data/test/service/SimpleMapper.java | 4 +- .../test/service/SimpleQueryInOutMapper.java | 53 ++++++++++++++++ .../data/test/util/TestDeployments.java | 4 +- 12 files changed, 224 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/mapping/SimpleQueryInOutMapperBase.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/mapping/SimpleQueryInOutMapperBase.java b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/mapping/SimpleQueryInOutMapperBase.java index a065755..ce8be8e 100644 --- a/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/mapping/SimpleQueryInOutMapperBase.java +++ b/deltaspike/modules/data/api/src/main/java/org/apache/deltaspike/data/api/mapping/SimpleQueryInOutMapperBase.java @@ -18,13 +18,47 @@ */ package org.apache.deltaspike.data.api.mapping; +import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; +import javax.inject.Inject; + +import org.apache.deltaspike.data.spi.QueryInvocationContext; + +/** + * A base mapper to map from Dto to Entity and vice versa. This should be sufficient + * for most mapping cases and simplify the implementation of a mapper. + * + * @param <Entity> The Entity type. + * @param <Dto> The Dto type. + */ public abstract class SimpleQueryInOutMapperBase<Entity, Dto> implements QueryInOutMapper<Entity> { + @Inject + private QueryInvocationContext context; + + /** + * Return the primary key of the Entity corresponding to the Dto. If this is a new + * Entity, return {@code null}. + * @param dto The Dto to map to an Entity. + * @return The Entity primary key, or {@code null} for a new Entity. + */ + protected abstract Object getPrimaryKey(Dto dto); + protected abstract Dto toDto(Entity entity); - protected abstract Entity toEntity(Dto dto); + + /** + * Map a Dto to an Entity. In case the Dto contains a valid primary key, + * the Entity will be retrieved first and used as method parameter. Otherwise + * Entity is a unmanaged new instance. + * + * @param entity Either a managed Entity looked up by the primary key, + * or a new Entity instance. + * @param dto The Dto to map. + * @return Mapped Entity. + */ + protected abstract Entity toEntity(Entity entity, Dto dto); @Override public Object mapResult(final Entity result) @@ -64,6 +98,33 @@ public abstract class SimpleQueryInOutMapperBase<Entity, Dto> implements QueryIn @Override public Object mapParameter(final Object parameter) { - return toEntity((Dto) parameter); + Dto dto = (Dto) parameter; + Object primaryKey = getPrimaryKey(dto); + if (primaryKey != null) + { + Entity entity = findEntity(primaryKey); + return toEntity(entity, dto); + } + return toEntity(newEntity(), dto); + } + + protected Entity newEntity() + { + try + { + Class<?> entityClass = context.getEntityClass(); + Constructor<?> constructor = entityClass.getDeclaredConstructor(); + constructor.setAccessible(true); + return (Entity) constructor.newInstance(); + } + catch (Exception e) + { + throw new RuntimeException("Failed instantiating new Entity", e); + } + } + + protected Entity findEntity(Object primaryKey) + { + return (Entity) context.getEntityManager().find(context.getEntityClass(), primaryKey); } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/api/src/test/java/org/apache/deltaspike/data/api/mapping/SimpleQueryInOutMapperBaseTest.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/api/src/test/java/org/apache/deltaspike/data/api/mapping/SimpleQueryInOutMapperBaseTest.java b/deltaspike/modules/data/api/src/test/java/org/apache/deltaspike/data/api/mapping/SimpleQueryInOutMapperBaseTest.java index 2bc4349..583f3a0 100644 --- a/deltaspike/modules/data/api/src/test/java/org/apache/deltaspike/data/api/mapping/SimpleQueryInOutMapperBaseTest.java +++ b/deltaspike/modules/data/api/src/test/java/org/apache/deltaspike/data/api/mapping/SimpleQueryInOutMapperBaseTest.java @@ -18,18 +18,19 @@ */ package org.apache.deltaspike.data.api.mapping; -import org.junit.Test; - -import java.util.Arrays; -import java.util.List; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + public class SimpleQueryInOutMapperBaseTest { + @Test public void checkDefault() { final SimpleQueryInOutMapperBase<String, Integer> mapper = new SimpleQueryInOutMapperBase<String, Integer>() @@ -40,7 +41,19 @@ public class SimpleQueryInOutMapperBaseTest } @Override - protected String toEntity(Integer b) { + protected String toEntity(String entity, Integer b) { + return entity; + } + + @Override + protected Object getPrimaryKey(Integer dto) + { + return null; + } + + @Override + protected String newEntity() + { return "ok"; } }; @@ -63,4 +76,5 @@ public class SimpleQueryInOutMapperBaseTest // but at least we test what is expected! assertEquals("ok", mapper.mapParameter(2)); } + } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java index d553114..5b6b892 100644 --- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java +++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java @@ -63,7 +63,7 @@ public class CdiQueryInvocationContext implements QueryInvocationContext this.cleanup = new LinkedList<Destroyable>(); } - public void init() + public void initMapper() { if (hasQueryInOutMapper()) { http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java index b2da59d..6b6ddb5 100755 --- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java +++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/QueryHandler.java @@ -103,8 +103,8 @@ public class QueryHandler implements Serializable, InvocationHandler { CdiQueryInvocationContext queryContext = new CdiQueryInvocationContext(proxy, method, args, repoMethod, entityManagerLookup.lookupFor(repo)); - queryContext.init(); context.set(queryContext); + queryContext.initMapper(); return queryContext; } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/QueryUtils.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/QueryUtils.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/QueryUtils.java index adea94d..306ab5b 100644 --- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/QueryUtils.java +++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/util/QueryUtils.java @@ -18,7 +18,6 @@ */ package org.apache.deltaspike.data.impl.util; -import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.Collection; @@ -83,21 +82,4 @@ public final class QueryUtils return value != null ? value : (fallback != null ? fallback : ""); } - public static boolean contains(Class<?> clazz, Method method) - { - return extract(clazz, method) != null; - } - - public static Method extract(Class<?> clazz, Method method) - { - try - { - String name = method.getName(); - return clazz.getMethod(name, method.getParameterTypes()); - } - catch (NoSuchMethodException e) - { - return null; - } - } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/audit/TimestampsProviderTest.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/audit/TimestampsProviderTest.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/audit/TimestampsProviderTest.java index baf4f0b..e8c87f7 100644 --- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/audit/TimestampsProviderTest.java +++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/audit/TimestampsProviderTest.java @@ -23,8 +23,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import org.apache.deltaspike.data.api.audit.CreatedOn; -import org.apache.deltaspike.data.impl.audit.AuditPropertyException; -import org.apache.deltaspike.data.impl.audit.TimestampsProvider; import org.apache.deltaspike.data.test.domain.AuditedEntity; import org.apache.deltaspike.data.test.domain.Simple; import org.junit.Test; @@ -68,7 +66,7 @@ public class TimestampsProviderTest public void should_not_fail_on_non_audited_entity() { // given - Simple entity = new Simple(); + Simple entity = new Simple("should_not_fail_on_non_audited_entity"); // when TimestampsProvider provider = new TimestampsProvider(); http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/mapping/MappedRepositoryTest.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/mapping/MappedRepositoryTest.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/mapping/MappedRepositoryTest.java index ff9db51..e539446 100644 --- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/mapping/MappedRepositoryTest.java +++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/mapping/MappedRepositoryTest.java @@ -36,8 +36,11 @@ import org.apache.deltaspike.data.test.domain.Simple; import org.apache.deltaspike.data.test.domain.Simple_; import org.apache.deltaspike.data.test.domain.dto.BooleanWrapper; import org.apache.deltaspike.data.test.domain.dto.SimpleDto; +import org.apache.deltaspike.data.test.domain.dto.SimpleId; +import org.apache.deltaspike.data.test.service.SimpleMappedDtoRepository; import org.apache.deltaspike.data.test.service.SimpleMappedRepository; import org.apache.deltaspike.data.test.service.SimpleMapper; +import org.apache.deltaspike.data.test.service.SimpleQueryInOutMapper; import org.apache.deltaspike.data.test.service.WrappedMapper; import org.apache.deltaspike.test.category.WebProfileCategory; import org.jboss.arquillian.container.test.api.Deployment; @@ -56,8 +59,10 @@ public class MappedRepositoryTest extends TransactionalTestCase initDeployment() .addClasses( SimpleMappedRepository.class, + SimpleMappedDtoRepository.class, SimpleMapper.class, - WrappedMapper.class) + WrappedMapper.class, + SimpleQueryInOutMapper.class) .addPackages(false, Simple.class.getPackage(), SimpleDto.class.getPackage())); @@ -66,6 +71,9 @@ public class MappedRepositoryTest extends TransactionalTestCase @Inject private SimpleMappedRepository repository; + @Inject + private SimpleMappedDtoRepository dtoRepository; + @Produces @PersistenceContext private EntityManager entityManager; @@ -156,6 +164,45 @@ public class MappedRepositoryTest extends TransactionalTestCase assertTrue(result.size() > 0); } + @Test + public void should_save_new_entity_with_simplemapper() + { + // given + SimpleDto dto = new SimpleDto(); + dto.setName("should_save_new_entity_with_simplemapper"); + dto.setEnabled(Boolean.TRUE); + + // when + SimpleDto result = dtoRepository.save(dto); + + // then + assertNotNull(result); + assertNotNull(result.getId()); + } + + @Test + public void should_update_existing_entity_with_simplemapper() + { + // given + final String name = "should_update_existing_entity_with_simplemapper"; + Simple simple = new Simple(name); + simple.setEnabled(Boolean.TRUE); + entityManager.persist(simple); + + SimpleDto dto = new SimpleDto(); + dto.setName(name + "_updated"); + dto.setEnabled(Boolean.TRUE); + dto.setId(new SimpleId(simple.getId())); + + // when + dtoRepository.save(dto); + Simple lookup = entityManager.find(Simple.class, simple.getId()); + + // then + assertNotNull(lookup); + assertEquals(name + "_updated", lookup.getName()); + } + @Override protected EntityManager getEntityManager() { http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/domain/Simple.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/domain/Simple.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/domain/Simple.java index 4f38f4d..5fadc99 100755 --- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/domain/Simple.java +++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/domain/Simple.java @@ -58,7 +58,7 @@ public class Simple private Date temporal; private EmbeddedSimple embedded; - public Simple() + protected Simple() { } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleMappedDtoRepository.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleMappedDtoRepository.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleMappedDtoRepository.java new file mode 100644 index 0000000..06f22a8 --- /dev/null +++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleMappedDtoRepository.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.deltaspike.data.test.service; + +import org.apache.deltaspike.data.api.EntityRepository; +import org.apache.deltaspike.data.api.Repository; +import org.apache.deltaspike.data.api.mapping.MappingConfig; +import org.apache.deltaspike.data.test.domain.Simple; +import org.apache.deltaspike.data.test.domain.dto.SimpleDto; +import org.apache.deltaspike.data.test.domain.dto.SimpleId; + +@Repository(forEntity = Simple.class) +@MappingConfig(SimpleQueryInOutMapper.class) +public interface SimpleMappedDtoRepository extends EntityRepository<SimpleDto, SimpleId> +{ +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleMapper.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleMapper.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleMapper.java index 51baaee..6a62fea 100644 --- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleMapper.java +++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleMapper.java @@ -63,11 +63,9 @@ public class SimpleMapper implements QueryInOutMapper<Simple> if (parameter instanceof SimpleDto) { SimpleDto dto = (SimpleDto) parameter; - Simple simple = new Simple(); + Simple simple = new Simple(dto.getName()); simple.setId(dto.getId() != null ? dto.getId().getId() : null); simple.setEnabled(dto.getEnabled()); - simple.setName(dto.getName()); - System.out.println("Converted " + simple); return simple; } return ((SimpleId) parameter).getId(); http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleQueryInOutMapper.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleQueryInOutMapper.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleQueryInOutMapper.java new file mode 100644 index 0000000..b92e801 --- /dev/null +++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleQueryInOutMapper.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.deltaspike.data.test.service; + +import org.apache.deltaspike.data.api.mapping.SimpleQueryInOutMapperBase; +import org.apache.deltaspike.data.test.domain.Simple; +import org.apache.deltaspike.data.test.domain.dto.SimpleDto; +import org.apache.deltaspike.data.test.domain.dto.SimpleId; + +public class SimpleQueryInOutMapper extends SimpleQueryInOutMapperBase<Simple, SimpleDto> +{ + + @Override + protected Object getPrimaryKey(SimpleDto dto) + { + return dto.getId() != null ? dto.getId().getId() : null; + } + + @Override + protected SimpleDto toDto(Simple entity) + { + SimpleDto dto = new SimpleDto(); + dto.setId(new SimpleId(entity.getId())); + dto.setEnabled(entity.getEnabled()); + dto.setName(entity.getName()); + return dto; + } + + @Override + protected Simple toEntity(Simple entity, SimpleDto dto) + { + entity.setName(dto.getName()); + entity.setEnabled(dto.getEnabled()); + return entity; + } + +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/3175cb26/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java index 68a65c1..a9dc8f1 100755 --- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java +++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/util/TestDeployments.java @@ -43,6 +43,7 @@ import org.apache.deltaspike.data.api.criteria.CriteriaSupport; import org.apache.deltaspike.data.api.criteria.QuerySelection; import org.apache.deltaspike.data.api.mapping.MappingConfig; import org.apache.deltaspike.data.api.mapping.QueryInOutMapper; +import org.apache.deltaspike.data.api.mapping.SimpleQueryInOutMapperBase; import org.apache.deltaspike.data.impl.RepositoryDefinitionException; import org.apache.deltaspike.data.impl.RepositoryExtension; import org.apache.deltaspike.data.impl.audit.AuditEntityListener; @@ -161,7 +162,8 @@ public abstract class TestDeployments .addClasses(Criteria.class, QuerySelection.class, CriteriaSupport.class) .addClasses(CreatedOn.class, CurrentUser.class, ModifiedBy.class, ModifiedOn.class) .addClasses(MappingConfig.class, QueryInOutMapper.class) - .addClasses(DelegateQueryHandler.class, QueryInvocationContext.class, RequiresTransaction.class); + .addClasses(DelegateQueryHandler.class, QueryInvocationContext.class, RequiresTransaction.class) + .addClasses(SimpleQueryInOutMapperBase.class); } public static WebArchive addDependencies(WebArchive archive)
