Skip to content

Commit

Permalink
Merge pull request #121 from GeoWerkstatt/validate-constraints-on-dom…
Browse files Browse the repository at this point in the history
…aindef

ILI2.4 Constraints zu Domains (claeis/ilivalidator#378)
  • Loading branch information
claeis authored Nov 15, 2023
2 parents 98c0109 + 4a5e891 commit f0fbb58
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 4 deletions.
30 changes: 28 additions & 2 deletions src/main/java/ch/interlis/iox_j/validator/Validator.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import ch.interlis.ili2c.generator.Interlis2Generator;
import ch.interlis.ili2c.metamodel.DomainConstraint;
import ch.interlis.ili2c.metamodel.Expression;
import ch.interlis.ili2c.metamodel.ValueRefThis;
import com.vividsolutions.jts.geom.Coordinate;
import ch.ehi.basics.logging.EhiLogger;
import ch.ehi.basics.settings.Settings;
Expand Down Expand Up @@ -137,6 +139,7 @@

public class Validator implements ch.interlis.iox.IoxValidator {
private static final String ENUM_TREE_VALUES = "ENUM_TREE_VALUES";
private static final String VALUE_REF_THIS = "Value";
public static final String ALL_OBJECTS_ACCESSIBLE="allObjectsAccessible";
public static final String REGEX_FOR_ID_VALIDATION = "^[0-9a-zA-Z_][0-9a-zA-Z\\_\\.\\-]*";
public static final String REGEX_FOR_TEXTOID_VALIDATION = "^[a-zA-Z_][0-9a-zA-Z\\_\\.\\-]*";
Expand Down Expand Up @@ -1889,6 +1892,10 @@ public Value evaluateExpression(IomObject parentObject, String validationKind, S
Value listOfIomObjectsValue = new Value(listOfIomObjects);
functions.put(expression, listOfIomObjectsValue);
return listOfIomObjectsValue;
} else if (expression instanceof ValueRefThis) {
Domain domain = (Domain) td.getElement(iomObj.getobjecttag());
String value = iomObj.getattrvalue(VALUE_REF_THIS);
return new Value(domain.getType(), value);
} else if(expression instanceof ParameterValue) {
ParameterValue paramValue=(ParameterValue)expression;
String paramName=paramValue.getParameter().getScopedName();
Expand Down Expand Up @@ -4232,9 +4239,28 @@ private void validateAttrValue(Viewable eleClass,IomObject iomObj, AttributeDef
}
}
}
if (domain != null) {
String rootDomainName = domain.getScopedName(null);

while (domain != null) {
Iterator<DomainConstraint> iterator = domain.iterator();
while (iterator.hasNext()){
DomainConstraint constraint = iterator.next();
Iom_jObject iomValueObject = new Iom_jObject(rootDomainName, null);
iomValueObject.setattrvalue(VALUE_REF_THIS, iomObj.getattrprim(attrName, structi));

Value result = evaluateExpression(null, constraint.getScopedName(), rootDomainName, iomValueObject, constraint.getCondition(), null);

if (!result.isTrue()){
logMsg(validateType, rsrc.getString("validateAttrValue.attributeXDoesNotSatisfyTheDomainConstraintY"), attrPath, constraint.getScopedName());
}
}
domain = domain.getExtending();
}
}
}
}
}
}
}

