diff --git a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/BaseIsInsideFunction.java b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/BaseIsInsideFunction.java index 023f878..c71df2c 100644 --- a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/BaseIsInsideFunction.java +++ b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/BaseIsInsideFunction.java @@ -25,7 +25,7 @@ import java.util.stream.Stream; public abstract class BaseIsInsideFunction extends BaseInterlisFunction { - protected final Value isInsideValidArea(String usageScope, Collection testObjects, String geometryAttribute, Supplier validAreaSupplier) { + protected final Value isInsideValidArea(String usageScope, Value testObjects, Value geometryAttribute, Supplier validAreaSupplier) { try { Geometry validArea = validAreaSupplier.get(); @@ -33,8 +33,9 @@ protected final Value isInsideValidArea(String usageScope, Collection return Value.createUndefined(); } - boolean allInsideValidArea = testObjects.stream() - .flatMap(obj -> getAttributes(obj, geometryAttribute).stream()) + Collection geometries = EvaluationHelper.evaluateObjectPath(td, validator, testObjects, geometryAttribute, null, usageScope); + + boolean allInsideValidArea = geometries.stream() .map(geometry -> logExceptionAsWarning(() -> geometry2JtsOrNull(geometry))) .filter(Objects::nonNull) .allMatch(validArea::contains); diff --git a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/EvaluationHelper.java b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/EvaluationHelper.java index 10864f7..e9d955d 100644 --- a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/EvaluationHelper.java +++ b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/EvaluationHelper.java @@ -78,6 +78,24 @@ public static Collection evaluateAttributes(Validator validator, Valu return attributes; } + /** + * Get the collection of {@link IomObject} inside {@code object} by following the provided {@code path} text. + * If the {@code path} is UNDEFINED, the direct collection of {@code object} is returned. + */ + public static Collection evaluateObjectPath(TransferDescription td, Validator validator, Value object, Value path, IomObject contextObject, String usageScope) { + if (path.isUndefined()) { + return object.getComplexObjects(); + } else { + Viewable contextClass = EvaluationHelper.getContextClass(td, contextObject, object); + if (contextClass == null) { + throw new IllegalStateException("unknown class in " + usageScope); + } + + PathEl[] attributePath = EvaluationHelper.getAttributePathEl(validator, contextClass, path); + return EvaluationHelper.evaluateAttributes(validator, object, attributePath); + } + } + /** * Applies the given function to each item in the collection and sums up the results. */ diff --git a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetAreaIoxPlugin.java b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetAreaIoxPlugin.java index 501fe07..d0d8672 100644 --- a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetAreaIoxPlugin.java +++ b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetAreaIoxPlugin.java @@ -1,7 +1,5 @@ package ch.geowerkstatt.ilivalidator.extensions.functions; -import ch.interlis.ili2c.metamodel.PathEl; -import ch.interlis.ili2c.metamodel.Viewable; import ch.interlis.iom.IomObject; import ch.interlis.iox.IoxException; import ch.interlis.iox_j.jts.Iox2jtsext; @@ -38,20 +36,7 @@ public Value evaluateInternal(String validationKind, String usageScope, IomObjec return Value.createUndefined(); } - Collection surfaces; - - if (argPath.isUndefined()) { - surfaces = argObjects.getComplexObjects(); - } else { - Viewable contextClass = EvaluationHelper.getContextClass(td, contextObject, argObjects); - - if (contextClass == null) { - throw new IllegalStateException("unknown class in " + usageScope); - } - - PathEl[] attributePath = EvaluationHelper.getAttributePathEl(validator, contextClass, argPath); - surfaces = EvaluationHelper.evaluateAttributes(validator, argObjects, attributePath); - } + Collection surfaces = EvaluationHelper.evaluateObjectPath(td, validator, argObjects, argPath, contextObject, usageScope); double areaSum = EvaluationHelper.sum(surfaces, this::getArea); return new Value(areaSum); diff --git a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetInnerRingsCountIoxPlugin.java b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetInnerRingsCountIoxPlugin.java index e5da813..54f1a35 100644 --- a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetInnerRingsCountIoxPlugin.java +++ b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetInnerRingsCountIoxPlugin.java @@ -1,7 +1,5 @@ package ch.geowerkstatt.ilivalidator.extensions.functions; -import ch.interlis.ili2c.metamodel.PathEl; -import ch.interlis.ili2c.metamodel.Viewable; import ch.interlis.iom.IomObject; import ch.interlis.iox_j.validator.Value; @@ -38,20 +36,7 @@ public Value evaluateInternal(String validationKind, String usageScope, IomObjec return Value.createUndefined(); } - Collection surfaces; - - if (argPath.isUndefined()) { - surfaces = argObjects.getComplexObjects(); - } else { - Viewable contextClass = EvaluationHelper.getContextClass(td, contextObject, argObjects); - - if (contextClass == null) { - throw new IllegalStateException("unknown class in " + usageScope); - } - - PathEl[] attributePath = EvaluationHelper.getAttributePathEl(validator, contextClass, argPath); - surfaces = EvaluationHelper.evaluateAttributes(validator, argObjects, attributePath); - } + Collection surfaces = EvaluationHelper.evaluateObjectPath(td, validator, argObjects, argPath, contextObject, usageScope); int innerRingsCount = surfaces.stream().map(this::getInnerRingsCount).reduce(0, Integer::sum); return new Value(innerRingsCount); diff --git a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetLengthIoxPlugin.java b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetLengthIoxPlugin.java index 234bb48..0a86c81 100644 --- a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetLengthIoxPlugin.java +++ b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/GetLengthIoxPlugin.java @@ -1,7 +1,5 @@ package ch.geowerkstatt.ilivalidator.extensions.functions; -import ch.interlis.ili2c.metamodel.PathEl; -import ch.interlis.ili2c.metamodel.Viewable; import ch.interlis.iom.IomObject; import ch.interlis.iox.IoxException; import ch.interlis.iox_j.jts.Iox2jtsext; @@ -38,20 +36,7 @@ public Value evaluateInternal(String validationKind, String usageScope, IomObjec return Value.createUndefined(); } - Collection polylines; - - if (argPath.isUndefined()) { - polylines = argObjects.getComplexObjects(); - } else { - Viewable contextClass = EvaluationHelper.getContextClass(td, contextObject, argObjects); - - if (contextClass == null) { - throw new IllegalStateException("unknown class in " + usageScope); - } - - PathEl[] attributePath = EvaluationHelper.getAttributePathEl(validator, contextClass, argPath); - polylines = EvaluationHelper.evaluateAttributes(validator, argObjects, attributePath); - } + Collection polylines = EvaluationHelper.evaluateObjectPath(td, validator, argObjects, argPath, contextObject, usageScope); double lengthSum = EvaluationHelper.sum(polylines, this::getLength); return new Value(lengthSum); diff --git a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideExternalDatasetIoxPlugin.java b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideExternalDatasetIoxPlugin.java index 627410d..b62dd16 100644 --- a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideExternalDatasetIoxPlugin.java +++ b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideExternalDatasetIoxPlugin.java @@ -41,16 +41,15 @@ protected Value evaluateInternal(String validationKind, String usageScope, IomOb Value argTestObject = arguments[2]; // OBJECT OF ANYCLASS Value argTestObjectgeometry = arguments[3]; // TEXT - if (argDatasetName.isUndefined() || argObjects.isUndefined() || argTestObject.isUndefined() || argTestObjectgeometry.isUndefined()) { + if (argDatasetName.isUndefined() || argObjects.isUndefined() || argTestObject.isUndefined()) { return Value.createSkipEvaluation(); } String transferIds = argObjects.getValue(); String datasetName = argDatasetName.getValue(); ValidAreaKey key = new ValidAreaKey(null, datasetName, transferIds); - String testObjectGeometryAttribute = argTestObjectgeometry.getValue(); - return isInsideValidArea(usageScope, argTestObject.getComplexObjects(), testObjectGeometryAttribute, () -> VALID_AREA_CACHE.computeIfAbsent(key, this::getValidArea)); + return isInsideValidArea(usageScope, argTestObject, argTestObjectgeometry, () -> VALID_AREA_CACHE.computeIfAbsent(key, this::getValidArea)); } /** diff --git a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideExternalDatasetResourceIoxPlugin.java b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideExternalDatasetResourceIoxPlugin.java index 386fb96..7c7a403 100644 --- a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideExternalDatasetResourceIoxPlugin.java +++ b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideExternalDatasetResourceIoxPlugin.java @@ -30,7 +30,7 @@ protected Value evaluateInternal(String validationKind, String usageScope, IomOb Value argTestObject = arguments[3]; // OBJECT OF ANYCLASS Value argTestObjectgeometry = arguments[4]; // TEXT - if (argTransferFile.isUndefined() || argDatasetName.isUndefined() || argObjects.isUndefined() || argTestObject.isUndefined() || argTestObjectgeometry.isUndefined()) { + if (argTransferFile.isUndefined() || argDatasetName.isUndefined() || argObjects.isUndefined() || argTestObject.isUndefined()) { return Value.createSkipEvaluation(); } @@ -38,9 +38,8 @@ protected Value evaluateInternal(String validationKind, String usageScope, IomOb String transferIds = argObjects.getValue(); String datasetName = argDatasetName.getValue(); ValidAreaKey key = new ValidAreaKey(transferFile, datasetName, transferIds); - String testObjectGeometryAttribute = argTestObjectgeometry.getValue(); - return isInsideValidArea(usageScope, argTestObject.getComplexObjects(), testObjectGeometryAttribute, () -> VALID_AREA_CACHE.computeIfAbsent(key, this::getValidArea)); + return isInsideValidArea(usageScope, argTestObject, argTestObjectgeometry, () -> VALID_AREA_CACHE.computeIfAbsent(key, this::getValidArea)); } /** diff --git a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideIoxPlugin.java b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideIoxPlugin.java index 6cc71a3..b4030b3 100644 --- a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideIoxPlugin.java +++ b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/IsInsideIoxPlugin.java @@ -22,28 +22,28 @@ public String getQualifiedIliName() { @Override protected Value evaluateInternal(String validationKind, String usageScope, IomObject mainObj, Value[] arguments) { - Value argReferenceGeometry = arguments[0]; // MULTIAREA - Value argTestObject = arguments[1]; // OBJECT OF ANYCLASS - Value argTestObjectgeometry = arguments[2]; // TEXT + Value argReferenceObject = arguments[0]; // ANYSTRUCTURE + Value argReferenceGeometryPath = arguments[1]; // TEXT + Value argTestObject = arguments[2]; // OBJECT OF ANYCLASS + Value argTestObjectgeometry = arguments[3]; // TEXT if (argTestObject.isUndefined() || argTestObjectgeometry.isUndefined()) { return Value.createSkipEvaluation(); } - if (argReferenceGeometry.isUndefined()) { + if (argReferenceObject.isUndefined()) { writeLogErrorMessage(usageScope, "Missing reference geometry."); return Value.createUndefined(); } - Collection referenceGeometryObjects = argReferenceGeometry.getComplexObjects(); + Collection referenceGeometryObjects = EvaluationHelper.evaluateObjectPath(td, validator, argReferenceObject, argReferenceGeometryPath, mainObj, usageScope); if (referenceGeometryObjects.size() != 1) { writeLogErrorMessage(usageScope, "Expected exactly one reference geometry."); return Value.createUndefined(); } IomObject referenceGeometry = referenceGeometryObjects.iterator().next(); - String testObjectGeometryAttribute = argTestObjectgeometry.getValue(); - return isInsideValidArea(usageScope, argTestObject.getComplexObjects(), testObjectGeometryAttribute, () -> VALID_AREA_CACHE.computeIfAbsent(referenceGeometry, this::getValidArea)); + return isInsideValidArea(usageScope, argTestObject, argTestObjectgeometry, () -> VALID_AREA_CACHE.computeIfAbsent(referenceGeometry, this::getValidArea)); } private Geometry getValidArea(IomObject referenceGeometry) { diff --git a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/PolylinesOverlapIoxPlugin.java b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/PolylinesOverlapIoxPlugin.java index 9d7f2e0..84a0eb8 100644 --- a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/PolylinesOverlapIoxPlugin.java +++ b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/PolylinesOverlapIoxPlugin.java @@ -1,7 +1,5 @@ package ch.geowerkstatt.ilivalidator.extensions.functions; -import ch.interlis.ili2c.metamodel.PathEl; -import ch.interlis.ili2c.metamodel.Viewable; import ch.interlis.iom.IomObject; import ch.interlis.iom_j.itf.impl.jtsext.geom.CompoundCurve; import ch.interlis.iox.IoxException; @@ -39,19 +37,7 @@ protected Value evaluateInternal(String validationKind, String usageScope, IomOb return Value.createUndefined(); } - Collection polylineObjects; - - if (argPath.isUndefined()) { - polylineObjects = argObjects.getComplexObjects(); - } else { - Viewable contextClass = EvaluationHelper.getContextClass(td, contextObject, argObjects); - if (contextClass == null) { - throw new IllegalStateException("unknown class in " + usageScope); - } - - PathEl[] attributePath = EvaluationHelper.getAttributePathEl(validator, contextClass, argPath); - polylineObjects = EvaluationHelper.evaluateAttributes(validator, argObjects, attributePath); - } + Collection polylineObjects = EvaluationHelper.evaluateObjectPath(td, validator, argObjects, argPath, contextObject, usageScope); Collection inputObjects = argObjects.getComplexObjects(); List objectIds = inputObjects.stream().map(IomObject::getobjectoid).collect(Collectors.toList()); diff --git a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/UnionIoxPlugin.java b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/UnionIoxPlugin.java index 3aeac17..d63c783 100644 --- a/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/UnionIoxPlugin.java +++ b/src/main/java/ch/geowerkstatt/ilivalidator/extensions/functions/UnionIoxPlugin.java @@ -1,8 +1,6 @@ package ch.geowerkstatt.ilivalidator.extensions.functions; import ch.ehi.basics.types.OutParam; -import ch.interlis.ili2c.metamodel.PathEl; -import ch.interlis.ili2c.metamodel.Viewable; import ch.interlis.iom.IomObject; import ch.interlis.iox.IoxException; import ch.interlis.iox_j.jts.Iox2jtsException; @@ -38,19 +36,7 @@ protected Value evaluateInternal(String validationKind, String usageScope, IomOb return Value.createSkipEvaluation(); } - Collection surfaces; - if (argPath.isUndefined()) { - surfaces = argObjects.getComplexObjects(); - } else { - Viewable contextClass = EvaluationHelper.getContextClass(td, contextObject, argObjects); - if (contextClass == null) { - throw new IllegalStateException("unknown class in " + usageScope); - } - - PathEl[] attributePath = EvaluationHelper.getAttributePathEl(validator, contextClass, argPath); - surfaces = EvaluationHelper.evaluateAttributes(validator, argObjects, attributePath); - } - + Collection surfaces = EvaluationHelper.evaluateObjectPath(td, validator, argObjects, argPath, contextObject, usageScope); if (surfaces == null) { return Value.createUndefined(); } diff --git a/src/model/GeoW_FunctionsExt.ili b/src/model/GeoW_FunctionsExt.ili index 8da1390..ab6721b 100644 --- a/src/model/GeoW_FunctionsExt.ili +++ b/src/model/GeoW_FunctionsExt.ili @@ -41,10 +41,10 @@ MODEL GeoW_FunctionsExt FUNCTION IsInsideExternalDatasetResource (TransferFile: TEXT; DatasetName: TEXT; Objects: TEXT; TestObject: OBJECT OF ANYCLASS; TestObjectgeometry: TEXT): BOOLEAN; !!@ fn.description = "Prüft, ob ein Objekt innerhalb der Geometrie eines anderen Objektes liegt."; - !!@ fn.param = "ReferenceGeometry: Referenzgeometrie, innerhalb welcher das TestObject liegen muss. TestObject: Objekt, welches zu prüfen ist. TestObjectgeometry: Geometriefeld, bezogen auf das unter Testobject übergebene Objekt"; + !!@ fn.param = "ReferenceObject: Referenzobjekt oder -geometrie, innerhalb welcher das TestObject liegen muss. ReferenceGeometryAttr: Pfad zum Geometrieattribut vom Referenzobjekt oder UNDEFINED. TestObject: Objekt, welches zu prüfen ist. TestObjectgeometry: Geometriefeld, bezogen auf das unter Testobject übergebene Objekt"; !!@ fn.return = "Boolean"; !!@ fn.since = "2023-12-21"; - FUNCTION IsInside (ReferenceGeometry: MULTIAREA; TestObject: OBJECT OF ANYCLASS; TestObjectgeometry: TEXT): BOOLEAN; + FUNCTION IsInside (ReferenceObject: ANYSTRUCTURE; ReferenceGeometryAttr: TEXT; TestObject: OBJECT OF ANYCLASS; TestObjectgeometry: TEXT): BOOLEAN; !!@ fn.description = "Fasst die Flächen-Geometrien aus der Eingabemenge zu einer Flächen-Geometrie zusammen. Für 'Objects' können Objekte oder Geometrien angegeben werden. Für 'GeometryAttr' soll der Pfad zur Flächen-Geometrie in INTERLIS 2 Syntax angegeben werden. Falls 'Objects' bereits die Geometrien enthält, soll für 'GeometryAttr' 'UNDEFINED' übergeben werden."; !!@ fn.param = "Objects: Objekte, deren Geometrien zusammengefasst werden sollen. GeometryAttr: Pfad zum Geometrieattribut oder UNDEFINED"; diff --git a/src/test/data/IsInside/MandatoryConstraintThis.ili b/src/test/data/IsInside/MandatoryConstraintThis.ili index 6d14622..8c5018b 100644 --- a/src/test/data/IsInside/MandatoryConstraintThis.ili +++ b/src/test/data/IsInside/MandatoryConstraintThis.ili @@ -19,13 +19,14 @@ MODEL TestSuite CLASS IsInsideKantonsgrenze EXTENDS ConstraintTestClass = testAttributeIsInsideKantonsgrenze : CHKoord; testAttributeKantonsgrenze : CHMultiArea; - MANDATORY CONSTRAINT IsInsideKantonsgrenze: GeoW_FunctionsExt.IsInside(THIS->testAttributeKantonsgrenze, THIS, "testAttributeIsInsideKantonsgrenze") == expected; + MANDATORY CONSTRAINT IsInsideKantonsgrenzePath: GeoW_FunctionsExt.IsInside(THIS, "testAttributeKantonsgrenze", THIS, "testAttributeIsInsideKantonsgrenze") == expected; + MANDATORY CONSTRAINT IsInsideKantonsgrenzeUndefinedPath: GeoW_FunctionsExt.IsInside(THIS->testAttributeKantonsgrenze, UNDEFINED, THIS->testAttributeIsInsideKantonsgrenze, UNDEFINED) == expected; END IsInsideKantonsgrenze; CLASS InvalidConstraints = geometryAttribute : CHKoord; area : CHMultiArea; - MANDATORY CONSTRAINT IsInsideMissingArea: GeoW_FunctionsExt.IsInside(THIS->area, THIS, "geometryAttribute"); + MANDATORY CONSTRAINT IsInsideMissingArea: GeoW_FunctionsExt.IsInside(THIS->area, UNDEFINED, THIS, "geometryAttribute"); END InvalidConstraints; END FunctionTestTopic;