/* * Hibernate OGM, Domain model persistence for NoSQL datastores * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.ogm.test.options; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.MapAssert.entry; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; import org.hibernate.ogm.options.navigation.impl.AppendableConfigurationContext; import org.hibernate.ogm.options.navigation.impl.OptionsContextImpl; import org.hibernate.ogm.options.navigation.source.impl.AnnotationOptionValueSource; import org.hibernate.ogm.options.navigation.source.impl.ConfigurationOptionValueSource; import org.hibernate.ogm.options.navigation.source.impl.OptionValueSource; import org.hibernate.ogm.options.navigation.source.impl.ProgrammaticOptionValueSource; import org.hibernate.ogm.options.spi.OptionsContext; import org.hibernate.ogm.test.options.examples.NameExampleOption; import org.hibernate.ogm.test.options.examples.PermissionOption; import org.hibernate.ogm.test.options.examples.annotations.NameExample; import org.hibernate.ogm.util.configurationreader.spi.ConfigurationPropertyReader; import org.junit.Before; import org.junit.Test; /** * Unit test for {@link OptionsContextImpl}. * * @author Gunnar Morling */ public class OptionsContextImplTest { private AppendableConfigurationContext optionsServiceContext; private Map<String, Object> cfg; @Before public void setupContext() { optionsServiceContext = new AppendableConfigurationContext(); cfg = new HashMap<>(); } @Test public void shouldProvideUniqueOptionValueFromPropertyLevel() { // given Class<?> entityType = Foo.class; String propertyName = "bar"; optionsServiceContext.addPropertyOption( entityType, propertyName, new NameExampleOption(), "foobar" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "foobar" ); } @Test public void shouldProvideUniqueOptionValueFromEntityLevel() { // given Class<?> entityType = Foo.class; String propertyName = "bar"; optionsServiceContext.addEntityOption( entityType, new NameExampleOption(), "foobar" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "foobar" ); } @Test public void shouldProvideUniqueOptionValueFromGlobalLevel() { // given Class<?> entityType = Foo.class; String propertyName = "bar"; optionsServiceContext.addGlobalOption( new NameExampleOption(), "foobar" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "foobar" ); } @Test public void shouldProvideNonUniqueOptionValueFromPropertyLevel() { // given Class<?> entityType = Foo.class; String propertyName = "bar"; optionsServiceContext.addPropertyOption( entityType, propertyName, new PermissionOption( "user" ), "read" ); optionsServiceContext.addPropertyOption( entityType, propertyName, new PermissionOption( "author" ), "read,write" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.get( PermissionOption.class, "user" ) ).isEqualTo( "read" ); assertThat( context.get( PermissionOption.class, "author" ) ).isEqualTo( "read,write" ); } @Test public void shouldProvideAllValuesForNonUniqueOptionFromPropertyLevel() { // given Class<?> entityType = Foo.class; String propertyName = "bar"; optionsServiceContext.addPropertyOption( entityType, propertyName, new PermissionOption( "user" ), "read" ); optionsServiceContext.addPropertyOption( entityType, propertyName, new PermissionOption( "author" ), "read,write" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getAll( PermissionOption.class ) ). hasSize( 2 ) .includes( entry( "user", "read" ), entry( "author", "read,write" ) ); } @Test // TODO It might actually make sense to merge values from other levels or from super-types for non-unique options; // re-visit based on an actual use case public void shouldIgnoreValuesFromEntityWhenGettingAllValuesForNonUniqueOptionWhenValuesPresentOnPropertyLevel() { // given Class<?> entityType = Foo.class; String propertyName = "bar"; optionsServiceContext.addPropertyOption( entityType, propertyName, new PermissionOption( "user" ), "read" ); optionsServiceContext.addPropertyOption( entityType, propertyName, new PermissionOption( "author" ), "read,write" ); optionsServiceContext.addEntityOption( entityType, new PermissionOption( "admin" ), "read,write,delete" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getAll( PermissionOption.class ) ). hasSize( 2 ) .includes( entry( "user", "read" ), entry( "author", "read,write" ) ); } @Test public void shouldGiveOptionValueFromPropertyLevelPrecedenceOverEntityLevel() { // given Class<?> entityType = Foo.class; String propertyName = "bar"; optionsServiceContext.addEntityOption( entityType, new NameExampleOption(), "foobar" ); optionsServiceContext.addPropertyOption( entityType, propertyName, new NameExampleOption(), "barfoo" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "barfoo" ); } @Test public void shouldGiveOptionValueConfiguredViaApiPrecedenceOverAnnotation() { // given Class<?> entityType = Baz.class; String propertyName = "qux"; optionsServiceContext.addPropertyOption( entityType, propertyName, new NameExampleOption(), "foo" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "foo" ); } @Test public void shouldGiveOptionValueConfiguredViaAnnotationOnPropertyLevelPrecedenceOverApiConfiguredValueOnEntityLevel() { // given Class<?> entityType = Baz.class; String propertyName = "qux"; optionsServiceContext.addEntityOption( entityType, new NameExampleOption(), "foo" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "qux" ); } @Test public void shouldProvideOptionValueConfiguredOnPropertyLevelForSuperClass() { // given Class<?> entityType = BazExt.class; String propertyName = "qux"; // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "qux" ); } @Test public void shouldGiveValueFromLocalPropertyLevelPrecedenceOverValueFromSuperTypePropertyLevel() { // given Class<?> entityType = BazExt.class; String propertyName = "qux"; optionsServiceContext.addPropertyOption( entityType, propertyName, new NameExampleOption(), "foo" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "foo" ); } @Test public void shouldGiveValueFromSuperTypePropertyLevelPrecedenceOverValueFromLocalEntityLevel() { // given Class<?> entityType = BazExt.class; String propertyName = "qux"; optionsServiceContext.addEntityOption( entityType, new NameExampleOption(), "foo" ); // when OptionsContext context = OptionsContextImpl.forProperty( getSources(), entityType, propertyName ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "qux" ); } @Test public void shouldProvideAccessToGlobalOptionSetViaProperty() { // given cfg.put( NameExampleOption.NAME_OPTION, "foobarqax" ); // when OptionsContext context = OptionsContextImpl.forGlobal( getSources() ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "foobarqax" ); } @Test public void shouldGiveGlobalOptionSetViaApiPrecedenceOverValueSetViaProperty() { // given cfg.put( NameExampleOption.NAME_OPTION, "foobarqax" ); optionsServiceContext.addGlobalOption( new NameExampleOption(), "foobar" ); // when OptionsContext context = OptionsContextImpl.forGlobal( getSources() ); // then assertThat( context.getUnique( NameExampleOption.class ) ).isEqualTo( "foobar" ); } private List<OptionValueSource> getSources() { return Arrays.<OptionValueSource>asList( new ProgrammaticOptionValueSource( optionsServiceContext ), new AnnotationOptionValueSource(), new ConfigurationOptionValueSource( new ConfigurationPropertyReader( cfg, new ClassLoaderServiceImpl() ) ) ); } private static class Foo { @SuppressWarnings("unused") public String getBar() { return null; } } private static class Baz { @NameExample("qux") public String getQux() { return null; } } private static class BazExt extends Baz { @Override public String getQux() { return null; } } }