diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/api/AxiomValue.java b/infra/axiom/src/main/java/com/evolveum/axiom/api/AxiomValue.java index 370599a308b..881a4622978 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/api/AxiomValue.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/api/AxiomValue.java @@ -34,4 +34,15 @@ static AxiomValue from(AxiomTypeDefinition typeDefinition, V value) { return new SimpleValue(typeDefinition, value); } + default Optional> onlyValue(Class type, AxiomItemDefinition... components) { + Optional> current = Optional.of(this); + for(AxiomItemDefinition name : components) { + current = current.get().item(name).map(v -> v.onlyValue()); + if(current.isEmpty()) { + return Optional.empty(); + } + } + return (Optional) current; + } + } diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/api/AxiomValueBuilder.java b/infra/axiom/src/main/java/com/evolveum/axiom/api/AxiomValueBuilder.java index 0f3b87e1dbd..65114745be9 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/api/AxiomValueBuilder.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/api/AxiomValueBuilder.java @@ -54,6 +54,7 @@ public Supplier> get(AxiomIdentifier name, Function> builder = ImmutableMap.builder(); for(Entry>> entry : children.entrySet()) { + AxiomItem item = entry.getValue().get(); builder.put(entry.getKey(), entry.getValue().get()); } return factory.create(type, value, builder.build()); diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/api/schema/AxiomTypeDefinition.java b/infra/axiom/src/main/java/com/evolveum/axiom/api/schema/AxiomTypeDefinition.java index 2a706716d17..0298895be02 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/api/schema/AxiomTypeDefinition.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/api/schema/AxiomTypeDefinition.java @@ -20,7 +20,7 @@ public interface AxiomTypeDefinition extends AxiomNamedDefinition, AxiomValue { public final AxiomIdentifier IDENTIFIER_MEMBER = AxiomIdentifier.axiom("name"); - public final AxiomIdentifier IDENTIFIER_SPACE = AxiomIdentifier.axiom("AxiomTypeDefinition"); + public final AxiomIdentifier SPACE = AxiomIdentifier.axiom("AxiomTypeDefinition"); @Override diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/api/AxiomBuiltIn.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/api/AxiomBuiltIn.java index 5789aa2fa4f..62770262611 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/api/AxiomBuiltIn.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/api/AxiomBuiltIn.java @@ -54,6 +54,8 @@ public static class Item implements AxiomItemDefinition { public static final AxiomItemDefinition ID_SPACE = new Item("space", Type.IDENTIFIER, false); public static final AxiomItemDefinition TARGET = new Item("target", Type.TYPE_REFERENCE, true); + public static final AxiomItemDefinition REF_TARGET = new Item("target", Type.TYPE_DEFINITION, true); + private final AxiomIdentifier identifier; private final AxiomTypeDefinition type; @@ -128,7 +130,10 @@ public static class Type implements AxiomTypeDefinition { public static final Type UUID = new Type("uuid"); public static final Type STRING = new Type("string"); public static final Type IDENTIFIER = new Type("AxiomIdentifier"); - public static final Type TYPE_REFERENCE = new Type("AxiomTypeReference"); + public static final Type TYPE_REFERENCE = new Type("AxiomTypeReference", null, () -> Item.NAME, () -> itemDefs( + Item.NAME, + Item.REF_TARGET + )); public static final Type BASE_DEFINITION = new Type("AxiomBaseDefinition", null, () -> Item.NAME, () -> itemDefs( Item.NAME, diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomItemContext.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomItemContext.java index ca571fb4294..48eeed9c865 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomItemContext.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomItemContext.java @@ -8,4 +8,6 @@ public interface AxiomItemContext { T onlyValue(); + void addOperationalValue(AxiomValueReference value); + } diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomSchemaContextImpl.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomSchemaContextImpl.java index 669cd29736f..f9baaab7af5 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomSchemaContextImpl.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomSchemaContextImpl.java @@ -23,7 +23,7 @@ public class AxiomSchemaContextImpl implements AxiomSchemaContext { public AxiomSchemaContextImpl(Map>> globalMap) { this.globals = globalMap; this.roots = Maps.transformValues(globalMap.get(AxiomItemDefinition.ROOT_SPACE), AxiomItemDefinition.class::cast); - this.types = Maps.transformValues(globalMap.get(AxiomTypeDefinition.IDENTIFIER_SPACE), AxiomTypeDefinition.class::cast); + this.types = Maps.transformValues(globalMap.get(AxiomTypeDefinition.SPACE), AxiomTypeDefinition.class::cast); } @Override @@ -53,7 +53,7 @@ private static IdentifierSpaceKey nameKey(AxiomIdentifier type) { public static AxiomSchemaContextImpl boostrapContext() { Map> root = ImmutableMap.of(nameKey(AxiomBuiltIn.Item.MODEL_DEFINITION.name()), AxiomBuiltIn.Item.MODEL_DEFINITION); Map>> global - = ImmutableMap.of(AxiomItemDefinition.ROOT_SPACE, root, AxiomTypeDefinition.IDENTIFIER_SPACE, ImmutableMap.of()); + = ImmutableMap.of(AxiomItemDefinition.ROOT_SPACE, root, AxiomTypeDefinition.SPACE, ImmutableMap.of()); return new AxiomSchemaContextImpl(global); } diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomStatementRule.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomStatementRule.java index 4b980f8d698..c33b538e4e6 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomStatementRule.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomStatementRule.java @@ -27,12 +27,16 @@ default AxiomTypeDefinition typeDefinition() { Dependency namespace(AxiomIdentifier name, IdentifierSpaceKey namespaceId); - Dependency> child(AxiomItemDefinition namespace, Class valueType); + Dependency> child(AxiomItemDefinition item, Class valueType); + + Dependency> onlyItemValue(AxiomItemDefinition item, Class valueType); Dependency> modify(AxiomIdentifier identifierSpace, IdentifierSpaceKey identifier); Dependency.Search> global(AxiomIdentifier identifierSpace, IdentifierSpaceKey identifier); + Dependency.Search> reference(AxiomIdentifier identifierSpace, IdentifierSpaceKey identifier); + Dependency.Search> namespaceValue(AxiomIdentifier space, IdentifierSpaceKey itemName); Dependency finalValue(); diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomValueReference.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomValueReference.java new file mode 100644 index 00000000000..b92bdf4852d --- /dev/null +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/AxiomValueReference.java @@ -0,0 +1,5 @@ +package com.evolveum.axiom.lang.impl; + +public interface AxiomValueReference { + +} diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/BasicStatementRule.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/BasicStatementRule.java index 136dd6fc253..b1eaf4389d3 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/BasicStatementRule.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/BasicStatementRule.java @@ -84,15 +84,21 @@ public void apply(Lookup context, ActionBuilder context, ActionBuilder action) throws AxiomSemanticException { - AxiomIdentifier type = context.originalValue(); - Dependency.Search> typeDef = action.require(context.global(AxiomTypeDefinition.IDENTIFIER_SPACE, AxiomTypeDefinition.identifier(type))); - typeDef.notFound(() -> action.error("type '%s' was not found.", type)); - typeDef.unsatisfied(() -> action.error("Referenced type %s is not complete.", type)); + + Dependency> typeDef = action.require(context.child(Item.NAME, AxiomIdentifier.class) + .unsatisfied(() -> action.error("type name is missing.")) + .map(v -> v.onlyValue().get()) + .flatMap(name -> + context.reference(AxiomTypeDefinition.SPACE,AxiomTypeDefinition.identifier(name)) + .notFound(() -> action.error("type '%s' was not found.", name)) + .unsatisfied(() -> action.error("Referenced type %s is not complete.", name)) + ) + ); action.apply(ctx -> { - ctx.replace(typeDef.get()); + ctx.childItem(Item.REF_TARGET).addOperationalValue((AxiomValueReference) typeDef.get()); }); } }, @@ -117,16 +123,13 @@ public void apply(Lookup context, ActionBuilder context, ActionBuilder action) throws AxiomSemanticException { - AxiomIdentifier type = context.originalValue(); - Dependency> typeName = action.require(context.parentValue().child(Item.NAME, AxiomIdentifier.class)) - .unsatisfied(() -> action.error("type does not have name defined")); - Dependency.Search> typeDef = action.require(context.global(AxiomTypeDefinition.IDENTIFIER_SPACE, AxiomTypeDefinition.identifier(type))); - - typeDef.notFound(() -> action.error("type '%s' was not found.", type)); - typeDef.unsatisfied(() -> action.error("Referenced type %s is not complete.", type)); + Dependency typeDef = + action.require( + context.onlyItemValue(Item.REF_TARGET, AxiomTypeDefinition.class) + .map(v -> v.get())); + typeDef.unsatisfied(() -> action.error("Supertype is not complete.")); action.apply(superTypeValue -> { - superTypeValue.replace(typeDef.get()); - addFromType(typeDef.get(), superTypeValue.parentValue(), typeName.get().onlyValue().get()); + addFromType(typeDef.get(), superTypeValue.parentValue(), typeDef.get().name()); }); } @@ -134,7 +137,6 @@ public void apply(Lookup context, ActionBuilder context, ActionBuilder action) throws AxiomSemanticException { Dependency req = action.require(context.namespace(Item.NAMESPACE.name(), namespaceId(AxiomModel.BUILTIN_TYPES))); @@ -174,9 +176,10 @@ public void apply(Lookup context, ActionBuilder context, ActionBuilder action) throws AxiomSemanticException { Dependency> targetRef = action.require(context.child(Item.TARGET, AxiomIdentifier.class) + .map(v -> v.onlyValue().item(Item.NAME).get())) .flatMap(item -> - context.modify(AxiomTypeDefinition.IDENTIFIER_SPACE, AxiomTypeDefinition.identifier(item.onlyValue().get())) - .unsatisfied(() -> action.error("Target %s not found.",item.onlyValue().get())) + context.modify(AxiomTypeDefinition.SPACE, AxiomTypeDefinition.identifier((AxiomIdentifier) item.onlyValue().get())) + .unsatisfied(() -> action.error("Target %s not found.",item.onlyValue().get()) )); Dependency> itemDef = action.require(context.child(Item.ITEM_DEFINITION, AxiomItemDefinition.class)); action.apply(ext -> { diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ItemContext.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ItemContext.java index f81d0c7f983..56f22b9508f 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ItemContext.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ItemContext.java @@ -58,7 +58,14 @@ protected Optional childDef(AxiomIdentifier id) { @Override public boolean isSatisfied() { - return Dependency.allSatisfied(values); + for (Dependency> value : values) { + if(!(value instanceof ValueContext.ReferenceDependency)) { + if(!value.isSatisfied()) { + return false; + } + } + } + return true; } @Override @@ -83,6 +90,12 @@ public AxiomValueContext addValue(V value) { return ret; } + @Override + public void addOperationalValue(AxiomValueReference value) { + Preconditions.checkState(value instanceof ValueContext.Reference); + values.add(((ValueContext.Reference) value).asDependency()); + } + @Override public V onlyValue() { Preconditions.checkState(values.size() == 1); @@ -99,4 +112,11 @@ public AxiomIdentifierResolver valueResolver() { return rootImpl().valueResolver(); } + public Dependency> onlyValue0() { + if(values.size() == 1) { + return values.iterator().next(); + } + return null; + } + } diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ItemValueImpl.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ItemValueImpl.java index 18448f51207..414daead9eb 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ItemValueImpl.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ItemValueImpl.java @@ -20,6 +20,9 @@ public class ItemValueImpl implements AxiomValue { private final Map> items; + protected X require(Optional value) { + return value.get(); + } public ItemValueImpl(AxiomTypeDefinition type, V value, Map> items) { super(); diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/LazyValue.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/LazyValue.java new file mode 100644 index 00000000000..db347a75621 --- /dev/null +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/LazyValue.java @@ -0,0 +1,33 @@ +package com.evolveum.axiom.lang.impl; + +import java.util.Optional; +import java.util.function.Supplier; + +import com.evolveum.axiom.api.AxiomValue; +import com.evolveum.axiom.api.schema.AxiomTypeDefinition; + +class LazyValue implements AxiomValue{ + + private final AxiomTypeDefinition type; + private Object delegate; + + public LazyValue(AxiomTypeDefinition type, Supplier> supplier) { + this.type = type; + this.delegate = supplier; + } + + @Override + public Optional type() { + return Optional.of(type); + } + + @Override + public V get() { + if(delegate instanceof AxiomValue) { + return ((AxiomValue) delegate).get(); + } + delegate = ((Supplier>)delegate).get(); + return get(); + } + +} diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ValueActionImpl.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ValueActionImpl.java index 3fb2463a63e..6b0c2aad5f7 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ValueActionImpl.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ValueActionImpl.java @@ -11,7 +11,6 @@ import com.evolveum.axiom.lang.spi.AxiomSemanticException; import com.evolveum.axiom.reactor.Dependency; import com.evolveum.axiom.reactor.DependantAction; -import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; public class ValueActionImpl implements AxiomStatementRule.ActionBuilder, DependantAction { @@ -91,7 +90,7 @@ public Collection> requirements() { @Override public void fail(Exception e) throws AxiomSemanticException { - this.error = e; + this.error = new AxiomSemanticException(context.startLocation(), e.getClass().getName() + " " + e.getMessage(), e); } diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ValueContext.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ValueContext.java index e7be20b0fbd..f4093abbaa8 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ValueContext.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/impl/ValueContext.java @@ -32,6 +32,9 @@ public class ValueContext extends AbstractContext> implements private final LookupImpl lookup = new LookupImpl(); private final V originalValue; private final Collection> dependencies = new HashSet<>(); + private AxiomValue lazyValue; + public ReferenceDependency referenceDependency = new ReferenceDependency(); + public Reference reference = new Reference(); public ValueContext(SourceLocation loc, IdentifierSpaceHolder space) { super(null, loc, space); @@ -43,6 +46,7 @@ public ValueContext(ItemContext itemContext, V value, SourceLocation loc) { super(itemContext, loc, AxiomIdentifierDefinition.Scope.LOCAL); originalValue = value; result = new Result(parent().type(), value); + lazyValue = new LazyValue<>(itemDefinition().typeDefinition(),() -> get()); } @Override @@ -70,7 +74,7 @@ public void endValue(SourceLocation loc) { } protected Result mutable() { - Preconditions.checkState(result instanceof ValueContext.Result); + Preconditions.checkState(result instanceof ValueContext.Result, "Result is not mutable."); return (Result) result; } @@ -81,6 +85,9 @@ public boolean isSatisfied() { @Override public AxiomValue get() { + if(isMutable()) { + result = Dependency.immediate(result.get()); + } return result.get(); } @@ -166,8 +173,8 @@ public void replace(AxiomValue axiomItemValue) { } @Override - public AxiomItemContext childItem(AxiomIdentifier name) { - return (AxiomItemContext) mutable().getOrCreateItem(Inheritance.adapt(parent().name(), name), SourceLocation.runtime()); + public ItemContext childItem(AxiomIdentifier name) { + return (ItemContext) mutable().getOrCreateItem(Inheritance.adapt(parent().name(), name), SourceLocation.runtime()); } @Override @@ -210,7 +217,7 @@ public void dependsOnAction(ValueActionImpl action) { addDependency(action); } - public Dependency> requireChild(AxiomIdentifier item) { + public Dependency.Search> requireChild(AxiomIdentifier item) { return Dependency.retriableDelegate(() -> { if(result instanceof ValueContext.Result) { return ((ValueContext.Result) result).getItem(item); @@ -265,6 +272,24 @@ public Dependency> child(AxiomItemDefinition definition, Class< return requireChild(Inheritance.adapt(parent().name(), definition)); } + @Override + public Dependency> onlyItemValue(AxiomItemDefinition definition, Class valueType) { + return Dependency.retriableDelegate(() -> { + Dependency> item; + if(result instanceof ValueContext.Result) { + item = ((ValueContext.Result) result).getItem(definition.name()); + } else { + item = result.flatMap(v -> Dependency.from(v.item(definition))); + } + if(item instanceof ItemContext) { + return ((ItemContext) item).onlyValue0(); + } else if (item == null) { + return null; + } + return item.map(i -> i.onlyValue()); + }); + } + @Override public Dependency> modify(AxiomIdentifier space, IdentifierSpaceKey key) { return (Dependency.retriableDelegate(() -> { @@ -289,6 +314,18 @@ public Dependency.Search> global(AxiomIdentifier space, }); } + @Override + public Dependency.Search> reference(AxiomIdentifier space, + IdentifierSpaceKey key) { + return Dependency.retriableDelegate(() -> { + ValueContext maybe = lookup(space, key); + if(maybe != null) { + return Dependency.immediate(maybe.reference); + } + return null; + }); + } + @Override public Dependency.Search> namespaceValue(AxiomIdentifier space, IdentifierSpaceKey key) { @@ -354,9 +391,40 @@ public AxiomIdentifierResolver itemResolver() { }; } + public AxiomValue lazyValue() { + return lazyValue; + } + @Override public AxiomIdentifierResolver valueResolver() { return rootImpl().valueResolver(); } + final class Reference implements AxiomValueReference { + + public ReferenceDependency asDependency() { + return referenceDependency; + } + + } + + final class ReferenceDependency implements Dependency> { + + @Override + public boolean isSatisfied() { + return ValueContext.this.isSatisfied(); + } + + @Override + public AxiomValue get() { + return lazyValue; + } + + @Override + public Exception errorMessage() { + // TODO Auto-generated method stub + return null; + } + } + } diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/spi/AxiomItemDefinitionImpl.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/spi/AxiomItemDefinitionImpl.java index 8c25fec3911..168416f6dd8 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/spi/AxiomItemDefinitionImpl.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/spi/AxiomItemDefinitionImpl.java @@ -5,6 +5,7 @@ import com.evolveum.axiom.api.AxiomIdentifier; import com.evolveum.axiom.api.AxiomItem; +import com.evolveum.axiom.api.AxiomValue; import com.evolveum.axiom.api.AxiomValueFactory; import com.evolveum.axiom.api.schema.AxiomItemDefinition; import com.evolveum.axiom.api.schema.AxiomTypeDefinition; @@ -13,12 +14,12 @@ public class AxiomItemDefinitionImpl extends AbstractBaseDefinition implements AxiomItemDefinition { public static final AxiomValueFactory FACTORY = AxiomItemDefinitionImpl::new ; - private final AxiomTypeDefinition valueType; + private final AxiomValue valueType; private final Optional> minOccurs; public AxiomItemDefinitionImpl(AxiomTypeDefinition axiomItemDefinition, AxiomItemDefinition value, Map> items) { super(axiomItemDefinition, value, items); - this.valueType = this.item(Item.TYPE_REFERENCE.name()).get().onlyValue().get(); + this.valueType = require(onlyValue(AxiomTypeDefinition.class,Item.TYPE_REFERENCE, Item.REF_TARGET)); minOccurs = this.item(Item.MIN_OCCURS.name()); } @@ -39,7 +40,7 @@ public AxiomItemDefinition get() { @Override public AxiomTypeDefinition typeDefinition() { - return valueType; + return valueType.get(); } @Override diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/lang/spi/AxiomTypeDefinitionImpl.java b/infra/axiom/src/main/java/com/evolveum/axiom/lang/spi/AxiomTypeDefinitionImpl.java index 2f849f4ad96..5a7e38226ee 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/lang/spi/AxiomTypeDefinitionImpl.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/lang/spi/AxiomTypeDefinitionImpl.java @@ -37,7 +37,7 @@ public AxiomTypeDefinitionImpl(AxiomTypeDefinition def, AxiomTypeDefinition valu } itemDefinitions = builder.build(); - superType = this.item(Item.SUPERTYPE_REFERENCE.name()).map(v -> v.onlyValue().get()); + superType = onlyValue(AxiomTypeDefinition.class,Item.SUPERTYPE_REFERENCE, Item.REF_TARGET).map(v -> v.get()); argument = this.item(Item.ARGUMENT.name()).flatMap(v -> itemDefinition(v.onlyValue().get())); identifiers = upcast(this.item(Item.IDENTIFIER_DEFINITION.name()).map(v -> v.values()).orElse(Collections.emptyList())); diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/reactor/Dependency.java b/infra/axiom/src/main/java/com/evolveum/axiom/reactor/Dependency.java index e37b5fc1593..3cb076ce517 100644 --- a/infra/axiom/src/main/java/com/evolveum/axiom/reactor/Dependency.java +++ b/infra/axiom/src/main/java/com/evolveum/axiom/reactor/Dependency.java @@ -146,6 +146,12 @@ public T get() { Preconditions.checkState(isSatisfied(), "Requirement was not satisfied"); return delegate().get(); } + + @Override + public Exception errorMessage() { + Exception maybe = super.errorMessage(); + return maybe != null ? maybe : delegate().errorMessage(); + } } public final class OptionalDep extends Delegated { @@ -240,21 +246,14 @@ static boolean allSatisfied(Collection> outstanding) { } default Dependency map(Function map) { - return new Suppliable(() -> { - if(isSatisfied()) { - return map.apply(get()); - } - return null; - }); + return new MapDependency<>(this, map); } default Dependency flatMap(Function> map) { - return new RetriableDelegate(() -> { - if(isSatisfied()) { - return map.apply(get()); - } - return null; - }); + return new FlatMapDependency<>(this, map); + } + static Dependency of(T from) { + return Dependency.immediate(from); } } diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/reactor/FlatMapDependency.java b/infra/axiom/src/main/java/com/evolveum/axiom/reactor/FlatMapDependency.java new file mode 100644 index 00000000000..21b2ea41e82 --- /dev/null +++ b/infra/axiom/src/main/java/com/evolveum/axiom/reactor/FlatMapDependency.java @@ -0,0 +1,25 @@ +package com.evolveum.axiom.reactor; + +import java.util.function.Function; + +public class FlatMapDependency extends Dependency.Delegated { + + private Dependency delegate; + private Function> mapping; + + public FlatMapDependency(Dependency delegate, Function> mapping) { + super(); + this.delegate = delegate; + this.mapping = mapping; + } + + @Override + Dependency delegate() { + if(mapping != null && delegate.isSatisfied()) { + delegate = mapping.apply((I) delegate.get()); + mapping = null; + } + return delegate; + } + +} diff --git a/infra/axiom/src/main/java/com/evolveum/axiom/reactor/MapDependency.java b/infra/axiom/src/main/java/com/evolveum/axiom/reactor/MapDependency.java new file mode 100644 index 00000000000..c2194e06681 --- /dev/null +++ b/infra/axiom/src/main/java/com/evolveum/axiom/reactor/MapDependency.java @@ -0,0 +1,26 @@ +package com.evolveum.axiom.reactor; + +import java.util.function.Function; + +public class MapDependency extends Dependency.Delegated { + + private Dependency delegate; + private Function mapping; + + public MapDependency(Dependency delegate, Function mapping) { + super(); + this.delegate = delegate; + this.mapping = mapping; + } + + @Override + Dependency delegate() { + return delegate; + } + + @Override + public O get() { + return mapping.apply(delegate.get()); + } + +} diff --git a/infra/axiom/src/main/resources/axiom-lang.axiom b/infra/axiom/src/main/resources/axiom-lang.axiom index 69c407bcca3..aaa2beb70c9 100644 --- a/infra/axiom/src/main/resources/axiom-lang.axiom +++ b/infra/axiom/src/main/resources/axiom-lang.axiom @@ -190,12 +190,14 @@ model axiom-lang { } type AxiomTypeReference { - //type AxiomIdentifier; - //reference { - // scope global; - // space AxiomTypeDefinition; - // argument name; - //} + argument name; + item name { + type AxiomIdentifier; + } + item target { + type AxiomTypeDefinition; + operational true; + } } type AxiomMixinDefinition {