Skip to content

Commit

Permalink
[Feature #53] Configure simpleLiteral attributes when building metamo…
Browse files Browse the repository at this point in the history
…del.
  • Loading branch information
ledsoft committed Jul 15, 2019
1 parent 01b6f2c commit cdd7e1a
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public abstract class AbstractAttribute<X, Y> implements Attribute<X, Y> {

private boolean lexicalForm;

private boolean simpleLiteral;

private final ParticipationConstraint[] constraints;

private ConverterWrapper converter;
Expand All @@ -60,6 +62,7 @@ public abstract class AbstractAttribute<X, Y> implements Attribute<X, Y> {
this.nonEmpty = builder.nonEmpty;
this.converter = builder.converter;
this.lexicalForm = builder.lexicalForm;
this.simpleLiteral = builder.simpleLiteral;
}

@Override
Expand Down Expand Up @@ -121,6 +124,10 @@ public boolean isLexicalForm() {
return lexicalForm;
}

public boolean isSimpleLiteral() {
return simpleLiteral;
}

@Override
public String getName() {
return field.getName();
Expand All @@ -146,6 +153,7 @@ abstract static class AbstractAttributeBuilder<X, Y> {
private boolean includeExplicit;
private boolean nonEmpty = false;
private boolean lexicalForm = false;
private boolean simpleLiteral = false;
private ParticipationConstraint[] constraints;
private ConverterWrapper converter;

Expand All @@ -157,6 +165,7 @@ public AbstractAttributeBuilder<X, Y> config(PropertyAttributes config) {
this.nonEmpty = config.isNonEmpty();
this.fetchType = config.getFetchType();
this.lexicalForm = config.isLexicalForm();
this.simpleLiteral = config.simpleLiteral;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ void resolve(Field field, MetamodelBuilder metamodelBuilder, Class<?> fieldValue
this.fetchType = oap.fetch();
this.type = BasicTypeImpl.get(fieldValueCls);
this.lexicalForm = oap.lexicalForm();
this.simpleLiteral = oap.simpleLiteral();
validator.validateAnnotationPropertyField(field, oap);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ void resolve(Field field, MetamodelBuilder metamodelBuilder, Class<?> fieldValue
this.fetchType = odp.fetch();
this.type = BasicTypeImpl.get(fieldValueCls);
this.lexicalForm = odp.lexicalForm();
this.simpleLiteral = odp.simpleLiteral();
validator.validateDataPropertyField(field, odp);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,25 @@ void validateAnnotationPropertyField(Field field, OWLAnnotationProperty config)
assert field != null;
assert config != null;
validateLexicalFormField(field, config.lexicalForm());
validateSimpleLiteralField(field, config.simpleLiteral());
}

void validateDataPropertyField(Field field, OWLDataProperty config) {
assert field != null;
assert config != null;
validateLexicalFormField(field, config.lexicalForm());
validateSimpleLiteralField(field, config.simpleLiteral());
}

private void validateLexicalFormField(Field field, boolean lexicalForm) {
assert field != null;
if (lexicalForm && !String.class.isAssignableFrom(field.getType())) {
throw new InvalidFieldMappingException("@LexicalForm can be used only on fields of type String.");
throw new InvalidFieldMappingException("lexicalForm mapping can be used only on fields of type String.");
}
}

private void validateSimpleLiteralField(Field field, boolean simpleLiteral) {
if (simpleLiteral && !String.class.isAssignableFrom(field.getType())) {
throw new InvalidFieldMappingException("simpleLiteral mapping can be used only on fields of type String.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ abstract class PropertyAttributes {
CascadeType[] cascadeTypes = new CascadeType[]{};
FetchType fetchType = FetchType.EAGER;
boolean lexicalForm = false;
boolean simpleLiteral = false;
private boolean nonEmpty = false;
private ParticipationConstraint[] participationConstraints = new ParticipationConstraint[]{};

Expand Down Expand Up @@ -70,6 +71,10 @@ boolean isLexicalForm() {
return lexicalForm;
}

boolean isSimpleLiteral() {
return simpleLiteral;
}

ParticipationConstraint[] getParticipationConstraints() {
return participationConstraints;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ public class OWLClassM {
@OWLDataProperty(iri = Vocabulary.p_m_lexicalForm, lexicalForm = true)
private String lexicalForm;

@OWLDataProperty(iri = Vocabulary.p_m_simpleLiteral, simpleLiteral = true)
private String simpleLiteral;

public enum Severity {
LOW, MEDIUM, HIGH
}
Expand Down Expand Up @@ -144,6 +147,7 @@ public String toString() {
", enumAttribute=" + enumAttribute +
", integerSet=" + integerSet +
", lexicalForm=" + lexicalForm +
", simpleLiteral=" + simpleLiteral +
'}';
}

Expand All @@ -159,9 +163,10 @@ public void initializeTestValues(boolean includingKey) {
this.enumAttribute = Severity.MEDIUM;
this.integerSet = IntStream.generate(Generators::randomInt).limit(10).boxed().collect(Collectors.toSet());
this.lexicalForm = "test";
this.simpleLiteral = "test";
}

public static String getClassIri() throws Exception {
public static String getClassIri() {
return OWLClassM.class.getAnnotation(OWLClass.class).iri();
}

Expand Down Expand Up @@ -200,4 +205,8 @@ public static Field getIntegerSetField() throws Exception {
public static Field getLexicalFormField() throws Exception {
return OWLClassM.class.getDeclaredField("lexicalForm");
}

public static Field getSimpleLiteralField() throws Exception {
return OWLClassM.class.getDeclaredField("simpleLiteral");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class Vocabulary {
public static final String p_m_enumAttribute = ATTRIBUTE_BASE + "m-enumAttribute";
public static final String p_m_IntegerSet = ATTRIBUTE_BASE + "m-pluralIntAttribute";
public static final String p_m_lexicalForm = ATTRIBUTE_BASE + "m-lexicalForm";
public static final String p_m_simpleLiteral = ATTRIBUTE_BASE + "m-simpleLiteral";

public static final String P_R_STRING_ATTRIBUTE = ATTRIBUTE_BASE + "R-stringAttribute";
public static final String P_HAS_A = ATTRIBUTE_BASE + "hasA";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,8 @@ public static void initOWLClassMMock(EntityTypeImpl<OWLClassM> etMock, AbstractA
AbstractAttribute intAtt, SingularAttributeImpl longAtt,
AbstractAttribute doubleAtt, AbstractAttribute dateAtt,
AbstractAttribute enumAtt, AbstractPluralAttribute intSetAtt,
SingularAttributeImpl lexicalFormAtt, Identifier idMock)
SingularAttributeImpl lexicalFormAtt, SingularAttributeImpl simpleLiteralAtt,
Identifier idMock)
throws Exception {
when(etMock.getJavaType()).thenReturn(OWLClassM.class);
when(etMock.getIRI()).thenReturn(IRI.create(OWLClassM.getClassIri()));
Expand All @@ -515,10 +516,10 @@ public static void initOWLClassMMock(EntityTypeImpl<OWLClassM> etMock, AbstractA
when(etMock.getFieldSpecification(idMock.getName())).thenReturn(idMock);
when(etMock.getAttributes()).thenReturn(
new HashSet<>(Arrays.<Attribute<? super OWLClassM, ?>>asList(booleanAtt, intAtt, longAtt, doubleAtt,
dateAtt, enumAtt, intSetAtt, lexicalFormAtt)));
dateAtt, enumAtt, intSetAtt, lexicalFormAtt, simpleLiteralAtt)));
when(etMock.getFieldSpecifications()).thenReturn(new HashSet<>(
Arrays.<FieldSpecification<? super OWLClassM, ?>>asList(booleanAtt, intAtt, longAtt, doubleAtt, dateAtt,
enumAtt, intSetAtt, lexicalFormAtt, idMock)));
enumAtt, intSetAtt, lexicalFormAtt, simpleLiteralAtt, idMock)));

when(booleanAtt.getJavaField()).thenReturn(OWLClassM.getBooleanAttributeField());
when(booleanAtt.getName()).thenReturn(OWLClassM.getBooleanAttributeField().getName());
Expand Down Expand Up @@ -612,6 +613,18 @@ public static void initOWLClassMMock(EntityTypeImpl<OWLClassM> etMock, AbstractA
when(lexicalFormAtt.isLexicalForm()).thenReturn(true);
when(etMock.getFieldSpecification(OWLClassM.getLexicalFormField().getName())).thenReturn(lexicalFormAtt);

when(simpleLiteralAtt.getJavaField()).thenReturn(OWLClassM.getSimpleLiteralField());
when(simpleLiteralAtt.getName()).thenReturn(OWLClassM.getSimpleLiteralField().getName());
when(simpleLiteralAtt.getJavaType()).thenReturn(OWLClassM.getSimpleLiteralField().getType());
when(simpleLiteralAtt.getIRI()).thenReturn(IRI.create(Vocabulary.p_m_simpleLiteral));
when(simpleLiteralAtt.getPersistentAttributeType()).thenReturn(Attribute.PersistentAttributeType.DATA);
when(simpleLiteralAtt.isCollection()).thenReturn(false);
when(simpleLiteralAtt.getDeclaringType()).thenReturn(etMock);
when(simpleLiteralAtt.getConstraints()).thenReturn(new ParticipationConstraint[0]);
when(simpleLiteralAtt.getConverter()).thenReturn(new ToLexicalFormConverter());
when(simpleLiteralAtt.isSimpleLiteral()).thenReturn(true);
when(etMock.getFieldSpecification(OWLClassM.getSimpleLiteralField().getName())).thenReturn(simpleLiteralAtt);

when(etMock.getLifecycleListenerManager()).thenReturn(EntityLifecycleListenerManager.empty());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ public class MetamodelMocks {
private AbstractPluralAttribute<OWLClassM, Set, Integer> mIntegerSetAtt;
@Mock
private SingularAttributeImpl<OWLClassM, String> mLexicalFormAtt;
@Mock
private SingularAttributeImpl<OWLClassM, String> mSimpleLiteralAtt;

@Mock
private EntityTypeImpl<OWLClassN> etN;
Expand Down Expand Up @@ -253,7 +255,7 @@ public MetamodelMocks() throws Exception {
MetamodelFactory.initOWLClassKMocks(etK, kOwlClassEAtt, idK);
MetamodelFactory.initOWLClassLMocks(etL, lReferencedList, lSimpleList, lSetAtt, lOwlClassAAtt, idL);
MetamodelFactory.initOWLClassMMock(etM, mBooleanAtt, mIntegerAtt, mLongAtt, mDoubleAtt, mDateAtt, mEnumAtt,
mIntegerSetAtt, mLexicalFormAtt, idM);
mIntegerSetAtt, mLexicalFormAtt, mSimpleLiteralAtt, idM);
MetamodelFactory.initOWLClassNMock(etN, nAnnotationAtt, nAnnotationUriAtt, nStringAtt, nPluralAnnotationAtt,
nProperties, idN);
MetamodelFactory.initOWLClassOMock(etO, oStringAtt, idO);
Expand Down Expand Up @@ -596,6 +598,10 @@ public AbstractPluralAttribute<OWLClassM, Set, Integer> integerSetAttribute() {
public AbstractAttribute<OWLClassM, String> lexicalFormAttribute() {
return MetamodelMocks.this.mLexicalFormAtt;
}

public AbstractAttribute<OWLClassM, String> simpleLiteralAttribute() {
return MetamodelMocks.this.mSimpleLiteralAtt;
}
}

public class OWLClassNMetamodel {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,18 @@ private static class WithLexicalForm {
@OWLAnnotationProperty(iri = Vocabulary.p_m_lexicalForm, lexicalForm = true)
private String lexicalForm;
}

@Test
void resolveResolvesSimpleLiteralConfigurationFromAnnotation() throws Exception {
final AnnotationPropertyAttributes sut = new AnnotationPropertyAttributes(validator);
sut.typeBuilderContext = typeBuilderContext;
sut.resolve(WithSimpleLiteral.class.getDeclaredField("simpleLiteral"), metamodelBuilder, String.class);
assertTrue(sut.isSimpleLiteral());
}

@SuppressWarnings("unused")
private static class WithSimpleLiteral {
@OWLAnnotationProperty(iri = Vocabulary.p_m_simpleLiteral, simpleLiteral = true)
private String simpleLiteral;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,12 @@ void resolveResolvesLexicalFormConfigurationFromAnnotation() throws Exception {
sut.resolve(OWLClassM.getLexicalFormField(), metamodelBuilder, OWLClassM.getLexicalFormField().getType());
assertTrue(sut.isLexicalForm());
}

@Test
void resolveResolvesSimpleLiteralConfigurationFromAnnotation() throws Exception {
final DataPropertyAttributes sut = new DataPropertyAttributes(validator);
sut.typeBuilderContext = typeBuilderContext;
sut.resolve(OWLClassM.getSimpleLiteralField(), metamodelBuilder, OWLClassM.getSimpleLiteralField().getType());
assertTrue(sut.isSimpleLiteral());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package cz.cvut.kbss.jopa.model.metamodel;

import cz.cvut.kbss.jopa.environment.OWLClassM;
import cz.cvut.kbss.jopa.environment.Vocabulary;
import cz.cvut.kbss.jopa.exception.InvalidFieldMappingException;
import cz.cvut.kbss.jopa.model.annotations.OWLAnnotationProperty;
Expand All @@ -38,7 +39,7 @@ void nonMapPropertiesFieldThrowsException() {
assertThrows(InvalidFieldMappingException.class, () -> validator.validatePropertiesField(getField("values")));
}

private Field getField(String name) throws Exception {
private static Field getField(String name) throws Exception {
return InvalidClass.class.getDeclaredField(name);
}

Expand Down Expand Up @@ -109,8 +110,8 @@ void invalidIdentifierTypeThrowsException() {

@Test
void lexicalFormAnnotationIsValidOnStringField() throws Exception {
validator.validateDataPropertyField(getField("validLexicalForm"),
getField("validLexicalForm").getAnnotation(OWLDataProperty.class));
validator.validateDataPropertyField(OWLClassM.getLexicalFormField(),
OWLClassM.getLexicalFormField().getAnnotation(OWLDataProperty.class));
}

@Test
Expand All @@ -127,6 +128,26 @@ void validateAnnotationPropertyFieldInvokesLexicalFormValidation() {
getField("invalidLexicalFormAnnotation").getAnnotation(OWLAnnotationProperty.class)));
}

@Test
void simpleLiteralAnnotationIsValidOnStringField() throws Exception {
validator.validateDataPropertyField(OWLClassM.getSimpleLiteralField(),
OWLClassM.getSimpleLiteralField().getAnnotation(OWLDataProperty.class));
}

@Test
void simpleLiteralAnnotationThrowsInvalidFieldMappingExceptionOnNonStringField() {
assertThrows(InvalidFieldMappingException.class,
() -> validator.validateDataPropertyField(getField("invalidSimpleLiteral"),
getField("invalidSimpleLiteral").getAnnotation(OWLDataProperty.class)));
}

@Test
void simpleLiteralAnnotationThrowsInvalidFieldMappingExceptionOnNonStringAnnotationPropertyField() {
assertThrows(InvalidFieldMappingException.class,
() -> validator.validateAnnotationPropertyField(getField("invalidSimpleLiteralAnnotation"),
getField("invalidSimpleLiteralAnnotation").getAnnotation(OWLAnnotationProperty.class)));
}

@SuppressWarnings("unused")
private static final class InvalidClass {

Expand Down Expand Up @@ -169,13 +190,16 @@ private static final class InvalidClass {

Integer invalidIdentifier;

@OWLDataProperty(iri = Vocabulary.p_m_lexicalForm, lexicalForm = true)
private String validLexicalForm;

@OWLDataProperty(iri = Vocabulary.p_m_lexicalForm, lexicalForm = true)
private Integer invalidLexicalForm;

@OWLAnnotationProperty(iri = Vocabulary.p_m_lexicalForm, lexicalForm = true)
private Integer invalidLexicalFormAnnotation;

@OWLDataProperty(iri = Vocabulary.p_m_simpleLiteral, simpleLiteral = true)
private Integer invalidSimpleLiteral;

@OWLAnnotationProperty(iri = Vocabulary.p_m_simpleLiteral, simpleLiteral = true)
private Integer invalidSimpleLiteralAnnotation;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import static org.mockito.Mockito.when;

@SuppressWarnings("unused")
public class MetamodelBuilderTest {
class MetamodelBuilderTest {

@Mock
private PersistenceUnitClassFinder finderMock;
Expand Down Expand Up @@ -201,4 +201,14 @@ void buildMetamodelSetsLexicalFormConfigOnAttributeMappingBasedOnAnnotation() th
.getAttribute(OWLClassM.getLexicalFormField().getName());
assertTrue(att.isLexicalForm());
}

@Test
void buildMetamodelSetsSimpleLiteralConfigOnAttributeMappingBasedOnAnnotation() throws Exception {
when(finderMock.getEntities()).thenReturn(Collections.singleton(OWLClassM.class));
builder.buildMetamodel(finderMock);
final EntityTypeImpl<OWLClassM> result = (EntityTypeImpl<OWLClassM>) builder.getEntityClass(OWLClassM.class);
final AbstractAttribute<OWLClassM, String> att = (AbstractAttribute<OWLClassM, String>) result
.getAttribute(OWLClassM.getSimpleLiteralField().getName());
assertTrue(att.isSimpleLiteral());
}
}

0 comments on commit cdd7e1a

Please sign in to comment.