library/conversion: javadocs + prototype opportunity function
Project: http://git-wip-us.apache.org/repos/asf/zest-qi4j/repo Commit: http://git-wip-us.apache.org/repos/asf/zest-qi4j/commit/f1483cde Tree: http://git-wip-us.apache.org/repos/asf/zest-qi4j/tree/f1483cde Diff: http://git-wip-us.apache.org/repos/asf/zest-qi4j/diff/f1483cde Branch: refs/heads/master Commit: f1483cde9952072f4d8b7e636e1b51c30fc01c74 Parents: 7e0c8ae Author: Paul Merlin <[email protected]> Authored: Wed Feb 13 12:04:36 2013 +0100 Committer: Paul Merlin <[email protected]> Committed: Wed Feb 13 12:04:36 2013 +0100 ---------------------------------------------------------------------- .../conversion/values/EntityToValue.java | 225 +++++++++++++------ .../conversion/values/EntityToValueService.java | 17 ++ .../values/PropertyNotPresentException.java | 17 ++ .../conversion/values/EntityToValueTest.java | 51 +++++ 4 files changed, 246 insertions(+), 64 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/f1483cde/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValue.java ---------------------------------------------------------------------- diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValue.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValue.java index 2e9368f..99490cb 100644 --- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValue.java +++ b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValue.java @@ -1,3 +1,22 @@ +/* + * Copyright 2010 Niclas Hedhman. + * Copyright 2011 Rickard Ãberg. + * Copyright 2013 Paul Merlin. + * + * Licensed 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.qi4j.library.conversion.values; import java.lang.reflect.AccessibleObject; @@ -20,7 +39,6 @@ import org.qi4j.api.structure.Module; import org.qi4j.api.type.CollectionType; import org.qi4j.api.value.NoSuchValueException; import org.qi4j.api.value.ValueBuilder; -import org.qi4j.api.value.ValueBuilderFactory; import org.qi4j.api.value.ValueDescriptor; import org.qi4j.functional.Function; import org.qi4j.functional.Iterables; @@ -29,23 +47,103 @@ import org.qi4j.spi.Qi4jSPI; @Mixins( EntityToValue.EntityToValueMixin.class ) public interface EntityToValue { + + /** + * Convert an entity to a value. + * + * @param <T> parametrized type of the value + * @param valueType type of the value + * @param entity the entity to convert to a value + * @return the resulting value + */ <T> T convert( Class<T> valueType, Object entity ); + /** + * Convert an entity to a value with an opportunity to customize its prototype. + * + * @param <T> parametrized type of the value + * @param valueType type of the value + * @param entity the entity to convert to a value + * @param prototypeOpportunity a Function that will be mapped on the value prototype before instanciantion + * @return the resulting value + */ + <T> T convert( Class<T> valueType, Object entity, Function<T, T> prototypeOpportunity ); + + /** + * Convert an iterable of entities to an iterable of values. + * + * @param <T> parametrized type of the value + * @param valueType type of the value + * @param entities the entities to convert to values + * @return the resulting values + */ + <T> Iterable<T> convert( Class<T> valueType, Iterable<Object> entities ); + + /** + * Convert an iterable of entities to an iterable of values with an opportunity to customize their prototypes. + * + * @param <T> parametrized type of the value + * @param valueType type of the value + * @param entities the entities to convert to values + * @param prototypeOpportunity a Function that will be mapped on each of the value prototypes before instanciation. + * @return the resulting values + */ + <T> Iterable<T> convert( Class<T> valueType, Iterable<Object> entities, Function<T, T> prototypeOpportunity ); + static class EntityToValueMixin implements EntityToValue { - @Structure - private ValueBuilderFactory vbf; @Structure private Qi4jSPI spi; - @Structure private Module module; @Override public <T> T convert( final Class<T> valueType, Object entity ) { + return createInstance( doConversion( valueType, entity ) ); + } + + @Override + @SuppressWarnings( "unchecked" ) + public <T> T convert( final Class<T> valueType, Object entity, Function<T, T> prototypeOpportunity ) + { + ValueBuilder<?> builder = doConversion( valueType, entity ); + prototypeOpportunity.map( (T) builder.prototype() ); + return createInstance( builder ); + } + + @Override + public <T> Iterable<T> convert( final Class<T> valueType, Iterable<Object> entities ) + { + return Iterables.map( + new Function<Object, T>() + { + @Override + public T map( Object entity ) + { + return convert( valueType, entity ); + } + }, entities ); + } + + @Override + public <T> Iterable<T> convert( final Class<T> valueType, Iterable<Object> entities, final Function<T, T> prototypeOpportunity ) + { + return Iterables.map( + new Function<Object, T>() + { + @Override + public T map( Object entity ) + { + return convert( valueType, entity, prototypeOpportunity ); + } + }, entities ); + } + + private <T> ValueBuilder<?> doConversion( final Class<T> valueType, Object entity ) + { ValueDescriptor valueDescriptor = module.valueDescriptor( valueType.getName() ); if( valueDescriptor == null ) { @@ -56,12 +154,12 @@ public interface EntityToValue final EntityComposite composite = (EntityComposite) entity; final EntityDescriptor entityDescriptor = spi.entityDescriptorFor( composite ); final AssociationStateHolder associationState = spi.stateOf( composite ); - ValueBuilder builder; + ValueBuilder<?> builder; if( unqualified == null || !unqualified.value() ) { // Copy state using qualified names - builder = vbf.newValueBuilderWithState( + builder = module.newValueBuilderWithState( valueType, new Function<PropertyDescriptor, Object>() { @@ -127,31 +225,30 @@ public interface EntityToValue } } }, new Function<AssociationDescriptor, EntityReference>() + { + @Override + public EntityReference map( AssociationDescriptor associationDescriptor ) { - @Override - public EntityReference map( AssociationDescriptor associationDescriptor ) - { - return EntityReference.entityReferenceFor( - associationState.associationFor( associationDescriptor.accessor() ).get() ); - } - }, new Function<AssociationDescriptor, Iterable<EntityReference>>() + return EntityReference.entityReferenceFor( + associationState.associationFor( associationDescriptor.accessor() ).get() ); + } + }, new Function<AssociationDescriptor, Iterable<EntityReference>>() + { + @Override + public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor ) { - @Override - public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor ) + List<EntityReference> refs = new ArrayList<EntityReference>(); + for( Object entity : associationState.manyAssociationFor( associationDescriptor.accessor() ) ) { - List<EntityReference> refs = new ArrayList<EntityReference>(); - for( Object entity : associationState.manyAssociationFor( associationDescriptor.accessor() ) ) - { - refs.add( EntityReference.entityReferenceFor( entity ) ); - } - return refs; + refs.add( EntityReference.entityReferenceFor( entity ) ); } + return refs; } - ); + } ); } else { - builder = vbf.newValueBuilderWithState( + builder = module.newValueBuilderWithState( valueType, new Function<PropertyDescriptor, Object>() { @@ -217,61 +314,61 @@ public interface EntityToValue } } }, new Function<AssociationDescriptor, EntityReference>() + { + @Override + public EntityReference map( AssociationDescriptor descriptor ) { - @Override - public EntityReference map( AssociationDescriptor descriptor ) + AssociationDescriptor associationDescriptor; + try { - AssociationDescriptor associationDescriptor; - try - { - associationDescriptor = entityDescriptor.state() - .getAssociationByName( descriptor.qualifiedName() - .name() ); - } - catch( Exception e ) - { - return null; - } - - AccessibleObject associationMethod = associationDescriptor.accessor(); - Association<Object> association = associationState.associationFor( associationMethod ); - return EntityReference.entityReferenceFor( association.get() ); + associationDescriptor = entityDescriptor.state() + .getAssociationByName( descriptor.qualifiedName() + .name() ); + } + catch( Exception e ) + { + return null; } - }, new Function<AssociationDescriptor, Iterable<EntityReference>>() + + AccessibleObject associationMethod = associationDescriptor.accessor(); + Association<Object> association = associationState.associationFor( associationMethod ); + return EntityReference.entityReferenceFor( association.get() ); + } + }, new Function<AssociationDescriptor, Iterable<EntityReference>>() + { + @Override + public Iterable<EntityReference> map( final AssociationDescriptor descriptor ) { - @Override - public Iterable<EntityReference> map( final AssociationDescriptor descriptor ) + AssociationDescriptor associationDescriptor; + try { - AssociationDescriptor associationDescriptor; - try - { - String associationName = descriptor.qualifiedName().name(); - AssociationStateDescriptor entityState = entityDescriptor.state(); - associationDescriptor = entityState.getManyAssociationByName( associationName ); - } - catch( IllegalArgumentException e ) - { - return Iterables.empty(); - } + String associationName = descriptor.qualifiedName().name(); + AssociationStateDescriptor entityState = entityDescriptor.state(); + associationDescriptor = entityState.getManyAssociationByName( associationName ); + } + catch( IllegalArgumentException e ) + { + return Iterables.empty(); + } - List<EntityReference> refs = new ArrayList<EntityReference>(); - AccessibleObject associationMethod = associationDescriptor.accessor(); - for( Object entity : associationState.manyAssociationFor( associationMethod ) ) - { - refs.add( EntityReference.entityReferenceFor( entity ) ); - } - return refs; + List<EntityReference> refs = new ArrayList<EntityReference>(); + AccessibleObject associationMethod = associationDescriptor.accessor(); + for( Object entity : associationState.manyAssociationFor( associationMethod ) ) + { + refs.add( EntityReference.entityReferenceFor( entity ) ); } + return refs; } - ); + } ); } - return createInstance( builder ); + return builder; } @SuppressWarnings( "unchecked" ) - private <T> T createInstance( ValueBuilder builder ) + private <T> T createInstance( ValueBuilder<?> builder ) { return (T) builder.newInstance(); } } + } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/f1483cde/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueService.java ---------------------------------------------------------------------- diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueService.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueService.java index 660fbd5..804d398 100644 --- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueService.java +++ b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueService.java @@ -1,3 +1,20 @@ +/* + * Copyright 2010 Niclas Hedhman. + * + * Licensed 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.qi4j.library.conversion.values; import org.qi4j.api.service.ServiceComposite; http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/f1483cde/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/PropertyNotPresentException.java ---------------------------------------------------------------------- diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/PropertyNotPresentException.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/PropertyNotPresentException.java index 0f84cc8..74ca600 100644 --- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/PropertyNotPresentException.java +++ b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/PropertyNotPresentException.java @@ -1,3 +1,20 @@ +/* + * Copyright 2010 Niclas Hedhman. + * + * Licensed 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.qi4j.library.conversion.values; import org.qi4j.api.entity.EntityComposite; http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/f1483cde/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/EntityToValueTest.java ---------------------------------------------------------------------- diff --git a/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/EntityToValueTest.java b/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/EntityToValueTest.java index f2e6030..1c5e641 100644 --- a/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/EntityToValueTest.java +++ b/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/EntityToValueTest.java @@ -1,3 +1,20 @@ +/* + * Copyright 2010 Niclas Hedhman. + * + * Licensed 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.qi4j.library.conversion.values; import java.util.Calendar; @@ -20,6 +37,7 @@ import org.qi4j.api.unitofwork.UnitOfWorkCompletionException; import org.qi4j.api.value.ValueComposite; import org.qi4j.bootstrap.AssemblyException; import org.qi4j.bootstrap.ModuleAssembly; +import org.qi4j.functional.Function; import org.qi4j.test.AbstractQi4jTest; import org.qi4j.test.EntityTestAssembler; @@ -140,6 +158,39 @@ public class EntityToValueTest } } + @Test + public void whenConvertingEntityToValueUsingPrototypeOpportunityExpectCorrectValues() + throws UnitOfWorkCompletionException + { + UnitOfWork uow = module.newUnitOfWork(); + try + { + PersonEntity entity = setupPersonEntities( uow ); + + // START SNIPPET: prototypeOpportunity + EntityToValueService conversion = module.findService( EntityToValueService.class ).get(); + PersonValue value = conversion.convert( PersonValue.class, entity, new Function<PersonValue, PersonValue>() + { + @Override + public PersonValue map( PersonValue prototype ) + { + prototype.firstName().set( "Prototype Opportunity" ); + return prototype; + } + } ); + // END SNIPPET: prototypeOpportunity + assertEquals( "Prototype Opportunity", value.firstName().get() ); + assertEquals( "Hedhman", value.lastName().get() ); + assertEquals( "id:Lis", value.spouse().get() ); + assertEquals( "id:Eric", value.children().get().get( 0 ) ); + uow.complete(); + } + finally + { + uow.discard(); + } + } + private PersonEntity setupPersonEntities( UnitOfWork uow ) { PersonEntity niclas = createNiclas( uow );
