From 6028a1fba7f126832fe494d9beb081c9def1c573 Mon Sep 17 00:00:00 2001 From: David Waltermire Date: Mon, 25 Nov 2024 15:06:59 -0500 Subject: [PATCH] Cleaned up atomize and getAtomicItem method use. --- .../core/metapath/ICollectionValue.java | 12 +++ .../metaschema/core/metapath/ISequence.java | 7 +- .../core/metapath/MetapathExpression.java | 2 +- .../core/metapath/StaticContext.java | 9 +- .../metapath/StaticMetapathException.java | 16 +++- .../core/metapath/cst/AbstractExpression.java | 2 +- .../core/metapath/cst/BuildCSTVisitor.java | 3 +- .../cst/items/FunctionCallAccessor.java | 3 +- .../metapath/cst/items/MapConstructor.java | 3 +- .../core/metapath/cst/items/StringConcat.java | 2 +- .../metapath/cst/logic/GeneralComparison.java | 4 +- .../core/metapath/cst/path/Axis.java | 9 +- .../metapath/function/DefaultFunction.java | 3 +- .../core/metapath/function/FunctionUtils.java | 3 +- .../core/metapath/function/IFunction.java | 8 +- .../metapath/function/library/FnData.java | 85 +------------------ .../metapath/function/library/MapMerge.java | 2 +- .../metapath/impl/AbstractKeySpecifier.java | 13 ++- .../core/metapath/item/DefaultItemWriter.java | 3 +- .../metaschema/core/metapath/item/IItem.java | 34 ++++++++ .../metapath/item/atomic/IAnyAtomicItem.java | 8 ++ .../item/atomic/IAtomicValuedItem.java | 10 +-- .../metapath/item/function/IArrayItem.java | 6 ++ .../metapath/item/node/IAssemblyNodeItem.java | 7 ++ .../item/node/IDocumentBasedNodeItem.java | 8 ++ .../node/IFeatureNoDataAtomicValuedItem.java | 1 - .../item/node/IFeatureNoDataValuedItem.java | 1 - .../metapath/type/IAtomicOrUnionType.java | 2 +- .../metaschema/core/model/AbstractModule.java | 8 ++ .../metaschema/core/model/IModule.java | 6 +- .../AbstractConstraintValidationHandler.java | 3 +- .../DefaultConstraintValidator.java | 5 +- .../core/model/constraint/IIndex.java | 3 +- .../core/metapath/cst/path/StepTest.java | 3 +- 34 files changed, 149 insertions(+), 145 deletions(-) diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ICollectionValue.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ICollectionValue.java index dc2fe6e1f..2ee886688 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ICollectionValue.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ICollectionValue.java @@ -6,6 +6,7 @@ package gov.nist.secauto.metaschema.core.metapath; import gov.nist.secauto.metaschema.core.metapath.item.IItem; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem; import gov.nist.secauto.metaschema.core.metapath.item.function.IMapItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -74,6 +75,17 @@ static Stream normalizeAsItems(@NonNull ICollectionValue value) : value.toSequence().stream(); } + /** + * Produce a stream of atomic items based on the atomic value of these items. + *

+ * Supports item + * atomization. + * + * @return a stream of atomized atomic items. + */ + @NonNull + Stream atomize(); + /** * Get the stream of items for the collection value. *

diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ISequence.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ISequence.java index 66f252e09..4b4c951f6 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ISequence.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ISequence.java @@ -5,7 +5,6 @@ package gov.nist.secauto.metaschema.core.metapath; -import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; import gov.nist.secauto.metaschema.core.metapath.impl.AbstractSequence; import gov.nist.secauto.metaschema.core.metapath.impl.SequenceN; import gov.nist.secauto.metaschema.core.metapath.impl.SingletonSequence; @@ -158,10 +157,10 @@ default ITEM getFirstItem(boolean requireSingleton) { * the sequence of items to atomize * @return the atomized result */ + @Override @NonNull - default ISequence atomize() { - return of(ObjectUtils.notNull(stream() - .flatMap(FnData::atomize))); + default Stream atomize() { + return ObjectUtils.notNull(stream().flatMap(IItem::atomize)); } /** diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathExpression.java index 93821ceef..b0d033dbb 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathExpression.java @@ -63,7 +63,7 @@ public enum ResultType { * The result is expected to be a {@link String} value. */ STRING(String.class, sequence -> { - IAnyAtomicItem item = sequence.atomize().getFirstItem(true); + IAnyAtomicItem item = ISequence.of(sequence.atomize()).getFirstItem(true); return item == null ? "" : item.asString(); }), /** diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java index 50c42cccb..d7e4d89a0 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticContext.java @@ -188,7 +188,6 @@ private String lookupNamespaceURIForPrefix(@NonNull String prefix) { * @return the namespace string bound to the prefix, or {@code null} if no * namespace is bound to the prefix */ - // FIXME: check for https://www.w3.org/TR/xpath-31/#ERRXPST0081 @Nullable public String lookupNamespaceForPrefix(@NonNull String prefix) { String result = lookupNamespaceURIForPrefix(prefix); @@ -633,7 +632,6 @@ public Builder baseUri(@NonNull URI uri) { * @see StaticContext#lookupNamespaceForPrefix(String) * @see StaticContext#getWellKnownNamespacesMap() */ - // FIXME: check for https://www.w3.org/TR/xpath-31/#ERRXPST0070 for "meta" @NonNull public Builder namespace(@NonNull String prefix, @NonNull URI uri) { return namespace(prefix, ObjectUtils.notNull(uri.toASCIIString())); @@ -648,12 +646,17 @@ public Builder namespace(@NonNull String prefix, @NonNull URI uri) { * the namespace URI * @return this builder * @throws IllegalArgumentException - * if the provided URI is invalid + * if the provided prefix or URI is invalid * @see StaticContext#lookupNamespaceForPrefix(String) * @see StaticContext#getWellKnownNamespacesMap() */ @NonNull public Builder namespace(@NonNull String prefix, @NonNull String uri) { + if (MetapathConstants.PREFIX_METAPATH.equals(prefix)) { + // check for https://www.w3.org/TR/xpath-31/#ERRXPST0070 for "meta" + throw new IllegalArgumentException( + "Redefining the prefix '" + MetapathConstants.PREFIX_METAPATH + "' is not allowed."); + } this.namespaces.put(prefix, uri); NamespaceCache.instance().indexOf(uri); return this; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticMetapathException.java index 9959a5e3a..da3842e2f 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticMetapathException.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticMetapathException.java @@ -31,9 +31,15 @@ public class StaticMetapathException * an AttributeName in an AttributeTest. */ - // FIXME: Check for use in all calls to the static or dyanmic context to lookup - // a name public static final int NOT_DEFINED = 8; + /** + * err:MPST0010: An + * implementation that does not support the namespace axis must raise a + * static error if + * it encounters a reference to the namespace axis and XPath 1.0 compatibility + * mode is false. + */ + public static final int AXIS_NAMESPACE_UNSUPPORTED = 10; /** * err:MPST0017: It @@ -104,6 +110,12 @@ public class StaticMetapathException */ public static final int PREFIX_NOT_EXPANDABLE = 81; + /** + * err:MPST0134: The + * namespace axis is not supported. + */ + public static final int AXIS_NAMESPACE_UNSUPPORTED_IN_TEST = 134; + /** * the serial version UID. */ diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java index d52935c6f..0ca25d703 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java @@ -30,7 +30,7 @@ public abstract class AbstractExpression implements IExpression { @Nullable public static IAnyAtomicItem getFirstDataItem(@NonNull ISequence sequence, boolean requireSingleton) { - return sequence.atomize().getFirstItem(requireSingleton); + return ISequence.of(sequence.atomize()).getFirstItem(requireSingleton); } @Override diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java index ae997dc24..b251c9b5b 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java @@ -1147,7 +1147,8 @@ protected IExpression handleSimplemapexpr(Metapath10.SimplemapexprContext contex @Override protected IExpression handleArrowexpr(Metapath10.ArrowexprContext context) { - // TODO: handle additional syntax for varef and parenthesized + // FIXME: handle additional syntax for varef and parenthesized + return handleGroupedNAiry(context, 0, 3, (ctx, idx, left) -> { // the next child is "=>" assert "=>".equals(ctx.getChild(idx).getText()); diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/FunctionCallAccessor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/FunctionCallAccessor.java index c1420dc17..5e0fbcd62 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/FunctionCallAccessor.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/FunctionCallAccessor.java @@ -74,8 +74,7 @@ public List getChildren() { public ISequence accept(DynamicContext dynamicContext, ISequence focus) { ISequence target = getBase().accept(dynamicContext, focus); IItem collection = target.getFirstItem(true); - IAnyAtomicItem key = getArgument().accept(dynamicContext, focus) - .atomize() + IAnyAtomicItem key = ISequence.of(getArgument().accept(dynamicContext, focus).atomize()) .getFirstItem(false); if (key == null) { throw new StaticMetapathException(StaticMetapathException.NO_FUNCTION_MATCH, diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/MapConstructor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/MapConstructor.java index 56a1c03df..44c12c60c 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/MapConstructor.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/MapConstructor.java @@ -53,8 +53,7 @@ public ISequence accept(DynamicContext dynamicContext, ISequenc ObjectUtils.notNull(getChildren().stream() .map(item -> { IExpression keyExpression = item.getKeyExpression(); - IAnyAtomicItem key = keyExpression.accept(dynamicContext, focus) - .atomize() + IAnyAtomicItem key = ISequence.of(keyExpression.accept(dynamicContext, focus).atomize()) .getFirstItem(true); if (key == null) { throw new InvalidTypeMetapathException(null, String.format( diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/StringConcat.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/StringConcat.java index 2ef84c679..ed5a8be7e 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/StringConcat.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/items/StringConcat.java @@ -51,6 +51,6 @@ public RESULT accept(IExpressionVisitor visit public ISequence accept(DynamicContext dynamicContext, ISequence focus) { return ISequence.of(FnConcat.concat(ObjectUtils.notNull(getChildren().stream() .map(child -> child.accept(dynamicContext, focus)) - .flatMap(result -> ObjectUtils.notNull(result).atomize().stream())))); + .flatMap(result -> ObjectUtils.notNull(result).atomize())))); } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/logic/GeneralComparison.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/logic/GeneralComparison.java index c79fc5fcb..e772f756a 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/logic/GeneralComparison.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/logic/GeneralComparison.java @@ -47,8 +47,8 @@ public RESULT accept(IExpressionVisitor visit @Override public ISequence accept(DynamicContext dynamicContext, ISequence focus) { - ISequence leftItems = getLeft().accept(dynamicContext, focus).atomize(); - ISequence rightItems = getRight().accept(dynamicContext, focus).atomize(); + ISequence leftItems = ISequence.of(getLeft().accept(dynamicContext, focus).atomize()); + ISequence rightItems = ISequence.of(getRight().accept(dynamicContext, focus).atomize()); return ISequence.of(ComparisonFunctions.generalCompairison(leftItems, getOperator(), rightItems)); } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Axis.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Axis.java index 9a7ffbc49..7437c4250 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Axis.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Axis.java @@ -7,6 +7,7 @@ import gov.nist.secauto.metaschema.core.metapath.DynamicContext; import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException; import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; import gov.nist.secauto.metaschema.core.metapath.cst.IExpressionVisitor; import gov.nist.secauto.metaschema.core.metapath.item.ItemUtils; @@ -20,7 +21,6 @@ import edu.umd.cs.findbugs.annotations.NonNull; -// FIXME: check for https://www.w3.org/TR/xpath-31/#ERRXQST0134 or err:XPST0010 @SuppressWarnings("PMD.ShortClassName") // intentional public enum Axis implements IExpression { SELF(Stream::of), @@ -34,7 +34,12 @@ public enum Axis implements IExpression { FOLLOWING_SIBLING(INodeItem::followingSibling), PRECEDING_SIBLING(INodeItem::precedingSibling), FOLLOWING(INodeItem::following), - PRECEDING(INodeItem::preceding); + PRECEDING(INodeItem::preceding), + NAMESPACE(focus -> { + throw new StaticMetapathException( + StaticMetapathException.AXIS_NAMESPACE_UNSUPPORTED, + "The 'namespace' axis is not supported"); + }); @NonNull private final Function> action; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DefaultFunction.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DefaultFunction.java index 31b6ec146..33cb600ba 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DefaultFunction.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/DefaultFunction.java @@ -10,7 +10,6 @@ import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.MetapathException; import gov.nist.secauto.metaschema.core.metapath.StaticContext; -import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.metapath.item.IItemVisitor; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; @@ -177,7 +176,7 @@ protected static ISequence convertSequence( Stream stream = sequence.safeStream(); if (IAnyAtomicItem.class.isAssignableFrom(requiredSequenceTypeClass)) { - Stream atomicStream = stream.flatMap(FnData::atomize); + Stream atomicStream = stream.flatMap(IItem::atomize); // if (IUntypedAtomicItem.class.isInstance(item)) { // NOPMD // // TODO: apply cast to atomic type diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionUtils.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionUtils.java index f5a4a5661..77819650f 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionUtils.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/FunctionUtils.java @@ -6,7 +6,6 @@ package gov.nist.secauto.metaschema.core.metapath.function; import gov.nist.secauto.metaschema.core.metapath.ISequence; -import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDecimalItem; @@ -126,7 +125,7 @@ public static INumericItem toNumeric(@NonNull ISequence sequence, boolean req @NonNull public static INumericItem toNumeric(@NonNull IItem item) { // atomize - IAnyAtomicItem atomicItem = ISequence.getFirstItem(FnData.atomize(item), true); + IAnyAtomicItem atomicItem = ISequence.getFirstItem(item.atomize(), true); if (atomicItem == null) { throw new InvalidTypeMetapathException(item, "Unable to cast null item"); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/IFunction.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/IFunction.java index 3b1608b36..311673276 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/IFunction.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/IFunction.java @@ -11,6 +11,7 @@ import gov.nist.secauto.metaschema.core.metapath.StaticContext; import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException; import gov.nist.secauto.metaschema.core.metapath.item.IItem; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import gov.nist.secauto.metaschema.core.metapath.type.IItemType; import gov.nist.secauto.metaschema.core.metapath.type.ISequenceType; import gov.nist.secauto.metaschema.core.metapath.type.Occurrence; @@ -193,6 +194,11 @@ ISequence execute( @NonNull DynamicContext dynamicContext, @NonNull ISequence focus); + @Override + default IAnyAtomicItem toAtomicItem() { + throw new InvalidTypeFunctionException(InvalidTypeFunctionException.DATA_ITEM_IS_FUNCTION, this); + } + /** * Get the signature of the function as a string. * @@ -235,7 +241,6 @@ static Builder builder(@NonNull StaticContext staticContext) { /** * Used to create a function's signature using a builder pattern. */ - // FIXME: Should return type be ISequenceType? @SuppressWarnings("PMD.LooseCoupling") final class Builder { @NonNull @@ -538,6 +543,7 @@ public IFunction build() { ObjectUtils.requireNonNull(namespace, "the namespace must not be null"), properties, new ArrayList<>(arguments), + // FIXME: Should return type be ISequenceType? ISequenceType.of(returnType, returnOccurrence), ObjectUtils.requireNonNull(functionHandler, "the function handler must not be null")); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnData.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnData.java index 643889949..94bd29e4f 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnData.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnData.java @@ -11,16 +11,12 @@ 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.function.InvalidTypeFunctionException; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; -import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAtomicValuedItem; -import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import java.util.List; -import java.util.stream.Stream; import edu.umd.cs.findbugs.annotations.NonNull; @@ -77,7 +73,7 @@ private static ISequence executeNoArg(@NonNull IFunction functio if (item == null) { retval = ISequence.empty(); } else { - IAnyAtomicItem data = fnDataItem(item); + IAnyAtomicItem data = item.toAtomicItem(); retval = ISequence.of(data); } return retval; @@ -91,83 +87,6 @@ private static ISequence executeOneArg( @NonNull DynamicContext dynamicContext, IItem focus) { - return FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(0))).atomize(); - } - - /** - * An implementation of - * item - * atomization. - * - * @param item - * the item to atomize - * @return the atomized result - * @throws InvalidTypeFunctionException - * if the item cannot be cast to an atomic value, most likely because - * it doesn't have a typed value - */ - @NonNull - public static IAnyAtomicItem fnDataItem(@NonNull IItem item) { - IAnyAtomicItem retval = null; - if (item instanceof IAtomicValuedItem) { - retval = ((IAtomicValuedItem) item).toAtomicItem(); - } - - if (retval != null) { - return retval; - } - throw new InvalidTypeFunctionException(InvalidTypeFunctionException.NODE_HAS_NO_TYPED_VALUE, item); - } - - /** - * An implementation of - * item - * atomization. - * - * @param item - * the item to atomize - * @return the atomized result - */ - // FIXME: implement atomize on the called methods - @NonNull - public static Stream fnDataItem(@NonNull IArrayItem item) { - return ObjectUtils.notNull(item.stream().flatMap(member -> { - Stream result; - if (member instanceof IItem) { - result = atomize((IItem) member); - } else if (member instanceof ISequence) { - result = ((ISequence) member).stream() - .flatMap(FnData::atomize); - } else { - throw new UnsupportedOperationException("array member not an item or sequence."); - } - return result; - })); - } - - /** - * An implementation of - * item - * atomization. - * - * @param item - * the item to atomize - * @return the atomized result - */ - @NonNull - public static Stream atomize(@NonNull IItem item) { - Stream retval; - if (item instanceof IAnyAtomicItem) { - retval = ObjectUtils.notNull(Stream.of((IAnyAtomicItem) item)); - } else if (item instanceof IAtomicValuedItem) { - retval = ObjectUtils.notNull(Stream.of(((IAtomicValuedItem) item).toAtomicItem())); - } else if (item instanceof IArrayItem) { - retval = fnDataItem((IArrayItem) item); - } else if (item instanceof IFunction) { - throw new InvalidTypeFunctionException(InvalidTypeFunctionException.DATA_ITEM_IS_FUNCTION, item); - } else { - throw new InvalidTypeFunctionException(InvalidTypeFunctionException.NODE_HAS_NO_TYPED_VALUE, item); - } - return retval; + return ISequence.of(FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(0))).atomize()); } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MapMerge.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MapMerge.java index 0b5677fea..859d67557 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MapMerge.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MapMerge.java @@ -188,7 +188,7 @@ public static IMapItem merge(@NonNull Collection lookupInArray( IArrayItem targetItem, DynamicContext dynamicContext, ISequence focus) { - ISequence keys = getKeyExpression().accept(dynamicContext, focus).atomize(); - - return ObjectUtils.notNull(keys.stream() + return ObjectUtils.notNull(getKeyExpression() + .accept(dynamicContext, focus) + .atomize() .flatMap(key -> { if (key instanceof IIntegerItem) { int index = ((IIntegerItem) key).asInteger().intValueExact(); @@ -265,11 +264,9 @@ protected Stream lookupInMap( IMapItem targetItem, DynamicContext dynamicContext, ISequence focus) { - ISequence keys = ObjectUtils.requireNonNull(getKeyExpression() + return ObjectUtils.notNull(getKeyExpression() .accept(dynamicContext, focus) - .atomize()); - - return ObjectUtils.notNull(keys.stream() + .atomize() .flatMap(key -> { assert key != null; return Stream.ofNullable(MapGet.get(targetItem, key)); diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/DefaultItemWriter.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/DefaultItemWriter.java index 3e2cf85e0..525dd6a88 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/DefaultItemWriter.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/DefaultItemWriter.java @@ -8,7 +8,6 @@ import gov.nist.secauto.metaschema.core.metapath.ICollectionValue; import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.function.IFunction; -import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAtomicValuedItem; import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem; @@ -110,7 +109,7 @@ public void writeNode(INodeItem node) { if (node instanceof IAtomicValuedItem) { writer.append('<'); - writer.append(FnData.fnDataItem(node).asString()); + writer.append(node.toAtomicItem().asString()); writer.append('>'); } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java index 77b206aa5..cda08b168 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/IItem.java @@ -8,7 +8,10 @@ import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter; import gov.nist.secauto.metaschema.core.metapath.ICollectionValue; import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.function.InvalidTypeFunctionException; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import gov.nist.secauto.metaschema.core.metapath.type.IItemType; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; import java.util.stream.Stream; @@ -59,6 +62,37 @@ default ISequence toSequence() { return ISequence.of(this); } + /** + * Get the atomic value for the item. This may be the same item if the item is + * an instance of {@link IAnyAtomicItem}. + *

+ * An implementation of + * item + * atomization. + * + * @return the atomic value or {@code null} if the item has no available value + * @throws InvalidTypeFunctionException + * with code + * {@link InvalidTypeFunctionException#NODE_HAS_NO_TYPED_VALUE} if the + * item does not have a typed value + */ + // FIXME: get rid of the possible null result and throw + // InvalidTypeFunctionException#NODE_HAS_NO_TYPED_VALUE + IAnyAtomicItem toAtomicItem(); + + /** + * {@inheritDoc} + * + * @throws InvalidTypeFunctionException + * with code + * {@link InvalidTypeFunctionException#NODE_HAS_NO_TYPED_VALUE} if the + * item does not have a typed value + */ + @Override + default Stream atomize() { + return ObjectUtils.notNull(Stream.of(this.toAtomicItem())); + } + @SuppressWarnings("null") @Override default Stream flatten() { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java index 59f64684d..4728d2d0a 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAnyAtomicItem.java @@ -13,6 +13,9 @@ import gov.nist.secauto.metaschema.core.metapath.item.function.IMapKey; import gov.nist.secauto.metaschema.core.metapath.type.IAtomicOrUnionType; import gov.nist.secauto.metaschema.core.metapath.type.IItemType; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import java.util.stream.Stream; import edu.umd.cs.findbugs.annotations.NonNull; @@ -60,6 +63,11 @@ default IAnyAtomicItem toAtomicItem() { @NonNull String asString(); + @Override + default Stream atomize() { + return ObjectUtils.notNull(Stream.of(this)); + } + /** * Get the atomic item value as a map key for use with an {@link IMapItem}. * diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAtomicValuedItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAtomicValuedItem.java index d520dee2f..848afbb8c 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAtomicValuedItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IAtomicValuedItem.java @@ -12,13 +12,5 @@ * associated {@link IAnyAtomicItem} value. */ public interface IAtomicValuedItem extends IItem { - /** - * Get the atomic value for the item. This may be the same item if the item is - * an instance of {@link IAnyAtomicItem}. - * - * @return the atomic value or {@code null} if the item has no available value - */ - // TODO: review all implementations and uses for correct behavior related to - // null - IAnyAtomicItem toAtomicItem(); + // no additional methods } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java index 055fa7eee..06bc63ccf 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/function/IArrayItem.java @@ -13,6 +13,7 @@ import gov.nist.secauto.metaschema.core.metapath.impl.ArrayItemN; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.metapath.item.IItemVisitor; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import gov.nist.secauto.metaschema.core.metapath.type.IItemType; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -78,6 +79,11 @@ default ISequence contentsAsSequence() { .flatMap(ICollectionValue::normalizeAsItems))); } + @Override + default Stream atomize() { + return ObjectUtils.notNull(stream().flatMap(ICollectionValue::atomize)); + } + /** * Determine if this sequence is empty. * diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IAssemblyNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IAssemblyNodeItem.java index aef85f665..7b844950f 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IAssemblyNodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IAssemblyNodeItem.java @@ -2,6 +2,8 @@ package gov.nist.secauto.metaschema.core.metapath.item.node; import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; +import gov.nist.secauto.metaschema.core.metapath.function.InvalidTypeFunctionException; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import gov.nist.secauto.metaschema.core.metapath.type.IItemType; import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition; import gov.nist.secauto.metaschema.core.model.IAssemblyInstance; @@ -42,6 +44,11 @@ default String format(@NonNull IPathFormatter formatter) { return formatter.formatAssembly(this); } + @Override + default IAnyAtomicItem toAtomicItem() { + throw new InvalidTypeFunctionException(InvalidTypeFunctionException.DATA_ITEM_IS_FUNCTION, this); + } + @Override default RESULT accept(@NonNull INodeItemVisitor visitor, CONTEXT context) { return visitor.visitAssembly(this, context); diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDocumentBasedNodeItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDocumentBasedNodeItem.java index 44f8524e7..e4cad07e6 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDocumentBasedNodeItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IDocumentBasedNodeItem.java @@ -1,6 +1,9 @@ package gov.nist.secauto.metaschema.core.metapath.item.node; +import gov.nist.secauto.metaschema.core.metapath.function.InvalidTypeFunctionException; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; + import java.net.URI; import edu.umd.cs.findbugs.annotations.Nullable; @@ -31,4 +34,9 @@ default INodeItem getParentNodeItem() { // there is no parent return null; } + + @Override + default IAnyAtomicItem toAtomicItem() { + throw new InvalidTypeFunctionException(InvalidTypeFunctionException.DATA_ITEM_IS_FUNCTION, this); + } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFeatureNoDataAtomicValuedItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFeatureNoDataAtomicValuedItem.java index db5cdefbc..f4aa60f68 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFeatureNoDataAtomicValuedItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFeatureNoDataAtomicValuedItem.java @@ -7,7 +7,6 @@ import edu.umd.cs.findbugs.annotations.Nullable; public interface IFeatureNoDataAtomicValuedItem extends IFeatureNoDataValuedItem, IAtomicValuedItem { - @Override @Nullable default IAnyAtomicItem toAtomicItem() { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFeatureNoDataValuedItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFeatureNoDataValuedItem.java index d34fcf9f0..a127be516 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFeatureNoDataValuedItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/node/IFeatureNoDataValuedItem.java @@ -14,7 +14,6 @@ * always have data. */ public interface IFeatureNoDataValuedItem extends IItem { - @Override @Nullable default Object getValue() { 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 0368afdb1..a5d9478d4 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 @@ -129,7 +129,7 @@ default boolean isSubType(@NonNull IAtomicOrUnionType other) { */ @Nullable default I cast(@NonNull ISequence sequence) { - IAnyAtomicItem item = sequence.atomize().getFirstItem(true); + IAnyAtomicItem item = ISequence.of(sequence.atomize()).getFirstItem(true); return item == null ? null : cast(item); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/AbstractModule.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/AbstractModule.java index 8977103c6..fc881447b 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/AbstractModule.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/AbstractModule.java @@ -54,6 +54,8 @@ public abstract class AbstractModule< private final List importedModules; @NonNull private final Lazy exports; + @NonNull + private final Lazy qname; /** * Construct a new Metaschema module object. @@ -66,6 +68,12 @@ public AbstractModule(@NonNull List importedModules) { this.importedModules = CollectionUtil.unmodifiableList(ObjectUtils.requireNonNull(importedModules, "importedModules")); this.exports = ObjectUtils.notNull(Lazy.lazy(() -> new Exports(importedModules))); + this.qname = ObjectUtils.notNull(Lazy.lazy(() -> IEnhancedQName.of(getXmlNamespace(), getShortName()))); + } + + @Override + public IEnhancedQName getQName() { + return ObjectUtils.notNull(qname.get()); } @Override diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IModule.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IModule.java index ab5e41cea..5287229d1 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/IModule.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/IModule.java @@ -101,10 +101,8 @@ public interface IModule { * * @return the qualified name */ - // FIXME: cache this value - default IEnhancedQName getQName() { - return IEnhancedQName.of(getXmlNamespace(), getShortName()); - } + @NonNull + IEnhancedQName getQName(); /** * Retrieves all Metaschema modules imported by this Metaschema module. diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintValidationHandler.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintValidationHandler.java index 3e718ee63..f40e06a80 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintValidationHandler.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/AbstractConstraintValidationHandler.java @@ -9,7 +9,6 @@ import gov.nist.secauto.metaschema.core.metapath.DynamicContext; import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; -import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.CustomCollectors; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -312,7 +311,7 @@ protected String newAllowedValuesViolationMessage( .collect(CustomCollectors.joiningWithOxfordComma("or")); return ObjectUtils.notNull(String.format("Value '%s' doesn't match one of '%s' at path '%s'", - FnData.fnDataItem(target).asString(), + target.toAtomicItem().asString(), allowedValues, toPath(target))); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidator.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidator.java index bf131b274..84646fbd3 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidator.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidator.java @@ -14,7 +14,6 @@ import gov.nist.secauto.metaschema.core.metapath.MetapathException; import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; import gov.nist.secauto.metaschema.core.metapath.function.library.FnBoolean; -import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; import gov.nist.secauto.metaschema.core.metapath.item.node.AbstractNodeItemVisitor; import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem; @@ -542,7 +541,7 @@ private void validateMatchesItem( @NonNull INodeItem node, @NonNull INodeItem item, @NonNull DynamicContext dynamicContext) { - String value = FnData.fnDataItem(item).asString(); + String value = item.toAtomicItem().asString(); IConstraintValidationHandler handler = getConstraintValidationHandler(); boolean valid = true; @@ -882,7 +881,7 @@ private class ValueStatus { public ValueStatus(@NonNull INodeItem item) { this.item = item; - this.value = FnData.fnDataItem(item).asString(); + this.value = item.toAtomicItem().asString(); } public void registerAllowedValue( diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IIndex.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IIndex.java index 4b51f58cf..41907d012 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IIndex.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/constraint/IIndex.java @@ -9,7 +9,6 @@ import gov.nist.secauto.metaschema.core.metapath.MetapathException; import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; import gov.nist.secauto.metaschema.core.metapath.MetapathExpression.ResultType; -import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.metapath.type.InvalidTypeMetapathException; @@ -173,7 +172,7 @@ private static String buildKeyItem( String keyValue = null; if (keyItem != null) { - keyValue = FnData.fnDataItem(keyItem).asString(); + keyValue = keyItem.toAtomicItem().asString(); assert keyValue != null; Pattern pattern = keyField.getPattern(); if (pattern != null) { diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/path/StepTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/path/StepTest.java index 1cce2b886..2cee195bd 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/path/StepTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/path/StepTest.java @@ -9,7 +9,6 @@ import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase; import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; -import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IFlagNodeItem; @@ -316,7 +315,7 @@ void testFlagAxis() { Assertions.assertThat(actual.getValue()) .hasOnlyElementsOfType(IFlagNodeItem.class) - .map(flag -> FnData.fnDataItem(ObjectUtils.requireNonNull(flag)).asString()) + .map(flag -> ObjectUtils.requireNonNull(flag).toAtomicItem().asString()) .containsExactly("flag-2-b-v1", "flag-2-b-v2", "flag-2-b-v3"); }