From a3f1e6872f4f768d14899a1e70bbdc14f32e478d Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sun, 20 Aug 2023 19:41:32 +0200 Subject: feat: improve semantics error reporting Also makes model seeds cancellable to reduce server load during semantic analysis. --- .../store/reasoning/literal/ModalConstraint.java | 3 +- .../store/reasoning/literal/PartialLiterals.java | 3 +- .../refinery/store/reasoning/seed/ModelSeed.java | 5 ++++ .../reasoning/translator/TranslationException.java | 35 ++++++++++++++++++++++ .../translator/containment/ContainmentInfo.java | 7 +++-- .../metamodel/ContainedTypeHierarchyBuilder.java | 3 +- .../translator/metamodel/MetamodelBuilder.java | 32 ++++++++++---------- .../multiobject/MultiObjectInitializer.java | 31 +++++++++++-------- .../multiplicity/ConstrainedMultiplicity.java | 7 +++-- .../InvalidMultiplicityErrorTranslator.java | 5 ++-- .../opposite/OppositeRelationTranslator.java | 11 +++++++ .../translator/predicate/PredicateTranslator.java | 5 ++-- .../translator/typehierarchy/TypeHierarchy.java | 8 +++-- .../typehierarchy/TypeHierarchyBuilder.java | 9 ++++-- .../translator/metamodel/MetamodelBuilderTest.java | 7 +++-- .../typehierarchy/TypeHierarchyTest.java | 3 +- 16 files changed, 123 insertions(+), 51 deletions(-) create mode 100644 subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslationException.java (limited to 'subprojects/store-reasoning/src') diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ModalConstraint.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ModalConstraint.java index 6e0e91e1..2235a95d 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ModalConstraint.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ModalConstraint.java @@ -6,6 +6,7 @@ package tools.refinery.store.reasoning.literal; import tools.refinery.store.query.Constraint; +import tools.refinery.store.query.InvalidQueryException; import tools.refinery.store.query.equality.LiteralEqualityHelper; import tools.refinery.store.query.literal.Reduction; import tools.refinery.store.query.term.Parameter; @@ -17,7 +18,7 @@ public record ModalConstraint(Modality modality, Concreteness concreteness, Cons implements Constraint { public ModalConstraint { if (constraint instanceof AnySymbolView || constraint instanceof ModalConstraint) { - throw new IllegalArgumentException("Already concrete constraints cannot be abstracted"); + throw new InvalidQueryException("Already concrete constraints cannot be abstracted"); } } diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/PartialLiterals.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/PartialLiterals.java index 2c879397..2614c26e 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/PartialLiterals.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/PartialLiterals.java @@ -5,6 +5,7 @@ */ package tools.refinery.store.reasoning.literal; +import tools.refinery.store.query.InvalidQueryException; import tools.refinery.store.query.literal.CallLiteral; public final class PartialLiterals { @@ -31,7 +32,7 @@ public final class PartialLiterals { public static CallLiteral addModality(CallLiteral literal, Modality modality, Concreteness concreteness) { var target = literal.getTarget(); if (target instanceof ModalConstraint) { - throw new IllegalArgumentException("Literal %s already has modality".formatted(literal)); + throw new InvalidQueryException("Literal %s already has modality".formatted(literal)); } var polarity = literal.getPolarity(); var modalTarget = new ModalConstraint(modality.commute(polarity), concreteness, target); diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/ModelSeed.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/ModelSeed.java index 28e6258e..e6b3eaf9 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/ModelSeed.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/ModelSeed.java @@ -13,6 +13,7 @@ import tools.refinery.store.tuple.Tuple; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; import java.util.function.Consumer; public class ModelSeed { @@ -43,6 +44,10 @@ public class ModelSeed { return seeds.containsKey(symbol); } + public Set getSeededSymbols() { + return Collections.unmodifiableSet(seeds.keySet()); + } + public Cursor getCursor(PartialSymbol partialSymbol, A defaultValue) { return getSeed(partialSymbol).getCursor(defaultValue, nodeCount); } diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslationException.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslationException.java new file mode 100644 index 00000000..edb886ba --- /dev/null +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslationException.java @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2023 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.store.reasoning.translator; + +import tools.refinery.store.reasoning.representation.AnyPartialSymbol; + +public class TranslationException extends RuntimeException { + private final transient AnyPartialSymbol partialSymbol; + + public TranslationException(AnyPartialSymbol partialSymbol) { + this.partialSymbol = partialSymbol; + } + + public TranslationException(AnyPartialSymbol partialSymbol, String message) { + super(message); + this.partialSymbol = partialSymbol; + } + + public TranslationException(AnyPartialSymbol partialSymbol, String message, Throwable cause) { + super(message, cause); + this.partialSymbol = partialSymbol; + } + + public TranslationException(AnyPartialSymbol partialSymbol, Throwable cause) { + super(cause); + this.partialSymbol = partialSymbol; + } + + public AnyPartialSymbol getPartialSymbol() { + return partialSymbol; + } +} diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/containment/ContainmentInfo.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/containment/ContainmentInfo.java index 1087e54d..e3457fa7 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/containment/ContainmentInfo.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/containment/ContainmentInfo.java @@ -6,17 +6,18 @@ package tools.refinery.store.reasoning.translator.containment; import tools.refinery.store.reasoning.representation.PartialRelation; +import tools.refinery.store.reasoning.translator.TranslationException; import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity; public record ContainmentInfo(PartialRelation sourceType, Multiplicity multiplicity, PartialRelation targetType) { public ContainmentInfo { if (sourceType.arity() != 1) { - throw new IllegalArgumentException("Expected source type %s to be of arity 1, got %d instead" - .formatted(sourceType, sourceType.arity())); + throw new TranslationException(sourceType, "Expected source type %s to be of arity 1, got %d instead" + .formatted(sourceType, sourceType.arity())); } if (targetType.arity() != 1) { - throw new IllegalArgumentException("Expected target type %s to be of arity 1, got %d instead" + throw new TranslationException(targetType, "Expected target type %s to be of arity 1, got %d instead" .formatted(targetType, targetType.arity())); } } diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ContainedTypeHierarchyBuilder.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ContainedTypeHierarchyBuilder.java index cc43bce6..a21da3d4 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ContainedTypeHierarchyBuilder.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ContainedTypeHierarchyBuilder.java @@ -6,6 +6,7 @@ package tools.refinery.store.reasoning.translator.metamodel; import tools.refinery.store.reasoning.representation.PartialRelation; +import tools.refinery.store.reasoning.translator.TranslationException; import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator; import tools.refinery.store.reasoning.translator.typehierarchy.TypeHierarchyBuilder; @@ -23,7 +24,7 @@ public class ContainedTypeHierarchyBuilder extends TypeHierarchyBuilder { for (var containedType : containedTypes) { var currentInfo = typeInfoMap.get(containedType); if (currentInfo == null) { - throw new IllegalArgumentException("Invalid contained type: " + containedType); + throw new TranslationException(containedType, "Invalid contained type: " + containedType); } var newInfo = currentInfo.addSupertype(ContainmentHierarchyTranslator.CONTAINED_SYMBOL); typeInfoMap.put(containedType, newInfo); diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java index d0732edc..ad0288ed 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java @@ -6,6 +6,7 @@ package tools.refinery.store.reasoning.translator.metamodel; import tools.refinery.store.reasoning.representation.PartialRelation; +import tools.refinery.store.reasoning.translator.TranslationException; import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator; import tools.refinery.store.reasoning.translator.containment.ContainmentInfo; import tools.refinery.store.reasoning.translator.crossreference.DirectedCrossReferenceInfo; @@ -13,7 +14,6 @@ import tools.refinery.store.reasoning.translator.crossreference.UndirectedCrossR import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity; import tools.refinery.store.reasoning.translator.multiplicity.UnconstrainedMultiplicity; import tools.refinery.store.reasoning.translator.typehierarchy.TypeInfo; -import tools.refinery.store.representation.cardinality.CardinalityIntervals; import java.util.*; @@ -70,12 +70,13 @@ public class MetamodelBuilder { public MetamodelBuilder reference(PartialRelation linkType, ReferenceInfo info) { if (linkType.arity() != 2) { - throw new IllegalArgumentException("Only references of arity 2 are supported, got %s with %d instead" - .formatted(linkType, linkType.arity())); + throw new TranslationException(linkType, + "Only references of arity 2 are supported, got %s with %d instead".formatted( + linkType, linkType.arity())); } var putResult = referenceInfoMap.put(linkType, info); if (putResult != null && !putResult.equals(info)) { - throw new IllegalArgumentException("Duplicate reference info for partial relation: " + linkType); + throw new TranslationException(linkType, "Duplicate reference info for partial relation: " + linkType); } return this; } @@ -154,11 +155,11 @@ public class MetamodelBuilder { var sourceType = info.sourceType(); var targetType = info.targetType(); if (typeHierarchyBuilder.isInvalidType(sourceType)) { - throw new IllegalArgumentException("Source type %s of %s is not in type hierarchy" + throw new TranslationException(linkType, "Source type %s of %s is not in type hierarchy" .formatted(sourceType, linkType)); } if (typeHierarchyBuilder.isInvalidType(targetType)) { - throw new IllegalArgumentException("Target type %s of %s is not in type hierarchy" + throw new TranslationException(linkType, "Target type %s of %s is not in type hierarchy" .formatted(targetType, linkType)); } var opposite = info.opposite(); @@ -173,8 +174,9 @@ public class MetamodelBuilder { } if (opposite.equals(linkType)) { if (!sourceType.equals(targetType)) { - throw new IllegalArgumentException("Target %s of undirected reference %s differs from source %s" - .formatted(targetType, linkType, sourceType)); + throw new TranslationException(linkType, + "Target %s of undirected reference %s differs from source %s".formatted( + targetType, linkType, sourceType)); } undirectedCrossReferences.put(linkType, new UndirectedCrossReferenceInfo(sourceType, info.multiplicity())); @@ -183,8 +185,8 @@ public class MetamodelBuilder { oppositeReferences.put(opposite, linkType); } if (info.containment()) { - if (targetMultiplicity.multiplicity().meet(CardinalityIntervals.ONE).isEmpty()) { - throw new IllegalArgumentException("Invalid opposite %s with multiplicity %s of containment %s" + if (!UnconstrainedMultiplicity.INSTANCE.equals(targetMultiplicity)) { + throw new TranslationException(opposite, "Invalid opposite %s with multiplicity %s of containment %s" .formatted(opposite, targetMultiplicity, linkType)); } containedTypes.add(targetType); @@ -200,23 +202,23 @@ public class MetamodelBuilder { var sourceType = info.sourceType(); var targetType = info.targetType(); if (oppositeInfo == null) { - throw new IllegalArgumentException("Opposite %s of %s is not defined" + throw new TranslationException(linkType, "Opposite %s of %s is not defined" .formatted(opposite, linkType)); } if (!linkType.equals(oppositeInfo.opposite())) { - throw new IllegalArgumentException("Expected %s to have opposite %s, got %s instead" + throw new TranslationException(opposite, "Expected %s to have opposite %s, got %s instead" .formatted(opposite, linkType, oppositeInfo.opposite())); } if (!targetType.equals(oppositeInfo.sourceType())) { - throw new IllegalArgumentException("Expected %s to have source type %s, got %s instead" + throw new TranslationException(linkType, "Expected %s to have source type %s, got %s instead" .formatted(opposite, targetType, oppositeInfo.sourceType())); } if (!sourceType.equals(oppositeInfo.targetType())) { - throw new IllegalArgumentException("Expected %s to have target type %s, got %s instead" + throw new TranslationException(linkType, "Expected %s to have target type %s, got %s instead" .formatted(opposite, sourceType, oppositeInfo.targetType())); } if (oppositeInfo.containment() && info.containment()) { - throw new IllegalArgumentException("Opposite %s of containment %s cannot be containment" + throw new TranslationException(opposite, "Opposite %s of containment %s cannot be containment" .formatted(opposite, linkType)); } } diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectInitializer.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectInitializer.java index fb84631d..f11ab46b 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectInitializer.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiobject/MultiObjectInitializer.java @@ -10,6 +10,7 @@ import tools.refinery.store.model.Model; import tools.refinery.store.reasoning.ReasoningAdapter; import tools.refinery.store.reasoning.refinement.PartialModelInitializer; import tools.refinery.store.reasoning.seed.ModelSeed; +import tools.refinery.store.reasoning.translator.TranslationException; import tools.refinery.store.representation.Symbol; import tools.refinery.store.representation.TruthValue; import tools.refinery.store.representation.cardinality.CardinalityInterval; @@ -37,7 +38,8 @@ class MultiObjectInitializer implements PartialModelInitializer { for (int i = 0; i < intervals.length; i++) { var interval = intervals[i]; if (interval.isEmpty()) { - throw new IllegalArgumentException("Inconsistent existence or equality for node " + i); + throw new TranslationException(ReasoningAdapter.EXISTS_SYMBOL, + "Inconsistent existence or equality for node " + i); } var uniqueInterval = uniqueTable.computeIfAbsent(intervals[i], Function.identity()); countInterpretation.put(Tuple.of(i), uniqueInterval); @@ -58,9 +60,10 @@ class MultiObjectInitializer implements PartialModelInitializer { } else { Arrays.fill(intervals, CardinalityIntervals.SET); if (!modelSeed.containsSeed(ReasoningAdapter.EXISTS_SYMBOL) || - !modelSeed.containsSeed(ReasoningAdapter.EQUALS_SYMBOL)) { - throw new IllegalArgumentException("Seed for %s and %s is required if there is no seed for %s" - .formatted(ReasoningAdapter.EXISTS_SYMBOL, ReasoningAdapter.EQUALS_SYMBOL, + !modelSeed.containsSeed(ReasoningAdapter.EQUALS_SYMBOL)) { + throw new TranslationException(MultiObjectTranslator.COUNT_SYMBOL, + "Seed for %s and %s is required if there is no seed for %s".formatted( + ReasoningAdapter.EXISTS_SYMBOL, ReasoningAdapter.EQUALS_SYMBOL, MultiObjectTranslator.COUNT_SYMBOL)); } } @@ -78,9 +81,10 @@ class MultiObjectInitializer implements PartialModelInitializer { switch (cursor.getValue()) { case TRUE -> intervals[i] = intervals[i].meet(CardinalityIntervals.SOME); case FALSE -> intervals[i] = intervals[i].meet(CardinalityIntervals.NONE); - case ERROR -> throw new IllegalArgumentException("Inconsistent existence for node " + i); - default -> throw new IllegalArgumentException("Invalid existence truth value %s for node %d" - .formatted(cursor.getValue(), i)); + case ERROR -> throw new TranslationException(ReasoningAdapter.EXISTS_SYMBOL, + "Inconsistent existence for node " + i); + default -> throw new TranslationException(ReasoningAdapter.EXISTS_SYMBOL, + "Invalid existence truth value %s for node %d".formatted(cursor.getValue(), i)); } } } @@ -96,8 +100,8 @@ class MultiObjectInitializer implements PartialModelInitializer { int i = key.get(0); int otherIndex = key.get(1); if (i != otherIndex) { - throw new IllegalArgumentException("Off-diagonal equivalence (%d, %d) is not permitted" - .formatted(i, otherIndex)); + throw new TranslationException(ReasoningAdapter.EQUALS_SYMBOL, + "Off-diagonal equivalence (%d, %d) is not permitted".formatted(i, otherIndex)); } checkNodeId(intervals, i); switch (cursor.getValue()) { @@ -105,14 +109,15 @@ class MultiObjectInitializer implements PartialModelInitializer { case UNKNOWN -> { // Nothing do to, {@code intervals} is initialized with unknown equality. } - case ERROR -> throw new IllegalArgumentException("Inconsistent equality for node " + i); - default -> throw new IllegalArgumentException("Invalid equality truth value %s for node %d" - .formatted(cursor.getValue(), i)); + case ERROR -> throw new TranslationException(ReasoningAdapter.EQUALS_SYMBOL, + "Inconsistent equality for node " + i); + default -> throw new TranslationException(ReasoningAdapter.EQUALS_SYMBOL, + "Invalid equality truth value %s for node %d".formatted(cursor.getValue(), i)); } } for (int i = 0; i < intervals.length; i++) { if (seed.get(Tuple.of(i, i)) == TruthValue.FALSE) { - throw new IllegalArgumentException("Inconsistent equality for node " + i); + throw new TranslationException(ReasoningAdapter.EQUALS_SYMBOL, "Inconsistent equality for node " + i); } } } diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiplicity/ConstrainedMultiplicity.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiplicity/ConstrainedMultiplicity.java index e441e41e..9db9cc96 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiplicity/ConstrainedMultiplicity.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiplicity/ConstrainedMultiplicity.java @@ -6,6 +6,7 @@ package tools.refinery.store.reasoning.translator.multiplicity; import tools.refinery.store.reasoning.representation.PartialRelation; +import tools.refinery.store.reasoning.translator.TranslationException; import tools.refinery.store.representation.cardinality.CardinalityInterval; import tools.refinery.store.representation.cardinality.CardinalityIntervals; import tools.refinery.store.representation.cardinality.NonEmptyCardinalityInterval; @@ -14,17 +15,17 @@ public record ConstrainedMultiplicity(NonEmptyCardinalityInterval multiplicity, implements Multiplicity { public ConstrainedMultiplicity { if (multiplicity.equals(CardinalityIntervals.SET)) { - throw new IllegalArgumentException("Expected a constrained cardinality interval"); + throw new TranslationException(errorSymbol, "Expected a constrained cardinality interval"); } if (errorSymbol.arity() != 1) { - throw new IllegalArgumentException("Expected error symbol %s to have arity 1, got %d instead" + throw new TranslationException(errorSymbol, "Expected error symbol %s to have arity 1, got %d instead" .formatted(errorSymbol, errorSymbol.arity())); } } public static ConstrainedMultiplicity of(CardinalityInterval multiplicity, PartialRelation errorSymbol) { if (!(multiplicity instanceof NonEmptyCardinalityInterval nonEmptyCardinalityInterval)) { - throw new IllegalArgumentException("Inconsistent multiplicity"); + throw new TranslationException(errorSymbol, "Inconsistent multiplicity"); } return new ConstrainedMultiplicity(nonEmptyCardinalityInterval, errorSymbol); } diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiplicity/InvalidMultiplicityErrorTranslator.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiplicity/InvalidMultiplicityErrorTranslator.java index 522d8455..c5e5e83e 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiplicity/InvalidMultiplicityErrorTranslator.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/multiplicity/InvalidMultiplicityErrorTranslator.java @@ -14,6 +14,7 @@ import tools.refinery.store.reasoning.lifting.DnfLifter; import tools.refinery.store.reasoning.literal.*; import tools.refinery.store.reasoning.representation.PartialRelation; import tools.refinery.store.reasoning.translator.PartialRelationTranslator; +import tools.refinery.store.reasoning.translator.TranslationException; import tools.refinery.store.representation.cardinality.FiniteUpperCardinality; import tools.refinery.store.representation.cardinality.UpperCardinalities; import tools.refinery.store.representation.cardinality.UpperCardinality; @@ -36,11 +37,11 @@ public class InvalidMultiplicityErrorTranslator implements ModelStoreConfigurati public InvalidMultiplicityErrorTranslator(PartialRelation nodeType, PartialRelation linkType, boolean inverse, Multiplicity multiplicity) { if (nodeType.arity() != 1) { - throw new IllegalArgumentException("Node type must be of arity 1, got %s with arity %d instead" + throw new TranslationException(linkType, "Node type must be of arity 1, got %s with arity %d instead" .formatted(nodeType, nodeType.arity())); } if (linkType.arity() != 2) { - throw new IllegalArgumentException("Link type must be of arity 2, got %s with arity %d instead" + throw new TranslationException(linkType, "Link type must be of arity 2, got %s with arity %d instead" .formatted(linkType, linkType.arity())); } this.nodeType = nodeType; diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/opposite/OppositeRelationTranslator.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/opposite/OppositeRelationTranslator.java index b25b9d7d..6e15a628 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/opposite/OppositeRelationTranslator.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/opposite/OppositeRelationTranslator.java @@ -17,6 +17,7 @@ import tools.refinery.store.reasoning.literal.Modality; import tools.refinery.store.reasoning.refinement.RefinementBasedInitializer; import tools.refinery.store.reasoning.representation.PartialRelation; import tools.refinery.store.reasoning.translator.PartialRelationTranslator; +import tools.refinery.store.reasoning.translator.TranslationException; import java.util.List; import java.util.Set; @@ -26,6 +27,16 @@ public class OppositeRelationTranslator implements ModelStoreConfiguration, Part private final PartialRelation opposite; public OppositeRelationTranslator(PartialRelation linkType, PartialRelation opposite) { + if (linkType.arity() != 2) { + throw new TranslationException(linkType, + "Expected relation with opposite %s to have arity 2, got %d instead" + .formatted(linkType, linkType.arity())); + } + if (opposite.arity() != 2) { + throw new TranslationException(linkType, + "Expected opposite %s of %s to have arity 2, got %d instead" + .formatted(opposite, linkType, opposite.arity())); + } this.linkType = linkType; this.opposite = opposite; } diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/predicate/PredicateTranslator.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/predicate/PredicateTranslator.java index ee022f2d..16745da1 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/predicate/PredicateTranslator.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/predicate/PredicateTranslator.java @@ -17,6 +17,7 @@ import tools.refinery.store.query.view.MayView; import tools.refinery.store.query.view.MustView; import tools.refinery.store.reasoning.representation.PartialRelation; import tools.refinery.store.reasoning.translator.PartialRelationTranslator; +import tools.refinery.store.reasoning.translator.TranslationException; import tools.refinery.store.representation.Symbol; import tools.refinery.store.representation.TruthValue; @@ -33,11 +34,11 @@ public class PredicateTranslator implements ModelStoreConfiguration { public PredicateTranslator(PartialRelation relation, RelationalQuery query, boolean mutable, TruthValue defaultValue) { if (relation.arity() != query.arity()) { - throw new IllegalArgumentException("Expected arity %d query for partial relation %s, got %d instead" + throw new TranslationException(relation, "Expected arity %d query for partial relation %s, got %d instead" .formatted(relation.arity(), relation, query.arity())); } if (defaultValue.must()) { - throw new IllegalArgumentException("Default value must be UNKNOWN or FALSE"); + throw new TranslationException(relation, "Default value must be UNKNOWN or FALSE"); } this.relation = relation; this.query = query; diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchy.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchy.java index 35ec54ad..3f918c97 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchy.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchy.java @@ -6,6 +6,7 @@ package tools.refinery.store.reasoning.translator.typehierarchy; import tools.refinery.store.reasoning.representation.PartialRelation; +import tools.refinery.store.reasoning.translator.TranslationException; import java.util.*; @@ -81,8 +82,9 @@ public class TypeHierarchy { for (var supertype : allSupertypes) { var supertypeInfo = extendedTypeInfoMap.get(supertype); if (supertypeInfo == null) { - throw new IllegalArgumentException("Supertype %s of %s is missing from the type hierarchy" - .formatted(supertype, extendedTypeInfo.getType())); + throw new TranslationException(extendedTypeInfo.getType(), + "Supertype %s of %s is missing from the type hierarchy" + .formatted(supertype, extendedTypeInfo.getType())); } found.addAll(supertypeInfo.getAllSupertypes()); } @@ -101,7 +103,7 @@ public class TypeHierarchy { } for (var supertype : extendedTypeInfo.getAllSupertypes()) { if (type.equals(supertype)) { - throw new IllegalArgumentException("%s cannot be a supertype of itself".formatted(type)); + throw new TranslationException(type, "%s cannot be a supertype of itself".formatted(type)); } var supertypeInfo = extendedTypeInfoMap.get(supertype); supertypeInfo.getAllSubtypes().add(type); diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyBuilder.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyBuilder.java index 36efb878..ce8fda05 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyBuilder.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyBuilder.java @@ -6,6 +6,7 @@ package tools.refinery.store.reasoning.translator.typehierarchy; import tools.refinery.store.reasoning.representation.PartialRelation; +import tools.refinery.store.reasoning.translator.TranslationException; import java.util.*; @@ -18,12 +19,14 @@ public class TypeHierarchyBuilder { public TypeHierarchyBuilder type(PartialRelation partialRelation, TypeInfo typeInfo) { if (partialRelation.arity() != 1) { - throw new IllegalArgumentException("Only types of arity 1 are supported, got %s with %d instead" - .formatted(partialRelation, partialRelation.arity())); + throw new TranslationException(partialRelation, + "Only types of arity 1 are supported, got %s with %d instead" + .formatted(partialRelation, partialRelation.arity())); } var putResult = typeInfoMap.put(partialRelation, typeInfo); if (putResult != null && !putResult.equals(typeInfo)) { - throw new IllegalArgumentException("Duplicate type info for partial relation: " + partialRelation); + throw new TranslationException(partialRelation, + "Duplicate type info for partial relation: " + partialRelation); } return this; } diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilderTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilderTest.java index 115ba8cd..0f1a1006 100644 --- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilderTest.java +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilderTest.java @@ -7,6 +7,7 @@ package tools.refinery.store.reasoning.translator.metamodel; import org.junit.jupiter.api.Test; import tools.refinery.store.reasoning.representation.PartialRelation; +import tools.refinery.store.reasoning.translator.TranslationException; import tools.refinery.store.reasoning.translator.multiplicity.ConstrainedMultiplicity; import tools.refinery.store.representation.cardinality.CardinalityIntervals; @@ -26,7 +27,7 @@ class MetamodelBuilderTest { .reference(courses, university, course, location) .reference(location, course, university); - assertThrows(IllegalArgumentException.class, builder::build); + assertThrows(TranslationException.class, builder::build); } @Test @@ -37,7 +38,7 @@ class MetamodelBuilderTest { .reference(courses, university, course, location) .reference(location, course, course, courses); - assertThrows(IllegalArgumentException.class, builder::build); + assertThrows(TranslationException.class, builder::build); } @Test @@ -52,6 +53,6 @@ class MetamodelBuilderTest { ConstrainedMultiplicity.of(CardinalityIntervals.atLeast(2), invalidMultiplicity), university, courses); - assertThrows(IllegalArgumentException.class, builder::build); + assertThrows(TranslationException.class, builder::build); } } diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyTest.java index 9fbf2334..931c62dd 100644 --- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyTest.java +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyTest.java @@ -8,6 +8,7 @@ package tools.refinery.store.reasoning.translator.typehierarchy; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import tools.refinery.store.reasoning.representation.PartialRelation; +import tools.refinery.store.reasoning.translator.TranslationException; import tools.refinery.store.representation.TruthValue; import java.util.Set; @@ -200,7 +201,7 @@ class TypeHierarchyTest { .type(c1, c2) .type(c2, c1); - assertThrows(IllegalArgumentException.class, builder::build); + assertThrows(TranslationException.class, builder::build); } @Test -- cgit v1.2.3-54-g00ecf