VIVO-1246 Improve the ConfigurationBeanLoader (#52)

* VIVO-1246 improve the ConfigurationBeanLoader:

Add cardinality parameters minOccurs and maxOccurs
Create README.md document in the edu.cornell.mannlib.vitro.webapp.utils.configuration package
Split large class of unit tests into separate classes by functionality

* VIVO-1247, remove duplicate code used with ConfigurationBeanLoader.

Now that the @Property annotation includes cardinality parameters, we can remove a lot of duplicate code.

* VIVO-1246 Move unit tests to the new location.

* VIVO-1246 The documentation was in the wrong place.
This commit is contained in:
Jim Blake 2017-01-03 12:12:11 -05:00 committed by GitHub
parent fc83c9f48d
commit a8ec633f71
22 changed files with 1414 additions and 703 deletions

View file

@ -43,6 +43,12 @@ public class ModelUtilitiesTestHelper {
createProperty(propertyUri), createPlainLiteral(objectValue));
}
public static Statement dataProperty(String subjectUri, String propertyUri,
Float objectValue) {
return createStatement(createResource(subjectUri),
createProperty(propertyUri), createTypedLiteral(objectValue));
}
public static Statement dataProperty(String subjectUri, String propertyUri,
Object objectValue, XSDDatatype dataType) {
return createStatement(createResource(subjectUri),

View file

@ -5,7 +5,6 @@ package edu.cornell.mannlib.vitro.webapp.utils.configuration;
import static org.apache.jena.datatypes.xsd.XSDDatatype.XSDfloat;
import static org.apache.jena.datatypes.xsd.XSDDatatype.XSDstring;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.dataProperty;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.model;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.objectProperty;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.typeStatement;
import static edu.cornell.mannlib.vitro.webapp.utils.configuration.ConfigurationBeanLoader.toJavaUri;
@ -20,7 +19,6 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@ -32,16 +30,13 @@ import stubs.javax.servlet.http.HttpSessionStub;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Statement;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ContextModelAccess;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.ModelAccessFactory;
import edu.cornell.mannlib.vitro.webapp.modelaccess.RequestModelAccess;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.ConfigurationRdfParser.InvalidConfigurationRdfException;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.InstanceWrapper.InstanceWrapperException;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.PropertyType.PropertyTypeException;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.WrappedInstance.NoSuchPropertyMethodException;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.WrappedInstance.ResourceUnavailableException;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.WrappedInstance.ValidationFailedException;
/**
* TODO
@ -50,47 +45,8 @@ import edu.cornell.mannlib.vitro.webapp.utils.configuration.WrappedInstance.Vali
* instances by URIs, so if a property refers to a created instance, we just
* pass it in.
*/
public class ConfigurationBeanLoaderTest extends AbstractTestClass {
private static final String GENERIC_INSTANCE_URI = "http://mytest.edu/some_instance";
private static final String GENERIC_PROPERTY_URI = "http://mytest.edu/some_property";
private static final String SIMPLE_SUCCESS_INSTANCE_URI = "http://mytest.edu/simple_success_instance";
private static final String FULL_SUCCESS_INSTANCE_URI = "http://mytest.edu/full_success_instance";
private static final String FULL_SUCCESS_BOOST_PROPERTY = "http://mydomain.edu/hasBoost";
private static final String FULL_SUCCESS_TEXT_PROPERTY = "http://mydomain.edu/hasText";
private static final String FULL_SUCCESS_HELPER_PROPERTY = "http://mydomain.edu/hasHelper";
private static final String FULL_SUCCESS_HELPER_INSTANCE_URI = "http://mytest.edu/full_success_helper_instance";
private ServletContextStub ctx;
private HttpSessionStub session;
private HttpServletRequestStub req;
private Model model;
private ConfigurationBeanLoader loader;
private ConfigurationBeanLoader noRequestLoader;
private ConfigurationBeanLoader noContextLoader;
@Before
public void setup() {
ctx = new ServletContextStub();
session = new HttpSessionStub();
session.setServletContext(ctx);
req = new HttpServletRequestStub();
req.setSession(session);
@SuppressWarnings("unused")
ModelAccessFactory maf = new ModelAccessFactoryStub();
model = model();
loader = new ConfigurationBeanLoader(model, req);
noRequestLoader = new ConfigurationBeanLoader(model, ctx);
noContextLoader = new ConfigurationBeanLoader(model);
}
public class ConfigurationBeanLoaderTest extends
ConfigurationBeanLoaderTestBase {
// ----------------------------------------------------------------------
// Constructor tests
@ -308,276 +264,6 @@ public class ConfigurationBeanLoaderTest extends AbstractTestClass {
// --------------------------------------------
@Test
public void propertyMethodHasNoParameter_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(NoParameterOnPropertyMethod.class)));
expectSimpleFailure(
NoParameterOnPropertyMethod.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"must accept exactly one parameter"));
}
public static class NoParameterOnPropertyMethod {
@Property(uri = GENERIC_PROPERTY_URI)
public void methodTakesNoParameters() {
// Not suitable as a property method.
}
}
// --------------------------------------------
@Test
public void propertyMethodHasMultipleParameters_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(MultipleParametersOnPropertyMethod.class)));
expectSimpleFailure(
MultipleParametersOnPropertyMethod.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"must accept exactly one parameter"));
}
public static class MultipleParametersOnPropertyMethod {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void methodTakesMultipleParameters(String s, Float f) {
// Not suitable as a property method.
}
}
// --------------------------------------------
@Test
public void propertyMethodHasInvalidParameter_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(InvalidParameterOnPropertyMethod.class)));
expectSimpleFailure(
InvalidParameterOnPropertyMethod.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"Failed to create the PropertyMethod"));
}
public static class InvalidParameterOnPropertyMethod {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void methodTakesInvalidParameters(byte b) {
// Not suitable as a property method.
}
}
// --------------------------------------------
@Test
public void propertyMethodDoesNotReturnVoid_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(PropertyMethodMustReturnVoid.class)));
expectSimpleFailure(
PropertyMethodMustReturnVoid.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class, "should return void"));
}
public static class PropertyMethodMustReturnVoid {
@Property(uri = GENERIC_PROPERTY_URI)
public String methodReturnIsNotVoid(String s) {
// Not suitable as a property method.
return s;
}
}
// --------------------------------------------
@Test
public void propertyMethodNotAccessible_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(PropertyMethodIsPrivate.class)));
model.add(dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"can't store in a private method."));
expectSimpleFailure(
PropertyMethodIsPrivate.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(PropertyTypeException.class,
"Property method failed."));
}
public static class PropertyMethodIsPrivate {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
private void methodReturnIsNotVoid(String s) {
// Not suitable as a property method.
}
}
// --------------------------------------------
@Test
public void propertyMethodThrowsException_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(PropertyMethodFails.class)));
model.add(dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"exception while loading."));
expectSimpleFailure(
PropertyMethodFails.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(PropertyTypeException.class,
"Property method failed."));
}
public static class PropertyMethodFails {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void methodThrowsException(String s) {
if (true) {
throw new RuntimeException("property method fails.");
}
}
}
// --------------------------------------------
@Test
public void propertyMethodDuplicateUri_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(TwoMethodsWithSameUri.class)));
expectSimpleFailure(
TwoMethodsWithSameUri.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"methods have the same URI"));
}
public static class TwoMethodsWithSameUri {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void firstProperty(String s) {
// Nothing to do
}
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void secondProperty(String s) {
// Nothing to do
}
}
// --------------------------------------------
@Test
public void validationMethodHasParameters_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ValidationMethodWithParameter.class)));
expectSimpleFailure(
ValidationMethodWithParameter.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"should not have parameters"));
}
public static class ValidationMethodWithParameter {
@SuppressWarnings("unused")
@Validation
public void validateWithParameter(String s) {
// Nothing to do
}
}
// --------------------------------------------
@Test
public void validationMethodDoesNotReturnVoid_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ValidationMethodShouldReturnVoid.class)));
expectSimpleFailure(
ValidationMethodShouldReturnVoid.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class, "should return void"));
}
public static class ValidationMethodShouldReturnVoid {
@Validation
public String validateWithReturnType() {
return "Hi there!";
}
}
// --------------------------------------------
@Test
public void validationMethodNotAccessible_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ValidationMethodIsPrivate.class)));
expectSimpleFailure(
ValidationMethodIsPrivate.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(ValidationFailedException.class,
"Error executing validation method"));
}
public static class ValidationMethodIsPrivate {
@Validation
private void validateIsPrivate() {
// private method
}
}
// --------------------------------------------
@Test
public void validationMethodThrowsException_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ValidationThrowsException.class)));
expectSimpleFailure(
ValidationThrowsException.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(ValidationFailedException.class,
"Error executing validation method"));
}
public static class ValidationThrowsException {
@Validation
public void validateFails() {
throw new RuntimeException("from validation method");
}
}
// --------------------------------------------
@Test
public void loaderCantSatisfyContextModelsUser_throwsException()
throws ConfigurationBeanLoaderException {
@ -1041,6 +727,7 @@ public class ConfigurationBeanLoaderTest extends AbstractTestClass {
// Additional tests
// ----------------------------------------------------------------------
@SuppressWarnings("unused")
@Test
@Ignore
// TODO
@ -1049,6 +736,7 @@ public class ConfigurationBeanLoaderTest extends AbstractTestClass {
fail("circularReferencesAreNotFatal not implemented");
}
@SuppressWarnings("unused")
@Test
@Ignore
// TODO deals with circularity.
@ -1057,6 +745,7 @@ public class ConfigurationBeanLoaderTest extends AbstractTestClass {
fail("subordinateObjectCantBeLoaded_leavesNoAccessibleInstanceOfParent not implemented");
}
@SuppressWarnings("unused")
@Test
@Ignore
// TODO deals with circularity.
@ -1065,42 +754,4 @@ public class ConfigurationBeanLoaderTest extends AbstractTestClass {
fail("parentObjectCantBeLoaded_leavesNoAccessibleInstanceOfSubordinate not implemented");
}
// ----------------------------------------------------------------------
// Helper methods for simple failure
// ----------------------------------------------------------------------
private void expectSimpleFailure(Class<?> failureClass,
ExpectedThrowable expected, ExpectedThrowable cause)
throws ConfigurationBeanLoaderException {
expectException(expected.getClazz(), expected.getMessageSubstring(),
cause.getClazz(), cause.getMessageSubstring());
@SuppressWarnings("unused")
Object unused = loader.loadInstance(GENERIC_INSTANCE_URI, failureClass);
}
private ExpectedThrowable throwable(Class<? extends Throwable> clazz,
String messageSubstring) {
return new ExpectedThrowable(clazz, messageSubstring);
}
private static class ExpectedThrowable {
private final Class<? extends Throwable> clazz;
private final String messageSubstring;
public ExpectedThrowable(Class<? extends Throwable> clazz,
String messageSubstring) {
this.clazz = clazz;
this.messageSubstring = messageSubstring;
}
public Class<? extends Throwable> getClazz() {
return clazz;
}
public String getMessageSubstring() {
return messageSubstring;
}
}
}

View file

@ -0,0 +1,100 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.configuration;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.model;
import org.apache.jena.rdf.model.Model;
import org.junit.Before;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.ModelAccessFactory;
import stubs.edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccessFactoryStub;
import stubs.javax.servlet.ServletContextStub;
import stubs.javax.servlet.http.HttpServletRequestStub;
import stubs.javax.servlet.http.HttpSessionStub;
/**
* TODO
*/
public class ConfigurationBeanLoaderTestBase extends AbstractTestClass {
protected static final String GENERIC_INSTANCE_URI = "http://mytest.edu/some_instance";
protected static final String GENERIC_PROPERTY_URI = "http://mytest.edu/some_property";
protected static final String SIMPLE_SUCCESS_INSTANCE_URI = "http://mytest.edu/simple_success_instance";
protected static final String FULL_SUCCESS_INSTANCE_URI = "http://mytest.edu/full_success_instance";
protected static final String FULL_SUCCESS_BOOST_PROPERTY = "http://mydomain.edu/hasBoost";
protected static final String FULL_SUCCESS_TEXT_PROPERTY = "http://mydomain.edu/hasText";
protected static final String FULL_SUCCESS_HELPER_PROPERTY = "http://mydomain.edu/hasHelper";
protected static final String FULL_SUCCESS_HELPER_INSTANCE_URI = "http://mytest.edu/full_success_helper_instance";
private ServletContextStub ctx;
private HttpSessionStub session;
private HttpServletRequestStub req;
protected Model model;
protected ConfigurationBeanLoader loader;
protected ConfigurationBeanLoader noRequestLoader;
protected ConfigurationBeanLoader noContextLoader;
@Before
public void setup() {
ctx = new ServletContextStub();
session = new HttpSessionStub();
session.setServletContext(ctx);
req = new HttpServletRequestStub();
req.setSession(session);
@SuppressWarnings("unused")
ModelAccessFactory maf = new ModelAccessFactoryStub();
model = model();
loader = new ConfigurationBeanLoader(model, req);
noRequestLoader = new ConfigurationBeanLoader(model, ctx);
noContextLoader = new ConfigurationBeanLoader(model);
}
// ----------------------------------------------------------------------
// Helper methods for simple failure
// ----------------------------------------------------------------------
protected void expectSimpleFailure(Class<?> failureClass,
ExpectedThrowable expected, ExpectedThrowable cause)
throws ConfigurationBeanLoaderException {
expectException(expected.getClazz(), expected.getMessageSubstring(),
cause.getClazz(), cause.getMessageSubstring());
@SuppressWarnings("unused")
Object unused = loader.loadInstance(GENERIC_INSTANCE_URI, failureClass);
}
protected ExpectedThrowable throwable(Class<? extends Throwable> clazz,
String messageSubstring) {
return new ExpectedThrowable(clazz, messageSubstring);
}
private static class ExpectedThrowable {
private final Class<? extends Throwable> clazz;
private final String messageSubstring;
public ExpectedThrowable(Class<? extends Throwable> clazz,
String messageSubstring) {
this.clazz = clazz;
this.messageSubstring = messageSubstring;
}
public Class<? extends Throwable> getClazz() {
return clazz;
}
public String getMessageSubstring() {
return messageSubstring;
}
}
}

View file

@ -0,0 +1,251 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.configuration;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.dataProperty;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.objectProperty;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.typeStatement;
import static edu.cornell.mannlib.vitro.webapp.utils.configuration.ConfigurationBeanLoader.toJavaUri;
import static org.junit.Assert.assertEquals;
import java.util.Set;
import org.apache.jena.rdf.model.Statement;
import org.junit.Test;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.InstanceWrapper.InstanceWrapperException;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.WrappedInstance.CardinalityException;
/**
* Tests for minOccurs, maxOccurs on the @Property annotation.
*/
public class ConfigurationBeanLoader_Cardinality_Test extends
ConfigurationBeanLoaderTestBase {
private static final Statement[] FOUND_NONE = new Statement[0];
private static final Statement[] FOUND_ONE = new Statement[] { dataProperty(
GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI, "value One") };
private static final Statement[] FOUND_TWO = new Statement[] {
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"value One"),
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"value Two") };
private static final Statement[] FOUND_THREE = new Statement[] {
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"value One"),
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"value Two"),
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"value Three") };
private static final Statement[] FOUND_FOUR = new Statement[] {
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"value One"),
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"value Two"),
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"value Three"),
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"value Four") };
// --------------------------------------------
@Test
public void minOccursIsNegative_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(NegativeMinOccurs.class)));
model.add(objectProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"http://some.other/uri"));
expectSimpleFailure(
NegativeMinOccurs.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"must not be negative"));
}
public static class NegativeMinOccurs {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI, minOccurs = -1)
public void setValue(String value) {
// Nothing to do
}
}
// --------------------------------------------
@Test
public void maxOccursLessThanMinOccurs_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(MaxOccursLessThanMinOccurs.class)));
model.add(objectProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"http://some.other/uri"));
expectSimpleFailure(
MaxOccursLessThanMinOccurs.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"not be less than minOccurs"));
}
public static class MaxOccursLessThanMinOccurs {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI, minOccurs = 2, maxOccurs = 1)
public void setValue(String value) {
// Nothing to do
}
}
// --------------------------------------------
@Test
public void expectingSomeFoundNone_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ExpectingSome.class)));
model.add(FOUND_NONE);
expectSimpleFailure(
ExpectingSome.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(CardinalityException.class, "Expecting at least 2"));
}
@Test
public void expectingSomeFoundFewer_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ExpectingSome.class)));
model.add(FOUND_ONE);
expectSimpleFailure(
ExpectingSome.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(CardinalityException.class, "Expecting at least 2"));
}
@Test
public void expectingSomeFoundMore_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ExpectingSome.class)));
model.add(FOUND_FOUR);
expectSimpleFailure(
ExpectingSome.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(CardinalityException.class,
"Expecting no more than 3"));
}
@Test
public void expectingSomeFoundSome_success()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ExpectingSome.class)));
model.add(FOUND_THREE);
Set<ExpectingSome> instances = loader.loadAll(ExpectingSome.class);
assertEquals(1, instances.size());
model.removeAll();
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ExpectingSome.class)));
model.add(FOUND_TWO);
instances = loader.loadAll(ExpectingSome.class);
assertEquals(1, instances.size());
}
public static class ExpectingSome {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI, minOccurs = 2, maxOccurs = 3)
public void setValue(String value) {
// Nothing to do
}
}
// --------------------------------------------
@Test
public void notSpecifiedFoundNone_success()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(CardinalityNotSpecified.class)));
model.add(FOUND_NONE);
Set<CardinalityNotSpecified> instances = loader
.loadAll(CardinalityNotSpecified.class);
assertEquals(1, instances.size());
}
@Test
public void notSpecifiedFoundSome_success()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(CardinalityNotSpecified.class)));
model.add(FOUND_FOUR);
Set<CardinalityNotSpecified> instances = loader
.loadAll(CardinalityNotSpecified.class);
assertEquals(1, instances.size());
}
public static class CardinalityNotSpecified {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void setValue(String value) {
// Nothing to do
}
}
// --------------------------------------------
@Test
public void expectNoneFoundNone_success()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ExpectNone.class)));
model.add(FOUND_NONE);
Set<ExpectNone> instances = loader.loadAll(ExpectNone.class);
assertEquals(1, instances.size());
}
public static class ExpectNone {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI, maxOccurs = 0)
public void setValue(String value) {
// Nothing to do
}
}
// --------------------------------------------
@Test
public void expectExactlyFoundExactly_success()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ExpectTwo.class)));
model.add(FOUND_TWO);
Set<ExpectTwo> instances = loader.loadAll(ExpectTwo.class);
assertEquals(1, instances.size());
}
public static class ExpectTwo {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI, minOccurs = 2, maxOccurs = 2)
public void setValue(String value) {
// Nothing to do
}
}
}

