diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnName.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnName.java new file mode 100644 index 000000000..546446a20 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnName.java @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.metapath.function.library; + +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.MetapathConstants; +import gov.nist.secauto.metaschema.core.metapath.StaticContext; +import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; +import gov.nist.secauto.metaschema.core.metapath.function.IArgument; +import gov.nist.secauto.metaschema.core.metapath.function.IFunction; +import gov.nist.secauto.metaschema.core.metapath.item.IItem; +import gov.nist.secauto.metaschema.core.metapath.item.ISequence; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import java.util.List; + +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * /** Implements + * fn:name + * functions. + */ +public final class FnName { + @NonNull + private static final String NAME = "name"; + @NonNull + static final IFunction SIGNATURE_NO_ARG = IFunction.builder() + .name(NAME) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) + .deterministic() + .contextDependent() + .focusDependent() + .returnType(IStringItem.type()) + .returnOne() + .functionHandler(FnName::executeNoArg) + .build(); + @NonNull + static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() + .name(NAME) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) + .deterministic() + .contextIndependent() + .focusDependent() + .argument(IArgument.builder() + .name("arg") + .type(INodeItem.type()) + .zeroOrOne() + .build()) + .returnType(IStringItem.type()) + .returnOne() + .functionHandler(FnName::executeOneArg) + .build(); + + @SuppressWarnings("unused") + @NonNull + private static ISequence executeNoArg(@NonNull IFunction function, + @NonNull List> arguments, + @NonNull DynamicContext dynamicContext, + IItem focus) { + + INodeItem arg = FunctionUtils.asType(ObjectUtils.requireNonNull(focus)); + + return ISequence.of( + IStringItem.valueOf(fnName(arg, dynamicContext.getStaticContext()))); + } + + @SuppressWarnings("unused") + @NonNull + private static ISequence executeOneArg(@NonNull IFunction function, + @NonNull List> arguments, + @NonNull DynamicContext dynamicContext, + IItem focus) { + INodeItem arg = FunctionUtils.asTypeOrNull(ObjectUtils.requireNonNull(arguments.get(0)).getFirstItem(true)); + + return ISequence.of( + IStringItem.valueOf(arg == null ? "" : fnName(arg, dynamicContext.getStaticContext()))); + } + + /** + * Get the name of the provided node item. + *

+ * Based on the XPath 3.1 + * fn:name + * function. + * + * @param arg + * the node item to get the name for + * @param staticContext + * the static context used to resolve the namespace prefix + * @return the name of the node if it has one, or an empty string otherwise + */ + @NonNull + public static String fnName(@NonNull INodeItem arg, @NonNull StaticContext staticContext) { + return arg instanceof IDefinitionNodeItem + ? ((IDefinitionNodeItem) arg).getQName().toEQName(staticContext) + : ""; + } + + private FnName() { + // disable construction + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractArrayItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractArrayItem.java index c8315574a..31ef93830 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractArrayItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractArrayItem.java @@ -10,19 +10,14 @@ import gov.nist.secauto.metaschema.core.metapath.function.IArgument; import gov.nist.secauto.metaschema.core.metapath.item.ICollectionValue; import gov.nist.secauto.metaschema.core.metapath.item.ISequence; -import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem; import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem; -import gov.nist.secauto.metaschema.core.metapath.type.ISequenceType; -import gov.nist.secauto.metaschema.core.metapath.type.Occurrence; import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; import gov.nist.secauto.metaschema.core.util.ObjectUtils; -import java.util.EnumSet; import java.util.Iterator; import java.util.List; import java.util.Objects; -import java.util.Set; import java.util.stream.Collectors; import edu.umd.cs.findbugs.annotations.NonNull; @@ -36,18 +31,12 @@ */ public abstract class AbstractArrayItem extends ImmutableCollections.AbstractImmutableDelegatedList - implements IArrayItem { + implements IArrayItem, IFeatureCollectionFunctionItem { @NonNull private static final IEnhancedQName QNAME = IEnhancedQName.of("array"); @NonNull - private static final Set PROPERTIES = ObjectUtils.notNull( - EnumSet.of(FunctionProperty.DETERMINISTIC)); - @NonNull private static final List ARGUMENTS = ObjectUtils.notNull(List.of( IArgument.builder().name("position").type(IIntegerItem.type()).one().build())); - @NonNull - private static final ISequenceType RESULT = ISequenceType.of( - IAnyAtomicItem.type(), Occurrence.ZERO_OR_ONE); @NonNull private static final IArrayItem EMPTY = new ArrayItemN<>(); @@ -65,51 +54,16 @@ public static IArrayItem empty() { return (IArrayItem) EMPTY; } - @Override - public boolean isDeterministic() { - return true; - } - - @Override - public boolean isContextDepenent() { - return false; - } - - @Override - public boolean isFocusDependent() { - return false; - } - @Override public IEnhancedQName getQName() { return QNAME; } - @Override - public Set getProperties() { - return PROPERTIES; - } - @Override public List getArguments() { return ARGUMENTS; } - @Override - public int arity() { - return 1; - } - - @Override - public boolean isArityUnbounded() { - return false; - } - - @Override - public ISequenceType getResult() { - return RESULT; - } - @Override public ISequence execute(List> arguments, DynamicContext dynamicContext, ISequence focus) { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractMapItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractMapItem.java index ee9925fa3..c1c748531 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractMapItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/AbstractMapItem.java @@ -15,17 +15,13 @@ import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem; import gov.nist.secauto.metaschema.core.metapath.item.function.IMapItem; import gov.nist.secauto.metaschema.core.metapath.item.function.IMapKey; -import gov.nist.secauto.metaschema.core.metapath.type.ISequenceType; -import gov.nist.secauto.metaschema.core.metapath.type.Occurrence; import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; import gov.nist.secauto.metaschema.core.util.ObjectUtils; -import java.util.EnumSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.stream.Collectors; import edu.umd.cs.findbugs.annotations.NonNull; @@ -39,18 +35,12 @@ */ public abstract class AbstractMapItem extends ImmutableCollections.AbstractImmutableDelegatedMap - implements IMapItem { + implements IMapItem, IFeatureCollectionFunctionItem { /** * The function qualified name. */ @NonNull private static final IEnhancedQName QNAME = IEnhancedQName.of("map"); - /** - * The function properties. - */ - @NonNull - private static final Set PROPERTIES = ObjectUtils.notNull( - EnumSet.of(FunctionProperty.DETERMINISTIC)); /** * The function arguments. */ @@ -58,10 +48,6 @@ public abstract class AbstractMapItem private static final List ARGUMENTS = ObjectUtils.notNull(List.of( IArgument.builder().name("key").type(IAnyAtomicItem.type()).one().build())); @NonNull - private static final ISequenceType RESULT = ISequenceType.of( - IAnyAtomicItem.type(), Occurrence.ZERO_OR_ONE); - - @NonNull private static final IMapItem EMPTY = new MapItemN<>(); /** @@ -78,51 +64,16 @@ public static IMapItem empty() { return (IMapItem) EMPTY; } - @Override - public boolean isDeterministic() { - return true; - } - - @Override - public boolean isContextDepenent() { - return false; - } - - @Override - public boolean isFocusDependent() { - return false; - } - @Override public IEnhancedQName getQName() { return QNAME; } - @Override - public Set getProperties() { - return PROPERTIES; - } - @Override public List getArguments() { return ARGUMENTS; } - @Override - public int arity() { - return 1; - } - - @Override - public boolean isArityUnbounded() { - return false; - } - - @Override - public ISequenceType getResult() { - return RESULT; - } - @Override public ISequence execute(List> arguments, DynamicContext dynamicContext, ISequence focus) { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/IFeatureCollectionFunctionItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/IFeatureCollectionFunctionItem.java new file mode 100644 index 000000000..0efe6d40b --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/impl/IFeatureCollectionFunctionItem.java @@ -0,0 +1,63 @@ + +package gov.nist.secauto.metaschema.core.metapath.impl; + +import gov.nist.secauto.metaschema.core.metapath.function.IFunction; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; +import gov.nist.secauto.metaschema.core.metapath.type.ISequenceType; +import gov.nist.secauto.metaschema.core.metapath.type.Occurrence; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import java.util.EnumSet; +import java.util.Set; + +import edu.umd.cs.findbugs.annotations.NonNull; + +public interface IFeatureCollectionFunctionItem extends IFunction { + /** + * The function properties. + */ + @NonNull + Set PROPERTIES = ObjectUtils.notNull( + EnumSet.of(FunctionProperty.DETERMINISTIC)); + /** + * The function result. + */ + @NonNull + ISequenceType RESULT = ISequenceType.of( + IAnyAtomicItem.type(), Occurrence.ZERO_OR_ONE); + + @Override + default boolean isDeterministic() { + return true; + } + + @Override + default boolean isContextDepenent() { + return false; + } + + @Override + default boolean isFocusDependent() { + return false; + } + + @Override + default Set getProperties() { + return PROPERTIES; + } + + @Override + default int arity() { + return 1; + } + + @Override + default boolean isArityUnbounded() { + return false; + } + + @Override + default ISequenceType getResult() { + return RESULT; + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractDefinitionNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractDefinitionNodeItem.java index 53b445b70..8f23466a3 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractDefinitionNodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractDefinitionNodeItem.java @@ -6,7 +6,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -abstract class AbstractDefinitionNodeItem +public abstract class AbstractDefinitionNodeItem extends AbstractNodeItem implements IFeatureOrhpanedDefinitionNodeItem { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractFlagInstanceNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractFlagInstanceNodeItem.java index dd7203c60..a2b0dd22f 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractFlagInstanceNodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractFlagInstanceNodeItem.java @@ -9,7 +9,7 @@ /** * A {@link INodeItem} supported by a {@link IFlagInstance}. */ -abstract class AbstractFlagInstanceNodeItem +public abstract class AbstractFlagInstanceNodeItem extends AbstractInstanceNodeItem> implements IFlagNodeItem { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractGlobalDefinitionNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractGlobalDefinitionNodeItem.java index 4734fb40c..2c0a62470 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractGlobalDefinitionNodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractGlobalDefinitionNodeItem.java @@ -15,7 +15,7 @@ * @param * the definition type */ -abstract class AbstractGlobalDefinitionNodeItem +public abstract class AbstractGlobalDefinitionNodeItem extends AbstractDefinitionNodeItem { @NonNull private final IModuleNodeItem metaschemaNodeItem; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractInstanceNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractInstanceNodeItem.java index db0d6074b..fffeca305 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractInstanceNodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractInstanceNodeItem.java @@ -7,7 +7,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -abstract class AbstractInstanceNodeItem< +public abstract class AbstractInstanceNodeItem< D extends IDefinition, I extends INamedInstance, P extends IModelNodeItem> diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractOrphanedDefinitionNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractOrphanedDefinitionNodeItem.java index a35267aa1..33671bba6 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractOrphanedDefinitionNodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/AbstractOrphanedDefinitionNodeItem.java @@ -11,7 +11,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -abstract class AbstractOrphanedDefinitionNodeItem +public abstract class AbstractOrphanedDefinitionNodeItem extends AbstractDefinitionNodeItem { @Nullable diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IAtomicValuedNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IAtomicValuedNodeItem.java new file mode 100644 index 000000000..0e4bd8285 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IAtomicValuedNodeItem.java @@ -0,0 +1,17 @@ + +package gov.nist.secauto.metaschema.core.metapath.item.node; + +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAtomicValuedItem; +import gov.nist.secauto.metaschema.core.metapath.type.IAtomicOrUnionType; + +import edu.umd.cs.findbugs.annotations.NonNull; + +public interface IAtomicValuedNodeItem extends IAtomicValuedItem, INodeItem { + @NonNull + IAtomicOrUnionType getValueItemType(); + + @Override + default String stringValue() { + return toAtomicItem().asString(); + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFieldNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFieldNodeItem.java index 503494598..1a197f49f 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFieldNodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFieldNodeItem.java @@ -4,7 +4,7 @@ import gov.nist.secauto.metaschema.core.metapath.StaticContext; import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; import gov.nist.secauto.metaschema.core.metapath.item.ICollectionValue; -import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAtomicValuedItem; +import gov.nist.secauto.metaschema.core.metapath.type.IAtomicOrUnionType; import gov.nist.secauto.metaschema.core.metapath.type.IItemType; import gov.nist.secauto.metaschema.core.metapath.type.IKindTest; import gov.nist.secauto.metaschema.core.model.IFieldDefinition; @@ -20,7 +20,7 @@ */ public interface IFieldNodeItem extends IModelNodeItem, - IAtomicValuedItem { + IAtomicValuedNodeItem { /** * Get the static type information of the node item. * @@ -55,6 +55,11 @@ default IKindTest getType() { staticContext); } + @Override + default IAtomicOrUnionType getValueItemType() { + return getDefinition().getJavaTypeAdapter().getItemType(); + } + @Override @Nullable default URI getBaseUri() { @@ -64,7 +69,7 @@ default URI getBaseUri() { @Override default @NonNull - String format(@NonNull IPathFormatter formatter) { + String format(@NonNull IPathFormatter formatter) { return formatter.formatField(this); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFlagNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFlagNodeItem.java index fbf8fce91..1df6bd05c 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFlagNodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFlagNodeItem.java @@ -4,7 +4,7 @@ import gov.nist.secauto.metaschema.core.metapath.StaticContext; import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; import gov.nist.secauto.metaschema.core.metapath.item.ICollectionValue; -import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAtomicValuedItem; +import gov.nist.secauto.metaschema.core.metapath.type.IAtomicOrUnionType; import gov.nist.secauto.metaschema.core.metapath.type.IItemType; import gov.nist.secauto.metaschema.core.metapath.type.IKindTest; import gov.nist.secauto.metaschema.core.model.IFlagDefinition; @@ -25,7 +25,7 @@ */ public interface IFlagNodeItem - extends IDefinitionNodeItem, IAtomicValuedItem { + extends IDefinitionNodeItem, IAtomicValuedNodeItem { /** * Get the static type information of the node item. * @@ -66,6 +66,11 @@ default IKindTest getType() { staticContext); } + @Override + default IAtomicOrUnionType getValueItemType() { + return getDefinition().getJavaTypeAdapter().getItemType(); + } + @Override @Nullable default URI getBaseUri() { @@ -100,7 +105,7 @@ default IFlagNodeItem getFlagByName(@NonNull IEnhancedQName name) { @SuppressWarnings("null") @Override default @NonNull - Stream flags() { + Stream flags() { // a flag does not have flags return Stream.empty(); } @@ -112,7 +117,7 @@ Stream flags() { @SuppressWarnings("null") @Override default @NonNull - Collection>> getModelItems() { + Collection>> getModelItems() { // a flag does not have model items return Collections.emptyList(); } @@ -141,7 +146,7 @@ Stream flags() { @Override default @NonNull - String format(@NonNull IPathFormatter formatter) { + String format(@NonNull IPathFormatter formatter) { return formatter.formatFlag(this); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/DataTypeItemType.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/DataTypeItemType.java index 1664d8dfa..3f5b8390a 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/DataTypeItemType.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/DataTypeItemType.java @@ -53,6 +53,12 @@ public IEnhancedQName getQName() { return getAdapter().getPreferredName(); } + @SuppressWarnings("unchecked") + @Override + public T newItem(Object value) { + return (T) getAdapter().newItem(value); + } + @Override public String toString() { return toSignature(); diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/IAtomicOrUnionType.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/IAtomicOrUnionType.java index 1de1ed90c..dcdf22673 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/IAtomicOrUnionType.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/IAtomicOrUnionType.java @@ -110,6 +110,7 @@ default boolean isSubType(@NonNull IAtomicOrUnionType other) { * @throws InvalidValueForCastFunctionException * if the provided {@code item} cannot be cast to this type */ + @NonNull I cast(@NonNull IAnyAtomicItem item); /** @@ -151,4 +152,14 @@ interface ICastExecutor { @NonNull ITEM cast(@NonNull IAnyAtomicItem item); } + + /** + * Construct a new instance of this type using the provided value. + * + * @param value + * the "wrapped" value of the type + * @return the new item + */ + @NonNull + I newItem(@NonNull Object value); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/impl/NonAdapterAtomicItemType.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/impl/NonAdapterAtomicItemType.java index 6761dfc0d..c63b04f3a 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/impl/NonAdapterAtomicItemType.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/type/impl/NonAdapterAtomicItemType.java @@ -79,4 +79,9 @@ public boolean equals(Object obj) { return Objects.equals(getItemClass(), other.getItemClass()) && Objects.equals(getQName(), other.getQName()); } + + @Override + public T newItem(Object value) { + throw new UnsupportedOperationException("Not a conrete atomic type."); + } }