static private Cardinality getCardinality(AttributeDef attr) { // move to ili2c
Type type=attr.getDomainOrDerivedDomain();
Expand Down
2 changes: 0 additions & 2 deletions src/main/java/ch/interlis/iox_j/validator/functions/Text.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ public Text(Validator validator, TransferDescription td, ch.interlis.iox.IoxVali
public Value evaluateFunction(Function currentFunction, FunctionCall functionCallObj, IomObject parentObject,
String validationKind, String usageScope, IomObject iomObj, TextType texttype, RoleDef firstRole) {

Validator validator = new Validator();

if (currentFunction.getScopedName(null).equals("Text.compareToIgnoreCase") ||
currentFunction.getScopedName(null).equals("Text.compareToIgnoreCaseM")) {
Evaluable[] arguments = functionCallObj.getArguments();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ validateAttrValue.attributeXHasAnUnexpectedTypeY=Attribute {0} has an unexpected
validateAttrValue.valueXIsNotAValidOidInAttributeY=value <{0}> is not a valid OID in attribute {1}
validateAttrValue.attributeXHasAInvalidValueY=Attribute <{0}> has a invalid value <{1}>
validateAttrValue.valueXIsAOutOfRangeInAttributeY=Value <{0}> is a out of range in attribute <{1}>
validateAttrValue.attributeXDoesNotSatisfyTheDomainConstraintY=Attribute {0} does not satisfy the domain constraint {1}
validateTextType.attributeXIsLengthRestrictedToY=Attribute {0} is length restricted to {1}
validateTextType.attributeXMustNotContainControlCharacters=Attribute {0} must not contain control characters
validateTextType.attributeXHasAnUnexpectedTypeY=Attribute {0} has an unexpected type {1}
Expand Down
22 changes: 22 additions & 0 deletions src/test/data/validator/DomainDef.ili
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
INTERLIS 2.4;

MODEL ModelA AT "http://www.interlis.ch/ili2c/tests/" VERSION "1" =
TOPIC TopicA =
DOMAIN
DomainText = TEXT*30;
DomainTextRestrictedThis = TEXT*30 CONSTRAINTS Values : THIS == "SomeConstant";
DomainConstraintThisFunction = TEXT*30 CONSTRAINTS Length : INTERLIS.len(THIS) > 20;
DomainMultiConstraintsNumeric = 0 .. 200 CONSTRAINTS Min : THIS > 10, Max100 : THIS <= 100;
DomainExtends EXTENDS DomainMultiConstraintsNumeric = 0 .. 150 CONSTRAINTS Max50 : THIS <= 50;


CLASS ObjectUnderTest =
DomainText : DomainText;
DomainTextRestrictedThis : DomainTextRestrictedThis;
DomainConstraintThisFunction : DomainConstraintThisFunction;
DomainMultiConstraintsNumeric : DomainMultiConstraintsNumeric;
DomainExtends : DomainExtends;
END ObjectUnderTest;

END TopicA;
END ModelA.
127 changes: 127 additions & 0 deletions src/test/java/ch/interlis/iox_j/validator/DomainDef24Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package ch.interlis.iox_j.validator;

import ch.ehi.basics.settings.Settings;
import ch.interlis.ili2c.metamodel.TransferDescription;
import ch.interlis.iom_j.Iom_jObject;
import ch.interlis.iox_j.EndBasketEvent;
import ch.interlis.iox_j.EndTransferEvent;
import ch.interlis.iox_j.ObjectEvent;
import ch.interlis.iox_j.PipelinePool;
import ch.interlis.iox_j.StartBasketEvent;
import ch.interlis.iox_j.StartTransferEvent;
import ch.interlis.iox_j.logging.LogEventFactory;
import org.junit.Before;
import org.junit.Test;

import java.util.UUID;

import static ch.interlis.iox_j.validator.LogCollectorAssertions.*;

public class DomainDef24Test {
private TransferDescription td = null;
private Validator validator;
private LogCollector logger = null;

@Before
public void setUp() throws Exception {
td = ValidatorTestHelper.compileIliFile("src/test/data/validator/DomainDef.ili");

ValidationConfig modelConfig = new ValidationConfig();
logger = new LogCollector();
LogEventFactory errFactory = new LogEventFactory();
Settings settings = new Settings();
validator = new Validator(td, modelConfig, logger, errFactory, new PipelinePool(), settings);
}

@Test
public void domainText() {
final String domainText = "DomainText";
validateObjectUnderTest(domainText, "This String has 24 chars");
AssertContainsError(domainText, 0, logger);

logger.clear();
validateObjectUnderTest("DomainText", "This String has over 30 characters.");
AssertContainsError("Attribute DomainText is length restricted to 30", 1, logger);

}

@Test
public void domainTextRestrictedThis() {
final String domainTextRestrictedThis = "DomainTextRestrictedThis";
validateObjectUnderTest(domainTextRestrictedThis, "SomeConstant");
AssertContainsError(domainTextRestrictedThis, 0, logger);

logger.clear();
validateObjectUnderTest(domainTextRestrictedThis, "Not the required Constant");
AssertContainsError("Attribute DomainTextRestrictedThis does not satisfy the domain constraint ModelA.TopicA.DomainTextRestrictedThis.Values", 1, logger);
}

@Test
public void domainConstraintThisFunction() {
final String domainConstraintThisFunction = "DomainConstraintThisFunction";
validateObjectUnderTest(domainConstraintThisFunction, "This String has 24 chars");
AssertContainsError(domainConstraintThisFunction, 0, logger);

logger.clear();
validateObjectUnderTest(domainConstraintThisFunction, "Too few chars");
AssertContainsError("Attribute DomainConstraintThisFunction does not satisfy the domain constraint ModelA.TopicA.DomainConstraintThisFunction.Length", 1, logger);
}

@Test
public void domainMultiConstraintsNumeric() {
final String domainMultiConstraintsNumeric = "DomainMultiConstraintsNumeric";
validateObjectUnderTest(domainMultiConstraintsNumeric, "20");
AssertContainsError(domainMultiConstraintsNumeric, 0, logger);

logger.clear();
validateObjectUnderTest(domainMultiConstraintsNumeric, "9");
AssertContainsError("Attribute DomainMultiConstraintsNumeric does not satisfy the domain constraint ModelA.TopicA.DomainMultiConstraintsNumeric.Min", 1, logger);

logger.clear();
validateObjectUnderTest(domainMultiConstraintsNumeric, "101");
AssertContainsError("Attribute DomainMultiConstraintsNumeric does not satisfy the domain constraint ModelA.TopicA.DomainMultiConstraintsNumeric.Max100", 1, logger);

logger.clear();
validateObjectUnderTest(domainMultiConstraintsNumeric, "201");
AssertContainsError("value 201 is out of range in attribute DomainMultiConstraintsNumeric", 1, logger);
AssertContainsError("Attribute DomainMultiConstraintsNumeric does not satisfy the domain constraint ModelA.TopicA.DomainMultiConstraintsNumeric.Max100", 1, logger);
}

@Test
public void domainExtends() {
final String domainExtends = "DomainExtends";
validateObjectUnderTest(domainExtends, "20");
AssertContainsError(domainExtends, 0, logger);

logger.clear();
validateObjectUnderTest(domainExtends, "9");
AssertContainsError("Attribute DomainExtends does not satisfy the domain constraint ModelA.TopicA.DomainMultiConstraintsNumeric.Min", 1, logger);

logger.clear();
validateObjectUnderTest(domainExtends, "51");
AssertContainsError("Attribute DomainExtends does not satisfy the domain constraint ModelA.TopicA.DomainExtends.Max50", 1, logger);

logger.clear();
validateObjectUnderTest(domainExtends, "101");
AssertContainsError("Attribute DomainExtends does not satisfy the domain constraint ModelA.TopicA.DomainExtends.Max50", 1, logger);
AssertContainsError("Attribute DomainExtends does not satisfy the domain constraint ModelA.TopicA.DomainMultiConstraintsNumeric.Max100", 1, logger);

logger.clear();
validateObjectUnderTest(domainExtends, "151");
AssertContainsError("value 151 is out of range in attribute DomainExtends", 1, logger);
AssertContainsError("Attribute DomainExtends does not satisfy the domain constraint ModelA.TopicA.DomainExtends.Max50", 1, logger);
AssertContainsError("Attribute DomainExtends does not satisfy the domain constraint ModelA.TopicA.DomainMultiConstraintsNumeric.Max100", 1, logger);
}

private void validateObjectUnderTest(String attributeName, String attributeValue) {
Iom_jObject iomObj = new Iom_jObject("ModelA.TopicA.ObjectUnderTest", UUID.randomUUID().toString());
iomObj.setattrvalue(attributeName, attributeValue);

validator.validate(new StartTransferEvent());
validator.validate(new StartBasketEvent("ModelA.TopicA", UUID.randomUUID().toString()));
validator.validate(new ObjectEvent(iomObj));
validator.validate(new EndBasketEvent());
validator.validate(new EndTransferEvent());
}

}
6 changes: 6 additions & 0 deletions src/test/java/ch/interlis/iox_j/validator/LogCollector.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,10 @@ public ArrayList<IoxLogEvent> getWarn() {
public ArrayList<IoxLogEvent> getInfo() {
return info;
}

public void clear() {
errs.clear();
warn.clear();
info.clear();
}
}

0 comments on commit f0fbb58

Please sign in to comment.