View file

@ -0,0 +1,338 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.configuration;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.dataProperty;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.typeStatement;
import static edu.cornell.mannlib.vitro.webapp.utils.configuration.ConfigurationBeanLoader.toJavaUri;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.apache.jena.rdf.model.Statement;
import org.junit.Test;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.InstanceWrapper.InstanceWrapperException;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.PropertyType.PropertyTypeException;
/**
* Tests of the @Property annotation.
*/
public class ConfigurationBeanLoader_PropertyTest extends
ConfigurationBeanLoaderTestBase {
protected static final String OTHER_PROPERTY_URI = "http://mytest.edu/different_property";
// --------------------------------------------
@Test
public void propertyMethodHasNoParameter_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(NoParameterOnPropertyMethod.class)));
expectSimpleFailure(
NoParameterOnPropertyMethod.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"must accept exactly one parameter"));
}
public static class NoParameterOnPropertyMethod {
@Property(uri = GENERIC_PROPERTY_URI)
public void methodTakesNoParameters() {
// Not suitable as a property method.
}
}
// --------------------------------------------
@Test
public void propertyMethodHasMultipleParameters_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(MultipleParametersOnPropertyMethod.class)));
expectSimpleFailure(
MultipleParametersOnPropertyMethod.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"must accept exactly one parameter"));
}
public static class MultipleParametersOnPropertyMethod {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void methodTakesMultipleParameters(String s, Float f) {
// Not suitable as a property method.
}
}
// --------------------------------------------
@Test
public void propertyMethodHasInvalidParameter_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(InvalidParameterOnPropertyMethod.class)));
expectSimpleFailure(
InvalidParameterOnPropertyMethod.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"Failed to create the PropertyMethod"));
}
public static class InvalidParameterOnPropertyMethod {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void methodTakesInvalidParameters(byte b) {
// Not suitable as a property method.
}
}
// --------------------------------------------
@Test
public void propertyMethodDoesNotReturnVoid_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(PropertyMethodMustReturnVoid.class)));
expectSimpleFailure(
PropertyMethodMustReturnVoid.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class, "should return void"));
}
public static class PropertyMethodMustReturnVoid {
@Property(uri = GENERIC_PROPERTY_URI)
public String methodReturnIsNotVoid(String s) {
// Not suitable as a property method.
return s;
}
}
// --------------------------------------------
@Test
public void propertyMethodNotAccessible_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(PropertyMethodIsPrivate.class)));
model.add(dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"can't store in a private method."));
expectSimpleFailure(
PropertyMethodIsPrivate.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(PropertyTypeException.class,
"Property method failed."));
}
public static class PropertyMethodIsPrivate {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
private void methodReturnIsNotVoid(String s) {
// Not suitable as a property method.
}
}
// --------------------------------------------
@Test
public void propertyMethodThrowsException_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(PropertyMethodFails.class)));
model.add(dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"exception while loading."));
expectSimpleFailure(
PropertyMethodFails.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(PropertyTypeException.class,
"Property method failed."));
}
public static class PropertyMethodFails {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void methodThrowsException(String s) {
if (true) {
throw new RuntimeException("property method fails.");
}
}
}
// --------------------------------------------
@Test
public void propertyMethodDuplicateUri_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(TwoMethodsWithSameUri.class)));
expectSimpleFailure(
TwoMethodsWithSameUri.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"methods have the same URI"));
}
public static class TwoMethodsWithSameUri {
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void firstProperty(String s) {
// Nothing to do
}
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void secondProperty(String s) {
// Nothing to do
}
}
// --------------------------------------------
@Test
public void superclassContainsPropertyAnnotation_success()
throws ConfigurationBeanLoaderException {
model.add(new Statement[] {
typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(EmptyPropertyMethodSubclass.class)),
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"Value") });
EmptyPropertyMethodSubclass instance = loader.loadInstance(
GENERIC_INSTANCE_URI, EmptyPropertyMethodSubclass.class);
assertNotNull(instance);
assertEquals("Value", instance.value);
}
@Test
public void propertyMethodOverridesPropertyMethod_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(PropertyMethodOverPropertyMethodSubclass.class)));
expectSimpleFailure(
PropertyMethodOverPropertyMethodSubclass.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"conflicts with a property method"));
}
@Test
public void plainMethodOverridesPropertyMethod_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(PlainOverPropertyMethodSubclass.class)));
expectSimpleFailure(
PlainOverPropertyMethodSubclass.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"conflicts with a property method"));
}
@Test
public void uriConflictsBetweenSubclassAndSuperclassPropertyMethods_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ConflictingUriPropertyMethodSubclass.class)));
expectSimpleFailure(
ConflictingUriPropertyMethodSubclass.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"Two property methods have the same URI"));
}
@Test
public void propertyMethodSameNameButDoesNotOverride_throwsException()
throws ConfigurationBeanLoaderException {
model.add(new Statement[] {
typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(DistinctPropertyMethodSubclass.class)),
dataProperty(GENERIC_INSTANCE_URI, GENERIC_PROPERTY_URI,
"Value"),
dataProperty(GENERIC_INSTANCE_URI, OTHER_PROPERTY_URI,
100.0F) });
expectSimpleFailure(
DistinctPropertyMethodSubclass.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"conflicts with a property method"));
}
public static class PropertyMethodSuperclass {
public String value = null;
@Property(uri = GENERIC_PROPERTY_URI)
public void propertySuper(String v) {
if (value != null) {
throw new RuntimeException("propertySuper has already run.");
}
value = v;
}
}
public static class EmptyPropertyMethodSubclass extends
PropertyMethodSuperclass {
// Just want to see that the superclass method is run.
}
public static class DistinctPropertyMethodSubclass extends
PropertyMethodSuperclass {
public float fvalue;
@Property(uri = OTHER_PROPERTY_URI)
public void propertySuper(Float f) {
if (fvalue != 0.0) {
throw new RuntimeException("propertySub has already run.");
}
fvalue = f;
}
}
public static class ConflictingUriPropertyMethodSubclass extends
PropertyMethodSuperclass {
@Property(uri = GENERIC_PROPERTY_URI)
public void propertyConflict(String v) {
// nothing to do.
}
}
public static class PropertyMethodOverPropertyMethodSubclass extends
EmptyPropertyMethodSubclass {
@Override
@SuppressWarnings("unused")
@Property(uri = GENERIC_PROPERTY_URI)
public void propertySuper(String v) {
// Should fail (two levels down)
}
}
public static class PlainOverPropertyMethodSubclass extends
PropertyMethodSuperclass {
@SuppressWarnings("unused")
public void propertySuper(Float f) {
// nothing to do
}
}
}

