package fr.openwide.core.test.wicket.more.link.descriptor; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import java.util.List; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.util.ListModel; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import fr.openwide.core.commons.util.functional.Suppliers2; import fr.openwide.core.test.wicket.more.business.person.model.Person; import fr.openwide.core.test.wicket.more.business.person.service.IPersonService; import fr.openwide.core.wicket.more.condition.Condition; import fr.openwide.core.wicket.more.link.descriptor.IImageResourceLinkDescriptor; import fr.openwide.core.wicket.more.link.descriptor.ILinkDescriptor; import fr.openwide.core.wicket.more.link.descriptor.IPageLinkDescriptor; import fr.openwide.core.wicket.more.link.descriptor.IResourceLinkDescriptor; import fr.openwide.core.wicket.more.link.descriptor.LinkInvalidTargetRuntimeException; import fr.openwide.core.wicket.more.link.descriptor.builder.LinkDescriptorBuilder; import fr.openwide.core.wicket.more.link.descriptor.builder.state.parameter.chosen.common.IOneChosenParameterState; import fr.openwide.core.wicket.more.link.descriptor.builder.state.terminal.ILateTargetDefinitionTerminalState; import fr.openwide.core.wicket.more.link.descriptor.mapper.IOneParameterLinkDescriptorMapper; import fr.openwide.core.wicket.more.link.descriptor.parameter.CommonParameters; import fr.openwide.core.wicket.more.link.descriptor.parameter.validator.LinkParameterModelValidationException; import fr.openwide.core.wicket.more.link.descriptor.parameter.validator.LinkParameterSerializedFormValidationException; import fr.openwide.core.wicket.more.link.descriptor.parameter.validator.LinkParameterValidationRuntimeException; import fr.openwide.core.wicket.more.markup.html.factory.ConditionFactories; import fr.openwide.core.wicket.more.markup.html.factory.DetachableFactories; import fr.openwide.core.wicket.more.model.CollectionCopyModel; import fr.openwide.core.wicket.more.model.GenericEntityModel; public abstract class AbstractAnyTargetTestLinkDescriptorMapper extends AbstractTestLinkDescriptor { @Autowired private IPersonService personService; protected abstract <T> IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, T> buildWithNullTarget( ILateTargetDefinitionTerminalState< IOneParameterLinkDescriptorMapper<IPageLinkDescriptor, T>, IOneParameterLinkDescriptorMapper<IResourceLinkDescriptor, T>, IOneParameterLinkDescriptorMapper<IImageResourceLinkDescriptor, T> > builder); protected abstract <T> IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, T> buildWithOneParameterTarget( ILateTargetDefinitionTerminalState< IOneParameterLinkDescriptorMapper<IPageLinkDescriptor, T>, IOneParameterLinkDescriptorMapper<IResourceLinkDescriptor, T>, IOneParameterLinkDescriptorMapper<IImageResourceLinkDescriptor, T> > builder); /** * @return A link descriptor mapper that will point to a null target. */ protected abstract <T> IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, T> buildWithParameterDependentNullTarget(IOneChosenParameterState< ?, T, IOneParameterLinkDescriptorMapper<IPageLinkDescriptor, T>, IOneParameterLinkDescriptorMapper<IResourceLinkDescriptor, T>, IOneParameterLinkDescriptorMapper<IImageResourceLinkDescriptor, T> > builder); /** * @return A link descriptor mapper that will point to the no-parameter target if the parameter is * absent, and to the one-parameter target otherwise. */ protected abstract <T> IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, T> buildWithParameterDependentTarget(IOneChosenParameterState< ?, T, IOneParameterLinkDescriptorMapper<IPageLinkDescriptor, T>, IOneParameterLinkDescriptorMapper<IResourceLinkDescriptor, T>, IOneParameterLinkDescriptorMapper<IImageResourceLinkDescriptor, T> > builder); protected abstract String getNoParameterTargetPathPrefix(); protected abstract String getOneParameterTargetPathPrefix(); @Test(expected = LinkInvalidTargetRuntimeException.class) public void url_oneParamOptional_missingTarget() { IModel<Long> model = Model.of((Long) null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithNullTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() ); mapper.map(model).url(); } @Test public void extract_oneParamOptional_missingTarget() throws Exception { IModel<Long> model = Model.of((Long) null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithNullTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() ); mapper.map(model).extract(new PageParameters()); // Just check that there is no exception thrown, which means that target validation is *not* performed } @Test(expected = LinkInvalidTargetRuntimeException.class) public void url_oneParamOptional_missingParameterDependentTarget() { IModel<Long> model = Model.of((Long) null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithParameterDependentNullTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() ); mapper.map(model).url(); } @Test public void extract_oneParamOptional_missingParameterDependentTarget() throws Exception { IModel<Long> model = Model.of((Long) null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithParameterDependentNullTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() ); mapper.map(model).extract(new PageParameters()); // Just check that there is no exception thrown, which means that target validation is *not* performed } @Test(expected = LinkParameterValidationRuntimeException.class) public void url_oneParamMandatory_mandatoryFails() { IModel<Long> model = Model.of((Long)null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).mandatory() ); mapper.map(model).url(); } @Test(expected = LinkParameterSerializedFormValidationException.class) public void extract_oneParamMandatory_mandatoryFails() throws Exception { IModel<Long> model = Model.of((Long)null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).mandatory() ); mapper.map(model).extract(new PageParameters()); } @Test public void url_oneParamMandatory_mandatoryPasses() { IModel<Long> model = Model.of(1L); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).mandatory() ); assertThat(mapper.map(model).url(), hasPathAndQuery(getOneParameterTargetPathPrefix() + "1")); } @Test public void extract_oneParamMandatory_mandatoryPasses() throws Exception { IModel<Long> model = Model.of((Long)null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).mandatory() ); mapper.map(model).extract(new PageParameters().add(CommonParameters.ID, 1L)); assertEquals(Long.valueOf(1L), model.getObject()); } @Test(expected = LinkParameterValidationRuntimeException.class) public void url_oneParamOptional_validatorFails() { IModel<Long> model = Model.of(1L); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).mandatory() .validator(Condition.alwaysFalse()) ); mapper.map(model).url(); } @Test(expected = LinkParameterModelValidationException.class) public void extract_oneParamOptional_validatorFails() throws Exception { IModel<Long> model = Model.of((Long) null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() .validator(Condition.alwaysFalse()) ); mapper.map(model).extract(new PageParameters()); } @Test public void url_oneParamOptional_validatorPasses() { IModel<Long> model = Model.of(1L); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() .validator(Condition.alwaysTrue()) ); assertThat(mapper.map(model).url(), hasPathAndQuery(getOneParameterTargetPathPrefix() + "1")); } @Test public void extract_oneParamOptional_validatorPasses() throws Exception { IModel<Long> model = Model.of((Long)null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).mandatory() .validator(Condition.alwaysTrue()) ); mapper.map(model).extract(new PageParameters().add(CommonParameters.ID, 1L)); assertEquals(Long.valueOf(1L), model.getObject()); } @Test(expected = LinkParameterValidationRuntimeException.class) public void url_oneParamOptional_parameterDependentValidatorFails() { IModel<Long> model = Model.of((Long) null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() .validator(DetachableFactories.forUnit(ConditionFactories.predicate(Predicates.notNull()))) ); mapper.map(model).url(); } @Test(expected = LinkParameterModelValidationException.class) public void extract_oneParamOptional_parameterDependentValidatorFails() throws Exception { IModel<Long> model = Model.of((Long) null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() .validator(DetachableFactories.forUnit(ConditionFactories.predicate(Predicates.notNull()))) ); mapper.map(model).extract(new PageParameters()); } @Test public void url_oneParamOptional_parameterDependentValidatorPasses() { IModel<Long> model = Model.of(1L); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() .validator(DetachableFactories.forUnit(ConditionFactories.predicate(Predicates.notNull()))) ); assertThat(mapper.map(model).url(), hasPathAndQuery(getOneParameterTargetPathPrefix() + "1")); } @Test public void extract_oneParamOptional_parameterDependentValidatorPasses() throws Exception { IModel<Long> model = Model.of((Long) null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() .validator(DetachableFactories.forUnit(ConditionFactories.predicate(Predicates.notNull()))) ); mapper.map(model).extract(new PageParameters().add(CommonParameters.ID, 1L)); assertEquals(Long.valueOf(1L), model.getObject()); } @Test public void url_oneParamOptional_genericEntity() throws Exception { Person person = new Person("John", "Doe"); personService.create(person); IModel<Person> model = GenericEntityModel.of(person); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Person> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Person.class).map(CommonParameters.ID).optional() ); assertThat(mapper.map(model).url(), hasPathAndQuery(getOneParameterTargetPathPrefix() + person.getId())); } @Test public void extract_oneParamOptional_genericEntity() throws Exception { Person person = new Person("John", "Doe"); personService.create(person); IModel<Person> model = GenericEntityModel.of(person); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Person> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Person.class).map(CommonParameters.ID).optional() ); mapper.map(model).extract(new PageParameters().add(CommonParameters.ID, person.getId())); assertEquals(person, model.getObject()); } @Test public void url_oneParamOptional_collection() { IModel<List<Long>> model = new ListModel<Long>(Lists.newArrayList(1L, 2L)); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, List<Long>> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .<List<Long>, Long>model(List.class, Long.class) .map(CommonParameters.ID).optional() ); assertThat(mapper.map(model).url(), hasPathAndQuery(getOneParameterTargetPathPrefix() + "1,2")); } @Test public void extract_oneParamOptional_collection() throws Exception { IModel<List<Long>> model = new ListModel<Long>(null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, List<Long>> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .<List<Long>, Long>model(List.class, Long.class) .map(CommonParameters.ID).optional() ); mapper.map(model).extract(new PageParameters().add(CommonParameters.ID, "1,2")); assertEquals(Lists.newArrayList(1L, 2L), model.getObject()); } @Test public void url_oneParamOptional_afterSerialization() { IModel<Long> model = Model.of(1L); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() ); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> deserializedMapper = serializeAndDeserialize(mapper); assertThat(deserializedMapper.map(model).url(), hasPathAndQuery(getOneParameterTargetPathPrefix() + "1")); } @Test public void extract_oneParamOptional_afterSerialization() throws Exception { IModel<Long> model = Model.of(1L); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() ); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> deserialized = serializeAndDeserialize(mapper); deserialized.map(model).extract(new PageParameters().add(CommonParameters.ID, 1L)); assertEquals(Long.valueOf(1L), model.getObject()); } /** * We've had issues in the past with serializing TypeDescriptors of Collection<? extends GenericEntity> */ @Test public void serialization_oneParamOptional_genericEntityCollection() throws Exception { Person person1 = new Person("Jane", "Doe"); personService.create(person1); Person person2 = new Person("John", "Doe"); personService.create(person2); IModel<List<Person>> model = CollectionCopyModel.custom( Suppliers2.<Person>arrayListAsList(), GenericEntityModel.<Person>factory() ); model.setObject(ImmutableList.of(person1, person2)); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, List<Person>> mapper = buildWithOneParameterTarget( LinkDescriptorBuilder.start() .<List<Person>, Person>model(List.class, Person.class) .map(CommonParameters.ID).optional() ); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, List<Person>> deserializedMapper = serializeAndDeserialize(mapper); assertThat(deserializedMapper.map(model).url(), hasPathAndQuery(getOneParameterTargetPathPrefix() + person1.getId() + "," + person2.getId())); } @Test public void url_oneParamOptional_targetDependsOnParameter() { IModel<Long> model = Model.of((Long) null); IOneParameterLinkDescriptorMapper<? extends ILinkDescriptor, Long> mapper = buildWithParameterDependentTarget( LinkDescriptorBuilder.start() .model(Long.class).map(CommonParameters.ID).optional() ); assertThat(mapper.map(model).url(), hasPathAndQuery(getNoParameterTargetPathPrefix())); model.setObject(1L); assertThat(mapper.map(model).url(), hasPathAndQuery(getOneParameterTargetPathPrefix() + "1")); } }