View file

@ -0,0 +1,215 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.configuration;
import static edu.cornell.mannlib.vitro.testing.ModelUtilitiesTestHelper.typeStatement;
import static edu.cornell.mannlib.vitro.webapp.utils.configuration.ConfigurationBeanLoader.toJavaUri;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.InstanceWrapper.InstanceWrapperException;
import edu.cornell.mannlib.vitro.webapp.utils.configuration.WrappedInstance.ValidationFailedException;
/**
* Test the @Validation annotation.
*/
public class ConfigurationBeanLoader_ValidationTest extends
ConfigurationBeanLoaderTestBase {
// --------------------------------------------
@Test
public void validationMethodHasParameters_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ValidationMethodWithParameter.class)));
expectSimpleFailure(
ValidationMethodWithParameter.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"should not have parameters"));
}
public static class ValidationMethodWithParameter {
@SuppressWarnings("unused")
@Validation
public void validateWithParameter(String s) {
// Nothing to do
}
}
// --------------------------------------------
@Test
public void validationMethodDoesNotReturnVoid_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ValidationMethodShouldReturnVoid.class)));
expectSimpleFailure(
ValidationMethodShouldReturnVoid.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class, "should return void"));
}
public static class ValidationMethodShouldReturnVoid {
@Validation
public String validateWithReturnType() {
return "Hi there!";
}
}
// --------------------------------------------
@Test
public void validationMethodNotAccessible_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ValidationMethodIsPrivate.class)));
expectSimpleFailure(
ValidationMethodIsPrivate.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(ValidationFailedException.class,
"Error executing validation method"));
}
public static class ValidationMethodIsPrivate {
@Validation
private void validateIsPrivate() {
// private method
}
}
// --------------------------------------------
@Test
public void validationMethodThrowsException_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ValidationThrowsException.class)));
expectSimpleFailure(
ValidationThrowsException.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(ValidationFailedException.class,
"Error executing validation method"));
}
public static class ValidationThrowsException {
@Validation
public void validateFails() {
throw new RuntimeException("from validation method");
}
}
// --------------------------------------------
@Test
public void superclassContainsValidationMethod_success()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(EmptyValidationSubclass.class)));
EmptyValidationSubclass instance = loader.loadInstance(
GENERIC_INSTANCE_URI, EmptyValidationSubclass.class);
assertNotNull(instance);
assertTrue(instance.validatorSuperHasRun);
}
@Test
public void superclassAndSubclassContainValidationMethods_success()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(AdditionalValidationSubclass.class)));
AdditionalValidationSubclass instance = loader.loadInstance(
GENERIC_INSTANCE_URI, AdditionalValidationSubclass.class);
assertNotNull(instance);
assertTrue(instance.validatorSuperHasRun);
assertTrue(instance.validatorSubHasRun);
}
@Test
public void validationMethodOverridesValidationMethod_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(ValidationOverValidationSubclass.class)));
expectSimpleFailure(
ValidationOverValidationSubclass.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"overrides a validation method"));
}
@Test
public void plainMethodOverridesValidationMethod_throwsException()
throws ConfigurationBeanLoaderException {
model.add(typeStatement(GENERIC_INSTANCE_URI,
toJavaUri(PlainOverValidationSubclass.class)));
expectSimpleFailure(
PlainOverValidationSubclass.class,
throwable(ConfigurationBeanLoaderException.class,
"Failed to load"),
throwable(InstanceWrapperException.class,
"overrides a validation method"));
}
public static class ValidationSuperclass {
public boolean validatorSuperHasRun = false;
@Validation
public void validatorSuper() {
if (validatorSuperHasRun) {
throw new RuntimeException("validatorSuper has already run.");
}
validatorSuperHasRun = true;
}
}
public static class EmptyValidationSubclass extends ValidationSuperclass {
// Just want to see that the superclass validation is run.
}
public static class AdditionalValidationSubclass extends
ValidationSuperclass {
public boolean validatorSubHasRun = false;
@Validation
public void validatorSub() {
if (validatorSubHasRun) {
throw new RuntimeException("validatorSub has already run.");
}
validatorSubHasRun = true;
}
}
public static class ValidationOverValidationSubclass extends
EmptyValidationSubclass {
@Override
@Validation
public void validatorSuper() {
// Should fail (two levels down)
}
}
public static class PlainOverValidationSubclass extends
ValidationSuperclass {
@Override
public void validatorSuper() {
// Should fail
}
}
}