diff --git a/core/metaschema b/core/metaschema index 88e050a9e..e807cba78 160000 --- a/core/metaschema +++ b/core/metaschema @@ -1 +1 @@ -Subproject commit 88e050a9e2b1ed7c158f35f4f5468e01e0e76d88 +Subproject commit e807cba7847a7143a1e9fa94b45049f6e7cc5282 diff --git a/core/src/main/antlr4/Metapath10.g4 b/core/src/main/antlr4/Metapath10.g4 new file mode 100644 index 000000000..5decc5cc4 --- /dev/null +++ b/core/src/main/antlr4/Metapath10.g4 @@ -0,0 +1,220 @@ +// This grammar is derived from the XPath 3.1 grammar produced by Ken Domino, et al (https://github.com/antlr/grammars-v4/blob/63359bd91593ece31a384acd507ae860d6cf7ff7/xpath/xpath31/XPath31Parser.g4). + +parser grammar Metapath10; + +options { tokenVocab=Metapath10Lexer; superClass=Metapath10ParserBase; } + +// Metapath extensions +metapath : expr EOF ; + +// [1] +// xpath : expr EOF ; +// paramlist : param ( COMMA param)* ; +// param : DOLLAR eqname typedeclaration? ; +// functionbody : enclosedexpr ; +// [5] +// enclosedexpr : OC expr? CC ; +expr : exprsingle ( COMMA exprsingle)* ; +exprsingle : forexpr | letexpr | quantifiedexpr | ifexpr | orexpr ; +forexpr : simpleforclause KW_RETURN exprsingle ; +simpleforclause : KW_FOR simpleforbinding ( COMMA simpleforbinding)* ; +// [10] +simpleforbinding : DOLLAR varname KW_IN exprsingle ; +letexpr : simpleletclause KW_RETURN exprsingle ; +simpleletclause : KW_LET simpleletbinding ( COMMA simpleletbinding)* ; +simpleletbinding : DOLLAR varname CEQ exprsingle ; +quantifiedexpr : ( KW_SOME | KW_EVERY) DOLLAR varname KW_IN exprsingle ( COMMA DOLLAR varname KW_IN exprsingle)* KW_SATISFIES exprsingle ; +// [15] +ifexpr : KW_IF OP expr CP KW_THEN exprsingle KW_ELSE exprsingle ; +orexpr : andexpr ( KW_OR andexpr )* ; +andexpr : comparisonexpr ( KW_AND comparisonexpr )* ; +// comparisonexpr : stringconcatexpr ( (valuecomp | generalcomp | nodecomp) stringconcatexpr )? ; +comparisonexpr : stringconcatexpr ( (valuecomp | generalcomp) stringconcatexpr )? ; +stringconcatexpr : rangeexpr ( PP rangeexpr )* ; +// [20] +rangeexpr : additiveexpr ( KW_TO additiveexpr )? ; +additiveexpr : multiplicativeexpr ( (PLUS | MINUS) multiplicativeexpr )* ; +multiplicativeexpr : unionexpr ( (STAR | KW_DIV | KW_IDIV | KW_MOD) unionexpr )* ; +unionexpr : intersectexceptexpr ( (KW_UNION | P) intersectexceptexpr )* ; +// intersectexceptexpr : instanceofexpr ( ( KW_INTERSECT | KW_EXCEPT) instanceofexpr )* ; +intersectexceptexpr : arrowexpr ( ( KW_INTERSECT | KW_EXCEPT) arrowexpr )* ; +// [25] +// instanceofexpr : treatexpr ( KW_INSTANCE KW_OF sequencetype )? ; +// treatexpr : castableexpr ( KW_TREAT KW_AS sequencetype )? ; +// castableexpr : castexpr ( KW_CASTABLE KW_AS singletype )? ; +// castexpr : arrowexpr ( KW_CAST KW_AS singletype )? ; +arrowexpr : unaryexpr ( EG arrowfunctionspecifier argumentlist )* ; +// [30] +unaryexpr : ( MINUS | PLUS)* valueexpr ; +valueexpr : simplemapexpr ; +generalcomp : EQ | NE | LT | LE | GT | GE ; +valuecomp : KW_EQ | KW_NE | KW_LT | KW_LE | KW_GT | KW_GE ; +// nodecomp : KW_IS | LL | GG ; +// [35] +simplemapexpr : pathexpr ( BANG pathexpr)* ; +pathexpr : SLASH relativepathexpr? | SS relativepathexpr | relativepathexpr ; +relativepathexpr : stepexpr (( SLASH | SS) stepexpr)* ; +stepexpr : postfixexpr | axisstep ; +axisstep : (reversestep | forwardstep) predicatelist ; +// [40] +// forwardstep : forwardaxis nodetest | abbrevforwardstep ; +forwardstep : forwardaxis nametest | abbrevforwardstep ; +// forwardaxis : KW_CHILD COLONCOLON | KW_DESCENDANT COLONCOLON | KW_ATTRIBUTE COLONCOLON | KW_SELF COLONCOLON | KW_DESCENDANT_OR_SELF COLONCOLON | KW_FOLLOWING_SIBLING COLONCOLON | KW_FOLLOWING COLONCOLON | KW_NAMESPACE COLONCOLON ; +forwardaxis : KW_CHILD COLONCOLON | KW_DESCENDANT COLONCOLON | KW_SELF COLONCOLON | KW_DESCENDANT_OR_SELF COLONCOLON ; +// abbrevforwardstep : AT? nodetest ; +abbrevforwardstep : AT? nametest ; +// reversestep : reverseaxis nodetest | abbrevreversestep ; +reversestep : reverseaxis nametest | abbrevreversestep ; +// reverseaxis : KW_PARENT COLONCOLON | KW_ANCESTOR COLONCOLON | KW_PRECEDING_SIBLING COLONCOLON | KW_PRECEDING COLONCOLON | KW_ANCESTOR_OR_SELF COLONCOLON ; +reverseaxis : KW_PARENT COLONCOLON | KW_ANCESTOR COLONCOLON | KW_ANCESTOR_OR_SELF COLONCOLON ; +// [45] +abbrevreversestep : DD ; +// nodetest : kindtest | nametest ; +nodetest : nametest ; +nametest : eqname | wildcard ; +wildcard : STAR | NCName CS | SC NCName | BracedURILiteral STAR ; +// postfixexpr : primaryexpr (predicate | argumentlist | lookup)* ; +postfixexpr : primaryexpr (predicate)* ; +// [50] +argumentlist : OP (argument ( COMMA argument)*)? CP ; +predicatelist : predicate* ; +predicate : OB expr CB ; +// lookup : QM keyspecifier ; +// keyspecifier : NCName | IntegerLiteral | parenthesizedexpr | STAR ; +// [55] +arrowfunctionspecifier : eqname | varref | parenthesizedexpr ; +// primaryexpr : literal | varref | parenthesizedexpr | contextitemexpr | functioncall | functionitemexpr | mapconstructor | arrayconstructor | unarylookup ; +primaryexpr : literal | varref | parenthesizedexpr | contextitemexpr | functioncall ; +literal : numericliteral | StringLiteral ; +numericliteral : IntegerLiteral | DecimalLiteral | DoubleLiteral ; +varref : DOLLAR varname ; +// [60] +varname : eqname ; +parenthesizedexpr : OP expr? CP ; +contextitemexpr : D ; +functioncall : { this.isFuncCall() }? eqname argumentlist ; +// argument : exprsingle | argumentplaceholder ; +argument : exprsingle ; +// [65] +// argumentplaceholder : QM ; +// functionitemexpr : namedfunctionref | inlinefunctionexpr ; +// namedfunctionref : eqname POUND IntegerLiteral /* xgc: reserved-function-names */; +// inlinefunctionexpr : KW_FUNCTION OP paramlist? CP ( KW_AS sequencetype)? functionbody ; +// mapconstructor : KW_MAP OC (mapconstructorentry ( COMMA mapconstructorentry)*)? CC ; +// [70] +// mapconstructorentry : mapkeyexpr COLON mapvalueexpr ; +// mapkeyexpr : exprsingle ; +// mapvalueexpr : exprsingle ; +// arrayconstructor : squarearrayconstructor | curlyarrayconstructor ; +// squarearrayconstructor : OB (exprsingle ( COMMA exprsingle)*)? CB ; +// [75] +// curlyarrayconstructor : KW_ARRAY enclosedexpr ; +// unarylookup : QM keyspecifier ; +// singletype : simpletypename QM? ; +// typedeclaration : KW_AS sequencetype ; +// sequencetype : KW_EMPTY_SEQUENCE OP CP | itemtype occurrenceindicator? ; +// [80] +// occurrenceindicator : QM | STAR | PLUS ; +// itemtype : kindtest | KW_ITEM OP CP | functiontest | maptest | arraytest | atomicoruniontype | parenthesizeditemtype ; +// atomicoruniontype : eqname ; +// kindtest : documenttest | elementtest | attributetest | schemaelementtest | schemaattributetest | pitest | commenttest | texttest | namespacenodetest | anykindtest ; +// anykindtest : KW_NODE OP CP ; +// [85] +// documenttest : KW_DOCUMENT_NODE OP (elementtest | schemaelementtest)? CP ; +// texttest : KW_TEXT OP CP ; +// commenttest : KW_COMMENT OP CP ; +// namespacenodetest : KW_NAMESPACE_NODE OP CP ; +// pitest : KW_PROCESSING_INSTRUCTION OP (NCName | StringLiteral)? CP ; +// [90] +// attributetest : KW_ATTRIBUTE OP (attribnameorwildcard ( COMMA typename_)?)? CP ; +// attribnameorwildcard : attributename | STAR ; +// schemaattributetest : KW_SCHEMA_ATTRIBUTE OP attributedeclaration CP ; +// attributedeclaration : attributename ; +// elementtest : KW_ELEMENT OP (elementnameorwildcard ( COMMA typename_ QM?)?)? CP ; +// [95] +// elementnameorwildcard : elementname | STAR ; +// schemaelementtest : KW_SCHEMA_ELEMENT OP elementdeclaration CP ; +// elementdeclaration : elementname ; +// attributename : eqname ; +// elementname : eqname ; +// [100] +// simpletypename : typename_ ; +// typename_ : eqname ; +// functiontest : anyfunctiontest | typedfunctiontest ; +// anyfunctiontest : KW_FUNCTION OP STAR CP ; +// typedfunctiontest : KW_FUNCTION OP (sequencetype ( COMMA sequencetype)*)? CP KW_AS sequencetype ; +// [105] +// maptest : anymaptest | typedmaptest ; +// anymaptest : KW_MAP OP STAR CP ; +// typedmaptest : KW_MAP OP atomicoruniontype COMMA sequencetype CP ; +// arraytest : anyarraytest | typedarraytest ; +// anyarraytest : KW_ARRAY OP STAR CP ; +// [110] +// typedarraytest : KW_ARRAY OP sequencetype CP ; +// parenthesizeditemtype : OP itemtype CP ; + + +// Error in the spec. EQName also includes acceptable keywords. +eqname : QName | URIQualifiedName + | KW_ANCESTOR + | KW_ANCESTOR_OR_SELF + | KW_AND +// | KW_ARRAY +// | KW_AS +// | KW_ATTRIBUTE +// | KW_CAST +// | KW_CASTABLE + | KW_CHILD +// | KW_COMMENT + | KW_DESCENDANT + | KW_DESCENDANT_OR_SELF + | KW_DIV +// | KW_DOCUMENT_NODE +// | KW_ELEMENT + | KW_ELSE + | KW_EMPTY_SEQUENCE + | KW_EQ + | KW_EVERY + | KW_EXCEPT +// | KW_FOLLOWING +// | KW_FOLLOWING_SIBLING + | KW_FOR +// | KW_FUNCTION + | KW_GE + | KW_GT + | KW_IDIV + | KW_IF + | KW_IN +// | KW_INSTANCE + | KW_INTERSECT +// | KW_IS +// | KW_ITEM + | KW_LE + | KW_LET + | KW_LT +// | KW_MAP + | KW_MOD +// | KW_NAMESPACE +// | KW_NAMESPACE_NODE + | KW_NE +// | KW_NODE +// | KW_OF + | KW_OR + | KW_PARENT + | KW_PRECEDING + | KW_PRECEDING_SIBLING +// | KW_PROCESSING_INSTRUCTION + | KW_RETURN + | KW_SATISFIES +// | KW_SCHEMA_ATTRIBUTE +// | KW_SCHEMA_ELEMENT + | KW_SELF + | KW_SOME +// | KW_TEXT + | KW_THEN +// | KW_TREAT + | KW_UNION + ; + +// Not per spec. Specified for testing. +//auxilary : (expr SEMI )+ EOF; diff --git a/core/src/main/antlr4/Metapath10Lexer.g4 b/core/src/main/antlr4/Metapath10Lexer.g4 new file mode 100644 index 000000000..f95456ef4 --- /dev/null +++ b/core/src/main/antlr4/Metapath10Lexer.g4 @@ -0,0 +1,166 @@ +// This grammar is derived from the XPath 3.1 grammar produced by Ken Domino, et al (https://github.com/antlr/grammars-v4/blob/63359bd91593ece31a384acd507ae860d6cf7ff7/xpath/xpath31/XPath31Lexer.g4). + +lexer grammar Metapath10Lexer; + +AT : '@' ; +BANG : '!' ; +CB : ']' ; +CC : '}' ; +CEQ : ':=' ; +COLON : ':' ; +COLONCOLON : '::' ; +COMMA : ',' ; +CP : ')' ; +CS : ':*' ; +D : '.' ; +DD : '..' ; +DOLLAR : '$' ; +EG : '=>' ; +EQ : '=' ; +GE : '>=' ; +GG : '>>' ; +GT : '>' ; +LE : '<=' ; +LL : '<<' ; +LT : '<' ; +MINUS : '-' ; +NE : '!=' ; +OB : '[' ; +OC : '{' ; +OP : '(' ; +P : '|' ; +PLUS : '+' ; +POUND : '#' ; +PP : '||' ; +QM : '?' ; +SC : '*:' ; +SLASH : '/' ; +SS : '//' ; +STAR : '*' ; + +// KEYWORDS + +KW_ANCESTOR : 'ancestor' ; +KW_ANCESTOR_OR_SELF : 'ancestor-or-self' ; +KW_AND : 'and' ; +KW_ARRAY : 'array' ; +KW_AS : 'as' ; +KW_ATTRIBUTE : 'attribute' ; +KW_CAST : 'cast' ; +KW_CASTABLE : 'castable' ; +KW_CHILD : 'child' ; +KW_COMMENT : 'comment' ; +KW_DESCENDANT : 'descendant' ; +KW_DESCENDANT_OR_SELF : 'descendant-or-self' ; +KW_DIV : 'div' ; +KW_DOCUMENT_NODE : 'document-node' ; +KW_ELEMENT : 'element' ; +KW_ELSE : 'else' ; +KW_EMPTY_SEQUENCE : 'empty-sequence' ; +KW_EQ : 'eq' ; +KW_EVERY : 'every' ; +KW_EXCEPT : 'except' ; +KW_FOLLOWING : 'following' ; +KW_FOLLOWING_SIBLING : 'following-sibling' ; +KW_FOR : 'for' ; +KW_FUNCTION : 'function' ; +KW_GE : 'ge' ; +KW_GT : 'gt' ; +KW_IDIV : 'idiv' ; +KW_IF : 'if' ; +KW_IN : 'in' ; +KW_INSTANCE : 'instance' ; +KW_INTERSECT : 'intersect' ; +KW_IS : 'is' ; +KW_ITEM : 'item' ; +KW_LE : 'le' ; +KW_LET : 'let' ; +KW_LT : 'lt' ; +KW_MAP : 'map' ; +KW_MOD : 'mod' ; +KW_NAMESPACE : 'namespace' ; +KW_NAMESPACE_NODE : 'namespace-node' ; +KW_NE : 'ne' ; +KW_NODE : 'node' ; +KW_OF : 'of' ; +KW_OR : 'or' ; +KW_PARENT : 'parent' ; +KW_PRECEDING : 'preceding' ; +KW_PRECEDING_SIBLING : 'preceding-sibling' ; +KW_PROCESSING_INSTRUCTION : 'processing-instruction' ; +KW_RETURN : 'return' ; +KW_SATISFIES : 'satisfies' ; +KW_SCHEMA_ATTRIBUTE : 'schema-attribute' ; +KW_SCHEMA_ELEMENT : 'schema-element' ; +KW_SELF : 'self' ; +KW_SOME : 'some' ; +KW_TEXT : 'text' ; +KW_THEN : 'then' ; +KW_TO : 'to' ; +KW_TREAT : 'treat' ; +KW_UNION : 'union' ; + +// A.2.1. TERMINAL SYMBOLS +// This isn't a complete list of tokens in the language. +// Keywords and symbols are terminals. + +IntegerLiteral : FragDigits ; +DecimalLiteral : '.' FragDigits | FragDigits '.' [0-9]* ; +DoubleLiteral : ('.' FragDigits | FragDigits ('.' [0-9]*)?) [eE] [+-]? FragDigits ; +StringLiteral : '"' (~["] | FragEscapeQuot)* '"' | '\'' (~['] | FragEscapeApos)* '\'' ; +URIQualifiedName : BracedURILiteral NCName ; +BracedURILiteral : 'Q' '{' [^{}]* '}' ; +// Error in spec: EscapeQuot and EscapeApos are not terminals! +fragment FragEscapeQuot : '""' ; +fragment FragEscapeApos : '\'\''; +// Error in spec: Comment isn't really a terminal, but an off-channel object. +Comment : '(:' (Comment | CommentContents)*? ':)' -> skip ; +QName : FragQName ; +NCName : FragmentNCName ; +// Error in spec: Char is not a terminal! +fragment Char : FragChar ; +fragment FragDigits : [0-9]+ ; +fragment CommentContents : Char ; +// https://www.w3.org/TR/REC-xml-names/#NT-QName +fragment FragQName : FragPrefixedName | FragUnprefixedName ; +fragment FragPrefixedName : FragPrefix ':' FragLocalPart ; +fragment FragUnprefixedName : FragLocalPart ; +fragment FragPrefix : FragmentNCName ; +fragment FragLocalPart : FragmentNCName ; +fragment FragNCNameStartChar + : 'A'..'Z' + | '_' + | 'a'..'z' + | '\u00C0'..'\u00D6' + | '\u00D8'..'\u00F6' + | '\u00F8'..'\u02FF' + | '\u0370'..'\u037D' + | '\u037F'..'\u1FFF' + | '\u200C'..'\u200D' + | '\u2070'..'\u218F' + | '\u2C00'..'\u2FEF' + | '\u3001'..'\uD7FF' + | '\uF900'..'\uFDCF' + | '\uFDF0'..'\uFFFD' + | '\u{10000}'..'\u{EFFFF}' + ; +fragment FragNCNameChar + : FragNCNameStartChar | '-' | '.' | '0'..'9' + | '\u00B7' | '\u0300'..'\u036F' + | '\u203F'..'\u2040' + ; +fragment FragmentNCName : FragNCNameStartChar FragNCNameChar* ; + +// https://www.w3.org/TR/REC-xml/#NT-Char + +fragment FragChar : '\u0009' | '\u000a' | '\u000d' + | '\u0020'..'\ud7ff' + | '\ue000'..'\ufffd' + | '\u{10000}'..'\u{10ffff}' + ; + +// https://github.com/antlr/grammars-v4/blob/17d3db3fd6a8fc319a12176e0bb735b066ec0616/xpath/xpath31/XPath31.g4#L389 +Whitespace : ('\u000d' | '\u000a' | '\u0020' | '\u0009')+ -> skip ; + +// Not per spec. Specified for testing. +SEMI : ';' ; diff --git a/core/src/main/antlr4/metapath10.g4 b/core/src/main/antlr4/metapath10.g4 deleted file mode 100644 index 0321ad699..000000000 --- a/core/src/main/antlr4/metapath10.g4 +++ /dev/null @@ -1,246 +0,0 @@ -// This grammar is derived from the XPath 3.1 grammar produced by Ken Domino (https://github.com/antlr/grammars-v4/blob/2b897252c8c3c4bce4ab4886bada62c00a049d90/xpath/xpath31/XPath31.g4). - -grammar metapath10; - -// [1] -metapath : expr EOF ; -// [5] -expr : exprsingle ( COMMA exprsingle)* ; -exprsingle : letexpr | orexpr ; -// [10] -letexpr : simpleletclause KW_RETURN exprsingle ; -simpleletclause : KW_LET simpleletbinding ( COMMA simpleletbinding)* ; -simpleletbinding : DOLLAR varname CEQ exprsingle ; -// [15] -orexpr : andexpr ( KW_OR andexpr )* ; -andexpr : comparisonexpr ( KW_AND comparisonexpr )* ; -comparisonexpr : stringconcatexpr ( (valuecomp | generalcomp) stringconcatexpr )? ; -stringconcatexpr : additiveexpr ( PP additiveexpr )* ; -// [20] -additiveexpr : multiplicativeexpr ( (PLUS | MINUS) multiplicativeexpr )* ; -multiplicativeexpr : unionexpr ( (STAR | KW_DIV | KW_IDIV | KW_MOD) unionexpr )* ; -unionexpr : intersectexceptexpr ( (KW_UNION | P) intersectexceptexpr )* ; -intersectexceptexpr : arrowexpr ( ( KW_INTERSECT | KW_EXCEPT) arrowexpr )* ; -// [25] -arrowexpr : unaryexpr ( EG arrowfunctionspecifier argumentlist )* ; -// [30] -unaryexpr : ( MINUS | PLUS)* valueexpr ; -//valueexpr : simplemapexpr ; -valueexpr : pathexpr ; -generalcomp : EQ | NE | LT | LE | GT | GE ; -valuecomp : KW_EQ | KW_NE | KW_LT | KW_LE | KW_GT | KW_GE ; -// [35] -//simplemapexpr : pathexpr ( BANG pathexpr)* ; -pathexpr : ( SLASH relativepathexpr?) | ( SS relativepathexpr) | relativepathexpr ; -relativepathexpr : stepexpr (( SLASH | SS) stepexpr)* ; -stepexpr : postfixexpr | axisstep ; -axisstep : (reversestep | forwardstep) predicatelist ; -// [40] -forwardstep : (forwardaxis nametest) | abbrevforwardstep ; -forwardaxis : ( KW_CHILD COLONCOLON) | ( KW_DESCENDANT COLONCOLON) | ( KW_SELF COLONCOLON) | ( KW_DESCENDANT_OR_SELF COLONCOLON) ; -abbrevforwardstep : AT? nametest ; -reversestep : (reverseaxis nametest) | abbrevreversestep ; -reverseaxis : ( KW_PARENT COLONCOLON) | ( KW_ANCESTOR COLONCOLON) | ( KW_ANCESTOR_OR_SELF COLONCOLON) ; -// [45] -abbrevreversestep : DD ; -nametest : eqname | wildcard ; -wildcard : STAR ; -postfixexpr : primaryexpr (predicate)* ; -// [50] -argumentlist : OP (argument ( COMMA argument)*)? CP ; -predicatelist : predicate* ; -predicate : OB expr CB ; -// [55] -arrowfunctionspecifier : eqname | varref | parenthesizedexpr ; -primaryexpr : literal | varref | parenthesizedexpr | contextitemexpr | functioncall ; -literal : numericliteral | StringLiteral ; -numericliteral : IntegerLiteral | DecimalLiteral | DoubleLiteral ; -varref : DOLLAR varname ; -// [60] -varname : eqname ; -parenthesizedexpr : OP expr? CP ; -contextitemexpr : D ; -functioncall : - { !( - getInputStream().LA(1)==KW_EMPTY_SEQUENCE - ) }? - eqname - argumentlist ; -argument : exprsingle ; -// [65] -// [70] -// [75] -// [80] -// [85] -// [90] -// [95] -// [100] -// [105] -// [110] - -// Error in the spec. EQName also includes acceptable keywords. -eqname : LocalName - | KW_ANCESTOR - | KW_ANCESTOR_OR_SELF - | KW_AND - | KW_CHILD - | KW_DESCENDANT - | KW_DESCENDANT_OR_SELF - | KW_DIV - | KW_EMPTY_SEQUENCE - | KW_EQ - | KW_EXCEPT - | KW_GE - | KW_GT - | KW_IDIV - | KW_INTERSECT - | KW_LE - | KW_LET - | KW_LT - | KW_MOD - | KW_NE - | KW_OR - | KW_PARENT - | KW_PRECEDING - | KW_PRECEDING_SIBLING - | KW_RETURN - | KW_SELF - | KW_UNION - ; - -// Not per spec. Specified for testing. -//auxilary : (expr SEMI )+ EOF; - - -AT : '@' ; -BANG : '!' ; -CB : ']' ; -CC : '}' ; -CEQ : ':=' ; -COLON : ':' ; -COLONCOLON : '::' ; -COMMA : ',' ; -CP : ')' ; -CS : ':*' ; -D : '.' ; -DD : '..' ; -DOLLAR : '$' ; -EG : '=>' ; -EQ : '=' ; -GE : '>=' ; -GG : '>>' ; -GT : '>' ; -LE : '<=' ; -LL : '<<' ; -LT : '<' ; -MINUS : '-' ; -NE : '!=' ; -OB : '[' ; -OC : '{' ; -OP : '(' ; -P : '|' ; -PLUS : '+' ; -POUND : '#' ; -PP : '||' ; -QM : '?' ; -SC : '*:' ; -SLASH : '/' ; -SS : '//' ; -STAR : '*' ; - -// KEYWORDS - -KW_ANCESTOR : 'ancestor' ; -KW_ANCESTOR_OR_SELF : 'ancestor-or-self' ; -KW_AND : 'and' ; -KW_CHILD : 'child' ; -KW_DESCENDANT : 'descendant' ; -KW_DESCENDANT_OR_SELF : 'descendant-or-self' ; -KW_DIV : 'div' ; -KW_EMPTY_SEQUENCE : 'empty-sequence' ; -KW_EQ : 'eq' ; -KW_EXCEPT : 'except' ; -KW_FOLLOWING : 'following' ; -KW_FOLLOWING_SIBLING : 'following-sibling' ; -KW_GE : 'ge' ; -KW_GT : 'gt' ; -KW_IDIV : 'idiv' ; -KW_INTERSECT : 'intersect' ; -KW_LE : 'le' ; -KW_LET : 'let' ; -KW_LT : 'lt' ; -KW_MOD : 'mod' ; -KW_NE : 'ne' ; -KW_OR : 'or' ; -KW_PARENT : 'parent' ; -KW_PRECEDING : 'preceding' ; -KW_PRECEDING_SIBLING : 'preceding-sibling' ; -KW_RETURN : 'return' ; -KW_SELF : 'self' ; -KW_UNION : 'union' ; - -// A.2.1. TEMINAL SYMBOLS -// This isn't a complete list of tokens in the language. -// Keywords and symbols are terminals. - -IntegerLiteral : FragDigits ; -DecimalLiteral : ('.' FragDigits) | (FragDigits '.' [0-9]*) ; -DoubleLiteral : (('.' FragDigits) | (FragDigits ('.' [0-9]*)?)) [eE] [+-]? FragDigits ; -StringLiteral : ('"' (FragEscapeQuot | ~[^"])*? '"') | ('\'' (FragEscapeApos | ~['])*? '\'') ; -//URIQualifiedName : BracedURILiteral NCName ; -//BracedURILiteral : 'Q' '{' [^{}]* '}' ; -// Error in spec: EscapeQuot and EscapeApos are not terminals! -fragment FragEscapeQuot : '""' ; -fragment FragEscapeApos : '\''; -// Error in spec: Comment isn't really a terminal, but an off-channel object. -Comment : '(:' (Comment | CommentContents)*? ':)' -> skip ; -LocalName : FragLocalPart ; -NCName : FragmentNCName ; -// Error in spec: Char is not a terminal! -fragment Char : FragChar ; -fragment FragDigits : [0-9]+ ; -fragment CommentContents : Char ; -// https://www.w3.org/TR/REC-xml-names/#NT-QName -//fragment FragQName : FragPrefixedName | FragUnprefixedName ; -//fragment FragQName : FragUnprefixedName ; -//fragment FragPrefixedName : FragPrefix ':' FragLocalPart ; -//fragment FragUnprefixedName : FragLocalPart ; -//fragment FragPrefix : FragmentNCName ; -fragment FragLocalPart : FragmentNCName ; -fragment FragNCNameStartChar - : 'A'..'Z' - | '_' - | 'a'..'z' - | '\u00C0'..'\u00D6' - | '\u00D8'..'\u00F6' - | '\u00F8'..'\u02FF' - | '\u0370'..'\u037D' - | '\u037F'..'\u1FFF' - | '\u200C'..'\u200D' - | '\u2070'..'\u218F' - | '\u2C00'..'\u2FEF' - | '\u3001'..'\uD7FF' - | '\uF900'..'\uFDCF' - | '\uFDF0'..'\uFFFD' -// | '\u{10000}'..'\u{EFFFF}' - ; -fragment FragNCNameChar - : FragNCNameStartChar | '-' | '.' | '0'..'9' - | '\u00B7' | '\u0300'..'\u036F' - | '\u203F'..'\u2040' - ; -fragment FragmentNCName : FragNCNameStartChar FragNCNameChar* ; - -// https://www.w3.org/TR/REC-xml/#NT-Char - -fragment FragChar : '\u0009' | '\u000a' | '\u000d' - | '\u0020'..'\ud7ff' - | '\ue000'..'\ufffd' -// | '\u{10000}'..'\u{10ffff}' - ; - -// https://github.com/antlr/grammars-v4/blob/17d3db3fd6a8fc319a12176e0bb735b066ec0616/xpath/xpath31/XPath31.g4#L389 -Whitespace : ('\u000d' | '\u000a' | '\u0020' | '\u0009')+ -> skip ; - -// Not per spec. Specified for testing. -//SEMI : ';' ; \ No newline at end of file diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/AbstractConfigurationFeature.java b/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/AbstractConfigurationFeature.java index b6eda4bc6..e8889134c 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/AbstractConfigurationFeature.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/configuration/AbstractConfigurationFeature.java @@ -34,7 +34,7 @@ * sets for a given purpose. * * @param - * the feature value type + * the feature value Java type */ public abstract class AbstractConfigurationFeature implements IConfigurationFeature { @NonNull diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/AstCollectingVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/AstCollectingVisitor.java index 41dd68d5d..2d51a98e2 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/AstCollectingVisitor.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/AstCollectingVisitor.java @@ -29,54 +29,45 @@ import com.vladsch.flexmark.util.ast.Node; import com.vladsch.flexmark.util.ast.NodeVisitorBase; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + import edu.umd.cs.findbugs.annotations.NonNull; -public class AstCollectingVisitor +public final class AstCollectingVisitor extends NodeVisitorBase { public static final String EOL = "\n"; - @NonNull - protected StringBuilder output = new StringBuilder(); // NOPMD - intentional - protected int indent; // 0; - protected boolean eolPending; // false; - @NonNull - public static String asString(@NonNull Node node) { - AstCollectingVisitor visitor = new AstCollectingVisitor(); - visitor.collect(node); - return visitor.getAst(); - } - - @SuppressWarnings("null") - @NonNull - public String getAst() { - return output.toString(); - } + @SuppressWarnings("PMD.AvoidStringBufferField") // short lived + private final StringBuilder strBuilder; + private int indent; // 0; - public void clear() { - output = new StringBuilder(); + private AstCollectingVisitor(@NonNull StringBuilder strBuilder) { + this.strBuilder = strBuilder; indent = 0; - eolPending = false; } - protected void appendIndent() { - for (int i = 0; i < indent * 2; i++) { - output.append(' '); - } - eolPending = true; - } - - protected void appendEOL() { - output.append(EOL); - eolPending = false; + /** + * Generate a string representation of an AST. + * + * @param node + * the branch of the tree to visualize + * @return the string representation of the AST. + */ + @NonNull + public static String asString(@NonNull Node node) { + StringBuilder builder = new StringBuilder(); + AstCollectingVisitor visitor = new AstCollectingVisitor(builder); + visitor.collect(node); + return ObjectUtils.notNull(builder.toString()); } - protected void appendPendingEOL() { - if (eolPending) { - appendEOL(); + private void appendIndent() { + for (int i = 0; i < indent * 2; i++) { + strBuilder.append(' '); } } - public void collect(@NonNull Node node) { + private void collect(@NonNull Node node) { visit(node); } @@ -84,8 +75,8 @@ public void collect(@NonNull Node node) { protected void visit(Node node) { assert node != null; appendIndent(); - node.astString(output, true); - output.append(EOL); + node.astString(strBuilder, true); + strBuilder.append(EOL); indent++; try { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ASTPrinter.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ASTPrinter.java deleted file mode 100644 index abff98ff3..000000000 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ASTPrinter.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Portions of this software was developed by employees of the National Institute - * of Standards and Technology (NIST), an agency of the Federal Government and is - * being made available as a public service. Pursuant to title 17 United States - * Code Section 105, works of NIST employees are not subject to copyright - * protection in the United States. This software may be subject to foreign - * copyright. Permission in the United States and in foreign countries, to the - * extent that NIST may hold copyright, to use, copy, modify, create derivative - * works, and distribute this software and its documentation without fee is hereby - * granted on a non-exclusive basis, provided that this notice and disclaimer - * of warranty appears in all copies. - * - * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER - * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY - * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM - * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE - * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT - * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, - * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, - * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, - * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR - * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT - * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. - */ - -package gov.nist.secauto.metaschema.core.metapath; - -import gov.nist.secauto.metaschema.core.metapath.ASTPrinter.State; - -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; - -@SuppressWarnings("PMD.CouplingBetweenObjects") -final class ASTPrinter - extends AbstractExpressionVisitor { - - private static final ASTPrinter SINGLETON = new ASTPrinter(); - - /** - * Get the singleton instance. - * - * @return the instance - */ - public static ASTPrinter instance() { - return SINGLETON; - } - - private ASTPrinter() { - // disable construction - } - - @Override - protected String visitChildren(IExpression expr, State context) { - context.push(); - String result = super.visitChildren(expr, context); - context.pop(); - return result; - } - - @Override - protected String aggregateResult(String result, String nextResult, State context) { - StringBuilder buffer = new StringBuilder(); - if (result != null) { - buffer.append(result); - // buffer.append(" ar "+System.lineSeparator()); - } - - buffer.append(context.getIndentation()) - .append(nextResult); - return buffer.toString(); - } - - @Override - protected String defaultResult() { - return ""; - } - - /** - * Append the {@code childResult} to the record produced for the current node. - * - * @param expr - * the current node - * @param childResult - * the output generated for the curren't node's children - * @param context - * the output context state - * @return the string representation of the node tree for the current node and - * its children - */ - @SuppressWarnings("static-method") - protected String appendNode(@NonNull IExpression expr, @Nullable String childResult, @NonNull State context) { - StringBuilder buffer = new StringBuilder(); - buffer.append(context.getIndentation()) - .append(expr.toASTString()); - if (childResult != null) { - buffer.append(System.lineSeparator()) - .append(childResult); - } - return buffer.toString(); - } - - /** - * Visit a node and produce a string representation of its the node tree. - * - * @param expression - * the node to build the node tree for - * @return the string representation of the node tree for the provided - * expression node and its children - */ - public String visit(@NonNull IExpression expression) { - return visit(expression, new State()); - } - - @Override - public String visitAddition(Addition expr, State context) { - return appendNode(expr, super.visitAddition(expr, context), context); - } - - @Override - public String visitAnd(And expr, State context) { - return appendNode(expr, super.visitAnd(expr, context), context); - } - - @Override - public String visitStep(Step expr, State context) { - return appendNode(expr, super.visitStep(expr, context), context); - } - - @Override - public String visitValueComparison(ValueComparison expr, State context) { - return appendNode(expr, super.visitValueComparison(expr, context), context); - } - - @Override - public String visitGeneralComparison(GeneralComparison expr, State context) { - return appendNode(expr, super.visitGeneralComparison(expr, context), context); - } - - @Override - public String visitContextItem(ContextItem expr, State context) { - return appendNode(expr, super.visitContextItem(expr, context), context); - } - - @Override - public String visitDecimalLiteral(DecimalLiteral expr, State context) { - return appendNode(expr, super.visitDecimalLiteral(expr, context), context); - } - - @Override - public String visitDivision(Division expr, State context) { - return appendNode(expr, super.visitDivision(expr, context), context); - } - - @Override - public String visitExcept(@NonNull Except expr, State context) { - return appendNode(expr, super.visitExcept(expr, context), context); - } - - @Override - public String visitFlag(Flag expr, State context) { - return appendNode(expr, super.visitFlag(expr, context), context); - } - - @Override - public String visitFunctionCall(FunctionCall expr, State context) { - return appendNode(expr, super.visitFunctionCall(expr, context), context); - } - - @Override - public String visitIntegerDivision(IntegerDivision expr, State context) { - return appendNode(expr, super.visitIntegerDivision(expr, context), context); - } - - @Override - public String visitIntegerLiteral(IntegerLiteral expr, State context) { - return appendNode(expr, super.visitIntegerLiteral(expr, context), context); - } - - @Override - public String visitIntersect(Intersect expr, State context) { - return appendNode(expr, super.visitIntersect(expr, context), context); - } - - @Override - public String visitMetapath(Metapath expr, State context) { - return appendNode(expr, super.visitMetapath(expr, context), context); - } - - @Override - public String visitModulo(Modulo expr, State context) { - return appendNode(expr, super.visitModulo(expr, context), context); - } - - @Override - public String visitModelInstance(ModelInstance expr, State context) { - return appendNode(expr, super.visitModelInstance(expr, context), context); - } - - @Override - public String visitMultiplication(Multiplication expr, State context) { - return appendNode(expr, super.visitMultiplication(expr, context), context); - } - - @Override - public String visitName(Name expr, State context) { - return appendNode(expr, super.visitName(expr, context), context); - } - - @Override - public String visitNegate(Negate expr, State context) { - return appendNode(expr, super.visitNegate(expr, context), context); - } - - @Override - public String visitOr(Or expr, State context) { - return appendNode(expr, super.visitOr(expr, context), context); - } - - @Override - public String visitAxis(Axis expr, State context) { - return appendNode(expr, super.visitAxis(expr, context), context); - } - - @Override - public String visitPredicate(Predicate expr, State context) { - return appendNode(expr, super.visitPredicate(expr, context), context); - } - - @Override - public String visitRelativeDoubleSlashPath(RelativeDoubleSlashPath expr, State context) { - return appendNode(expr, super.visitRelativeDoubleSlashPath(expr, context), context); - } - - @Override - public String visitRelativeSlashPath(RelativeSlashPath expr, State context) { - return appendNode(expr, super.visitRelativeSlashPath(expr, context), context); - } - - @Override - public String visitRootDoubleSlashPath(RootDoubleSlashPath expr, State context) { - return appendNode(expr, super.visitRootDoubleSlashPath(expr, context), context); - } - - @Override - public String visitRootSlashOnlyPath(RootSlashOnlyPath expr, State context) { - return appendNode(expr, super.visitRootSlashOnlyPath(expr, context), context); - } - - @Override - public String visitRootSlashPath(RootSlashPath expr, State context) { - return appendNode(expr, super.visitRootSlashPath(expr, context), context); - } - - @Override - public String visitStringConcat(StringConcat expr, State context) { - return appendNode(expr, super.visitStringConcat(expr, context), context); - } - - @Override - public String visitStringLiteral(StringLiteral expr, State context) { - return appendNode(expr, super.visitStringLiteral(expr, context), context); - } - - @Override - public String visitSubtraction(Subtraction expr, State context) { - return appendNode(expr, super.visitSubtraction(expr, context), context); - } - - @Override - public String visitUnion(Union expr, State context) { - return appendNode(expr, super.visitUnion(expr, context), context); - } - - @Override - public String visitWildcard(Wildcard expr, State context) { - return appendNode(expr, super.visitWildcard(expr, context), context); - } - - @Override - public String visitLet(Let expr, State context) { - return appendNode(expr, super.visitLet(expr, context), context); - } - - @Override - public String visitVariableReference(VariableReference expr, State context) { - return appendNode(expr, super.visitVariableReference(expr, context), context); - } - - static class State { - private int indentation; // 0; - private int lastIndentation; // 0; - private String indentationPadding = ""; - - public String getIndentation() { - if (indentation != lastIndentation) { - StringBuilder buffer = new StringBuilder(); - for (int i = 0; i < indentation; i++) { - buffer.append(" "); - } - lastIndentation = indentation; - indentationPadding = buffer.toString(); - } - return indentationPadding; - } - - public State push() { - indentation++; - return this; - } - - public State pop() { - indentation--; - return this; - } - } -} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractAstVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractAstVisitor.java deleted file mode 100644 index 509a8beaf..000000000 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractAstVisitor.java +++ /dev/null @@ -1,638 +0,0 @@ -/* - * Portions of this software was developed by employees of the National Institute - * of Standards and Technology (NIST), an agency of the Federal Government and is - * being made available as a public service. Pursuant to title 17 United States - * Code Section 105, works of NIST employees are not subject to copyright - * protection in the United States. This software may be subject to foreign - * copyright. Permission in the United States and in foreign countries, to the - * extent that NIST may hold copyright, to use, copy, modify, create derivative - * works, and distribute this software and its documentation without fee is hereby - * granted on a non-exclusive basis, provided that this notice and disclaimer - * of warranty appears in all copies. - * - * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER - * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY - * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM - * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE - * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT - * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, - * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, - * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, - * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR - * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT - * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. - */ - -package gov.nist.secauto.metaschema.core.metapath; // NOPMD requires a large number of public methods - -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10BaseVisitor; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.AbbrevforwardstepContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.AbbrevreversestepContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.AdditiveexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.AndexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ArgumentContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ArgumentlistContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ArrowexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ArrowfunctionspecifierContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.AxisstepContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ComparisonexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ContextitemexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.EqnameContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ExprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ExprsingleContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ForwardaxisContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ForwardstepContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.FunctioncallContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.GeneralcompContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.IntersectexceptexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.LetexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.LiteralContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.MetapathContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.MultiplicativeexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.NametestContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.NumericliteralContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.OrexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ParenthesizedexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.PathexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.PostfixexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.PredicateContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.PredicatelistContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.PrimaryexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.RelativepathexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ReverseaxisContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ReversestepContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.SimpleletbindingContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.SimpleletclauseContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.StepexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.StringconcatexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.UnaryexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.UnionexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ValuecompContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ValueexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.VarnameContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.VarrefContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.WildcardContext; -import gov.nist.secauto.metaschema.core.util.ObjectUtils; - -import org.antlr.v4.runtime.ParserRuleContext; -import org.antlr.v4.runtime.RuleContext; - -import java.util.function.Function; - -import edu.umd.cs.findbugs.annotations.NonNull; - -abstract class AbstractAstVisitor // NOPMD - extends metapath10BaseVisitor { - - /** - * This dispatch method will call the node handler on a leaf node or if multiple - * child expressions exist. Otherwise, it will delegate to the single child - * expression. - * - * @param - * the visitor context type - * @param ctx - * the visitor context - * @param handler - * the node handler - * @return the result - */ - protected R handle(T ctx, @NonNull Function handler) { - T context = ObjectUtils.requireNonNull(ctx); - - R retval; - if (context.getChildCount() == 1 && context.getChild(0) instanceof ParserRuleContext) { - // delegate to the child expression, since this expression doesn't require any - // action - retval = context.getChild(0).accept(this); - } else { - retval = handler.apply(context); - } - return retval; - } - - /** - * This dispatch method expects a single child expression which will be called. - * Other cases will result in an exception. - * - * @param - * the visitor context type - * @param ctx - * the visitor context - * @return the result - * @throws IllegalStateException - * if there was not a single child expression - */ - protected R passThrough(@NonNull T ctx) { - if (ctx.getChildCount() == 1) { - return ctx.getChild(0).accept(this); - } - throw new IllegalStateException("a single child expression was expected"); - } - - @Override - public R visitMetapath(MetapathContext ctx) { - assert ctx != null; - return passThrough(ctx); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleExpr(@NonNull ExprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitExpr(ExprContext ctx) { - return handle(ctx, (context) -> handleExpr(ctx)); - } - - @Override - public R visitExprsingle(ExprsingleContext ctx) { - assert ctx != null; - return passThrough(ctx); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleOrexpr(@NonNull OrexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitOrexpr(OrexprContext ctx) { - return handle(ctx, (context) -> handleOrexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleAndexpr(@NonNull AndexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitAndexpr(AndexprContext ctx) { - return handle(ctx, (context) -> handleAndexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleComparisonexpr(@NonNull ComparisonexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitComparisonexpr(ComparisonexprContext ctx) { - return handle(ctx, (context) -> handleComparisonexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleStringconcatexpr(@NonNull StringconcatexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitStringconcatexpr(StringconcatexprContext ctx) { - return handle(ctx, (context) -> handleStringconcatexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleAdditiveexpr(@NonNull AdditiveexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitAdditiveexpr(AdditiveexprContext ctx) { - return handle(ctx, (context) -> handleAdditiveexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleMultiplicativeexpr(@NonNull MultiplicativeexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitMultiplicativeexpr(MultiplicativeexprContext ctx) { - return handle(ctx, (context) -> handleMultiplicativeexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleUnionexpr(@NonNull UnionexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitUnionexpr(UnionexprContext ctx) { - return handle(ctx, (context) -> handleUnionexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleIntersectexceptexpr(@NonNull IntersectexceptexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitIntersectexceptexpr(IntersectexceptexprContext ctx) { - return handle(ctx, (context) -> handleIntersectexceptexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleArrowexpr(@NonNull ArrowexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitArrowexpr(ArrowexprContext ctx) { - return handle(ctx, (context) -> handleArrowexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleUnaryexpr(@NonNull UnaryexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitUnaryexpr(UnaryexprContext ctx) { - return handle(ctx, (context) -> handleUnaryexpr(ctx)); - } - - @Override - public R visitValueexpr(ValueexprContext ctx) { - assert ctx != null; - return passThrough(ctx); - } - - @Override - public R visitGeneralcomp(GeneralcompContext ctx) { - // should never be called, since this is handled by the parent expression - throw new IllegalStateException(); - } - - @Override - public R visitValuecomp(ValuecompContext ctx) { - // should never be called, since this is handled by the parent expression - throw new IllegalStateException(); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handlePathexpr(@NonNull PathexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitPathexpr(PathexprContext ctx) { - return handle(ctx, (context) -> handlePathexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleRelativepathexpr(@NonNull RelativepathexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitRelativepathexpr(RelativepathexprContext ctx) { - return handle(ctx, (context) -> handleRelativepathexpr(ctx)); - } - - @Override - public R visitStepexpr(StepexprContext ctx) { - assert ctx != null; - return passThrough(ctx); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleAxisstep(@NonNull AxisstepContext ctx); - - @SuppressWarnings("null") - @Override - public R visitAxisstep(AxisstepContext ctx) { - return handle(ctx, (context) -> handleAxisstep(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleForwardstep(@NonNull ForwardstepContext ctx); - - @SuppressWarnings("null") - @Override - public R visitForwardstep(ForwardstepContext ctx) { - return handle(ctx, (context) -> handleForwardstep(ctx)); - } - - @Override - public R visitForwardaxis(ForwardaxisContext ctx) { - // should never be called, since this is handled by handleForwardstep - throw new IllegalStateException(); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleAbbrevforwardstep(@NonNull AbbrevforwardstepContext ctx); - - @SuppressWarnings("null") - @Override - public R visitAbbrevforwardstep(AbbrevforwardstepContext ctx) { - return handleAbbrevforwardstep(ctx); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleReversestep(@NonNull ReversestepContext ctx); - - @SuppressWarnings("null") - @Override - public R visitReversestep(ReversestepContext ctx) { - return handle(ctx, (context) -> handleReversestep(ctx)); - } - - @Override - public R visitReverseaxis(ReverseaxisContext ctx) { - // should never be called, since this is handled by handleReversestep - throw new IllegalStateException(); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleAbbrevreversestep(@NonNull AbbrevreversestepContext ctx); - - @SuppressWarnings("null") - @Override - public R visitAbbrevreversestep(AbbrevreversestepContext ctx) { - return handleAbbrevreversestep(ctx); - } - - @Override - public R visitNametest(NametestContext ctx) { - assert ctx != null; - return passThrough(ctx); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleWildcard(@NonNull WildcardContext ctx); - - @SuppressWarnings("null") - @Override - public R visitWildcard(WildcardContext ctx) { - return handleWildcard(ctx); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handlePostfixexpr(@NonNull PostfixexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitPostfixexpr(PostfixexprContext ctx) { - return handle(ctx, (context) -> handlePostfixexpr(ctx)); - } - - @Override - public R visitArgumentlist(ArgumentlistContext ctx) { - // should never be called, since this is handled by the parent expression - throw new IllegalStateException(); - } - - @Override - public R visitPredicatelist(PredicatelistContext ctx) { - // should never be called, since this is handled by the parent expression - throw new IllegalStateException(); - } - - @Override - public R visitPredicate(PredicateContext ctx) { - // should never be called, since this is handled by the parent expression - throw new IllegalStateException(); - } - - @Override - public R visitPrimaryexpr(PrimaryexprContext ctx) { - assert ctx != null; - return passThrough(ctx); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleStringLiteral(@NonNull LiteralContext ctx); - - @SuppressWarnings("null") - @Override - public R visitLiteral(LiteralContext ctx) { - return handle(ctx, (context) -> handleStringLiteral(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleNumericLiteral(@NonNull NumericliteralContext ctx); - - @SuppressWarnings("null") - @Override - public R visitNumericliteral(NumericliteralContext ctx) { - return handle(ctx, (context) -> handleNumericLiteral(ctx)); - } - - @Override - public R visitParenthesizedexpr(ParenthesizedexprContext ctx) { - return ctx.expr().accept(this); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleContextitemexpr(@NonNull ContextitemexprContext ctx); - - @SuppressWarnings("null") - @Override - public R visitContextitemexpr(ContextitemexprContext ctx) { - return handle(ctx, (context) -> handleContextitemexpr(ctx)); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleFunctioncall(@NonNull FunctioncallContext ctx); - - @SuppressWarnings("null") - @Override - public R visitFunctioncall(FunctioncallContext ctx) { - return handle(ctx, (context) -> handleFunctioncall(ctx)); - } - - @Override - public R visitArgument(ArgumentContext ctx) { - assert ctx != null; - return passThrough(ctx); - } - - /** - * Handle the provided expression. - * - * @param ctx - * the provided expression context - * @return the result - */ - protected abstract R handleEqname(@NonNull EqnameContext ctx); - - @SuppressWarnings("null") - @Override - public R visitEqname(EqnameContext ctx) { - return handleEqname(ctx); - } - - protected abstract R handleLet(@NonNull LetexprContext ctx); - - @Override - public R visitLetexpr(LetexprContext ctx) { - assert ctx != null; - return handleLet(ctx); - } - - @Override - public R visitSimpleletclause(SimpleletclauseContext ctx) { - // should never be called, since this is handled by the parent expression - throw new IllegalStateException(); - } - - @Override - public R visitSimpleletbinding(SimpleletbindingContext ctx) { - // should never be called, since this is handled by the parent expression - throw new IllegalStateException(); - } - - @Override - public R visitArrowfunctionspecifier(ArrowfunctionspecifierContext ctx) { - // should never be called, since this is handled by the parent expression - throw new IllegalStateException(); - } - - protected abstract R handleVarref(@NonNull VarrefContext ctx); - - @Override - public R visitVarref(VarrefContext ctx) { - assert ctx != null; - return handleVarref(ctx); - } - - @Override - public R visitVarname(VarnameContext ctx) { - assert ctx != null; - return passThrough(ctx); - } - -} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicContext.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicContext.java index 75105a67a..0b13b5479 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicContext.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicContext.java @@ -36,11 +36,7 @@ import gov.nist.secauto.metaschema.core.util.ObjectUtils; import java.io.IOException; -import java.io.InputStream; import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Path; import java.time.Clock; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -51,99 +47,156 @@ import edu.umd.cs.findbugs.annotations.NonNull; +// TODO: add support for in-scope namespaces +/** + * The implementation of a Metapath + * dynamic context. + */ public class DynamicContext { // NOPMD - intentional data class - @NonNull - private final StaticContext staticContext; - @NonNull - private final ZoneId implicitTimeZone; - @NonNull - private final ZonedDateTime currentDateTime; - @NonNull - private final Map availableDocuments; - private final Map> functionResultCache; - private CachingLoader documentLoader; - @NonNull - private final IMutableConfiguration> configuration; @NonNull private final Map> letVariableMap; + @NonNull + private final SharedState sharedState; + + /** + * Construct a new Metapath dynamic context. + * + * @param staticContext + * the Metapath static context + */ + DynamicContext(@NonNull StaticContext staticContext) { + this.letVariableMap = new ConcurrentHashMap<>(); + this.sharedState = new SharedState(staticContext); + } - @SuppressWarnings("null") - public DynamicContext(@NonNull StaticContext staticContext) { - this.staticContext = staticContext; + private DynamicContext(@NonNull DynamicContext context) { + this.letVariableMap = new ConcurrentHashMap<>(context.letVariableMap); + this.sharedState = context.sharedState; + } - Clock clock = Clock.systemDefaultZone(); + private static class SharedState { + @NonNull + private final StaticContext staticContext; + @NonNull + private final ZoneId implicitTimeZone; + @NonNull + private final ZonedDateTime currentDateTime; + @NonNull + private final Map availableDocuments; + private final Map> functionResultCache; + private CachingLoader documentLoader; + @NonNull + private final IMutableConfiguration> configuration; - this.implicitTimeZone = clock.getZone(); - this.currentDateTime = ZonedDateTime.now(clock); - this.availableDocuments = new HashMap<>(); - this.functionResultCache = new HashMap<>(); - this.configuration = new DefaultConfiguration<>(); - this.configuration.enableFeature(MetapathEvaluationFeature.METAPATH_EVALUATE_PREDICATES); - this.letVariableMap = new ConcurrentHashMap<>(); + public SharedState(@NonNull StaticContext staticContext) { + this.staticContext = staticContext; + + Clock clock = Clock.systemDefaultZone(); + + this.implicitTimeZone = ObjectUtils.notNull(clock.getZone()); + this.currentDateTime = ObjectUtils.notNull(ZonedDateTime.now(clock)); + this.availableDocuments = new HashMap<>(); + this.functionResultCache = new HashMap<>(); + this.configuration = new DefaultConfiguration<>(); + this.configuration.enableFeature(MetapathEvaluationFeature.METAPATH_EVALUATE_PREDICATES); + } + } + + /** + * Generate a new dynamic context that is based on this object. + *

+ * This method can be used to create a new sub-context where changes can be made + * without affecting this context. This is useful for setting information that + * is only used in a limited evaluation scope, such as variables. + * + * @return a new dynamic context + */ + @NonNull + public DynamicContext subContext() { + return new DynamicContext(this); } + /** + * Get the static context associated with this dynamic context. + * + * @return the associated static context + */ @NonNull public StaticContext getStaticContext() { - return staticContext; + return sharedState.staticContext; } + /** + * Get the default time zone used for evaluation. + * + * @return the time zone identifier object + */ @NonNull public ZoneId getImplicitTimeZone() { - return implicitTimeZone; + return sharedState.implicitTimeZone; } + /** + * Get the current date and time. + * + * @return the current date and time + */ @NonNull public ZonedDateTime getCurrentDateTime() { - return currentDateTime; + return sharedState.currentDateTime; } @SuppressWarnings("null") @NonNull public Map getAvailableDocuments() { - return Collections.unmodifiableMap(availableDocuments); + return Collections.unmodifiableMap(sharedState.availableDocuments); } public IDocumentLoader getDocumentLoader() { - return documentLoader; + return sharedState.documentLoader; } public void setDocumentLoader(@NonNull IDocumentLoader documentLoader) { - this.documentLoader = new CachingLoader(documentLoader); + this.sharedState.documentLoader = new CachingLoader(documentLoader); } public ISequence getCachedResult(@NonNull CallingContext callingContext) { - return functionResultCache.get(callingContext); + return sharedState.functionResultCache.get(callingContext); } @NonNull public DynamicContext disablePredicateEvaluation() { - this.configuration.disableFeature(MetapathEvaluationFeature.METAPATH_EVALUATE_PREDICATES); + this.sharedState.configuration.disableFeature(MetapathEvaluationFeature.METAPATH_EVALUATE_PREDICATES); return this; } @NonNull public IConfiguration> getConfiguration() { - return configuration; + return sharedState.configuration; } public void cacheResult(@NonNull CallingContext callingContext, @NonNull ISequence result) { - ISequence old = functionResultCache.put(callingContext, result); + ISequence old = sharedState.functionResultCache.put(callingContext, result); assert old == null; } @NonNull - public ISequence getVariableValue(String name) { + public ISequence getVariableValue(@NonNull String name) { return ObjectUtils.requireNonNull(letVariableMap.get(name)); } - public void setVariableValue(String name, ISequence boundValue) { + /** + * Bind the variable {@code name} to the sequence {@code value}. + * + * @param name + * the name of the variable to bind + * @param boundValue + * the value to bind to the variable + */ + public void bindVariableValue(@NonNull String name, @NonNull ISequence boundValue) { letVariableMap.put(name, boundValue); } - public void clearVariableValue(String name) { - letVariableMap.remove(name); - } - private class CachingLoader implements IDocumentLoader { @NonNull private final IDocumentLoader proxy; @@ -168,46 +221,16 @@ protected IDocumentLoader getProxiedDocumentLoader() { return proxy; } - @Override - public IDocumentNodeItem loadAsNodeItem(Path path) throws IOException { - URI uri = path.toUri(); - IDocumentNodeItem retval = availableDocuments.get(uri); - if (retval == null) { - retval = getProxiedDocumentLoader().loadAsNodeItem(path); - availableDocuments.put(uri, retval); - } - return retval; - } - - @Override - public IDocumentNodeItem loadAsNodeItem(URL url) throws IOException, URISyntaxException { - URI uri = ObjectUtils.notNull(url.toURI()); - IDocumentNodeItem retval = availableDocuments.get(uri); - if (retval == null) { - retval = getProxiedDocumentLoader().loadAsNodeItem(uri); - availableDocuments.put(uri, retval); - } - return retval; - } - @Override public IDocumentNodeItem loadAsNodeItem(URI uri) throws IOException { - IDocumentNodeItem retval = availableDocuments.get(uri); + IDocumentNodeItem retval = sharedState.availableDocuments.get(uri); if (retval == null) { retval = getProxiedDocumentLoader().loadAsNodeItem(uri); - availableDocuments.put(uri, retval); + sharedState.availableDocuments.put(uri, retval); } return retval; } - @Override - public @NonNull IDocumentNodeItem loadAsNodeItem( - @NonNull InputStream is, - @NonNull URI documentUri) throws IOException { - throw new UnsupportedOperationException(); - // return getProxiedDocumentLoader().loadAsNodeItem(is, documentUri); - } - public class ContextUriResolver implements IUriResolver { /** @@ -232,4 +255,5 @@ public URI resolve(URI uri) { } } } + } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicMetapathException.java index dbbc657ca..df5f8fcc0 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicMetapathException.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicMetapathException.java @@ -26,6 +26,10 @@ package gov.nist.secauto.metaschema.core.metapath; +/** + * MPDY: Exceptions related to the Metapath dynamic context and dynamic + * evaluation. + */ public class DynamicMetapathException extends AbstractCodedMetapathException { @@ -34,24 +38,74 @@ public class DynamicMetapathException */ private static final long serialVersionUID = 1L; + /** + * err:MPDY0002: It + * is a dynamic + * error if evaluation of an expression relies on some part of the + * dynamic + * context that is + * absent. + */ public static final int DYNAMIC_CONTEXT_ABSENT = 2; - public static final int INVALID_PATH_GRAMMAR = 3; + + /** + * err:MPDY0050: It + * is a dynamic + * error if the + * dynamic type of + * the operand of a treat expression does not match the + * sequence type + * specified by the treat expression. This error might also be + * raised by a path expression beginning with "/" or "//" if the context node is + * not in a tree that is rooted at a document node. This is because a leading + * "/" or "//" in a path expression is an abbreviation for an initial step that + * includes the clause treat as document-node(). + */ public static final int CONTEXT_NODE_NOT_A_DOCUMENT_NODE = 50; + /** + * Constructs a new exception with the provided {@code code}, {@code message}, + * and no cause. + * + * @param code + * the error code value + * @param message + * the exception message + */ public DynamicMetapathException(int code, String message) { super(code, message); } + /** + * Constructs a new exception with the provided {@code code}, {@code message}, + * and {@code cause}. + * + * @param code + * the error code value + * @param message + * the exception message + * @param cause + * the original exception cause + */ public DynamicMetapathException(int code, String message, Throwable cause) { super(code, message, cause); } + /** + * Constructs a new exception with the provided {@code code}, no message, and + * the {@code cause}. + * + * @param code + * the error code value + * @param cause + * the original exception cause + */ public DynamicMetapathException(int code, Throwable cause) { super(code, cause); } @Override protected String getCodePrefix() { - return "XPDY"; + return "MPDY"; } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IDocumentLoader.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IDocumentLoader.java index 54b6366d0..d092d86ec 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IDocumentLoader.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IDocumentLoader.java @@ -33,38 +33,81 @@ import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; -import java.nio.file.Files; import java.nio.file.Path; import edu.umd.cs.findbugs.annotations.NonNull; +/** + * Supports loading documents referenced in Metapath expressions. + */ public interface IDocumentLoader extends IResourceResolver { + /** + * Allows setting an {@link IUriResolver}, which will be used to map URIs prior + * to loading the resource. + * + * @param resolver + * the resolver to set + */ void setUriResolver(@NonNull IUriResolver resolver); + /** + * Load a Metaschema-based document from a file resource. + * + * @param file + * the file to load + * @return a document item representing the contents of the document. + * @throws IOException + * if an error occurred while parsing the file + */ @NonNull default IDocumentNodeItem loadAsNodeItem(@NonNull File file) throws IOException { return loadAsNodeItem(ObjectUtils.notNull(file.toPath())); } + /** + * Load a Metaschema-based document from a file resource identified by a path. + * + * @param path + * the file to load + * @return a document item representing the contents of the document. + * @throws IOException + * if an error occurred while parsing the file + */ @NonNull default IDocumentNodeItem loadAsNodeItem(@NonNull Path path) throws IOException { - try (InputStream is = ObjectUtils.notNull(Files.newInputStream(path))) { - return loadAsNodeItem(is, ObjectUtils.notNull(path.toUri())); - } + return loadAsNodeItem(ObjectUtils.notNull(path.toUri())); } + /** + * Load a Metaschema-based document from a URL resource. + * + * @param url + * the resource to load + * @return a document item representing the contents of the document. + * @throws IOException + * if an error occurred while parsing the resource + * @throws URISyntaxException + * if the URL is not a valid URI + */ @NonNull default IDocumentNodeItem loadAsNodeItem(@NonNull URL url) throws IOException, URISyntaxException { return loadAsNodeItem(ObjectUtils.notNull(url.toURI())); } + /** + * Load a Metaschema-based document from a URI resource. + *

+ * This is the expected, primary entry point for implementations. + * + * @param uri + * the resource to load + * @return a document item representing the contents of the document. + * @throws IOException + * if an error occurred while parsing the resource + */ @NonNull IDocumentNodeItem loadAsNodeItem(@NonNull URI uri) throws IOException; - - @NonNull - IDocumentNodeItem loadAsNodeItem(@NonNull InputStream is, @NonNull URI documentUri) throws IOException; } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IExpressionVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IExpressionVisitor.java deleted file mode 100644 index ef8b686b4..000000000 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IExpressionVisitor.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Portions of this software was developed by employees of the National Institute - * of Standards and Technology (NIST), an agency of the Federal Government and is - * being made available as a public service. Pursuant to title 17 United States - * Code Section 105, works of NIST employees are not subject to copyright - * protection in the United States. This software may be subject to foreign - * copyright. Permission in the United States and in foreign countries, to the - * extent that NIST may hold copyright, to use, copy, modify, create derivative - * works, and distribute this software and its documentation without fee is hereby - * granted on a non-exclusive basis, provided that this notice and disclaimer - * of warranty appears in all copies. - * - * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER - * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY - * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM - * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE - * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT - * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, - * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, - * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, - * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR - * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT - * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. - */ - -package gov.nist.secauto.metaschema.core.metapath; - -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; - -/** - * Used to support processing a Metapath expression based on the visitor - * pattern. Each type of expression node in the Metapath abstract syntax tree - * (AST) is represented. - * - * @param - * the result of processing any node - * @param - * additional state to pass between nodes visited - */ -interface IExpressionVisitor { - - @Nullable - RESULT visitAddition(@NonNull Addition expr, @NonNull CONTEXT context); - - RESULT visitAnd(@NonNull And expr, @NonNull CONTEXT context); - - RESULT visitExcept(@NonNull Except except, @NonNull CONTEXT context); - - RESULT visitAxis(@NonNull Axis expr, @NonNull CONTEXT context); - - RESULT visitStep(@NonNull Step expr, @NonNull CONTEXT context); - - RESULT visitValueComparison(@NonNull ValueComparison expr, @NonNull CONTEXT context); - - RESULT visitGeneralComparison(@NonNull GeneralComparison generalComparison, @NonNull CONTEXT context); - - RESULT visitContextItem(@NonNull ContextItem expr, @NonNull CONTEXT context); - - RESULT visitDecimalLiteral(@NonNull DecimalLiteral expr, @NonNull CONTEXT context); - - RESULT visitDivision(@NonNull Division expr, @NonNull CONTEXT context); - - RESULT visitFlag(@NonNull Flag expr, @NonNull CONTEXT context); - - RESULT visitFunctionCall(@NonNull FunctionCall expr, @NonNull CONTEXT context); - - RESULT visitIntegerDivision(@NonNull IntegerDivision expr, @NonNull CONTEXT context); - - RESULT visitIntegerLiteral(@NonNull IntegerLiteral expr, @NonNull CONTEXT context); - - RESULT visitIntersect(@NonNull Intersect intersect, @NonNull CONTEXT context); - - RESULT visitMetapath(@NonNull Metapath expr, @NonNull CONTEXT context); - - RESULT visitModulo(@NonNull Modulo expr, @NonNull CONTEXT context); - - RESULT visitModelInstance(@NonNull ModelInstance modelInstance, @NonNull CONTEXT context); - - RESULT visitMultiplication(@NonNull Multiplication expr, @NonNull CONTEXT context); - - RESULT visitName(@NonNull Name expr, @NonNull CONTEXT context); - - RESULT visitNegate(@NonNull Negate expr, @NonNull CONTEXT context); - - RESULT visitOr(@NonNull Or expr, @NonNull CONTEXT context); - - RESULT visitPredicate(@NonNull Predicate predicate, @NonNull CONTEXT context); - - RESULT visitRelativeDoubleSlashPath(@NonNull RelativeDoubleSlashPath relativeDoubleSlashPath, - @NonNull CONTEXT context); - - RESULT visitRelativeSlashPath(@NonNull RelativeSlashPath relativeSlashPath, @NonNull CONTEXT context); - - RESULT visitRootDoubleSlashPath(@NonNull RootDoubleSlashPath rootDoubleSlashPath, @NonNull CONTEXT context); - - RESULT visitRootSlashOnlyPath(@NonNull RootSlashOnlyPath rootSlashOnlyPath, @NonNull CONTEXT context); - - RESULT visitRootSlashPath(@NonNull RootSlashPath rootSlashPath, @NonNull CONTEXT context); - - RESULT visitStringConcat(@NonNull StringConcat expr, @NonNull CONTEXT context); - - RESULT visitStringLiteral(@NonNull StringLiteral expr, @NonNull CONTEXT context); - - RESULT visitSubtraction(@NonNull Subtraction expr, @NonNull CONTEXT context); - - RESULT visitUnion(@NonNull Union expr, @NonNull CONTEXT context); - - RESULT visitWildcard(@NonNull Wildcard expr, @NonNull CONTEXT context); - - RESULT visitLet(@NonNull Let expr, @NonNull CONTEXT context); - - RESULT visitVariableReference(@NonNull VariableReference expr, @NonNull CONTEXT context); -} 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 4b73e9a90..0cb851cd8 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 @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -46,7 +47,16 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -public interface ISequence extends Iterable { +/** + * Represents an ordered collection of Metapath expression results. + *

+ * Items is a sequence are typically ordered based on their position in the + * original node graph based on a depth first ordering. + * + * @param + * the Java type of the items in a sequence + */ +public interface ISequence extends Collection { @SuppressWarnings("rawtypes") ISequence EMPTY = new EmptyListImpl<>(); @@ -190,6 +200,7 @@ default Stream safeStream() { * @return {@code true} if the sequence contains no items, or {@code false} * otherwise */ + @Override boolean isEmpty(); /** @@ -197,6 +208,7 @@ default Stream safeStream() { * * @return the count of items */ + @Override int size(); /** @@ -270,4 +282,54 @@ static ISequence map( .map(item -> mapFunction.apply(item)) .collect(toSequence()); } + + @Override + default boolean contains(Object obj) { + return asList().contains(obj); + } + + @Override + default Object[] toArray() { + return asList().toArray(); + } + + @Override + default T[] toArray(T[] array) { + return asList().toArray(array); + } + + @Override + default boolean add(ITEM_TYPE item) { + throw new UnsupportedOperationException(); + } + + @Override + default boolean remove(Object obj) { + throw new UnsupportedOperationException(); + } + + @Override + default boolean containsAll(Collection collection) { + return asList().containsAll(collection); + } + + @Override + default boolean addAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + default boolean removeAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + default boolean retainAll(Collection collection) { + throw new UnsupportedOperationException(); + } + + @Override + default void clear() { + throw new UnsupportedOperationException(); + } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/InvalidTypeMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/InvalidTypeMetapathException.java index a0e228596..f7ace0bbf 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/InvalidTypeMetapathException.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/InvalidTypeMetapathException.java @@ -31,6 +31,10 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; +/** + * Provides a convenient way to raise a + * {@link TypeMetapathException#INVALID_TYPE_ERROR}. + */ public class InvalidTypeMetapathException extends TypeMetapathException { @@ -42,27 +46,68 @@ public class InvalidTypeMetapathException @Nullable private final IItem item; + /** + * Constructs a new exception with the provided {@code item} and {@code cause}, + * using a default message. + * + * @param item + * the item related to the invalid type error + * @param cause + * the original exception cause + */ public InvalidTypeMetapathException(@NonNull IItem item, @NonNull Throwable cause) { super(TypeMetapathException.INVALID_TYPE_ERROR, String.format("Invalid data type '%s'", item.getClass().getName()), cause); this.item = item; } + /** + * Constructs a new exception with the provided {@code item} and no cause, using + * a default message. + * + * @param item + * the item related to the invalid type error + */ public InvalidTypeMetapathException(@NonNull IItem item) { super(TypeMetapathException.INVALID_TYPE_ERROR, String.format("Invalid data type '%s'", item.getClass().getName())); this.item = item; } + /** + * Constructs a new exception with the provided {@code item}, {@code message}, + * and {@code cause}. + * + * @param item + * the item related to the invalid type error + * @param message + * the exception message + * @param cause + * the original exception cause + */ public InvalidTypeMetapathException(@Nullable IItem item, @Nullable String message, @NonNull Throwable cause) { super(TypeMetapathException.INVALID_TYPE_ERROR, message, cause); this.item = item; } + /** + * Constructs a new exception with the provided {@code item}, {@code message}, + * and no cause. + * + * @param item + * the item related to the invalid type error + * @param message + * the exception message + */ public InvalidTypeMetapathException(@Nullable IItem item, @Nullable String message) { super(TypeMetapathException.INVALID_TYPE_ERROR, message); this.item = item; } + /** + * Get the associated item, if provided for the exception. + * + * @return the item or {@code null} if not item was provided + */ @Nullable public IItem getItem() { return item; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathConstants.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathConstants.java index 05ddb55af..f261c550e 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathConstants.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathConstants.java @@ -34,6 +34,9 @@ import edu.umd.cs.findbugs.annotations.NonNull; +/** + * Provides constant values used in Metapath. + */ public final class MetapathConstants { @NonNull public static final URI NS_METAPATH = ObjectUtils.requireNonNull( @@ -42,11 +45,13 @@ public final class MetapathConstants { public static final URI NS_XML_SCHEMA = ObjectUtils.requireNonNull( URI.create(XMLConstants.W3C_XML_SCHEMA_NS_URI)); @NonNull - public static final URI NS_XPATH_FUNCTIONS = ObjectUtils.requireNonNull( - URI.create("http://www.w3.org/2005/xpath-functions")); + public static final URI NS_METAPATH_FUNCTIONS = ObjectUtils.requireNonNull( + URI.create("http://csrc.nist.gov/ns/metaschema/metapath-functions")); + @NonNull + public static final URI NS_METAPATH_FUNCTIONS_MATH = ObjectUtils.requireNonNull( + URI.create("http://csrc.nist.gov/ns/metaschema/metapath-functions/math")); @NonNull - public static final URI NS_XPATH_FUNCTIONS_MATH = ObjectUtils.requireNonNull( - URI.create("http://www.w3.org/2005/xpath-functions/math")); + public static final URI NS_METAPATH_FUNCTIONS_EXTENDED = NS_METAPATH_FUNCTIONS_MATH; @NonNull public static final String PREFIX_METAPATH = "mp"; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathEvaluationFeature.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathEvaluationFeature.java index 9374ffc42..2268507fa 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathEvaluationFeature.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/MetapathEvaluationFeature.java @@ -30,10 +30,18 @@ import edu.umd.cs.findbugs.annotations.NonNull; +/** + * Provides a mechanism to configure Metapath evaluation settings. + * + * @param + * the feature value Java type + */ public final class MetapathEvaluationFeature extends AbstractConfigurationFeature { /** - * If enabled, evaluate {@link Predicate} nodes, otherwise skip evaluating them. + * If enabled, evaluate predicates, + * otherwise skip evaluating them. */ @NonNull public static final MetapathEvaluationFeature METAPATH_EVALUATE_PREDICATES 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 5dfa379b2..421a9d02f 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 @@ -26,8 +26,14 @@ package gov.nist.secauto.metaschema.core.metapath; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Lexer; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser; +import gov.nist.secauto.metaschema.core.metapath.antlr.FailingErrorListener; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10Lexer; +import gov.nist.secauto.metaschema.core.metapath.antlr.ParseTreePrinter; +import gov.nist.secauto.metaschema.core.metapath.cst.BuildCSTVisitor; +import gov.nist.secauto.metaschema.core.metapath.cst.CSTPrinter; +import gov.nist.secauto.metaschema.core.metapath.cst.ContextItem; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; import gov.nist.secauto.metaschema.core.metapath.function.library.FnBoolean; import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; @@ -35,6 +41,7 @@ import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDecimalItem; import gov.nist.secauto.metaschema.core.metapath.item.atomic.INumericItem; +import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import org.antlr.v4.runtime.CharStreams; @@ -47,19 +54,37 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; +import java.math.BigDecimal; import java.nio.charset.StandardCharsets; -import java.util.Arrays; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; +/** + * Supports compiling and executing Metapath expressions. + */ public class MetapathExpression { public enum ResultType { + /** + * The result is expected to be a {@link BigDecimal} value. + */ NUMBER, + /** + * The result is expected to be a {@link String} value. + */ STRING, + /** + * The result is expected to be a {@link Boolean} value. + */ BOOLEAN, + /** + * The result is expected to be an {@link ISequence} value. + */ SEQUENCE, + /** + * The result is expected to be an {@link INodeItem} value. + */ NODE; } @@ -88,9 +113,12 @@ public static MetapathExpression compile(@NonNull String path) { retval = CONTEXT_NODE; } else { try { - metapath10Lexer lexer = new metapath10Lexer(CharStreams.fromString(path)); + Metapath10Lexer lexer = new Metapath10Lexer(CharStreams.fromString(path)); + lexer.removeErrorListeners(); + lexer.addErrorListener(new FailingErrorListener()); + CommonTokenStream tokens = new CommonTokenStream(lexer); - metapath10Parser parser = new metapath10Parser(tokens); + Metapath10 parser = new Metapath10(tokens); parser.removeErrorListeners(); parser.addErrorListener(new FailingErrorListener()); @@ -99,26 +127,26 @@ public static MetapathExpression compile(@NonNull String path) { if (LOGGER.isDebugEnabled()) { try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { try (PrintStream ps = new PrintStream(os, true, StandardCharsets.UTF_8)) { - CSTPrinter printer = new CSTPrinter(ps); - printer.print(tree, Arrays.asList(metapath10Parser.ruleNames)); + ParseTreePrinter printer = new ParseTreePrinter(ps); + printer.print(tree, Metapath10.ruleNames); ps.flush(); } - LOGGER.atDebug().log(String.format("Metapath CST:%n%s", os.toString(StandardCharsets.UTF_8))); + LOGGER.atDebug().log(String.format("Metapath AST:%n%s", os.toString(StandardCharsets.UTF_8))); } catch (IOException ex) { LOGGER.atError().withThrowable(ex).log("An unexpected error occured while closing the steam."); } } - IExpression expr = new BuildAstVisitor().visit(tree); + IExpression expr = new BuildCSTVisitor().visit(tree); if (LOGGER.isDebugEnabled()) { - LOGGER.atDebug().log(String.format("Metapath AST:%n%s", ASTPrinter.instance().visit(expr))); + LOGGER.atDebug().log(String.format("Metapath CST:%n%s", CSTPrinter.toString(expr))); } retval = new MetapathExpression(path, expr); } catch (MetapathException | ParseCancellationException ex) { String msg = String.format("Unable to compile Metapath '%s'", path); LOGGER.atError().withThrowable(ex).log(msg); - throw new MetapathException(msg, ex); + throw new StaticMetapathException(StaticMetapathException.INVALID_PATH_GRAMMAR, msg, ex); } } return retval; @@ -158,7 +186,7 @@ protected IExpression getASTNode() { @Override public String toString() { - return ASTPrinter.instance().visit(getASTNode()); + return CSTPrinter.toString(getASTNode()); } /** @@ -234,7 +262,7 @@ public T evaluateAs( */ @Nullable public T evaluateAs( - @NonNull IItem focus, + @Nullable IItem focus, @NonNull ResultType resultType, @NonNull DynamicContext dynamicContext) { ISequence result = evaluate(focus, dynamicContext); @@ -332,7 +360,7 @@ public ISequence evaluate( return (ISequence) evaluate( focus, StaticContext.builder() - .build().newDynamicContext()); + .build().dynamicContext()); } /** 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 aa3d8fb8b..2f8fe34c8 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 @@ -34,18 +34,69 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +// add support for default namespace +/** + * The implementation of a Metapath + * static context. + */ public final class StaticContext { + @NonNull + private static final Map WELL_KNOWN_NAMESPACES; + + static { + Map knownNamespaces = new ConcurrentHashMap<>(); + knownNamespaces.put( + MetapathConstants.PREFIX_METAPATH, + MetapathConstants.NS_METAPATH); + knownNamespaces.put( + MetapathConstants.PREFIX_XML_SCHEMA, + MetapathConstants.NS_XML_SCHEMA); + knownNamespaces.put( + MetapathConstants.PREFIX_XPATH_FUNCTIONS, + MetapathConstants.NS_METAPATH_FUNCTIONS); + knownNamespaces.put( + MetapathConstants.PREFIX_XPATH_FUNCTIONS_MATH, + MetapathConstants.NS_METAPATH_FUNCTIONS_MATH); + WELL_KNOWN_NAMESPACES = CollectionUtil.unmodifiableMap(knownNamespaces); + } + @Nullable private final URI baseUri; @NonNull private final Map knownNamespaces; + /** + * Get the mapping of prefix to namespace URI for all well-known namespaces + * provided by default to the static context. + *

+ * These namespaces can be overridden using the + * {@link Builder#namespace(String, URI)} method. + * + * @return the mapping of prefix to namespace URI for all well-known namespaces + */ + @SuppressFBWarnings("MS_EXPOSE_REP") + public static Map getWellKnownNamespaces() { + return WELL_KNOWN_NAMESPACES; + } + + /** + * Create a new static context instance using default values. + * + * @return a new static context instance + */ @NonNull - public static StaticContext newInstance() { + public static StaticContext instance() { return builder().build(); } + /** + * Create a new static context builder that allows for fine-grained adjustments + * when creating a new static context. + * + * @return a new builder + */ @NonNull public static Builder builder() { return new Builder(); @@ -72,9 +123,47 @@ public URI getBaseUri() { } } + /** + * Get the namespace URI associated with the provided {@code prefix}, if any is + * bound. + *

+ * This method uses the namespaces set by the + * {@link Builder#namespace(String, URI)} method, falling back to the well-known + * namespace bindings when a prefix match is not found. + *

+ * The well-known namespace bindings can be retrieved using the + * {@link StaticContext#getWellKnownNamespaces()} method. + * + * @param prefix + * the namespace prefix + * @return the namespace URI bound to the prefix, or {@code null} if no + * namespace is bound to the prefix + * @see Builder#namespace(String, URI) + * @see #getWellKnownNamespaces() + */ @Nullable - public URI getUriForPrefix(@NonNull String prefix) { - return knownNamespaces.get(prefix); + public URI lookupNamespaceURIForPrefix(@NonNull String prefix) { + URI retval = knownNamespaces.get(prefix); + if (retval == null) { + // fall back to well-known namespaces + retval = WELL_KNOWN_NAMESPACES.get(prefix); + } + return retval; + } + + /** + * Get the namespace associated with the provided {@code prefix} as a string, if + * any is bound. + * + * @param prefix + * the namespace prefix + * @return the namespace string bound to the prefix, or {@code null} if no + * namespace is bound to the prefix + */ + @Nullable + public String lookupNamespaceForPrefix(@NonNull String prefix) { + URI result = lookupNamespaceURIForPrefix(prefix); + return result == null ? null : result.toASCIIString(); } /** @@ -83,28 +172,31 @@ public URI getUriForPrefix(@NonNull String prefix) { * @return the generated dynamic context */ @NonNull - public DynamicContext newDynamicContext() { + public DynamicContext dynamicContext() { return new DynamicContext(this); } + /** + * A builder used to generate the static context. + */ public static class Builder { private URI baseUri; @NonNull - private final Map knownNamespaces = new ConcurrentHashMap<>(); + private final Map namespaces = new ConcurrentHashMap<>(); private Builder() { - knownNamespaces.put( + namespaces.put( MetapathConstants.PREFIX_METAPATH, MetapathConstants.NS_METAPATH); - knownNamespaces.put( + namespaces.put( MetapathConstants.PREFIX_XML_SCHEMA, MetapathConstants.NS_XML_SCHEMA); - knownNamespaces.put( + namespaces.put( MetapathConstants.PREFIX_XPATH_FUNCTIONS, - MetapathConstants.NS_XPATH_FUNCTIONS); - knownNamespaces.put( + MetapathConstants.NS_METAPATH_FUNCTIONS); + namespaces.put( MetapathConstants.PREFIX_XPATH_FUNCTIONS_MATH, - MetapathConstants.NS_XPATH_FUNCTIONS_MATH); + MetapathConstants.NS_METAPATH_FUNCTIONS_MATH); } /** @@ -122,17 +214,42 @@ public Builder baseUri(@NonNull URI uri) { return this; } + /** + * Adds a new prefix to namespace URI binding to the mapping of + * statically + * known namespaces. + *

+ * A namespace set by this method can be resolved using the + * {@link StaticContext#lookupNamespaceForPrefix(String)} method. + *

+ * Well-known namespace bindings are used by default, which can be retrieved + * using the {@link StaticContext#getWellKnownNamespaces()} method. + * + * @param prefix + * the prefix to associate with the namespace, which may be + * @param uri + * the namespace URI + * @return this builder + * @see StaticContext#lookupNamespaceForPrefix(String) + * @see StaticContext#lookupNamespaceURIForPrefix(String) + * @see StaticContext#getWellKnownNamespaces() + */ @NonNull public Builder namespace(@NonNull String prefix, @NonNull URI uri) { - this.knownNamespaces.put(prefix, uri); + this.namespaces.put(prefix, uri); return this; } + /** + * Construct a new static context using the information provided to the builder. + * + * @return the new static context + */ @NonNull public StaticContext build() { return new StaticContext( baseUri, - CollectionUtil.unmodifiableMap(knownNamespaces)); + CollectionUtil.unmodifiableMap(namespaces)); } } } 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 0aef34340..eea69c7a7 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 @@ -26,23 +26,104 @@ package gov.nist.secauto.metaschema.core.metapath; +/** + * MPST: Exceptions related to the Metapath static context and static + * evaluation. + */ +@SuppressWarnings("PMD.DataClass") public class StaticMetapathException extends AbstractCodedMetapathException { + /** + * err:MPST0003: It + * is a static + * error if an expression is not a valid instance of the Metapath grammar. + */ + // TODO: need a Metapath grammar link + public static final int INVALID_PATH_GRAMMAR = 3; + + /** + * err:MPST0017: It + * is a static + * error if the + * expanded + * QName and number of arguments in a static function call do not match the + * name and arity of a + * function + * signature in the + * static + * context. + */ public static final int NO_FUNCTION_MATCH = 17; + /** + * err:MPST0070: A + * static error is + * raised if any of the following conditions is statically detected in any + * expression. + *

    + *
  • The prefix xml is bound to some namespace URI other than + * http://www.w3.org/XML/1998/namespace.
  • + *
  • A prefix other than xml is bound to the namespace URI + * http://www.w3.org/XML/1998/namespace.
  • + *
  • The prefix xmlns is bound to any namespace URI.
  • + *
  • A prefix other than xmlns is bound to the namespace URI + * http://www.w3.org/2000/xmlns/.
  • + *
+ */ + public static final int NAMESPACE_MISUSE = 70; + + /** + * err:MPST0070: It + * is a static + * error if a QName used in an expression contains a namespace prefix that + * cannot be expanded into a namespace URI by using the + * statically + * known namespaces. + */ + public static final int PREFIX_NOT_EXPANDABLE = 81; + /** * the serial version UID. */ private static final long serialVersionUID = 2L; - public StaticMetapathException(int code, String message) { - super(code, message); - } - + /** + * Constructs a new exception with the provided {@code code}, {@code message}, + * and {@code cause}. + * + * @param code + * the error code value + * @param message + * the exception message + * @param cause + * the original exception cause + */ public StaticMetapathException(int code, String message, Throwable cause) { super(code, message, cause); } + /** + * Constructs a new exception with the provided {@code code}, {@code message}, + * and no cause. + * + * @param code + * the error code value + * @param message + * the exception message + */ + public StaticMetapathException(int code, String message) { + super(code, message); + } + + /** + * Constructs a new exception with the provided {@code code}, no message, and + * the {@code cause}. + * + * @param code + * the error code value + * @param cause + * the original exception cause + */ public StaticMetapathException(int code, Throwable cause) { super(code, cause); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/TypeMetapathException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/TypeMetapathException.java index 22e495c9c..89de22791 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/TypeMetapathException.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/TypeMetapathException.java @@ -26,15 +26,36 @@ package gov.nist.secauto.metaschema.core.metapath; +/** + * MPTY: Exceptions related to Metapath type errors. + */ public class TypeMetapathException extends AbstractCodedMetapathException { + /** + * err:MPTY0004: It + * is a type error + * if during the + * static analysis + * phase, an expression is found to have a + * static type that + * is not appropriate for the context in which the expression occurs, or during + * the dynamic + * evaluation phase, the + * dynamic type of + * a value does not match a required type as specified by the matching rules in + * 2.5.5 + * SequenceType Matching. + */ public static final int INVALID_TYPE_ERROR = 4; /** - * E1 in a path expression E1/E2 does not evaluate to a sequence of nodes. + * err:MPTY0019: It + * is a type error + * if {@code E1} in a path expression {@code E1/E2} does not evaluate to a + * sequence of nodes. */ public static final int BASE_PATH_NOT_A_SEQUENCE = 19; /** - * The context item is not a node when evaluating an axis {@link Step}. + * The context item is not a node when evaluating an axis step. */ public static final int NOT_A_NODE_ITEM_FOR_STEP = 20; @@ -43,14 +64,43 @@ public class TypeMetapathException */ private static final long serialVersionUID = 2L; + /** + * Constructs a new exception with the provided {@code code}, {@code message}, + * and {@code cause}. + * + * @param code + * the error code value + * @param message + * the exception message + * @param cause + * the original exception cause + */ public TypeMetapathException(int code, String message, Throwable cause) { super(code, message, cause); } + /** + * Constructs a new exception with the provided {@code code}, {@code message}, + * and no cause. + * + * @param code + * the error code value + * @param message + * the exception message + */ public TypeMetapathException(int code, String message) { super(code, message); } + /** + * Constructs a new exception with the provided {@code code}, no message, and + * the {@code cause}. + * + * @param code + * the error code value + * @param cause + * the original exception cause + */ public TypeMetapathException(int code, Throwable cause) { super(code, cause); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/AbstractAstVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/AbstractAstVisitor.java new file mode 100644 index 000000000..3b3d16983 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/AbstractAstVisitor.java @@ -0,0 +1,899 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.antlr; // NOPMD requires a large number of public methods + +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.AbbrevforwardstepContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.AbbrevreversestepContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.AdditiveexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.AndexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ArgumentContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ArgumentlistContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ArrowexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ArrowfunctionspecifierContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.AxisstepContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ComparisonexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ContextitemexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.EqnameContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ExprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ExprsingleContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ForexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ForwardaxisContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ForwardstepContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.FunctioncallContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.GeneralcompContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.IfexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.IntersectexceptexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.LetexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.LiteralContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.MetapathContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.MultiplicativeexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.NametestContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.NodetestContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.NumericliteralContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.OrexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ParenthesizedexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.PathexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.PostfixexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.PredicateContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.PredicatelistContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.PrimaryexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.QuantifiedexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.RangeexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.RelativepathexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ReverseaxisContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ReversestepContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.SimpleforbindingContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.SimpleforclauseContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.SimpleletbindingContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.SimpleletclauseContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.SimplemapexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.StepexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.StringconcatexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.UnaryexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.UnionexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ValuecompContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ValueexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.VarnameContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.VarrefContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.WildcardContext; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.RuleContext; + +import java.util.function.Function; + +import edu.umd.cs.findbugs.annotations.NonNull; + +public abstract class AbstractAstVisitor // NOPMD + extends Metapath10BaseVisitor { + + /** + * This dispatch method will call the node handler on a leaf node or if multiple + * child expressions exist. Otherwise, it will delegate to the single child + * expression. + * + * @param + * the visitor context type + * @param ctx + * the visitor context + * @param handler + * the node handler + * @return the result + */ + protected R handle(T ctx, @NonNull Function handler) { + T context = ObjectUtils.requireNonNull(ctx); + + R retval; + if (context.getChildCount() == 1 && context.getChild(0) instanceof ParserRuleContext) { + // delegate to the child expression, since this expression doesn't require any + // action + retval = context.getChild(0).accept(this); + } else { + retval = handler.apply(context); + } + return retval; + } + + /** + * This dispatch method expects a single child expression which will be called. + * Other cases will result in an exception. + * + * @param + * the visitor context type + * @param ctx + * the visitor context + * @return the result + * @throws IllegalStateException + * if there was not a single child expression + */ + protected R delegateToChild(@NonNull T ctx) { + if (ctx.getChildCount() == 1) { + return ctx.getChild(0).accept(this); + } + throw new IllegalStateException("a single child expression was expected"); + } + + /* ============================================================ + * Expressions - https://www.w3.org/TR/xpath-31/#id-expressions + * ============================================================ + */ + + @Override + public R visitMetapath(MetapathContext ctx) { + assert ctx != null; + return delegateToChild(ctx); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleExpr(@NonNull ExprContext ctx); + + @Override + public R visitExpr(ExprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleExpr(ctx)); + } + + @Override + public R visitExprsingle(ExprsingleContext ctx) { + assert ctx != null; + return delegateToChild(ctx); + } + /* ============================================================================ + * Primary Expressions - https://www.w3.org/TR/xpath-31/#id-primary-expressions + * ============================================================================ + */ + + @Override + public R visitPrimaryexpr(PrimaryexprContext ctx) { + assert ctx != null; + return delegateToChild(ctx); + } + + /* ================================================================= + * Literal Expressions - https://www.w3.org/TR/xpath-31/#id-literals + * ================================================================= + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleStringLiteral(@NonNull LiteralContext ctx); + + @Override + public R visitLiteral(LiteralContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleStringLiteral(ctx)); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleNumericLiteral(@NonNull NumericliteralContext ctx); + + @Override + public R visitNumericliteral(NumericliteralContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleNumericLiteral(ctx)); + } + + /* ================================================================== + * Variable References - https://www.w3.org/TR/xpath-31/#id-variables + * ================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleVarref(@NonNull VarrefContext ctx); + + @Override + public R visitVarref(VarrefContext ctx) { + assert ctx != null; + return handleVarref(ctx); + } + + @Override + public R visitVarname(VarnameContext ctx) { + assert ctx != null; + return delegateToChild(ctx); + } + + /* ================================================================================= + * Parenthesized Expressions - https://www.w3.org/TR/xpath-31/#id-paren-expressions + * ================================================================================= + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleEmptyParenthesizedexpr(@NonNull ParenthesizedexprContext ctx); + + @Override + public R visitParenthesizedexpr(ParenthesizedexprContext ctx) { + assert ctx != null; + ExprContext expr = ctx.expr(); + return expr == null ? handleEmptyParenthesizedexpr(ctx) : visit(expr); + } + + /* ===================================================================================== + * Context Item Expression - https://www.w3.org/TR/xpath-31/#id-context-item-expression + * ===================================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleContextitemexpr(@NonNull ContextitemexprContext ctx); + + @Override + public R visitContextitemexpr(ContextitemexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleContextitemexpr(ctx)); + } + + /* ========================================================================= + * Static Function Calls - https://www.w3.org/TR/xpath-31/#id-function-calls + * ========================================================================= + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleFunctioncall(@NonNull FunctioncallContext ctx); + + @Override + public R visitFunctioncall(FunctioncallContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleFunctioncall(ctx)); + } + + @Override + public R visitArgumentlist(ArgumentlistContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } + + @Override + public R visitArgument(ArgumentContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } + + /* ========================================================================= + * Filter Expressions - https://www.w3.org/TR/xpath-31/#id-filter-expression + * ========================================================================= + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handlePostfixexpr(@NonNull PostfixexprContext ctx); + + @Override + public R visitPostfixexpr(PostfixexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handlePostfixexpr(ctx)); + } + + @Override + public R visitPredicate(PredicateContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } + + /* ====================================================================== + * Path Expressions - https://www.w3.org/TR/xpath-31/#id-path-expressions + * ====================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handlePathexpr(@NonNull PathexprContext ctx); + + @Override + public R visitPathexpr(PathexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handlePathexpr(ctx)); + } + + /* ======================================================================================= + * RelativePath Expressions - https://www.w3.org/TR/xpath-31/#id-relative-path-expressions + * ======================================================================================= + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleRelativepathexpr(@NonNull RelativepathexprContext ctx); + + @Override + public R visitRelativepathexpr(RelativepathexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleRelativepathexpr(ctx)); + } + + /* ================================================ + * Steps - https://www.w3.org/TR/xpath-31/#id-steps + * ================================================ + */ + + @Override + public R visitStepexpr(StepexprContext ctx) { + assert ctx != null; + return delegateToChild(ctx); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleForwardstep(@NonNull ForwardstepContext ctx); + + @Override + public R visitForwardstep(ForwardstepContext ctx) { + assert ctx != null; + // this will either call the handler or forward for AbbrevforwardstepContext + return handle(ctx, (context) -> handleForwardstep(ctx)); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleReversestep(@NonNull ReversestepContext ctx); + + @Override + public R visitReversestep(ReversestepContext ctx) { + assert ctx != null; + // this will either call the handler or forward for AbbrevreversestepContext + return handle(ctx, (context) -> handleReversestep(ctx)); + } + + /* ====================================================================== + * Predicates within Steps - https://www.w3.org/TR/xpath-31/#id-predicate + * ====================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleAxisstep(@NonNull AxisstepContext ctx); + + @Override + public R visitAxisstep(AxisstepContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleAxisstep(ctx)); + } + + @Override + public R visitPredicatelist(PredicatelistContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } + + /* =========================================== + * Axes - https://www.w3.org/TR/xpath-31/#axes + * =========================================== + */ + + @Override + public R visitForwardaxis(ForwardaxisContext ctx) { + // should never be called, since this is handled by handleForwardstep + throw new IllegalStateException(); + } + + @Override + public R visitReverseaxis(ReverseaxisContext ctx) { + // should never be called, since this is handled by handleReversestep + throw new IllegalStateException(); + } + + /* ======================================================= + * Node Tests - https://www.w3.org/TR/xpath-31/#node-tests + * ======================================================= + */ + + @Override + public R visitNodetest(NodetestContext ctx) { + // TODO: revisit once kindtest is implemented + assert ctx != null; + return delegateToChild(ctx); + } + + @Override + public R visitNametest(NametestContext ctx) { + assert ctx != null; + return delegateToChild(ctx); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleEqname(@NonNull EqnameContext ctx); + + @Override + public R visitEqname(EqnameContext ctx) { + assert ctx != null; + return handleEqname(ctx); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleWildcard(@NonNull WildcardContext ctx); + + @Override + public R visitWildcard(WildcardContext ctx) { + assert ctx != null; + return handleWildcard(ctx); + } + + /* =========================================================== + * Abbreviated Syntax - https://www.w3.org/TR/xpath-31/#abbrev + * =========================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleAbbrevforwardstep(@NonNull AbbrevforwardstepContext ctx); + + @Override + public R visitAbbrevforwardstep(AbbrevforwardstepContext ctx) { + assert ctx != null; + return handleAbbrevforwardstep(ctx); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleAbbrevreversestep(@NonNull AbbrevreversestepContext ctx); + + @Override + public R visitAbbrevreversestep(AbbrevreversestepContext ctx) { + assert ctx != null; + return handleAbbrevreversestep(ctx); + } + + /* ====================================================================== + * Constructing Sequences - https://www.w3.org/TR/xpath-31/#construct_seq + * ====================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleRangeexpr(@NonNull RangeexprContext ctx); + + @Override + public R visitRangeexpr(RangeexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleRangeexpr(ctx)); + } + + /* ======================================================================== + * Combining Node Sequences - https://www.w3.org/TR/xpath-31/#combining_seq + * ======================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleUnionexpr(@NonNull UnionexprContext ctx); + + @Override + public R visitUnionexpr(UnionexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleUnionexpr(ctx)); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleIntersectexceptexpr(@NonNull IntersectexceptexprContext ctx); + + @Override + public R visitIntersectexceptexpr(IntersectexceptexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleIntersectexceptexpr(ctx)); + } + + /* ====================================================================== + * Arithmetic Expressions - https://www.w3.org/TR/xpath-31/#id-arithmetic + * ====================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleAdditiveexpr(@NonNull AdditiveexprContext ctx); + + @Override + public R visitAdditiveexpr(AdditiveexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleAdditiveexpr(ctx)); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleMultiplicativeexpr(@NonNull MultiplicativeexprContext ctx); + + @Override + public R visitMultiplicativeexpr(MultiplicativeexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleMultiplicativeexpr(ctx)); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleUnaryexpr(@NonNull UnaryexprContext ctx); + + @Override + public R visitUnaryexpr(UnaryexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleUnaryexpr(ctx)); + } + + @Override + public R visitValueexpr(ValueexprContext ctx) { + assert ctx != null; + return delegateToChild(ctx); + } + + /* ======================================================================================== + * String Concatenation Expressions - https://www.w3.org/TR/xpath-31/#id-string-concat-expr + * ======================================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleStringconcatexpr(@NonNull StringconcatexprContext ctx); + + @Override + public R visitStringconcatexpr(StringconcatexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleStringconcatexpr(ctx)); + } + + /* ======================================================================= + * Comparison Expressions - https://www.w3.org/TR/xpath-31/#id-comparisons + * ======================================================================= + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleComparisonexpr(@NonNull ComparisonexprContext ctx); + + @Override + public R visitComparisonexpr(ComparisonexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleComparisonexpr(ctx)); + } + + @Override + public R visitValuecomp(ValuecompContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } + + @Override + public R visitGeneralcomp(GeneralcompContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } + + /* ============================================================================ + * Logical Expressions - https://www.w3.org/TR/xpath-31/#id-logical-expressions + * ============================================================================ + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleOrexpr(@NonNull OrexprContext ctx); + + @Override + public R visitOrexpr(OrexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleOrexpr(ctx)); + } + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleAndexpr(@NonNull AndexprContext ctx); + + @Override + public R visitAndexpr(AndexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleAndexpr(ctx)); + } + + /* ==================================================================== + * For Expressions - https://www.w3.org/TR/xpath-31/#id-for-expressions + * ==================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleForexpr(@NonNull ForexprContext ctx); + + @Override + public R visitForexpr(ForexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleForexpr(ctx)); + } + + @Override + public R visitSimpleforclause(SimpleforclauseContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } + + @Override + public R visitSimpleforbinding(SimpleforbindingContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } + + /* ==================================================================== + * Let Expressions - https://www.w3.org/TR/xpath-31/#id-let-expressions + * ==================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleLet(@NonNull LetexprContext ctx); + + @Override + public R visitLetexpr(LetexprContext ctx) { + assert ctx != null; + return handleLet(ctx); + } + + @Override + public R visitSimpleletclause(SimpleletclauseContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } + + @Override + public R visitSimpleletbinding(SimpleletbindingContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } + + /* ========================================================================= + * Conditional Expressions - https://www.w3.org/TR/xpath-31/#id-conditionals + * ========================================================================= + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleIfexpr(@NonNull IfexprContext ctx); + + @Override + public R visitIfexpr(IfexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleIfexpr(ctx)); + } + + /* ================================================================================== + * Quantified Expressions - https://www.w3.org/TR/xpath-31/#id-quantified-expressions + * ================================================================================== + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleQuantifiedexpr(@NonNull QuantifiedexprContext ctx); + + @Override + public R visitQuantifiedexpr(QuantifiedexprContext ctx) { + assert ctx != null; + return handleQuantifiedexpr(ctx); + } + + /* ========================================================================= + * Simple map operator (!) - https://www.w3.org/TR/xpath-31/#id-map-operator + * ========================================================================= + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleSimplemapexpr(@NonNull SimplemapexprContext ctx); + + @Override + public R visitSimplemapexpr(SimplemapexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleSimplemapexpr(ctx)); + } + + /* ======================================================================= + * Arrow operator (=>) - https://www.w3.org/TR/xpath-31/#id-arrow-operator + * ======================================================================= + */ + + /** + * Handle the provided expression. + * + * @param ctx + * the provided expression context + * @return the result + */ + protected abstract R handleArrowexpr(@NonNull ArrowexprContext ctx); + + @Override + public R visitArrowexpr(ArrowexprContext ctx) { + assert ctx != null; + return handle(ctx, (context) -> handleArrowexpr(ctx)); + } + + @Override + public R visitArrowfunctionspecifier(ArrowfunctionspecifierContext ctx) { + // should never be called, since this is handled by the parent expression + throw new IllegalStateException(); + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/FailingErrorListener.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/FailingErrorListener.java similarity index 96% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/FailingErrorListener.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/FailingErrorListener.java index c9f1be225..df7ea62a8 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/FailingErrorListener.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/FailingErrorListener.java @@ -24,14 +24,14 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.antlr; import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.RecognitionException; import org.antlr.v4.runtime.Recognizer; import org.antlr.v4.runtime.misc.ParseCancellationException; -class FailingErrorListener +public class FailingErrorListener extends BaseErrorListener { @Override public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/Metapath10ParserBase.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/Metapath10ParserBase.java new file mode 100644 index 000000000..f6c9ae823 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/Metapath10ParserBase.java @@ -0,0 +1,68 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.antlr; + +import org.antlr.v4.runtime.Parser; +import org.antlr.v4.runtime.TokenStream; + +public abstract class Metapath10ParserBase + extends Parser { + /** + * Construct a new parser base. + * + * @param input + * the input token stream + */ + protected Metapath10ParserBase(TokenStream input) { + super(input); + } + + /** + * Check if functional call name does not include a keyword. + * + * @return {@code true} if the function call name is free of keywords, or + * {@code false} otherwise + */ + protected boolean isFuncCall() { + return !(getInputStream().LA(1) == Metapath10.KW_ARRAY + || getInputStream().LA(1) == Metapath10.KW_ATTRIBUTE + || getInputStream().LA(1) == Metapath10.KW_COMMENT + || getInputStream().LA(1) == Metapath10.KW_DOCUMENT_NODE + || getInputStream().LA(1) == Metapath10.KW_ELEMENT + || getInputStream().LA(1) == Metapath10.KW_EMPTY_SEQUENCE + || getInputStream().LA(1) == Metapath10.KW_FUNCTION + || getInputStream().LA(1) == Metapath10.KW_IF + || getInputStream().LA(1) == Metapath10.KW_ITEM + || getInputStream().LA(1) == Metapath10.KW_MAP + || getInputStream().LA(1) == Metapath10.KW_NAMESPACE_NODE + || getInputStream().LA(1) == Metapath10.KW_NODE + || getInputStream().LA(1) == Metapath10.KW_PROCESSING_INSTRUCTION + || getInputStream().LA(1) == Metapath10.KW_SCHEMA_ATTRIBUTE + || getInputStream().LA(1) == Metapath10.KW_SCHEMA_ELEMENT + || getInputStream().LA(1) == Metapath10.KW_TEXT); + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/CSTPrinter.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/ParseTreePrinter.java similarity index 78% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/CSTPrinter.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/ParseTreePrinter.java index 10ad070a6..d689eac17 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/CSTPrinter.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/ParseTreePrinter.java @@ -24,22 +24,15 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; - -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser; -import gov.nist.secauto.metaschema.core.util.ObjectUtils; +package gov.nist.secauto.metaschema.core.metapath.antlr; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.RuleContext; import org.antlr.v4.runtime.tree.ParseTree; import java.io.PrintStream; -import java.util.List; - -import edu.umd.cs.findbugs.annotations.NonNull; -class CSTPrinter { - @NonNull +public class ParseTreePrinter { private final PrintStream outputStream; private boolean ignoringWrappers = true; @@ -49,8 +42,8 @@ class CSTPrinter { * @param outputStream * the stream to print to */ - public CSTPrinter(@NonNull PrintStream outputStream) { - this.outputStream = ObjectUtils.requireNonNull(outputStream, "outputStream"); + public ParseTreePrinter(PrintStream outputStream) { + this.outputStream = outputStream; } /** @@ -64,16 +57,6 @@ public void setIgnoringWrappers(boolean ignoringWrappers) { this.ignoringWrappers = ignoringWrappers; } - /** - * Print a given CST {@link RuleContext} node. - * - * @param ctx - * the CST node - */ - public void print(@NonNull RuleContext ctx) { - explore(ctx, 0); - } - /** * Print a given CST {@link ParseTree} using the provided {@code ruleNames}. * @@ -82,13 +65,15 @@ public void print(@NonNull RuleContext ctx) { * @param ruleNames * the list of rule names to use for human readability */ - public void print(ParseTree tree, List ruleNames) { - explore((RuleContext) tree.getPayload(), 0); + @SuppressWarnings("PMD.UseVarargs") + public void print(ParseTree tree, String[] ruleNames) { + explore((RuleContext) tree.getPayload(), 0, ruleNames); } - private void explore(RuleContext ctx, int indentation) { + @SuppressWarnings("PMD.UseVarargs") + private void explore(RuleContext ctx, int indentation, String[] ruleNames) { boolean toBeIgnored = ignoringWrappers && ctx.getChildCount() == 1 && ctx.getChild(0) instanceof ParserRuleContext; - String ruleName = metapath10Parser.ruleNames[ctx.getRuleIndex()]; + String ruleName = ruleNames[ctx.getRuleIndex()]; for (int i = 0; i < indentation; i++) { outputStream.print(" "); } @@ -103,7 +88,7 @@ private void explore(RuleContext ctx, int indentation) { for (int i = 0; i < ctx.getChildCount(); i++) { ParseTree element = ctx.getChild(i); if (element instanceof RuleContext) { - explore((RuleContext) element, indentation + 1); + explore((RuleContext) element, indentation + 1, ruleNames); } } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/package-info.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/package-info.java new file mode 100644 index 000000000..1fb9b99fb --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/package-info.java @@ -0,0 +1,27 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.antlr; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractBinaryExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractBinaryExpression.java similarity index 95% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractBinaryExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractBinaryExpression.java index 07818c82b..ade7b13fe 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractBinaryExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractBinaryExpression.java @@ -24,7 +24,7 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import java.util.List; import java.util.Objects; @@ -40,7 +40,7 @@ * @param * the type of the right expression */ -abstract class AbstractBinaryExpression +public abstract class AbstractBinaryExpression extends AbstractExpression { @NonNull private final L left; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractCSTVisitorBase.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractCSTVisitorBase.java new file mode 100644 index 000000000..637d24caf --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractCSTVisitorBase.java @@ -0,0 +1,295 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst; + +import gov.nist.secauto.metaschema.core.metapath.StaticContext; +import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException; +import gov.nist.secauto.metaschema.core.metapath.antlr.AbstractAstVisitor; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.EqnameContext; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.namespace.QName; + +import edu.umd.cs.findbugs.annotations.NonNull; + +public abstract class AbstractCSTVisitorBase + extends AbstractAstVisitor { + + private static final Pattern QUALIFIED_NAME_PATTERN = Pattern.compile("^Q\\{([^}]*)\\}(.+)$"); + + /** + * Get the QName for an + * expanded + * QName. + * + * @param eqname + * the expanded QName + * @param context + * the Metapath evaluation static context + * @param requireNamespace + * if {@code true} require the resulting QName to have a namespace, or + * {@code false} otherwise + * @return the QName + * @throws StaticMetapathException + * if the expanded QName prefix is not bound or if the resulting + * namespace is invalid + */ + @SuppressWarnings({ "PMD.CyclomaticComplexity", "PMD.CognitiveComplexity" }) + @NonNull + static QName toQName(@NonNull EqnameContext eqname, @NonNull StaticContext context, boolean requireNamespace) { + String namespaceUri; + String localName; + TerminalNode node; + if ((node = eqname.URIQualifiedName()) != null) { + // BracedURILiteral - Q{uri}name - + // https://www.w3.org/TR/xpath-31/#doc-xpath31-BracedURILiteral + Matcher matcher = QUALIFIED_NAME_PATTERN.matcher(node.getText()); + if (matcher.matches()) { + namespaceUri = matcher.group(1); + localName = matcher.group(2); + } else { + // the syntax should always match above, since ANTLR is parsing it + throw new IllegalStateException(); + } + } else { + String prefix; + String[] tokens = eqname.getText().split(":", 2); + if (tokens.length == 2) { + // lexical QName with prefix - prefix:name + // https://www.w3.org/TR/xpath-31/#dt-qname + prefix = ObjectUtils.notNull(tokens[0]); + localName = tokens[1]; + } else { + // lexical QName without prefix - name + // https://www.w3.org/TR/xpath-31/#dt-qname + prefix = ""; + localName = tokens[0]; + } + namespaceUri = context.lookupNamespaceForPrefix(prefix); + if (namespaceUri == null && requireNamespace) { + throw new StaticMetapathException( + StaticMetapathException.PREFIX_NOT_EXPANDABLE, + String.format("The static context does not have a namespace URI configured for prefix '%s'.", prefix)); + } + } + + QName retval; + if (namespaceUri == null) { + retval = new QName(localName); + } else { + if ("http://www.w3.org/2000/xmlns/".equals(namespaceUri)) { + throw new StaticMetapathException(StaticMetapathException.NAMESPACE_MISUSE, + "The namespace of an expanded QName cannot be: http://www.w3.org/2000/xmlns/"); + } + retval = new QName(namespaceUri, localName); + } + return retval; + } + + @SuppressWarnings("null") + @Override + @NonNull + public IExpression visit(ParseTree tree) { + assert tree != null; + return super.visit(tree); + } + + /** + * Parse the provided context as an n-ary phrase, which will be one of the + * following. + *
    + *
  1. A single expr for which that expr will be returned
  2. + *
  3. left (operator right)* for which a collection of the left + * and right members will be returned based on what is provided by the + * supplier.
  4. + *
+ * + * @param + * the context type to parse + * @param + * the type of expression + * @param context + * the context instance + * @param supplier + * a supplier that will instantiate an expression based on the provided + * parsed collection + * @return the left expression or the supplied expression for a collection + */ + @NonNull + protected IExpression + handleNAiryCollection( + @NonNull CONTEXT context, + @NonNull Function, IExpression> supplier) { + return handleNAiryCollection(context, 1, 2, (ctx, idx) -> { + // skip operator, since we know what it is + ParseTree tree = ctx.getChild(idx + 1); + @SuppressWarnings({ "unchecked", "null" }) + @NonNull NODE node = (NODE) tree.accept(this); + return node; + }, supplier); + } + + /** + * Parse the provided context as an n-ary phrase, which will be one of the + * following. + *
    + *
  1. expr for which the expr will be returned.
  2. + *
  3. left plus a number of additional recurring tokens as defined + * by the step.
  4. + *
+ *

+ * In the second case, the supplier will be used to generate an expression from + * the collection of tuples. + * + * @param + * the context type to parse + * @param + * the child expression type + * @param context + * the context instance + * @param startIndex + * the starting context child position + * @param step + * the amount to advance the loop over the context children + * @param parser + * a binary function used to parse the context children + * @param supplier + * a supplier that will instantiate an expression based on the provided + * collection + * @return the left expression or the supplied expression for a collection + */ + @NonNull + protected IExpression + handleNAiryCollection( + @NonNull CONTEXT context, + int startIndex, + int step, + @NonNull BiFunction parser, + @NonNull Function, IExpression> supplier) { + int numChildren = context.getChildCount(); + + if (numChildren == 0) { + throw new IllegalStateException("there should always be a child expression"); + } else if (startIndex > numChildren) { + throw new IllegalStateException("Start index is out of bounds"); + } + + ParseTree leftTree = context.getChild(0); + @SuppressWarnings({ "unchecked", "null" }) + @NonNull EXPRESSION leftResult = (EXPRESSION) leftTree.accept(this); + + IExpression retval; + if (numChildren == 1) { + retval = leftResult; + } else { + List children = new ArrayList<>(numChildren - 1 / step); + children.add(leftResult); + for (int i = startIndex; i < numChildren; i = i + step) { + EXPRESSION result = parser.apply(context, i); + children.add(result); + } + IExpression result = ObjectUtils.notNull(supplier.apply(children)); + retval = result; + } + return retval; + } + + /** + * Parse the provided context as a simple n-ary phrase, which will be one of the + * following. + *

    + *
  1. expr for which the expr will be returned
  2. + *
  3. left (operator right)* for which a collection of the left + * and right members will be returned based on what is provided by the supplier. + *
+ *

+ * In the second case, the supplier will be used to generate an expression from + * the collection of tuples. + * + * @param + * the context type to parse + * @param context + * the context instance + * @param startingIndex + * the index of the first child expression, which must be a + * non-negative value that is less than the number of children + * @param step + * the amount to advance the loop over the context children + * @param parser + * a trinary function used to parse the context children and supply a + * result + * @return the left expression or the supplied expression + */ + protected IExpression handleGroupedNAiry( + @NonNull CONTEXT context, + int startingIndex, + int step, + @NonNull ITriFunction parser) { + int numChildren = context.getChildCount(); + if (startingIndex >= numChildren) { + throw new IndexOutOfBoundsException( + String.format("The starting index '%d' exceeds the child count '%d'", + startingIndex, + numChildren)); + } + + IExpression retval = null; + if (numChildren > 0) { + ParseTree leftTree = context.getChild(startingIndex); + IExpression result = ObjectUtils.notNull(leftTree.accept(this)); + + for (int i = startingIndex + 1; i < numChildren; i = i + step) { + result = parser.apply(context, i, result); + } + retval = result; + } + return retval; + } + + @FunctionalInterface + interface ITriFunction { + + R apply(T argT, U argU, V argV); + + default ITriFunction andThen(Function after) { + Objects.requireNonNull(after); + return (T t, U u, V v) -> after.apply(apply(t, u, v)); + } + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java similarity index 91% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java index 0e7b3c78a..967b413c2 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpression.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.TypeMetapathException; import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; import gov.nist.secauto.metaschema.core.metapath.item.IItem; @@ -34,7 +36,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -abstract class AbstractExpression implements IExpression { +public abstract class AbstractExpression implements IExpression { /** * Get the first data item of the provided {@code sequence} cast to an * {@link IAnyAtomicItem}. @@ -59,6 +61,6 @@ public static IAnyAtomicItem getFirstDataItem(@NonNull ISequence sequence, @Override public String toString() { - return ASTPrinter.instance().visit(this); + return CSTPrinter.toString(this); } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractExpressionVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpressionVisitor.java similarity index 82% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractExpressionVisitor.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpressionVisitor.java index 98f04a26c..0d128a059 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractExpressionVisitor.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpressionVisitor.java @@ -24,7 +24,25 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; + +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.GeneralComparison; +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.ValueComparison; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Addition; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Division; +import gov.nist.secauto.metaschema.core.metapath.cst.math.IntegerDivision; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Modulo; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Multiplication; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Subtraction; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Axis; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Flag; +import gov.nist.secauto.metaschema.core.metapath.cst.path.ModelInstance; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RelativeDoubleSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RelativeSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootDoubleSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootSlashOnlyPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Step; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; @@ -39,7 +57,7 @@ * additional state to pass between nodes visited */ @SuppressWarnings("PMD.CouplingBetweenObjects") -abstract class AbstractExpressionVisitor implements IExpressionVisitor { +public abstract class AbstractExpressionVisitor implements IExpressionVisitor { /** * This dispatch method will visit the provided {@code expression}. @@ -302,4 +320,24 @@ public RESULT visitLet(Let expr, CONTEXT context) { public RESULT visitVariableReference(VariableReference expr, CONTEXT context) { return visitChildren(expr, context); } + + @Override + public RESULT visitEmptySequence(EmptySequence expr, CONTEXT context) { + return defaultResult(); + } + + @Override + public RESULT visitRange(Range expr, CONTEXT context) { + return visitChildren(expr, context); + } + + @Override + public RESULT visitIf(If expr, CONTEXT context) { + return visitChildren(expr, context); + } + + @Override + public RESULT visitQuantified(Quantified expr, CONTEXT context) { + return visitChildren(expr, context); + } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractFilterExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractFilterExpression.java similarity index 90% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractFilterExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractFilterExpression.java index 907fe2cd0..0408ab3ed 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractFilterExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractFilterExpression.java @@ -24,15 +24,22 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import java.util.List; import edu.umd.cs.findbugs.annotations.NonNull; -abstract class AbstractFilterExpression +/** + * An abstract CST node for a Metapath + * filtering + * expression. + */ +public abstract class AbstractFilterExpression extends AbstractBinaryExpression { @NonNull diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractLiteralExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractLiteralExpression.java similarity index 94% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractLiteralExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractLiteralExpression.java index 975ce6e13..e4a3bfb19 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractLiteralExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractLiteralExpression.java @@ -24,13 +24,13 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import edu.umd.cs.findbugs.annotations.NonNull; -abstract class AbstractLiteralExpression +public abstract class AbstractLiteralExpression extends AbstractExpression implements ILiteralExpression { @NonNull diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractNAryExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractNAryExpression.java similarity index 95% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractNAryExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractNAryExpression.java index f31d82aab..af53767cd 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractNAryExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractNAryExpression.java @@ -24,7 +24,7 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import java.util.List; import java.util.Objects; @@ -34,7 +34,7 @@ /** * An immutable expression that has a number of sub-expression children. */ -abstract class AbstractNAryExpression +public abstract class AbstractNAryExpression extends AbstractExpression { @NonNull private final List children; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractNamedInstanceExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractNamedInstanceExpression.java similarity index 91% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractNamedInstanceExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractNamedInstanceExpression.java index 33703bc34..69d79049f 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractNamedInstanceExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractNamedInstanceExpression.java @@ -24,15 +24,16 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.cst.path.AbstractPathExpression; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import java.util.List; import edu.umd.cs.findbugs.annotations.NonNull; -abstract class AbstractNamedInstanceExpression +public abstract class AbstractNamedInstanceExpression extends AbstractPathExpression { @NonNull private final IExpression test; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractUnaryExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractUnaryExpression.java similarity index 96% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractUnaryExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractUnaryExpression.java index 0f8356a93..b7072ff27 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractUnaryExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractUnaryExpression.java @@ -24,7 +24,7 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import java.util.List; import java.util.Objects; @@ -34,7 +34,7 @@ /** * An immutable expression with a single sub-expression. */ -abstract class AbstractUnaryExpression +public abstract class AbstractUnaryExpression extends AbstractExpression { @NonNull private final IExpression expr; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/And.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/And.java similarity index 73% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/And.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/And.java index b6b0fd491..4b65e3554 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/And.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/And.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.function.library.FnBoolean; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem; @@ -33,20 +35,32 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class And // NOPMD - intentional name +/** + * An implementation of + * And + * expression supporting conditional evaluation. + *

+ * Determines the logical conjunction of the result of evaluating a list of + * expressions. The boolean result of each expression is determined by applying + * {@link FnBoolean#fnBooleanAsPrimitive(ISequence)} to each function's + * {@link ISequence} result. + *

+ * This implementation will short-circuit and return {@code false} when the + * first expression evaluates to {@code false}, otherwise it will return + * {@code true}. + */ +public class And // NOPMD - intentional name extends AbstractNAryExpression implements IBooleanLogicExpression { /** - * Determines the logical conjunction of the result of evaluating a list of - * expressions. The boolean result of each expression is determined by applying - * {@link FnBoolean#fnBooleanAsPrimitive(ISequence)} to each function's - * {@link ISequence} result. + * Construct a new "and" logical expression. * * @param expressions - * the list of expressions + * the expressions to evaluate + * */ - protected And(@NonNull List expressions) { + public And(@NonNull List expressions) { super(expressions); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/BuildAstVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java similarity index 50% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/BuildAstVisitor.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java index fadd91706..63438a074 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/BuildAstVisitor.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildCSTVisitor.java @@ -24,47 +24,69 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; - -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Lexer; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.AbbrevforwardstepContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.AbbrevreversestepContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.AdditiveexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.AndexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ArgumentlistContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ArrowexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.AxisstepContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ComparisonexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ContextitemexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.EqnameContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ExprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ForwardstepContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.FunctioncallContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.GeneralcompContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.IntersectexceptexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.LetexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.LiteralContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.MultiplicativeexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.NumericliteralContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.OrexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.PathexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.PostfixexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.PredicateContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.RelativepathexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ReversestepContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.SimpleletbindingContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.SimpleletclauseContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.StringconcatexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.UnaryexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.UnionexprContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.ValuecompContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.VarrefContext; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser.WildcardContext; +package gov.nist.secauto.metaschema.core.metapath.cst; + +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.AbbrevforwardstepContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.AbbrevreversestepContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.AdditiveexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.AndexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ArgumentlistContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ArrowexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.AxisstepContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ComparisonexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ContextitemexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.EqnameContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ExprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ForexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ForwardstepContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.FunctioncallContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.GeneralcompContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.IfexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.IntersectexceptexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.LetexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.LiteralContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.MultiplicativeexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.NumericliteralContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.OrexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ParenthesizedexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.PathexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.PostfixexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.PredicateContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.QuantifiedexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.RangeexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.RelativepathexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ReversestepContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.SimpleletbindingContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.SimpleletclauseContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.SimplemapexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.StringconcatexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.UnaryexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.UnionexprContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ValuecompContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.VarrefContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.WildcardContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10Lexer; +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.GeneralComparison; +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.ValueComparison; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Addition; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Division; +import gov.nist.secauto.metaschema.core.metapath.cst.math.IntegerDivision; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Modulo; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Multiplication; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Subtraction; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Axis; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Flag; +import gov.nist.secauto.metaschema.core.metapath.cst.path.ModelInstance; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RelativeDoubleSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RelativeSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootDoubleSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootSlashOnlyPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Step; import gov.nist.secauto.metaschema.core.metapath.function.ComparisonFunctions; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; -import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; @@ -72,296 +94,268 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; import java.util.ListIterator; -import java.util.Objects; -import java.util.function.BiFunction; -import java.util.function.Function; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; import edu.umd.cs.findbugs.annotations.NonNull; -@SuppressWarnings("PMD.CouplingBetweenObjects") -class BuildAstVisitor // NOPMD - this visitor has many methods - extends AbstractAstVisitor { +/** + * Supports converting a Metapath abstract syntax tree (AST) generated by + * ANTLRv4 into a compact syntax tree + * (CST). + */ +@SuppressWarnings({ "PMD.GodClass", "PMD.CyclomaticComplexity" }) // acceptable complexity +public class BuildCSTVisitor + extends AbstractCSTVisitorBase { + + /* ============================================================ + * Expressions - https://www.w3.org/TR/xpath-31/#id-expressions + * ============================================================ + */ - @SuppressWarnings("null") @Override - @NonNull - public IExpression visit(ParseTree tree) { - return super.visit(tree); + protected IExpression handleExpr(ExprContext ctx) { + return handleNAiryCollection(ctx, children -> { + assert children != null; + return new Metapath(children); + }); } - // TODO: verify javadocs are accurate for the following n-ary functions. + /* ================================================================= + * Literal Expressions - https://www.w3.org/TR/xpath-31/#id-literals + * ================================================================= + */ - /** - * Parse the provided context as a simple n-ary phrase, which will be one of the - * following. - *

    - *
  1. expr for which the expr will be returned
  2. - *
  3. left (operator right)* for which a collection of the left - * and right members will be returned based on what is provided by the supplier. - *
- * - * @param - * the context type to parse - * @param - * the type of expression - * @param context - * the context instance - * @param supplier - * a supplier that will instantiate an expression based on the provided - * collection - * @return the left expression or the supplied expression for a collection + @Override + protected IExpression handleStringLiteral(LiteralContext ctx) { + ParseTree tree = ctx.getChild(0); + return new StringLiteral(ObjectUtils.notNull(tree.getText())); + } + + @Override + protected IExpression handleNumericLiteral(NumericliteralContext ctx) { + ParseTree tree = ctx.getChild(0); + Token token = (Token) tree.getPayload(); + IExpression retval; + switch (token.getType()) { + case Metapath10Lexer.IntegerLiteral: + retval = new IntegerLiteral(new BigInteger(token.getText())); + break; + case Metapath10Lexer.DecimalLiteral: + case Metapath10Lexer.DoubleLiteral: + retval = new DecimalLiteral(new BigDecimal(token.getText())); + break; + default: + throw new UnsupportedOperationException(token.getText()); + } + return retval; + } + + /* ================================================================== + * Variable References - https://www.w3.org/TR/xpath-31/#id-variables + * ================================================================== */ - @NonNull - protected IExpression - handleNAiryCollection( - @NonNull CONTEXT context, - @NonNull Function, IExpression> supplier) { - return handleNAiryCollection(context, 1, 2, (ctx, idx) -> { - // skip operator, since we know what it is - ParseTree tree = ctx.getChild(idx + 1); - @SuppressWarnings({ "unchecked", "null" }) - @NonNull NODE node = (NODE) tree.accept(this); - return node; - }, supplier); + + @Override + protected IExpression handleVarref(VarrefContext ctx) { + Name varName = (Name) ctx.varname().accept(this); + assert varName != null; + return new VariableReference(varName); + } + + /* ================================================================================= + * Parenthesized Expressions - https://www.w3.org/TR/xpath-31/#id-paren-expressions + * ================================================================================= + */ + + @Override + protected IExpression handleEmptyParenthesizedexpr(ParenthesizedexprContext ctx) { + return EmptySequence.instance(); + } + + /* ===================================================================================== + * Context Item Expression - https://www.w3.org/TR/xpath-31/#id-context-item-expression + * ===================================================================================== + */ + + @Override + protected IExpression handleContextitemexpr(ContextitemexprContext ctx) { + return ContextItem.instance(); } + /* ========================================================================= + * Static Function Calls - https://www.w3.org/TR/xpath-31/#id-function-calls + * ========================================================================= + */ + /** - * Parse the provided context as a simple n-ary phrase, which will be one of the - * following. - *
    - *
  1. expr for which the expr will be returned
  2. - *
  3. left (operator right)* for which a collection of the left - * and right members will be returned based on what is provided by the supplier. - *
+ * Parse a list of arguments. * - * @param - * the context type to parse - * @param - * the child expression type * @param context - * the context instance - * @param startIndex - * the starting context child position - * @param step - * the amount to advance the loop over the context children - * @param parser - * a binary function used to parse the context children - * @param supplier - * a supplier that will instantiate an expression based on the provided - * collection - * @return the left expression or the supplied expression for a collection + * the argument list AST + * @return a stream of CST expressions for each argument, in the original + * argument order */ @NonNull - protected IExpression - handleNAiryCollection( - @NonNull CONTEXT context, - int startIndex, - int step, - @NonNull BiFunction parser, - @NonNull Function, IExpression> supplier) { + protected Stream parseArgumentList(@NonNull ArgumentlistContext context) { int numChildren = context.getChildCount(); - if (numChildren == 0) { - throw new IllegalStateException("there should always be a child expression"); - } else if (startIndex > numChildren) { - throw new IllegalStateException("Start index is out of bounds"); - } - - ParseTree leftTree = context.getChild(0); - @SuppressWarnings({ "unchecked", "null" }) - @NonNull EXPRESSION leftResult = (EXPRESSION) leftTree.accept(this); - - IExpression retval; - if (numChildren == 1) { - retval = leftResult; + Stream retval; + if (numChildren == 2) { + // just the OP CP tokens, which is an empty list + retval = Stream.empty(); } else { - List children = new ArrayList<>(numChildren - 1 / step); - children.add(leftResult); - for (int i = startIndex; i < numChildren; i = i + step) { - EXPRESSION result = parser.apply(context, i); - children.add(result); - } - IExpression result = ObjectUtils.notNull(supplier.apply(children)); - retval = result; + retval = context.argument().stream() + .map(argument -> { + return argument.exprsingle().accept(this); + }); } + assert retval != null; + return retval; } + @Override + protected IExpression handleFunctioncall(FunctioncallContext ctx) { + EqnameContext nameCtx = ctx.eqname(); + String name = nameCtx.getText(); + + assert name != null; + + return new FunctionCall( + name, + ObjectUtils.notNull(parseArgumentList(ObjectUtils.notNull(ctx.argumentlist())) + .collect(Collectors.toUnmodifiableList()))); + } + + /* ========================================================================= + * Filter Expressions - https://www.w3.org/TR/xpath-31/#id-filter-expression + * ========================================================================= + */ + + /** + * Parse a predicate AST. + * + * @param predicate + * the predicate expression + * @return the CST expression generated for the predicate + */ + @NonNull + protected IExpression parsePredicate(@NonNull PredicateContext predicate) { + // the expression is always the second child + return visit(predicate.getChild(1)); + } + /** - * Parse the provided context as a simple n-ary phrase, which will be one of the - * following. - *
    - *
  1. expr for which the expr will be returned
  2. - *
  3. left (operator right)* for which a collection of the left - * and right members will be returned based on what is provided by the supplier. - *
+ * Parse a series of predicate ASTs. * - * @param - * the context type to parse * @param context - * the context instance - * @param startingIndex - * the index of the first child expression, which must be a - * non-negative value that is less than the number of children - * @param step - * the amount to advance the loop over the context children - * @param parser - * a trinary function used to parse the context children and supply a - * result - * @return the left expression or the supplied expression + * the parse tree node containing the predicates + * @param staringChild + * the first child node corresponding to a predicate + * @return the list of CST predicate expressions in the same order as the + * original predicate list */ - protected IExpression handleGroupedNAiry( - @NonNull CONTEXT context, - int startingIndex, - int step, - @NonNull ITriFunction parser) { + @NonNull + protected List parsePredicates(@NonNull ParseTree context, int staringChild) { int numChildren = context.getChildCount(); - if (startingIndex >= numChildren) { - throw new IndexOutOfBoundsException( - String.format("The starting index '%d' exceeds the child count '%d'", - startingIndex, - numChildren)); - } - - IExpression retval = null; - if (numChildren > 0) { - ParseTree leftTree = context.getChild(startingIndex); - IExpression result = ObjectUtils.notNull(leftTree.accept(this)); + int numPredicates = numChildren - staringChild; - for (int i = startingIndex + 1; i < numChildren; i = i + step) { - result = parser.apply(context, i, result); + List predicates; + if (numPredicates == 0) { + // no predicates + predicates = CollectionUtil.emptyList(); + } else if (numPredicates == 1) { + // single predicate + PredicateContext predicate = ObjectUtils.notNull((PredicateContext) context.getChild(staringChild)); + predicates = CollectionUtil.singletonList(parsePredicate(predicate)); + } else { + // multiple predicates + predicates = new ArrayList<>(numPredicates); + for (int i = staringChild; i < numChildren; i++) { + PredicateContext predicate = ObjectUtils.notNull((PredicateContext) context.getChild(i)); + predicates.add(parsePredicate(predicate)); } - retval = result; } - return retval; + return predicates; } @Override - protected IExpression handleExpr(ExprContext ctx) { - return handleNAiryCollection(ctx, children -> { - assert children != null; - return new Metapath(children); - }); - } + protected IExpression handlePostfixexpr(PostfixexprContext ctx) { + int numChildren = ctx.getChildCount(); + ParseTree primaryTree = ctx.getChild(0); + IExpression retval = ObjectUtils.notNull(primaryTree.accept(this)); - @Override - protected IExpression handleOrexpr(OrexprContext ctx) { - return handleNAiryCollection(ctx, children -> { - assert children != null; - return new Or(children); - }); - } + List predicates = numChildren > 1 ? parsePredicates(ctx, 1) : CollectionUtil.emptyList(); - @Override - protected IExpression handleAndexpr(AndexprContext ctx) { - return handleNAiryCollection(ctx, children -> { - assert children != null; - return new And(children); - }); + if (!predicates.isEmpty()) { + retval = new Predicate(retval, predicates); + } + return retval; } + /* ====================================================================== + * Path Expressions - https://www.w3.org/TR/xpath-31/#id-path-expressions + * ====================================================================== + */ @Override - protected IExpression handleComparisonexpr(ComparisonexprContext ctx) { // NOPMD - ok - assert ctx.getChildCount() == 3; - - IExpression left = visit(ctx.getChild(0)); - IExpression right = visit(ctx.getChild(2)); - - // the operator - ParseTree operatorTree = ctx.getChild(1); - Object payload = operatorTree.getPayload(); + protected IExpression handlePathexpr(PathexprContext ctx) { + int numChildren = ctx.getChildCount(); - ComparisonFunctions.Operator operator; - IBooleanLogicExpression retval; - if (payload instanceof GeneralcompContext) { - GeneralcompContext compContext = (GeneralcompContext) payload; - int type = ((TerminalNode) compContext.getChild(0)).getSymbol().getType(); - switch (type) { - case metapath10Lexer.EQ: - operator = ComparisonFunctions.Operator.EQ; - break; - case metapath10Lexer.NE: - operator = ComparisonFunctions.Operator.NE; - break; - case metapath10Lexer.LT: - operator = ComparisonFunctions.Operator.LT; - break; - case metapath10Lexer.LE: - operator = ComparisonFunctions.Operator.LE; - break; - case metapath10Lexer.GT: - operator = ComparisonFunctions.Operator.GT; - break; - case metapath10Lexer.GE: - operator = ComparisonFunctions.Operator.GE; - break; - default: - throw new UnsupportedOperationException(((TerminalNode) compContext.getChild(0)).getSymbol().getText()); - } - retval = new GeneralComparison(left, operator, right); - } else if (payload instanceof ValuecompContext) { - ValuecompContext compContext = (ValuecompContext) payload; - int type = ((TerminalNode) compContext.getChild(0)).getSymbol().getType(); + IExpression retval; + ParseTree tree = ctx.getChild(0); + if (tree instanceof TerminalNode) { + int type = ((TerminalNode) tree).getSymbol().getType(); switch (type) { - case metapath10Lexer.KW_EQ: - operator = ComparisonFunctions.Operator.EQ; - break; - case metapath10Lexer.KW_NE: - operator = ComparisonFunctions.Operator.NE; - break; - case metapath10Lexer.KW_LT: - operator = ComparisonFunctions.Operator.LT; - break; - case metapath10Lexer.KW_LE: - operator = ComparisonFunctions.Operator.LE; - break; - case metapath10Lexer.KW_GT: - operator = ComparisonFunctions.Operator.GT; + case Metapath10Lexer.SLASH: + // a slash expression with optional path + if (numChildren == 2) { + // the optional path + retval = new RootSlashPath(visit(ctx.getChild(1))); + } else { + retval = new RootSlashOnlyPath(); + } break; - case metapath10Lexer.KW_GE: - operator = ComparisonFunctions.Operator.GE; + case Metapath10Lexer.SS: + // a double slash expression with path + retval = new RootDoubleSlashPath(visit(ctx.getChild(1))); break; default: - throw new UnsupportedOperationException(((TerminalNode) compContext.getChild(0)).getSymbol().getText()); + throw new UnsupportedOperationException(((TerminalNode) tree).getSymbol().getText()); } - retval = new ValueComparison(left, operator, right); } else { - throw new UnsupportedOperationException(); + // a relative expression or something else + retval = visit(tree); } return retval; } - @Override - protected IExpression handleStringconcatexpr(StringconcatexprContext ctx) { - return handleNAiryCollection(ctx, children -> { - assert children != null; - return new StringConcat(children); - }); - } + /* ======================================================================================= + * RelativePath Expressions - https://www.w3.org/TR/xpath-31/#id-relative-path-expressions + * ======================================================================================= + */ @Override - protected IExpression handleAdditiveexpr(AdditiveexprContext context) { + protected IExpression handleRelativepathexpr(RelativepathexprContext context) { return handleGroupedNAiry(context, 0, 2, (ctx, idx, left) -> { - ParseTree operatorTree = ctx.getChild(idx); - ParseTree rightTree = ctx.getChild(idx + 1); - IExpression right = rightTree.accept(this); - assert left != null; - assert right != null; + + ParseTree operatorTree = ctx.getChild(idx); + IExpression right = visit(ctx.getChild(idx + 1)); int type = ((TerminalNode) operatorTree).getSymbol().getType(); IExpression retval; switch (type) { - case metapath10Lexer.PLUS: - retval = new Addition(left, right); + case Metapath10Lexer.SLASH: + retval = new RelativeSlashPath(left, right); break; - case metapath10Lexer.MINUS: - retval = new Subtraction(left, right); + case Metapath10Lexer.SS: + retval = new RelativeDoubleSlashPath(left, right); break; default: throw new UnsupportedOperationException(((TerminalNode) operatorTree).getSymbol().getText()); @@ -370,37 +364,139 @@ protected IExpression handleAdditiveexpr(AdditiveexprContext context) { }); } - @Override - protected IExpression handleMultiplicativeexpr(MultiplicativeexprContext context) { - return handleGroupedNAiry(context, 0, 2, (ctx, idx, left) -> { - ParseTree operatorTree = ctx.getChild(idx); - ParseTree rightTree = ctx.getChild(idx + 1); - IExpression right = rightTree.accept(this); + /* ================================================ + * Steps - https://www.w3.org/TR/xpath-31/#id-steps + * ================================================ + */ - assert left != null; - assert right != null; + @Override + protected IExpression handleForwardstep(ForwardstepContext ctx) { + assert ctx.getChildCount() == 2; - int type = ((TerminalNode) operatorTree).getSymbol().getType(); - IExpression retval; - switch (type) { - case metapath10Lexer.STAR: - retval = new Multiplication(left, right); - break; - case metapath10Lexer.KW_DIV: - retval = new Division(left, right); - break; - case metapath10Lexer.KW_IDIV: - retval = new IntegerDivision(left, right); - break; - case metapath10Lexer.KW_MOD: - retval = new Modulo(left, right); - break; - default: - throw new UnsupportedOperationException(((TerminalNode) operatorTree).getSymbol().getText()); - } - return retval; - }); - } + Token token = (Token) ctx.forwardaxis().getChild(0).getPayload(); + + Axis axis; + switch (token.getType()) { + case Metapath10Lexer.KW_SELF: + axis = Axis.SELF; + break; + case Metapath10Lexer.KW_CHILD: + axis = Axis.CHILDREN; + break; + case Metapath10Lexer.KW_DESCENDANT: + axis = Axis.DESCENDANT; + break; + case Metapath10Lexer.KW_DESCENDANT_OR_SELF: + axis = Axis.DESCENDANT_OR_SELF; + break; + default: + throw new UnsupportedOperationException(token.getText()); + } + return new Step(axis, visit(ctx.nametest())); + } + + @Override + protected IExpression handleReversestep(ReversestepContext ctx) { + assert ctx.getChildCount() == 2; + + Token token = (Token) ctx.reverseaxis().getChild(0).getPayload(); + + Axis axis; + switch (token.getType()) { + case Metapath10Lexer.KW_PARENT: + axis = Axis.PARENT; + break; + case Metapath10Lexer.KW_ANCESTOR: + axis = Axis.ANCESTOR; + break; + case Metapath10Lexer.KW_ANCESTOR_OR_SELF: + axis = Axis.ANCESTOR_OR_SELF; + break; + default: + throw new UnsupportedOperationException(token.getText()); + } + return new Step(axis, visit(ctx.nametest())); + } + + /* ====================================================================== + * Predicates within Steps - https://www.w3.org/TR/xpath-31/#id-predicate + * ====================================================================== + */ + + @Override + protected IExpression handleAxisstep(AxisstepContext ctx) { + IExpression step = visit(ctx.getChild(0)); + ParseTree predicateTree = ctx.getChild(1); + assert predicateTree != null; + + List predicates = parsePredicates(predicateTree, 0); + + return predicates.isEmpty() ? step : new Predicate(step, predicates); + } + + /* ======================================================= + * Node Tests - https://www.w3.org/TR/xpath-31/#node-tests + * ======================================================= + */ + + @Override + protected IExpression handleEqname(EqnameContext ctx) { + ParseTree tree = ctx.getChild(0); + String name = ((TerminalNode) tree).getText(); + + assert name != null; + + return new Name(name); + } + + @Override + protected IExpression handleWildcard(WildcardContext ctx) { + return new Wildcard(); + } + + /* =========================================================== + * Abbreviated Syntax - https://www.w3.org/TR/xpath-31/#abbrev + * =========================================================== + */ + + @Override + protected IExpression handleAbbrevforwardstep(AbbrevforwardstepContext ctx) { + int numChildren = ctx.getChildCount(); + + IExpression retval; + if (numChildren == 1) { + retval = new ModelInstance(visit(ctx.getChild(0))); + } else { + // this is an AT test + retval = new Flag(visit(ctx.getChild(1))); + } + return retval; + } + + @Override + protected IExpression handleAbbrevreversestep(AbbrevreversestepContext ctx) { + return Axis.PARENT; + } + + /* ====================================================================== + * Constructing Sequences - https://www.w3.org/TR/xpath-31/#construct_seq + * ====================================================================== + */ + + @Override + protected IExpression handleRangeexpr(RangeexprContext ctx) { + assert ctx.getChildCount() == 3; + + IExpression left = visit(ctx.getChild(0)); + IExpression right = visit(ctx.getChild(2)); + + return new Range(left, right); + } + + /* ======================================================================== + * Combining Node Sequences - https://www.w3.org/TR/xpath-31/#combining_seq + * ======================================================================== + */ @Override protected IExpression handleUnionexpr(UnionexprContext ctx) { @@ -412,6 +508,36 @@ protected IExpression handleUnionexpr(UnionexprContext ctx) { @Override protected IExpression handleIntersectexceptexpr(IntersectexceptexprContext context) { + return handleGroupedNAiry(context, 0, 2, (ctx, idx, left) -> { + assert left != null; + + ParseTree operatorTree = ctx.getChild(idx); + IExpression right = visit(ctx.getChild(idx + 1)); + + int type = ((TerminalNode) operatorTree).getSymbol().getType(); + + IExpression retval; + switch (type) { + case Metapath10Lexer.KW_INTERSECT: + retval = new Intersect(left, right); + break; + case Metapath10Lexer.KW_EXCEPT: + retval = new Except(left, right); + break; + default: + throw new UnsupportedOperationException(((TerminalNode) operatorTree).getSymbol().getText()); + } + return retval; + }); + } + + /* ====================================================================== + * Arithmetic Expressions - https://www.w3.org/TR/xpath-31/#id-arithmetic + * ====================================================================== + */ + + @Override + protected IExpression handleAdditiveexpr(AdditiveexprContext context) { return handleGroupedNAiry(context, 0, 2, (ctx, idx, left) -> { ParseTree operatorTree = ctx.getChild(idx); ParseTree rightTree = ctx.getChild(idx + 1); @@ -424,11 +550,11 @@ protected IExpression handleIntersectexceptexpr(IntersectexceptexprContext conte IExpression retval; switch (type) { - case metapath10Lexer.KW_INTERSECT: - retval = new Intersect(left, right); + case Metapath10Lexer.PLUS: + retval = new Addition(left, right); break; - case metapath10Lexer.KW_EXCEPT: - retval = new Except(left, right); + case Metapath10Lexer.MINUS: + retval = new Subtraction(left, right); break; default: throw new UnsupportedOperationException(((TerminalNode) operatorTree).getSymbol().getText()); @@ -437,24 +563,35 @@ protected IExpression handleIntersectexceptexpr(IntersectexceptexprContext conte }); } - @SuppressWarnings("resource") @Override - protected IExpression handleArrowexpr(ArrowexprContext context) { - // TODO: handle new syntax - + protected IExpression handleMultiplicativeexpr(MultiplicativeexprContext context) { return handleGroupedNAiry(context, 0, 2, (ctx, idx, left) -> { - // the next child is "=>" - assert "=>".equals(ctx.getChild(idx).getText()); + assert left != null; - FunctioncallContext fcCtx = ctx.getChild(FunctioncallContext.class, idx + 1); - String name = fcCtx.eqname().getText(); - assert name != null; + ParseTree operatorTree = ctx.getChild(idx); + IExpression right = visit(ctx.getChild(idx + 1)); - Stream args = parseArgumentList(ObjectUtils.notNull(fcCtx.argumentlist())); - args = Stream.concat(Stream.of(left), args); - assert args != null; + assert right != null; - return new FunctionCall(name, ObjectUtils.notNull(args.collect(Collectors.toUnmodifiableList()))); + int type = ((TerminalNode) operatorTree).getSymbol().getType(); + IExpression retval; + switch (type) { + case Metapath10Lexer.STAR: + retval = new Multiplication(left, right); + break; + case Metapath10Lexer.KW_DIV: + retval = new Division(left, right); + break; + case Metapath10Lexer.KW_IDIV: + retval = new IntegerDivision(left, right); + break; + case Metapath10Lexer.KW_MOD: + retval = new Modulo(left, right); + break; + default: + throw new UnsupportedOperationException(((TerminalNode) operatorTree).getSymbol().getText()); + } + return retval; }); } @@ -468,9 +605,9 @@ protected IExpression handleUnaryexpr(UnaryexprContext ctx) { ParseTree tree = ctx.getChild(idx); int type = ((TerminalNode) tree).getSymbol().getType(); switch (type) { - case metapath10Lexer.PLUS: + case Metapath10Lexer.PLUS: break; - case metapath10Lexer.MINUS: + case Metapath10Lexer.MINUS: negateCount++; break; default: @@ -478,323 +615,245 @@ protected IExpression handleUnaryexpr(UnaryexprContext ctx) { } } - ParseTree expr = ctx.getChild(0); - IExpression retval = expr.accept(this); - assert retval != null; + IExpression retval = visit(ctx.getChild(idx)); if (negateCount % 2 != 0) { retval = new Negate(retval); } return retval; } - @Override - protected IExpression handlePathexpr(PathexprContext ctx) { - int numChildren = ctx.getChildCount(); + /* ======================================================================================== + * String Concatenation Expressions - https://www.w3.org/TR/xpath-31/#id-string-concat-expr + * ======================================================================================== + */ - IExpression retval; - ParseTree tree = ctx.getChild(0); - if (tree instanceof TerminalNode) { - int type = ((TerminalNode) tree).getSymbol().getType(); - switch (type) { - case metapath10Lexer.SLASH: - // a slash expression with optional path - if (numChildren == 2) { - // the optional path - ParseTree pathTree = ctx.getChild(1); - retval = new RootSlashPath(ObjectUtils.notNull(pathTree.accept(this))); - } else { - retval = new RootSlashOnlyPath(); - } - break; - case metapath10Lexer.SS: - // a double slash expression with path - ParseTree pathTree = ctx.getChild(1); - IExpression node = pathTree.accept(this); - assert node != null; - retval = new RootDoubleSlashPath(node); - break; - default: - throw new UnsupportedOperationException(((TerminalNode) tree).getSymbol().getText()); - } - } else { - // a relative expression or something else - retval = tree.accept(this); - } - return retval; + @Override + protected IExpression handleStringconcatexpr(StringconcatexprContext ctx) { + return handleNAiryCollection(ctx, children -> { + assert children != null; + return new StringConcat(children); + }); } + /* ======================================================================= + * Comparison Expressions - https://www.w3.org/TR/xpath-31/#id-comparisons + * ======================================================================= + */ + @Override - protected IExpression handleRelativepathexpr(RelativepathexprContext context) { - return handleGroupedNAiry(context, 0, 2, (ctx, idx, left) -> { - ParseTree operatorTree = ctx.getChild(idx); - ParseTree rightTree = ctx.getChild(idx + 1); - IExpression rightResult = rightTree.accept(this); + protected IExpression handleComparisonexpr(ComparisonexprContext ctx) { // NOPMD - ok + assert ctx.getChildCount() == 3; - assert left != null; - assert rightResult != null; + IExpression left = visit(ctx.getChild(0)); + IExpression right = visit(ctx.getChild(2)); - int type = ((TerminalNode) operatorTree).getSymbol().getType(); + // the operator + ParseTree operatorTree = ctx.getChild(1); + Object payload = operatorTree.getPayload(); - IExpression retval; + ComparisonFunctions.Operator operator; + IBooleanLogicExpression retval; + if (payload instanceof GeneralcompContext) { + GeneralcompContext compContext = (GeneralcompContext) payload; + int type = ((TerminalNode) compContext.getChild(0)).getSymbol().getType(); switch (type) { - case metapath10Lexer.SLASH: - retval = new RelativeSlashPath(left, rightResult); + case Metapath10Lexer.EQ: + operator = ComparisonFunctions.Operator.EQ; + break; + case Metapath10Lexer.NE: + operator = ComparisonFunctions.Operator.NE; + break; + case Metapath10Lexer.LT: + operator = ComparisonFunctions.Operator.LT; break; - case metapath10Lexer.SS: - retval = new RelativeDoubleSlashPath(left, rightResult); + case Metapath10Lexer.LE: + operator = ComparisonFunctions.Operator.LE; + break; + case Metapath10Lexer.GT: + operator = ComparisonFunctions.Operator.GT; + break; + case Metapath10Lexer.GE: + operator = ComparisonFunctions.Operator.GE; break; default: - throw new UnsupportedOperationException(((TerminalNode) operatorTree).getSymbol().getText()); + throw new UnsupportedOperationException(((TerminalNode) compContext.getChild(0)).getSymbol().getText()); } - return retval; - }); - } - - @SuppressWarnings("null") - @NonNull - protected IExpression parsePredicate(@NonNull PredicateContext context) { - // the expression is always the second child - ParseTree tree = context.getChild(1); - return tree.accept(this); - } - - @NonNull - protected List parsePredicates(@NonNull ParseTree context, int staringChild) { - int numChildren = context.getChildCount(); - int numPredicates = numChildren - staringChild; - - List predicates; - if (numPredicates == 0) { - // no predicates - predicates = CollectionUtil.emptyList(); - } else if (numPredicates == 1) { - // single predicate - PredicateContext predicate = ObjectUtils.notNull((PredicateContext) context.getChild(staringChild)); - predicates = CollectionUtil.singletonList(parsePredicate(predicate)); - } else { - // multiple predicates - predicates = new ArrayList<>(numPredicates); - for (int i = staringChild; i < numChildren; i++) { - PredicateContext predicate = ObjectUtils.notNull((PredicateContext) context.getChild(i)); - predicates.add(parsePredicate(predicate)); + retval = new GeneralComparison(left, operator, right); + } else if (payload instanceof ValuecompContext) { + ValuecompContext compContext = (ValuecompContext) payload; + int type = ((TerminalNode) compContext.getChild(0)).getSymbol().getType(); + switch (type) { + case Metapath10Lexer.KW_EQ: + operator = ComparisonFunctions.Operator.EQ; + break; + case Metapath10Lexer.KW_NE: + operator = ComparisonFunctions.Operator.NE; + break; + case Metapath10Lexer.KW_LT: + operator = ComparisonFunctions.Operator.LT; + break; + case Metapath10Lexer.KW_LE: + operator = ComparisonFunctions.Operator.LE; + break; + case Metapath10Lexer.KW_GT: + operator = ComparisonFunctions.Operator.GT; + break; + case Metapath10Lexer.KW_GE: + operator = ComparisonFunctions.Operator.GE; + break; + default: + throw new UnsupportedOperationException(((TerminalNode) compContext.getChild(0)).getSymbol().getText()); } + retval = new ValueComparison(left, operator, right); + } else { + throw new UnsupportedOperationException(); } - return predicates; + return retval; } - @Override - protected IExpression handlePostfixexpr(PostfixexprContext ctx) { - int numChildren = ctx.getChildCount(); - ParseTree primaryTree = ctx.getChild(0); - IExpression retval = ObjectUtils.notNull(primaryTree.accept(this)); - - List predicates = numChildren > 1 ? parsePredicates(ctx, 1) : CollectionUtil.emptyList(); - - if (!predicates.isEmpty()) { - retval = new Predicate(retval, predicates); - } - return retval; + /* ============================================================================ + * Logical Expressions - https://www.w3.org/TR/xpath-31/#id-logical-expressions + * ============================================================================ + */ + @Override + protected IExpression handleOrexpr(OrexprContext ctx) { + return handleNAiryCollection(ctx, children -> { + assert children != null; + return new Or(children); + }); } @Override - protected IExpression handleAxisstep(AxisstepContext ctx) { - IExpression step = ctx.getChild(0).accept(this); - assert step != null; - - ParseTree predicateTree = ctx.getChild(1); - assert predicateTree != null; + protected IExpression handleAndexpr(AndexprContext ctx) { + return handleNAiryCollection(ctx, children -> { + assert children != null; + return new And(children); + }); + } - List predicates = parsePredicates(predicateTree, 0); + /* ==================================================================== + * For Expressions - https://www.w3.org/TR/xpath-31/#id-for-expressions + * ==================================================================== + */ - return predicates.isEmpty() ? step : new Predicate(step, predicates); + @Override + protected IExpression handleForexpr(ForexprContext ctx) { + throw new UnsupportedOperationException("implement"); } + /* ==================================================================== + * Let Expressions - https://www.w3.org/TR/xpath-31/#id-let-expressions + * ==================================================================== + */ + @Override - protected IExpression handleForwardstep(ForwardstepContext ctx) { - assert ctx.getChildCount() == 2; + protected IExpression handleLet(LetexprContext context) { + @NonNull IExpression retval = ObjectUtils.notNull(context.exprsingle().accept(this)); - Token token = (Token) ctx.forwardaxis().getChild(0).getPayload(); + SimpleletclauseContext letClause = context.simpleletclause(); + List clauses = letClause.simpleletbinding(); - Axis axis; - switch (token.getType()) { - case metapath10Lexer.KW_SELF: - axis = Axis.SELF; - break; - case metapath10Lexer.KW_CHILD: - axis = Axis.CHILDREN; - break; - case metapath10Lexer.KW_DESCENDANT: - axis = Axis.DESCENDANT; - break; - case metapath10Lexer.KW_DESCENDANT_OR_SELF: - axis = Axis.DESCENDANT_OR_SELF; - break; - default: - throw new UnsupportedOperationException(token.getText()); - } - return new Step(axis, ObjectUtils.notNull(ctx.nametest().accept(this))); - } + ListIterator reverseListIterator = clauses.listIterator(clauses.size()); + while (reverseListIterator.hasPrevious()) { + SimpleletbindingContext simpleCtx = reverseListIterator.previous(); - @Override - protected IExpression handleAbbrevforwardstep(AbbrevforwardstepContext ctx) { - int numChildren = ctx.getChildCount(); + Name varName = (Name) simpleCtx.varname().accept(this); + IExpression boundExpression = simpleCtx.exprsingle().accept(this); - IExpression retval; - if (numChildren == 1) { - ParseTree tree = ctx.getChild(0); - retval = new ModelInstance(ObjectUtils.notNull(tree.accept(this))); - } else { - // this is an AT test - ParseTree tree = ctx.getChild(1); - retval = new Flag(ObjectUtils.notNull(tree.accept(this))); + assert varName != null; + assert boundExpression != null; + retval = new Let(varName, boundExpression, retval); // NOPMD intended } return retval; } - @Override - protected IExpression handleReversestep(ReversestepContext ctx) { - assert ctx.getChildCount() == 2; - - Token token = (Token) ctx.reverseaxis().getChild(0).getPayload(); - - Axis axis; - switch (token.getType()) { - case metapath10Lexer.KW_PARENT: - axis = Axis.PARENT; - break; - case metapath10Lexer.KW_ANCESTOR: - axis = Axis.ANCESTOR; - break; - case metapath10Lexer.KW_ANCESTOR_OR_SELF: - axis = Axis.ANCESTOR_OR_SELF; - break; - default: - throw new UnsupportedOperationException(token.getText()); - } - return new Step(axis, ObjectUtils.notNull(ctx.nametest().accept(this))); - } + /* ========================================================================= + * Conditional Expressions - https://www.w3.org/TR/xpath-31/#id-conditionals + * ========================================================================= + */ @Override - protected IExpression handleAbbrevreversestep(AbbrevreversestepContext ctx) { - return Axis.PARENT; - } + protected IExpression handleIfexpr(IfexprContext ctx) { + IExpression testExpr = visit(ctx.expr()); + IExpression thenExpr = visit(ctx.exprsingle(0)); + IExpression elseExpr = visit(ctx.exprsingle(1)); - @Override - protected IExpression handleStringLiteral(LiteralContext ctx) { - ParseTree tree = ctx.getChild(0); - return new StringLiteral(ObjectUtils.notNull(tree.getText())); + return new If(testExpr, thenExpr, elseExpr); } + /* ================================================================================== + * Quantified Expressions - https://www.w3.org/TR/xpath-31/#id-quantified-expressions + * ================================================================================== + */ + @Override - protected IExpression handleNumericLiteral(NumericliteralContext ctx) { - ParseTree tree = ctx.getChild(0); - Token token = (Token) tree.getPayload(); - IExpression retval; - switch (token.getType()) { - case metapath10Lexer.IntegerLiteral: - retval = new IntegerLiteral(new BigInteger(token.getText())); + protected IExpression handleQuantifiedexpr(QuantifiedexprContext ctx) { + Quantified.Quantifier quantifier; + int type = ((TerminalNode) ctx.getChild(0)).getSymbol().getType(); + switch (type) { + case Metapath10Lexer.KW_SOME: + quantifier = Quantified.Quantifier.SOME; break; - case metapath10Lexer.DecimalLiteral: - case metapath10Lexer.DoubleLiteral: - retval = new DecimalLiteral(new BigDecimal(token.getText())); + case Metapath10Lexer.KW_EVERY: + quantifier = Quantified.Quantifier.EVERY; break; default: - throw new UnsupportedOperationException(token.getText()); + throw new UnsupportedOperationException(((TerminalNode) ctx.getChild(0)).getSymbol().getText()); } - return retval; - } - - @Override - protected IExpression handleContextitemexpr(ContextitemexprContext ctx) { - return ContextItem.instance(); - } - @NonNull - protected Stream parseArgumentList(@NonNull ArgumentlistContext context) { - int numChildren = context.getChildCount(); + int numVars = (ctx.getChildCount() - 2) / 5; // children - "satisfies expr" / ", $ varName in expr" + Map vars = new LinkedHashMap<>(); // NOPMD ordering needed + int offset = 0; + for (; offset < numVars; offset++) { + // $ + String varName = ((Name) visit(ctx.varname(offset))).getValue(); + // in + IExpression varExpr = visit(ctx.exprsingle(offset)); - Stream retval; - if (numChildren == 2) { - // just the OP CP tokens, which is an empty list - retval = Stream.empty(); - } else { - retval = context.argument().stream() - .map(argument -> { - return argument.exprsingle().accept(this); - }); + vars.put(varName, varExpr); } - assert retval != null; - return retval; - } + IExpression satisfies = visit(ctx.exprsingle(offset)); - @Override - protected IExpression handleFunctioncall(FunctioncallContext ctx) { - EqnameContext nameCtx = ctx.eqname(); - String name = nameCtx.getText(); - - assert name != null; - - return new FunctionCall( - name, - ObjectUtils.notNull(parseArgumentList(ObjectUtils.notNull(ctx.argumentlist())) - .collect(Collectors.toUnmodifiableList()))); + return new Quantified(quantifier, vars, satisfies); } - @Override - protected IExpression handleEqname(EqnameContext ctx) { - ParseTree tree = ctx.getChild(0); - String name = ((TerminalNode) tree).getText(); - - assert name != null; - - return new Name(name); - } + /* ========================================================================= + * Simple map operator (!) - https://www.w3.org/TR/xpath-31/#id-map-operator + * ========================================================================= + */ @Override - protected IExpression handleWildcard(WildcardContext ctx) { - return new Wildcard(); + protected IExpression handleSimplemapexpr(SimplemapexprContext ctx) { + throw new UnsupportedOperationException("implement"); } - @FunctionalInterface - interface ITriFunction { - - R apply(T argT, U argU, V argV); - - default ITriFunction andThen(Function after) { - Objects.requireNonNull(after); - return (T t, U u, V v) -> after.apply(apply(t, u, v)); - } - } + /* ======================================================================= + * Arrow operator (=>) - https://www.w3.org/TR/xpath-31/#id-arrow-operator + * ======================================================================= + */ @Override - protected IExpression handleLet(LetexprContext context) { - @NonNull IExpression retval = ObjectUtils.notNull(context.exprsingle().accept(this)); - - SimpleletclauseContext letClause = context.simpleletclause(); - List clauses = letClause.simpleletbinding(); - - ListIterator reverseListIterator = clauses.listIterator(clauses.size()); - while (reverseListIterator.hasPrevious()) { - SimpleletbindingContext simpleCtx = reverseListIterator.previous(); - - Name varName = (Name) simpleCtx.varname().accept(this); - IExpression boundExpression = simpleCtx.exprsingle().accept(this); + protected IExpression handleArrowexpr(ArrowexprContext context) { + // TODO: handle additional syntax for varef and parenthesized + return handleGroupedNAiry(context, 0, 2, (ctx, idx, left) -> { + // the next child is "=>" + assert "=>".equals(ctx.getChild(idx).getText()); - assert varName != null; - assert boundExpression != null; + FunctioncallContext fcCtx = ctx.getChild(FunctioncallContext.class, idx + 1); + // QName name = toQName( + String name = fcCtx.eqname().getText(); + assert name != null; - retval = new Let(varName, boundExpression, retval); // NOPMD intended - } - return retval; - } + try (Stream args = Stream.concat( + Stream.of(left), + parseArgumentList(ObjectUtils.notNull(fcCtx.argumentlist())))) { + assert args != null; - @Override - protected IExpression handleVarref(VarrefContext ctx) { - Name varName = (Name) ctx.varname().accept(this); - assert varName != null; - return new VariableReference(varName); + return new FunctionCall(name, ObjectUtils.notNull(args.collect(Collectors.toUnmodifiableList()))); + } + }); } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/CSTPrinter.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/CSTPrinter.java new file mode 100644 index 000000000..600540688 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/CSTPrinter.java @@ -0,0 +1,355 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst; + +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.GeneralComparison; +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.ValueComparison; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Addition; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Division; +import gov.nist.secauto.metaschema.core.metapath.cst.math.IntegerDivision; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Modulo; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Multiplication; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Subtraction; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Axis; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Flag; +import gov.nist.secauto.metaschema.core.metapath.cst.path.ModelInstance; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RelativeDoubleSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RelativeSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootDoubleSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootSlashOnlyPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Step; + +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; + +@SuppressWarnings("PMD.CouplingBetweenObjects") +public final class CSTPrinter { + private CSTPrinter() { + // disable construction + } + + /** + * Generate a string representation of the CST tree. + * + * @param expr + * an expression that is a branch in the tree to visualize. + * @return a string representation of the CST graph + */ + public static String toString(@NonNull IExpression expr) { + return new CSTPrinterVisitor().visit(expr); + } + + private static class CSTPrinterVisitor + extends AbstractExpressionVisitor { + + @Override + protected String visitChildren(IExpression expr, State context) { + context.push(); + String result = super.visitChildren(expr, context); + context.pop(); + return result; + } + + @Override + protected String aggregateResult(String result, String nextResult, State context) { + StringBuilder buffer = new StringBuilder(); + if (result != null) { + buffer.append(result); + // buffer.append(" ar "+System.lineSeparator()); + } + + buffer.append(context.getIndentation()) + .append(nextResult); + return buffer.toString(); + } + + @Override + protected String defaultResult() { + return ""; + } + + /** + * Append the {@code childResult} to the record produced for the current node. + * + * @param expr + * the current node + * @param childResult + * the output generated for the curren't node's children + * @param context + * the output context state + * @return the string representation of the node tree for the current node and + * its children + */ + @SuppressWarnings("static-method") + protected String appendNode(@NonNull IExpression expr, @Nullable String childResult, @NonNull State context) { + StringBuilder buffer = new StringBuilder(); + buffer.append(context.getIndentation()) + .append(expr.toASTString()); + if (childResult != null) { + buffer.append(System.lineSeparator()) + .append(childResult); + } + return buffer.toString(); + } + + /** + * Visit a node and produce a string representation of its the node tree. + * + * @param expression + * the node to build the node tree for + * @return the string representation of the node tree for the provided + * expression node and its children + */ + public String visit(@NonNull IExpression expression) { + return visit(expression, new State()); + } + + @Override + public String visitAddition(Addition expr, State context) { + return appendNode(expr, super.visitAddition(expr, context), context); + } + + @Override + public String visitAnd(And expr, State context) { + return appendNode(expr, super.visitAnd(expr, context), context); + } + + @Override + public String visitStep(Step expr, State context) { + return appendNode(expr, super.visitStep(expr, context), context); + } + + @Override + public String visitValueComparison(ValueComparison expr, State context) { + return appendNode(expr, super.visitValueComparison(expr, context), context); + } + + @Override + public String visitGeneralComparison(GeneralComparison expr, State context) { + return appendNode(expr, super.visitGeneralComparison(expr, context), context); + } + + @Override + public String visitContextItem(ContextItem expr, State context) { + return appendNode(expr, super.visitContextItem(expr, context), context); + } + + @Override + public String visitDecimalLiteral(DecimalLiteral expr, State context) { + return appendNode(expr, super.visitDecimalLiteral(expr, context), context); + } + + @Override + public String visitDivision(Division expr, State context) { + return appendNode(expr, super.visitDivision(expr, context), context); + } + + @Override + public String visitExcept(@NonNull Except expr, State context) { + return appendNode(expr, super.visitExcept(expr, context), context); + } + + @Override + public String visitFlag(Flag expr, State context) { + return appendNode(expr, super.visitFlag(expr, context), context); + } + + @Override + public String visitFunctionCall(FunctionCall expr, State context) { + return appendNode(expr, super.visitFunctionCall(expr, context), context); + } + + @Override + public String visitIntegerDivision(IntegerDivision expr, State context) { + return appendNode(expr, super.visitIntegerDivision(expr, context), context); + } + + @Override + public String visitIntegerLiteral(IntegerLiteral expr, State context) { + return appendNode(expr, super.visitIntegerLiteral(expr, context), context); + } + + @Override + public String visitIntersect(Intersect expr, State context) { + return appendNode(expr, super.visitIntersect(expr, context), context); + } + + @Override + public String visitMetapath(Metapath expr, State context) { + return appendNode(expr, super.visitMetapath(expr, context), context); + } + + @Override + public String visitModulo(Modulo expr, State context) { + return appendNode(expr, super.visitModulo(expr, context), context); + } + + @Override + public String visitModelInstance(ModelInstance expr, State context) { + return appendNode(expr, super.visitModelInstance(expr, context), context); + } + + @Override + public String visitMultiplication(Multiplication expr, State context) { + return appendNode(expr, super.visitMultiplication(expr, context), context); + } + + @Override + public String visitName(Name expr, State context) { + return appendNode(expr, super.visitName(expr, context), context); + } + + @Override + public String visitNegate(Negate expr, State context) { + return appendNode(expr, super.visitNegate(expr, context), context); + } + + @Override + public String visitOr(Or expr, State context) { + return appendNode(expr, super.visitOr(expr, context), context); + } + + @Override + public String visitAxis(Axis expr, State context) { + return appendNode(expr, super.visitAxis(expr, context), context); + } + + @Override + public String visitPredicate(Predicate expr, State context) { + return appendNode(expr, super.visitPredicate(expr, context), context); + } + + @Override + public String visitRelativeDoubleSlashPath(RelativeDoubleSlashPath expr, State context) { + return appendNode(expr, super.visitRelativeDoubleSlashPath(expr, context), context); + } + + @Override + public String visitRelativeSlashPath(RelativeSlashPath expr, State context) { + return appendNode(expr, super.visitRelativeSlashPath(expr, context), context); + } + + @Override + public String visitRootDoubleSlashPath(RootDoubleSlashPath expr, State context) { + return appendNode(expr, super.visitRootDoubleSlashPath(expr, context), context); + } + + @Override + public String visitRootSlashOnlyPath(RootSlashOnlyPath expr, State context) { + return appendNode(expr, super.visitRootSlashOnlyPath(expr, context), context); + } + + @Override + public String visitRootSlashPath(RootSlashPath expr, State context) { + return appendNode(expr, super.visitRootSlashPath(expr, context), context); + } + + @Override + public String visitStringConcat(StringConcat expr, State context) { + return appendNode(expr, super.visitStringConcat(expr, context), context); + } + + @Override + public String visitStringLiteral(StringLiteral expr, State context) { + return appendNode(expr, super.visitStringLiteral(expr, context), context); + } + + @Override + public String visitSubtraction(Subtraction expr, State context) { + return appendNode(expr, super.visitSubtraction(expr, context), context); + } + + @Override + public String visitUnion(Union expr, State context) { + return appendNode(expr, super.visitUnion(expr, context), context); + } + + @Override + public String visitWildcard(Wildcard expr, State context) { + return appendNode(expr, super.visitWildcard(expr, context), context); + } + + @Override + public String visitLet(Let expr, State context) { + return appendNode(expr, super.visitLet(expr, context), context); + } + + @Override + public String visitVariableReference(VariableReference expr, State context) { + return appendNode(expr, super.visitVariableReference(expr, context), context); + } + + @Override + public String visitEmptySequence(EmptySequence expr, State context) { + return appendNode(expr, super.visitEmptySequence(expr, context), context); + } + + @Override + public String visitRange(Range expr, State context) { + return appendNode(expr, super.visitRange(expr, context), context); + } + + @Override + public String visitIf(If expr, State context) { + return appendNode(expr, super.visitIf(expr, context), context); + } + + @Override + public String visitQuantified(Quantified expr, State context) { + return appendNode(expr, super.visitQuantified(expr, context), context); + } + } + + static class State { + private int indentation; // 0; + private int lastIndentation; // 0; + private String indentationPadding = ""; + + public String getIndentation() { + if (indentation != lastIndentation) { + StringBuilder buffer = new StringBuilder(); + for (int i = 0; i < indentation; i++) { + buffer.append(" "); + } + lastIndentation = indentation; + indentationPadding = buffer.toString(); + } + return indentationPadding; + } + + public State push() { + indentation++; + return this; + } + + public State pop() { + indentation--; + return this; + } + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ContextItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/ContextItem.java similarity index 86% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ContextItem.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/ContextItem.java index 71c6a78f1..b5c5cab00 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ContextItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/ContextItem.java @@ -24,8 +24,12 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.path.AbstractPathExpression; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import java.util.Collections; @@ -33,11 +37,16 @@ import edu.umd.cs.findbugs.annotations.NonNull; -final class ContextItem +public final class ContextItem extends AbstractPathExpression { @NonNull private static final ContextItem SINGLETON = new ContextItem(); + /** + * Get the singleton context item CST node. + * + * @return the singleton instance + */ @NonNull public static ContextItem instance() { return SINGLETON; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DecimalLiteral.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/DecimalLiteral.java similarity index 89% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DecimalLiteral.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/DecimalLiteral.java index 68ef3dfc0..433c36f9d 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DecimalLiteral.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/DecimalLiteral.java @@ -24,15 +24,17 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDecimalItem; import java.math.BigDecimal; import edu.umd.cs.findbugs.annotations.NonNull; -class DecimalLiteral +public class DecimalLiteral extends AbstractLiteralExpression { /** @@ -41,7 +43,7 @@ class DecimalLiteral * @param value * the literal value */ - protected DecimalLiteral(@NonNull BigDecimal value) { + public DecimalLiteral(@NonNull BigDecimal value) { super(value); } @@ -55,6 +57,7 @@ public RESULT accept(IExpressionVisitor visit return visitor.visitDecimalLiteral(this, context); } + // REFACTOR: store decimal item value @Override public ISequence accept(DynamicContext dynamicContext, ISequence focus) { return ISequence.of(IDecimalItem.valueOf(getValue())); diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/EmptySequence.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/EmptySequence.java new file mode 100644 index 000000000..975b825c6 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/EmptySequence.java @@ -0,0 +1,78 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst; + +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.item.IItem; + +import java.util.Collections; +import java.util.List; + +import edu.umd.cs.findbugs.annotations.NonNull; + +public final class EmptySequence + extends AbstractExpression { + @NonNull + private static final EmptySequence SINGLETON = new EmptySequence<>(); + + /** + * Get a singleton CST node instance representing an expression that returns an + * empty sequence. + * + * @param + * the Java type of the resulting empty sequence + * @return the singleton CST node instance + */ + @SuppressWarnings("unchecked") + @NonNull + public static EmptySequence instance() { + return (EmptySequence) SINGLETON; + } + + private EmptySequence() { + // disable construction + } + + @SuppressWarnings("null") + @Override + public List getChildren() { + // no children + return Collections.emptyList(); + } + + @Override + public ISequence accept(DynamicContext dynamicContext, ISequence focus) { + return ISequence.empty(); + } + + @Override + public RESULT accept(IExpressionVisitor visitor, CONTEXT context) { + return visitor.visitEmptySequence(this, context); + } + +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Except.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Except.java similarity index 80% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Except.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Except.java index 91aa236eb..cacef3b31 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Except.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Except.java @@ -24,18 +24,32 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import java.util.List; import edu.umd.cs.findbugs.annotations.NonNull; -class Except +/** + * The CST node for a Metapath + * except + * expression. + */ +public class Except extends AbstractFilterExpression { - protected Except(@NonNull IExpression left, @NonNull IExpression right) { + /** + * Construct a new Metapath except expression CST node. + * + * @param left + * an expression indicating the items to filter + * @param right + * an expression indicating the items to omit + */ + public Except(@NonNull IExpression left, @NonNull IExpression right) { super(left, right); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ExpressionUtils.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/ExpressionUtils.java similarity index 98% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ExpressionUtils.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/ExpressionUtils.java index 78296b81c..2f6330c9d 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ExpressionUtils.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/ExpressionUtils.java @@ -24,7 +24,7 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -34,7 +34,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -final class ExpressionUtils { +public final class ExpressionUtils { private ExpressionUtils() { // disable } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/FunctionCall.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/FunctionCall.java similarity index 91% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/FunctionCall.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/FunctionCall.java index 9177a383a..dbdcf6ea9 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/FunctionCall.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/FunctionCall.java @@ -24,8 +24,11 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +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.function.FunctionService; import gov.nist.secauto.metaschema.core.metapath.function.IFunction; import gov.nist.secauto.metaschema.core.metapath.item.IItem; @@ -37,7 +40,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class FunctionCall implements IExpression { +public class FunctionCall implements IExpression { @NonNull private final String name; @NonNull @@ -52,7 +55,7 @@ class FunctionCall implements IExpression { * @param arguments * the expressions used to provide arguments to the function call */ - protected FunctionCall(@NonNull String name, @NonNull List arguments) { + public FunctionCall(@NonNull String name, @NonNull List arguments) { this.name = Objects.requireNonNull(name, "name"); this.arguments = Objects.requireNonNull(arguments, "arguments"); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IBooleanLogicExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IBooleanLogicExpression.java similarity index 94% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IBooleanLogicExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IBooleanLogicExpression.java index fcb00910b..968fc33ed 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IBooleanLogicExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IBooleanLogicExpression.java @@ -24,11 +24,11 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem; -interface IBooleanLogicExpression extends IExpression { +public interface IBooleanLogicExpression extends IExpression { @Override default Class getBaseResultType() { return IBooleanItem.class; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IExpression.java similarity index 95% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IExpression.java index f76a7151e..a0f2bcefb 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IExpression.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import java.util.List; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IExpressionVisitor.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IExpressionVisitor.java new file mode 100644 index 000000000..83cdcd5f6 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IExpressionVisitor.java @@ -0,0 +1,489 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst; + +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.GeneralComparison; +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.ValueComparison; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Addition; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Division; +import gov.nist.secauto.metaschema.core.metapath.cst.math.IntegerDivision; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Modulo; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Multiplication; +import gov.nist.secauto.metaschema.core.metapath.cst.math.Subtraction; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Axis; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Flag; +import gov.nist.secauto.metaschema.core.metapath.cst.path.ModelInstance; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RelativeDoubleSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RelativeSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootDoubleSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootSlashOnlyPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootSlashPath; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Step; + +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * Used to support processing a Metapath expression based on the visitor + * pattern. Each type of expression node in the Metapath abstract syntax tree + * (AST) is represented as a "visit" method. + * + * @param + * the result of processing any node + * @param + * additional state to pass between nodes visited + */ +public interface IExpressionVisitor { + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitAddition(@NonNull Addition expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitAnd(@NonNull And expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitExcept(@NonNull Except expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitAxis(@NonNull Axis expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitStep(@NonNull Step expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitValueComparison(@NonNull ValueComparison expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitGeneralComparison(@NonNull GeneralComparison expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitContextItem(@NonNull ContextItem expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitDecimalLiteral(@NonNull DecimalLiteral expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitDivision(@NonNull Division expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitFlag(@NonNull Flag expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitFunctionCall(@NonNull FunctionCall expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitIntegerDivision(@NonNull IntegerDivision expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitIntegerLiteral(@NonNull IntegerLiteral expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitIntersect(@NonNull Intersect expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitMetapath(@NonNull Metapath expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitModulo(@NonNull Modulo expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitModelInstance(@NonNull ModelInstance expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitMultiplication(@NonNull Multiplication expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitName(@NonNull Name expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitNegate(@NonNull Negate expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitOr(@NonNull Or expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitPredicate(@NonNull Predicate expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitRelativeDoubleSlashPath(@NonNull RelativeDoubleSlashPath expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitRelativeSlashPath(@NonNull RelativeSlashPath expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitRootDoubleSlashPath(@NonNull RootDoubleSlashPath expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitRootSlashOnlyPath(@NonNull RootSlashOnlyPath expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitRootSlashPath(@NonNull RootSlashPath expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitStringConcat(@NonNull StringConcat expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitStringLiteral(@NonNull StringLiteral expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitSubtraction(@NonNull Subtraction expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitUnion(@NonNull Union expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitWildcard(@NonNull Wildcard expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitLet(@NonNull Let expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitVariableReference(@NonNull VariableReference expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitEmptySequence(@NonNull EmptySequence expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitRange(@NonNull Range expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitIf(@NonNull If expr, @NonNull CONTEXT context); + + /** + * Visit the CST node. + * + * @param expr + * the CST node to visit + * @param context + * the processing context + * @return the visitation result or {@code null} if no result was produced + */ + RESULT visitQuantified(@NonNull Quantified expr, @NonNull CONTEXT context); +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ILiteralExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/ILiteralExpression.java similarity index 93% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ILiteralExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/ILiteralExpression.java index 42bd223b4..edd4b5659 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ILiteralExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/ILiteralExpression.java @@ -24,7 +24,7 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; @@ -33,7 +33,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -interface ILiteralExpression extends IExpression { +public interface ILiteralExpression extends IExpression { /** * Get the literal value. * diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IPathExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IPathExpression.java similarity index 93% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IPathExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IPathExpression.java index 4c5037b2e..0034e18a7 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IPathExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IPathExpression.java @@ -24,11 +24,11 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import gov.nist.secauto.metaschema.core.metapath.item.IItem; -interface IPathExpression extends IExpression { +public interface IPathExpression extends IExpression { @Override Class getBaseResultType(); diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/If.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/If.java new file mode 100644 index 000000000..798d17d50 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/If.java @@ -0,0 +1,120 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst; + +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.function.library.FnBoolean; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import java.util.List; + +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * An implementation of + * If + * expression supporting conditional evaluation. + */ +@SuppressWarnings("PMD.ShortClassName") +public class If + extends AbstractExpression { + private final IExpression testExpression; + private final IExpression thenExpression; + private final IExpression elseExpression; + + /** + * Construct a new conditional expression. + * + * @param testExpression + * the first expression to evaluate + * @param thenExpression + * the expression to evaluate if the test is {@code true} + * @param elseExpression + * the expression to evaluate if the test is {@code false} + */ + public If( + @NonNull IExpression testExpression, + @NonNull IExpression thenExpression, + @NonNull IExpression elseExpression) { + this.testExpression = testExpression; + this.thenExpression = thenExpression; + this.elseExpression = elseExpression; + } + + /** + * Get the "test" expression. + * + * @return the expression + */ + protected IExpression getTestExpression() { + return testExpression; + } + + /** + * Get the "then" expression. + * + * @return the expression + */ + protected IExpression getThenExpression() { + return thenExpression; + } + + /** + * Get the "else" expression. + * + * @return the expression + */ + protected IExpression getElseExpression() { + return elseExpression; + } + + @Override + public List getChildren() { + return ObjectUtils.notNull(List.of(testExpression, thenExpression, elseExpression)); + } + + @Override + public ISequence accept(DynamicContext dynamicContext, ISequence focus) { + ISequence result = getTestExpression().accept(dynamicContext, focus); + + ISequence retval; + IBooleanItem effectiveResult = FnBoolean.fnBoolean(result); + if (effectiveResult.toBoolean()) { + retval = getThenExpression().accept(dynamicContext, focus); + } else { + retval = getElseExpression().accept(dynamicContext, focus); + } + return retval; + } + + @Override + public RESULT accept(IExpressionVisitor visitor, CONTEXT context) { + return visitor.visitIf(this, context); + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IntegerLiteral.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IntegerLiteral.java similarity index 90% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IntegerLiteral.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IntegerLiteral.java index c5b615886..9a86b0119 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IntegerLiteral.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/IntegerLiteral.java @@ -24,15 +24,17 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem; import java.math.BigInteger; import edu.umd.cs.findbugs.annotations.NonNull; -class IntegerLiteral +public class IntegerLiteral extends AbstractLiteralExpression { /** @@ -41,7 +43,7 @@ class IntegerLiteral * @param value * the literal value */ - protected IntegerLiteral(@NonNull BigInteger value) { + public IntegerLiteral(@NonNull BigInteger value) { super(value); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Intersect.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Intersect.java similarity index 80% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Intersect.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Intersect.java index 513f75643..04999c6de 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Intersect.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Intersect.java @@ -24,18 +24,33 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import java.util.List; import edu.umd.cs.findbugs.annotations.NonNull; -class Intersect +/** + * The CST node for a Metapath + * intersect + * expression. + */ +public class Intersect extends AbstractFilterExpression { - protected Intersect(@NonNull IExpression left, @NonNull IExpression right) { + /** + * Construct a new Metapath except expression CST node. + * + * @param left + * an expression indicating the items to filter + * @param right + * an expression indicating the items to keep + */ + + public Intersect(@NonNull IExpression left, @NonNull IExpression right) { super(left, right); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Let.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Let.java similarity index 72% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Let.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Let.java index f41ca45af..47cb542c1 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Let.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Let.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -33,7 +35,12 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Let implements IExpression { // NOPMD class name ok +/** + * An implementation of + * Let + * expression supporting variable value binding. + */ +public class Let implements IExpression { // NOPMD class name ok @NonNull private final Name name; @NonNull @@ -41,23 +48,47 @@ class Let implements IExpression { // NOPMD class name ok @NonNull private final IExpression returnExpression; + /** + * Construct a new Let CST expression. + * + * @param name + * the variable name + * @param boundExpression + * the expression bound to the variable + * @param returnExpression + * the inner expression to evaluate with the variable in-scope + */ public Let(@NonNull Name name, @NonNull IExpression boundExpression, @NonNull IExpression returnExpression) { - super(); this.name = name; this.boundExpression = boundExpression; this.returnExpression = returnExpression; } + /** + * Get the variable name. + * + * @return the variable name + */ @NonNull public Name getName() { return name; } + /** + * Get the expression bound to the variable. + * + * @return the bound expression + */ @NonNull public IExpression getBoundExpression() { return boundExpression; } + /** + * Get the inner expression to evaluate with the variable in-scope. + * + * @return the inner expression + */ @NonNull public IExpression getReturnExpression() { return returnExpression; @@ -79,12 +110,11 @@ public ISequence accept(DynamicContext dynamicContext, ISequenc ISequence result = getBoundExpression().accept(dynamicContext, focus); String name = getName().getValue(); - dynamicContext.setVariableValue(name, result); - ISequence retval = getReturnExpression().accept(dynamicContext, focus); + DynamicContext subDynamicContext = dynamicContext.subContext(); - dynamicContext.clearVariableValue(name); + subDynamicContext.bindVariableValue(name, result); - return retval; + return getReturnExpression().accept(subDynamicContext, focus); } } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Metapath.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Metapath.java similarity index 93% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Metapath.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Metapath.java index 767cca35c..8abb5a942 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Metapath.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Metapath.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -34,7 +36,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Metapath +public class Metapath extends AbstractNAryExpression { @NonNull diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Name.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Name.java similarity index 85% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Name.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Name.java index 91b6e12e6..010fdf629 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Name.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Name.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.ItemUtils; import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; @@ -35,21 +37,33 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Name // NOPMD - intentional +/** + * The CST node for a Metapath + * expanded QName + * name test. + */ +public class Name // NOPMD - intentional implements IExpression { + @NonNull private final String value; /** - * Create a new literal expression. + * Construct a new expanded QName-based literal expression. * * @param value * the literal value */ - protected Name(@NonNull String value) { + public Name(@NonNull String value) { this.value = value; } + /** + * Get the string value of the name. + * + * @return the string value of the name + */ + @NonNull public String getValue() { return value; } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Negate.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Negate.java similarity index 92% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Negate.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Negate.java index 683597aac..3f4b73b36 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Negate.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Negate.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; import gov.nist.secauto.metaschema.core.metapath.function.OperationFunctions; import gov.nist.secauto.metaschema.core.metapath.item.atomic.INumericItem; @@ -34,7 +36,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Negate +public class Negate extends AbstractUnaryExpression { @NonNull @@ -47,7 +49,7 @@ class Negate * the expression whose item result will be complemented */ @SuppressWarnings("null") - protected Negate(@NonNull IExpression expr) { + public Negate(@NonNull IExpression expr) { super(expr); this.staticResultType = ExpressionUtils.analyzeStaticResultType(INumericItem.class, List.of(expr)); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Or.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Or.java similarity index 74% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Or.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Or.java index cc7d7bf1c..8d3d3191a 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Or.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Or.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.function.library.FnBoolean; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem; @@ -34,12 +36,33 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Or // NOPMD - intentional name +/** + * An implementation of + * Or + * expression supporting conditional evaluation. + *

+ * Determines the logical conjunction of the result of evaluating a list of + * expressions. The boolean result of each expression is determined by applying + * {@link FnBoolean#fnBooleanAsPrimitive(ISequence)} to each function's + * {@link ISequence} result. + *

+ * This implementation will short-circuit and return {@code true} when the first + * expression evaluates to {@code true}, otherwise it will return {@code false}. + */ +@SuppressWarnings("PMD.ShortClassName") +public class Or extends AbstractNAryExpression implements IBooleanLogicExpression { + /** + * Construct a new "or" logical expression. + * + * @param expressions + * the expressions to evaluate + * + */ @SuppressWarnings("null") - protected Or(@NonNull IExpression... expressions) { + public Or(@NonNull IExpression... expressions) { this(Arrays.asList(expressions)); } @@ -52,7 +75,7 @@ protected Or(@NonNull IExpression... expressions) { * @param expressions * the list of expressions */ - protected Or(@NonNull List expressions) { + public Or(@NonNull List expressions) { super(expressions); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Predicate.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Predicate.java similarity index 92% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Predicate.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Predicate.java index 5f4107559..7881452e7 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Predicate.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Predicate.java @@ -24,8 +24,11 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.MetapathEvaluationFeature; import gov.nist.secauto.metaschema.core.metapath.function.library.FnBoolean; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -39,7 +42,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Predicate implements IExpression { +public class Predicate implements IExpression { @NonNull private final IExpression base; @NonNull @@ -53,7 +56,7 @@ class Predicate implements IExpression { * @param predicates * the expression(s) to apply as a filter */ - protected Predicate(@NonNull IExpression base, @NonNull List predicates) { + public Predicate(@NonNull IExpression base, @NonNull List predicates) { this.base = base; this.predicates = predicates; } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Quantified.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Quantified.java new file mode 100644 index 000000000..45ee293f8 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Quantified.java @@ -0,0 +1,245 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst; + +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.function.library.FnBoolean; +import gov.nist.secauto.metaschema.core.metapath.item.IItem; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import edu.umd.cs.findbugs.annotations.NonNull; + +public class Quantified + extends AbstractExpression { + public enum Quantifier { + SOME, + EVERY; + } + + @NonNull + private final Quantifier quantifier; + @NonNull + private final Map inClauses; + @NonNull + private final IExpression satisfies; + + public Quantified( + @NonNull Quantifier quantifier, + @NonNull Map inClauses, + @NonNull IExpression satisfies) { + this.quantifier = quantifier; + this.inClauses = inClauses; + this.satisfies = satisfies; + } + + @NonNull + public Quantifier getQuantifier() { + return quantifier; + } + + @NonNull + public Map getInClauses() { + return inClauses; + } + + @NonNull + public IExpression getSatisfies() { + return satisfies; + } + + @Override + public List getChildren() { + return ObjectUtils.notNull(Stream.concat(inClauses.values().stream(), Stream.of(satisfies)) + .collect(Collectors.toList())); + } + + @SuppressWarnings("PMD.SystemPrintln") + @Override + public ISequence accept(DynamicContext dynamicContext, ISequence focus) { + Map> clauses = getInClauses().entrySet().stream() + .map(entry -> Map.entry( + entry.getKey(), + entry.getValue().accept(dynamicContext, focus))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); + + List clauseKeys = new ArrayList<>(clauses.keySet()); + List> clauseValues = new ArrayList<>(clauses.values()); + + boolean retval = true; + for (List product : new CartesianProduct<>(clauseValues)) { + DynamicContext subDynamicContext = dynamicContext.subContext(); + for (int idx = 0; idx < product.size(); idx++) { + String var = clauseKeys.get(idx); + IItem item = product.get(idx); + + assert var != null; + + subDynamicContext.bindVariableValue(var, ISequence.of(item)); + } + boolean result = FnBoolean.fnBooleanAsPrimitive(getSatisfies().accept(subDynamicContext, focus)); + if (Quantifier.EVERY.equals(quantifier) && !result) { + // fail on first false + retval = false; + break; + } else if (Quantifier.SOME.equals(quantifier)) { + if (result) { + // pass on first true + retval = true; + break; + } + // store (false) result + retval = false; + } + } + + return ISequence.of(IBooleanItem.valueOf(retval)); + } + + @Override + public RESULT accept(IExpressionVisitor visitor, CONTEXT context) { + return visitor.visitQuantified(this, context); + } + + public static Iterable> cartesianProduct( + @NonNull List> axes) { + return new CartesianProduct<>(axes); + } + + // based on https://gist.github.com/jhorstmann/a7aba9947bc4926a75f6de8f69560c6e + private static class CartesianProductIterator implements Iterator> { + private final Object[][] dimensions; + private final int length; + private final int[] indizes; + private boolean reachedMax; + + @SuppressWarnings({ + "PMD.UseVarargs", + "PMD.ArrayIsStoredDirectly" // ok for internal use + }) + CartesianProductIterator(final Object[][] dimensions) { + this.dimensions = dimensions; + this.length = dimensions.length; + this.indizes = new int[length]; + } + + private void increment(final int index) { + if (index >= length) { + reachedMax = true; + } else { + indizes[index]++; + if (indizes[index] == dimensions[index].length) { + indizes[index] = 0; + increment(index + 1); + } + } + } + + private void increment() { + increment(0); + } + + @SuppressWarnings("unchecked") + @Override + public List next() { + if (reachedMax) { + throw new NoSuchElementException(); + } + + List list = new ArrayList<>(); + for (int i = 0; i < length; i++) { + list.add((T) dimensions[i][indizes[i]]); + } + + increment(); + + return Collections.unmodifiableList(list); + } + + @Override + public boolean hasNext() { + return !reachedMax; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("remove not supported"); + } + } + + // based on https://gist.github.com/jhorstmann/a7aba9947bc4926a75f6de8f69560c6e + private static final class CartesianProduct implements Iterable> { + private final Object[][] dimensions; + private final long size; + + private CartesianProduct(final List> axes) { + Object[][] dimensions = new Object[axes.size()][]; + long size = dimensions.length == 0 ? 0 : 1; + for (int i = 0; i < axes.size(); i++) { + dimensions[i] = axes.get(i).toArray(); + size *= dimensions[i].length; + } + this.dimensions = dimensions; + this.size = size; + } + + @SuppressWarnings("PMD.OnlyOneReturn") // readability + @Override + public Iterator> iterator() { + if (size == 0) { + return Collections.emptyListIterator(); + } + return new CartesianProductIterator(dimensions); + } + + // /** + // * Get a stream of list items, representing each Cartesian product, based on + // * this iterator. + // * + // * @return a stream of list items representing each Cartesian product + // */ + // @NonNull + // public Stream> stream() { + // int characteristics = Spliterator.ORDERED | Spliterator.SIZED | + // Spliterator.IMMUTABLE; + // return StreamSupport.stream(Spliterators.spliterator(iterator(), size, + // characteristics), false); + // } + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Range.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Range.java new file mode 100644 index 000000000..a0914210e --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Range.java @@ -0,0 +1,96 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst; + +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * The CST node for a Metapath + * range + * expression. + */ +public class Range + extends AbstractBinaryExpression { + + /** + * Construct a new range expression. + * + * @param start + * the expressions representing the start of the range + * @param end + * the expressions representing the end of the range + * + */ + public Range(@NonNull IExpression start, @NonNull IExpression end) { + super(start, end); + } + + @Override + public Class getBaseResultType() { + return IIntegerItem.class; + } + + @Override + public ISequence accept(DynamicContext dynamicContext, ISequence focus) { + IAnyAtomicItem leftItem = getFirstDataItem(getLeft().accept(dynamicContext, focus), true); + IAnyAtomicItem rightItem = getFirstDataItem(getRight().accept(dynamicContext, focus), true); + + IIntegerItem left = leftItem == null ? null : IIntegerItem.cast(leftItem); + IIntegerItem right = rightItem == null ? null : IIntegerItem.cast(rightItem); + + ISequence retval; + if (left == null || right == null || left.compareTo(right) > 0) { + retval = ISequence.empty(); + } else { + + BigInteger min = right.asInteger(); + BigInteger max = right.asInteger(); + + List range = new ArrayList<>(max.subtract(min).add(BigInteger.ONE).intValueExact()); + for (BigInteger val = left.asInteger(); val.compareTo(max) <= 0; val = val.add(BigInteger.ONE)) { + range.add(IIntegerItem.valueOf(val)); + } + + retval = ISequence.of(range); + } + return retval; + } + + @Override + public RESULT accept(IExpressionVisitor visitor, CONTEXT context) { + return visitor.visitRange(this, context); + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StringConcat.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/StringConcat.java similarity index 92% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StringConcat.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/StringConcat.java index df8cd04dd..2f7c36f27 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StringConcat.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/StringConcat.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +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.atomic.IStringItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -34,7 +36,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class StringConcat +public class StringConcat extends AbstractNAryExpression { /** @@ -44,7 +46,7 @@ class StringConcat * @param expressions * the expressions to evaluate */ - protected StringConcat(@NonNull List expressions) { + public StringConcat(@NonNull List expressions) { super(expressions); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StringLiteral.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/StringLiteral.java similarity index 92% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StringLiteral.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/StringLiteral.java index 7bcc6b589..5d0fbaabe 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StringLiteral.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/StringLiteral.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem; import java.util.regex.Matcher; @@ -33,7 +35,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class StringLiteral +public class StringLiteral extends AbstractLiteralExpression { private static final Pattern QUOTE_PATTERN = Pattern.compile("^'(.*)'$|^\"(.*)\"$"); @@ -44,7 +46,7 @@ class StringLiteral * @param value * the literal value */ - protected StringLiteral(@NonNull String value) { + public StringLiteral(@NonNull String value) { super(removeQuotes(value)); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Union.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Union.java similarity index 88% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Union.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Union.java index 7a3f2338e..7eaacd691 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Union.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Union.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -34,7 +36,11 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Union +/** + * The CST node for a Metapath + * union expression. + */ +public class Union extends AbstractNAryExpression { @NonNull @@ -47,7 +53,7 @@ class Union * @param expressions * the expressions to evaluate */ - protected Union(@NonNull List expressions) { + public Union(@NonNull List expressions) { super(expressions); this.staticResultType = ExpressionUtils.analyzeStaticResultType(IItem.class, expressions); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/VariableReference.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/VariableReference.java similarity index 83% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/VariableReference.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/VariableReference.java index fa6806808..9cd5beb7e 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/VariableReference.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/VariableReference.java @@ -24,8 +24,10 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.util.CollectionUtil; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -34,14 +36,30 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class VariableReference implements IExpression { +/** + * The CST node for a Metapath + * variable + * reference. + */ +public class VariableReference implements IExpression { @NonNull private final Name name; + /** + * Construct a new Metapath variable reference CST node. + * + * @param name + * the variable name + */ public VariableReference(@NonNull Name name) { this.name = name; } + /** + * Get the variable name. + * + * @return the variable name + */ @NonNull public Name getName() { return name; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Wildcard.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Wildcard.java similarity index 88% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Wildcard.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Wildcard.java index 61aadfe03..087e7cdf5 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Wildcard.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/Wildcard.java @@ -24,20 +24,22 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.ItemUtils; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import java.util.Collections; import java.util.List; -class Wildcard implements IExpression { - - protected Wildcard() { - // reduce visibility - } - +/** + * The CST node for a Metapath + * wildcard name + * test. + */ +public class Wildcard implements IExpression { @SuppressWarnings("null") @Override public List getChildren() { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractComparison.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/AbstractComparison.java similarity index 90% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractComparison.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/AbstractComparison.java index c707123f6..090b0c244 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractComparison.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/AbstractComparison.java @@ -24,8 +24,11 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.comparison; +import gov.nist.secauto.metaschema.core.metapath.cst.AbstractBinaryExpression; +import gov.nist.secauto.metaschema.core.metapath.cst.IBooleanLogicExpression; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; import gov.nist.secauto.metaschema.core.metapath.function.ComparisonFunctions; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -36,7 +39,7 @@ * expressions representing the left and right sides of the comparison, and a * comparison operator. */ -abstract class AbstractComparison // NOPMD - unavoidable +public abstract class AbstractComparison // NOPMD - unavoidable extends AbstractBinaryExpression implements IBooleanLogicExpression { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/GeneralComparison.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/GeneralComparison.java similarity index 86% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/GeneralComparison.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/GeneralComparison.java index 06978b165..c804e862a 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/GeneralComparison.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/GeneralComparison.java @@ -24,8 +24,12 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.comparison; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +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.function.ComparisonFunctions; import gov.nist.secauto.metaschema.core.metapath.function.library.FnData; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; @@ -33,7 +37,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class GeneralComparison +public class GeneralComparison extends AbstractComparison { /** @@ -46,7 +50,9 @@ class GeneralComparison * @param right * the expression to compare with */ - protected GeneralComparison(@NonNull IExpression left, @NonNull ComparisonFunctions.Operator operator, + public GeneralComparison( + @NonNull IExpression left, + @NonNull ComparisonFunctions.Operator operator, @NonNull IExpression right) { super(left, operator, right); } @@ -62,5 +68,4 @@ public ISequence accept(DynamicContext dynamicContext, I ISequence rightItems = FnData.fnData(getRight().accept(dynamicContext, focus)); return ISequence.of(ComparisonFunctions.generalCompairison(leftItems, getOperator(), rightItems)); } - } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ValueComparison.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/ValueComparison.java similarity index 90% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ValueComparison.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/ValueComparison.java index de16ef0f7..4489d2dea 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ValueComparison.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/ValueComparison.java @@ -24,8 +24,12 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.comparison; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +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.function.ComparisonFunctions; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem; @@ -33,7 +37,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -class ValueComparison +public class ValueComparison extends AbstractComparison { /** @@ -46,7 +50,7 @@ class ValueComparison * @param right * the expression to compare with */ - protected ValueComparison( + public ValueComparison( @NonNull IExpression left, @NonNull ComparisonFunctions.Operator operator, @NonNull IExpression right) { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/package-info.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/package-info.java new file mode 100644 index 000000000..9c0f9b514 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/comparison/package-info.java @@ -0,0 +1,27 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst.comparison; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractArithmeticExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/AbstractArithmeticExpression.java similarity index 89% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractArithmeticExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/AbstractArithmeticExpression.java index fae11fc2b..816aaf6ee 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractArithmeticExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/AbstractArithmeticExpression.java @@ -24,8 +24,11 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.math; +import gov.nist.secauto.metaschema.core.metapath.cst.AbstractBinaryExpression; +import gov.nist.secauto.metaschema.core.metapath.cst.ExpressionUtils; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import java.util.List; @@ -41,7 +44,7 @@ * @param * the base result of evaluating the arithmetic expression */ -abstract class AbstractArithmeticExpression +public abstract class AbstractArithmeticExpression extends AbstractBinaryExpression { @NonNull diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractBasicArithmeticExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/AbstractBasicArithmeticExpression.java similarity index 92% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractBasicArithmeticExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/AbstractBasicArithmeticExpression.java index ccc145d93..a05af29e8 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractBasicArithmeticExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/AbstractBasicArithmeticExpression.java @@ -24,14 +24,17 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.math; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -abstract class AbstractBasicArithmeticExpression +public abstract class AbstractBasicArithmeticExpression extends AbstractArithmeticExpression { /** diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Addition.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Addition.java similarity index 94% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Addition.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Addition.java index 6b513a2ff..d8715fdcf 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Addition.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Addition.java @@ -24,8 +24,11 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.math; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +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.function.FunctionUtils; import gov.nist.secauto.metaschema.core.metapath.function.OperationFunctions; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; @@ -37,7 +40,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Addition +public class Addition extends AbstractBasicArithmeticExpression { /** @@ -48,7 +51,7 @@ class Addition * @param right * an expression whose result is summed */ - protected Addition(@NonNull IExpression left, @NonNull IExpression right) { + public Addition(@NonNull IExpression left, @NonNull IExpression right) { super(left, right); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Division.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Division.java similarity index 92% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Division.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Division.java index 71d9c9b81..235becc13 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Division.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Division.java @@ -24,8 +24,12 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.math; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.InvalidTypeMetapathException; +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.function.FunctionUtils; import gov.nist.secauto.metaschema.core.metapath.function.OperationFunctions; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; @@ -35,7 +39,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Division +public class Division extends AbstractBasicArithmeticExpression { /** @@ -47,7 +51,7 @@ class Division * @param divisor * the expression whose result is to divide by */ - protected Division(@NonNull IExpression dividend, @NonNull IExpression divisor) { + public Division(@NonNull IExpression dividend, @NonNull IExpression divisor) { super(dividend, divisor); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IntegerDivision.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/IntegerDivision.java similarity index 90% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IntegerDivision.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/IntegerDivision.java index 60a6a9ed2..3ab966ba9 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/IntegerDivision.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/IntegerDivision.java @@ -24,8 +24,12 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.math; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +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.function.FunctionUtils; import gov.nist.secauto.metaschema.core.metapath.function.OperationFunctions; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem; @@ -34,7 +38,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -class IntegerDivision +public class IntegerDivision extends AbstractArithmeticExpression { /** @@ -46,7 +50,7 @@ class IntegerDivision * @param divisor * the expression whose item result will be divided by */ - protected IntegerDivision(@NonNull IExpression dividend, @NonNull IExpression divisor) { + public IntegerDivision(@NonNull IExpression dividend, @NonNull IExpression divisor) { super(dividend, divisor, IIntegerItem.class); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Modulo.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Modulo.java similarity index 90% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Modulo.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Modulo.java index 9912cbf08..0e0672544 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Modulo.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Modulo.java @@ -24,8 +24,12 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.math; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +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.function.FunctionUtils; import gov.nist.secauto.metaschema.core.metapath.function.OperationFunctions; import gov.nist.secauto.metaschema.core.metapath.item.atomic.INumericItem; @@ -33,7 +37,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -class Modulo +public class Modulo extends AbstractArithmeticExpression { /** @@ -45,7 +49,7 @@ class Modulo * @param divisor * the item to divide by */ - protected Modulo(@NonNull IExpression dividend, @NonNull IExpression divisor) { + public Modulo(@NonNull IExpression dividend, @NonNull IExpression divisor) { super(dividend, divisor, INumericItem.class); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Multiplication.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Multiplication.java similarity index 91% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Multiplication.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Multiplication.java index 30ffe7392..858069e42 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Multiplication.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Multiplication.java @@ -24,8 +24,12 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.math; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.InvalidTypeMetapathException; +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.function.FunctionUtils; import gov.nist.secauto.metaschema.core.metapath.function.OperationFunctions; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; @@ -35,7 +39,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Multiplication +public class Multiplication extends AbstractBasicArithmeticExpression { /** @@ -46,7 +50,7 @@ class Multiplication * @param right * the item to divide by */ - protected Multiplication(@NonNull IExpression left, @NonNull IExpression right) { + public Multiplication(@NonNull IExpression left, @NonNull IExpression right) { super(left, right); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Subtraction.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Subtraction.java similarity index 93% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Subtraction.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Subtraction.java index 8169ae8c7..85bc3badc 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Subtraction.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/Subtraction.java @@ -24,8 +24,12 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.math; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.InvalidTypeMetapathException; +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.function.FunctionUtils; import gov.nist.secauto.metaschema.core.metapath.function.OperationFunctions; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; @@ -37,7 +41,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Subtraction +public class Subtraction extends AbstractBasicArithmeticExpression { /** @@ -48,7 +52,7 @@ class Subtraction * @param subtrahend * an expression whose result is the value being subtracted */ - protected Subtraction(@NonNull IExpression minuend, @NonNull IExpression subtrahend) { + public Subtraction(@NonNull IExpression minuend, @NonNull IExpression subtrahend) { super(minuend, subtrahend); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/package-info.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/package-info.java new file mode 100644 index 000000000..bf4fc162c --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/math/package-info.java @@ -0,0 +1,27 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst.math; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/package-info.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/package-info.java new file mode 100644 index 000000000..35ca2ba10 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/package-info.java @@ -0,0 +1,39 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +/** + * Provides compact syntax tree (CST) node implementation for the Metapath + * syntax. + *

+ * The {@link gov.nist.secauto.metaschema.core.metapath.cst.BuildCSTVisitor} + * class is responsible for converting the abstract syntax tree (AST) generated + * by ANTLRv4 into a CST. + *

+ * The {@link gov.nist.secauto.metaschema.core.metapath.cst.CSTPrinter} can be + * used to visualize the CST as a string. This can be useful for debugging. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractPathExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractPathExpression.java similarity index 94% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractPathExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractPathExpression.java index e6cccc25d..410e900f0 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractPathExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractPathExpression.java @@ -24,8 +24,13 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.AbstractExpression; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; +import gov.nist.secauto.metaschema.core.metapath.cst.IPathExpression; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.metapath.item.ItemUtils; import gov.nist.secauto.metaschema.core.metapath.item.node.ICycledAssemblyNodeItem; @@ -35,7 +40,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -abstract class AbstractPathExpression +public abstract class AbstractPathExpression extends AbstractExpression implements IPathExpression { @Override diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractRelativePathExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractRelativePathExpression.java similarity index 92% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractRelativePathExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractRelativePathExpression.java index 4f5b7f2da..e0f49e61e 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractRelativePathExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractRelativePathExpression.java @@ -24,15 +24,17 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; +import gov.nist.secauto.metaschema.core.metapath.cst.ExpressionUtils; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import java.util.List; import edu.umd.cs.findbugs.annotations.NonNull; -abstract class AbstractRelativePathExpression +public abstract class AbstractRelativePathExpression extends AbstractPathExpression { @NonNull private final IExpression left; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractRootPathExpression.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractRootPathExpression.java similarity index 92% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractRootPathExpression.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractRootPathExpression.java index 86c9adbf0..ce1601be2 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractRootPathExpression.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/AbstractRootPathExpression.java @@ -24,15 +24,17 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; +import gov.nist.secauto.metaschema.core.metapath.cst.ExpressionUtils; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import java.util.List; import edu.umd.cs.findbugs.annotations.NonNull; -abstract class AbstractRootPathExpression +public abstract class AbstractRootPathExpression extends AbstractPathExpression { @NonNull private final IExpression expression; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Axis.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Axis.java similarity index 79% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Axis.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Axis.java index f0d42ab44..1895941a9 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Axis.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Axis.java @@ -24,9 +24,12 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Lexer; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +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; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.CollectionUtil; @@ -40,32 +43,21 @@ @SuppressWarnings("PMD.ShortClassName") // intentional public enum Axis implements IExpression { - SELF(metapath10Lexer.KW_SELF, focus -> Stream.of(focus)), - PARENT(metapath10Lexer.KW_PARENT, focus -> Stream.ofNullable(focus.getParentNodeItem())), - ANCESTOR(metapath10Lexer.KW_ANCESTOR, INodeItem::ancestor), - ANCESTOR_OR_SELF(metapath10Lexer.KW_ANCESTOR_OR_SELF, INodeItem::ancestorOrSelf), - CHILDREN(metapath10Lexer.KW_CHILD, INodeItem::modelItems), - DESCENDANT(metapath10Lexer.KW_DESCENDANT, INodeItem::descendant), - DESCENDANT_OR_SELF(metapath10Lexer.KW_DESCENDANT_OR_SELF, INodeItem::descendantOrSelf); + SELF(focus -> Stream.of(focus)), + PARENT(focus -> Stream.ofNullable(focus.getParentNodeItem())), + ANCESTOR(INodeItem::ancestor), + ANCESTOR_OR_SELF(INodeItem::ancestorOrSelf), + CHILDREN(INodeItem::modelItems), + DESCENDANT(INodeItem::descendant), + DESCENDANT_OR_SELF(INodeItem::descendantOrSelf); - private final int keywordIndex; @NonNull private final Function> action; - Axis(int keywordIndex, @NonNull Function> action) { - this.keywordIndex = keywordIndex; + Axis(@NonNull Function> action) { this.action = action; } - /** - * The ANTLR keyword for this axis type. - * - * @return the keyword - */ - public int getKeywordIndex() { - return keywordIndex; - } - /** * Execute the axis operation on the provided {@code focus}. * diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Flag.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Flag.java similarity index 86% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Flag.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Flag.java index fb2f62607..60d9e2a46 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Flag.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Flag.java @@ -24,8 +24,14 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.AbstractNamedInstanceExpression; +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.cst.Name; import gov.nist.secauto.metaschema.core.metapath.item.ItemUtils; import gov.nist.secauto.metaschema.core.metapath.item.node.IFlagNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; @@ -34,7 +40,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; -class Flag // NOPMD - intentional name +public class Flag // NOPMD - intentional name extends AbstractNamedInstanceExpression { /** @@ -44,7 +50,7 @@ class Flag // NOPMD - intentional name * @param test * the test to use to match */ - protected Flag(@NonNull IExpression test) { + public Flag(@NonNull IExpression test) { super(test); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ModelInstance.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/ModelInstance.java similarity index 87% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ModelInstance.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/ModelInstance.java index 532887fa7..f63c0a7f6 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ModelInstance.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/ModelInstance.java @@ -24,8 +24,14 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.AbstractNamedInstanceExpression; +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.cst.Name; import gov.nist.secauto.metaschema.core.metapath.item.ItemUtils; import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; @@ -36,7 +42,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; @SuppressWarnings("rawtypes") -class ModelInstance +public class ModelInstance extends AbstractNamedInstanceExpression { /** @@ -46,7 +52,7 @@ class ModelInstance * @param test * the test to use to match */ - protected ModelInstance(@NonNull IExpression test) { + public ModelInstance(@NonNull IExpression test) { super(test); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RelativeDoubleSlashPath.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RelativeDoubleSlashPath.java similarity index 84% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RelativeDoubleSlashPath.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RelativeDoubleSlashPath.java index 4f1539a85..b8487c689 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RelativeDoubleSlashPath.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RelativeDoubleSlashPath.java @@ -24,18 +24,22 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +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.node.INodeItem; import java.util.stream.Stream; import edu.umd.cs.findbugs.annotations.NonNull; -class RelativeDoubleSlashPath +public class RelativeDoubleSlashPath extends AbstractRelativePathExpression { - protected RelativeDoubleSlashPath(@NonNull IExpression left, @NonNull IExpression right) { + public RelativeDoubleSlashPath(@NonNull IExpression left, @NonNull IExpression right) { super(left, right); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RelativeSlashPath.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RelativeSlashPath.java similarity index 83% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RelativeSlashPath.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RelativeSlashPath.java index ad87cba68..5c61fdbf9 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RelativeSlashPath.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RelativeSlashPath.java @@ -24,14 +24,19 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; + +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpressionVisitor; import edu.umd.cs.findbugs.annotations.NonNull; -class RelativeSlashPath +public class RelativeSlashPath extends AbstractRelativePathExpression { - protected RelativeSlashPath(@NonNull IExpression left, @NonNull IExpression right) { + public RelativeSlashPath(@NonNull IExpression left, @NonNull IExpression right) { super(left, right); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RootDoubleSlashPath.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootDoubleSlashPath.java similarity index 84% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RootDoubleSlashPath.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootDoubleSlashPath.java index 89c3c63ba..b11ef79e3 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RootDoubleSlashPath.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootDoubleSlashPath.java @@ -24,14 +24,19 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; + +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpressionVisitor; import edu.umd.cs.findbugs.annotations.NonNull; -class RootDoubleSlashPath +public class RootDoubleSlashPath extends AbstractRootPathExpression { - protected RootDoubleSlashPath(@NonNull IExpression node) { + public RootDoubleSlashPath(@NonNull IExpression node) { super(node); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RootSlashOnlyPath.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPath.java similarity index 88% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RootSlashOnlyPath.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPath.java index 8b696bf68..c5e5902ea 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RootSlashOnlyPath.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashOnlyPath.java @@ -24,8 +24,12 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +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; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.CollectionUtil; @@ -33,13 +37,9 @@ import java.util.List; -class RootSlashOnlyPath +public class RootSlashOnlyPath extends AbstractPathExpression { - protected RootSlashOnlyPath() { - // reduce visibility - } - @Override public List getChildren() { return CollectionUtil.emptyList(); diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RootSlashPath.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashPath.java similarity index 86% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RootSlashPath.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashPath.java index 2aa0a0120..aecd482f6 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/RootSlashPath.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/RootSlashPath.java @@ -24,17 +24,21 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +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; import gov.nist.secauto.metaschema.core.util.ObjectUtils; import edu.umd.cs.findbugs.annotations.NonNull; -class RootSlashPath +public class RootSlashPath extends AbstractRootPathExpression { - protected RootSlashPath(@NonNull IExpression node) { + public RootSlashPath(@NonNull IExpression node) { super(node); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Step.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Step.java similarity index 86% rename from core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Step.java rename to core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Step.java index 5161da7d7..9cb6c7c92 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/Step.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/Step.java @@ -24,8 +24,13 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst.path; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.ExpressionUtils; +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.IItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; @@ -39,7 +44,7 @@ * with the evaluation of a series of predicate expressions that filter the * result of the evaluation. */ -class Step implements IExpression { // NOPMD - intentional +public class Step implements IExpression { // NOPMD - intentional @NonNull private final Axis axisExpression; @@ -57,7 +62,7 @@ class Step implements IExpression { // NOPMD - intentional * the sub-expression to evaluate before filtering with the predicates */ @SuppressWarnings("null") - protected Step(@NonNull Axis axis, @NonNull IExpression step) { + public Step(@NonNull Axis axis, @NonNull IExpression step) { this.axisExpression = axis; this.stepExpression = step; this.staticResultType = ExpressionUtils.analyzeStaticResultType(IItem.class, List.of(step)); @@ -69,7 +74,7 @@ public Axis getAxis() { } /** - * Get the stepExpression's sub-expression. + * Get the step expression's sub-expression. * * @return the sub-expression */ diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/package-info.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/package-info.java new file mode 100644 index 000000000..12e74f148 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/path/package-info.java @@ -0,0 +1,27 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst.path; 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 bb92e01ba..8907d8d66 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 @@ -328,24 +328,12 @@ public ISequence execute( if (isDeterministic()) { // check cache callingContext = new CallingContext(arguments, contextItem); + // TODO: implement something like computeIfAbsent // attempt to get the result from the cache result = dynamicContext.getCachedResult(callingContext); } if (result == null) { - // logger.info(String.format("Executing function '%s' with arguments '%s'.", - // toSignature(), - // convertedArguments.toString())); - - // INodeItem actualFocus = focus == null ? null : focus.getNodeItem(); - // if (isFocusDepenent() && actualFocus == null) { - // throw new - // DynamicMetapathException(DynamicMetapathException.DYNAMIC_CONTEXT_ABSENT, - // "Null - // focus"); - // } - // result = handler.execute(this, convertedArguments, dynamicContext, - // actualFocus); result = handler.execute(this, convertedArguments, dynamicContext, contextItem); if (callingContext != null) { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UriFunctionException.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UriFunctionException.java index 62767fc62..f30461b7e 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UriFunctionException.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/UriFunctionException.java @@ -27,10 +27,28 @@ package gov.nist.secauto.metaschema.core.metapath.function; import gov.nist.secauto.metaschema.core.metapath.AbstractCodedMetapathException; +import gov.nist.secauto.metaschema.core.metapath.function.library.FnResolveUri; +/** + * FONS: Exceptions related to function namespaces. + */ public class UriFunctionException extends AbstractCodedMetapathException { + /** + * err:FONS0004: + * Raised by fn:resolve-QName + * and analogous functions if a supplied QName has a prefix that has no binding + * to a namespace. + */ public static final int NO_NAMESPACE_FOUND_FOR_PREFIX = 4; + /** + * err:FONS0005: + * Raised by {@link FnResolveUri} if no base URI is available for resolving a + * relative URI. + */ public static final int BASE_URI_NOT_DEFINED_IN_STATIC_CONTEXT = 5; /** @@ -38,14 +56,43 @@ public class UriFunctionException */ private static final long serialVersionUID = 2L; + /** + * Constructs a new exception with the provided {@code code}, {@code message}, + * and no cause. + * + * @param code + * the error code value + * @param message + * the exception message + */ public UriFunctionException(int code, String message) { super(code, message); } + /** + * Constructs a new exception with the provided {@code code}, {@code message}, + * and {@code cause}. + * + * @param code + * the error code value + * @param message + * the exception message + * @param cause + * the original exception cause + */ public UriFunctionException(int code, String message, Throwable cause) { super(code, message, cause); } + /** + * Constructs a new exception with the provided {@code code}, no message, and + * the {@code cause}. + * + * @param code + * the error code value + * @param cause + * the original exception cause + */ public UriFunctionException(int code, Throwable cause) { super(code, cause); } diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/DefaultFunctionLibrary.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/DefaultFunctionLibrary.java index a3204c8cb..46c95dab7 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/DefaultFunctionLibrary.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/DefaultFunctionLibrary.java @@ -98,7 +98,7 @@ public DefaultFunctionLibrary() { // NOPMD - intentional // https://www.w3.org/TR/xpath-functions-31/#func-false registerFunction(FnFalse.SIGNATURE); // P1: https://www.w3.org/TR/xpath-functions-31/#func-floor - registerFunction(NumericFunction.signature(MetapathConstants.NS_XPATH_FUNCTIONS, "floor", INumericItem::floor)); + registerFunction(NumericFunction.signature(MetapathConstants.NS_METAPATH_FUNCTIONS, "floor", INumericItem::floor)); // P2: https://www.w3.org/TR/xpath-functions-31/#func-format-date // P2: https://www.w3.org/TR/xpath-functions-31/#func-format-dateTime // P2: https://www.w3.org/TR/xpath-functions-31/#func-format-integer diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAbs.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAbs.java index b14d36385..0d0a999f8 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAbs.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAbs.java @@ -51,7 +51,7 @@ public final class FnAbs { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name(NAME) - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAvg.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAvg.java index a57508a1b..27384f524 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAvg.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnAvg.java @@ -64,7 +64,7 @@ public final class FnAvg { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name(NAME) - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBaseUri.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBaseUri.java index 9f60633d6..91486eda6 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBaseUri.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBaseUri.java @@ -52,7 +52,7 @@ public final class FnBaseUri { @NonNull static final IFunction SIGNATURE_NO_ARG = IFunction.builder() .name("base-uri") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextDependent() .focusDependent() @@ -64,7 +64,7 @@ public final class FnBaseUri { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("base-uri") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBoolean.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBoolean.java index aae808a8e..4d044095a 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBoolean.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnBoolean.java @@ -51,7 +51,7 @@ public final class FnBoolean { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name("boolean") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCeiling.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCeiling.java index 75b8ea092..215ede52b 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCeiling.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCeiling.java @@ -51,7 +51,7 @@ public final class FnCeiling { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name(NAME) - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCompare.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCompare.java index 98ad6a20e..a4be84cfe 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCompare.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCompare.java @@ -46,7 +46,7 @@ public class FnCompare { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name("compare") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextDependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCount.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCount.java index 366d25f0e..ce3b62898 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCount.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnCount.java @@ -46,7 +46,7 @@ public final class FnCount { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name(NAME) - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() 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 21a70b33d..e287ec810 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 @@ -53,7 +53,7 @@ public final class FnData { @NonNull static final IFunction SIGNATURE_NO_ARG = IFunction.builder() .name("data") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextDependent() .focusDependent() @@ -65,7 +65,7 @@ public final class FnData { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("data") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnDoc.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnDoc.java index 19103406b..efb74b3a0 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnDoc.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnDoc.java @@ -51,7 +51,7 @@ public final class FnDoc { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name("doc") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextDependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnDocumentUri.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnDocumentUri.java index 19732d39f..2e02b919e 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnDocumentUri.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnDocumentUri.java @@ -49,7 +49,7 @@ public final class FnDocumentUri { @NonNull static final IFunction SIGNATURE_NO_ARG = IFunction.builder() .name("document-uri") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextDependent() .focusDependent() @@ -61,7 +61,7 @@ public final class FnDocumentUri { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("document-uri") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnExists.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnExists.java index 55b4865b1..03f5f8db8 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnExists.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnExists.java @@ -48,7 +48,7 @@ public final class FnExists { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name("exists") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnFalse.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnFalse.java index 8ad3b7ee7..af651985b 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnFalse.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnFalse.java @@ -41,7 +41,7 @@ public final class FnFalse { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name("false") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMinMax.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMinMax.java index 7f166ff7e..0035a917e 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMinMax.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnMinMax.java @@ -56,7 +56,7 @@ public final class FnMinMax { @NonNull static final IFunction SIGNATURE_MIN = IFunction.builder() .name(NAME_MIN) - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() @@ -73,7 +73,7 @@ public final class FnMinMax { @NonNull static final IFunction SIGNATURE_MAX = IFunction.builder() .name(NAME_MAX) - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNot.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNot.java index 6df486e7d..453912700 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNot.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnNot.java @@ -43,7 +43,7 @@ public final class FnNot { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name("not") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnPath.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnPath.java index 3a7d8fd1f..1242f9bbc 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnPath.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnPath.java @@ -53,7 +53,7 @@ public final class FnPath { @NonNull static final IFunction SIGNATURE_NO_ARG = IFunction.builder() .name("path") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextDependent() .focusDependent() @@ -65,7 +65,7 @@ public final class FnPath { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("path") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnResolveUri.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnResolveUri.java index 013ce26d2..fbfe91ec3 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnResolveUri.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnResolveUri.java @@ -48,7 +48,7 @@ public final class FnResolveUri { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("resolve-uri") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextDependent() .focusIndependent() @@ -65,7 +65,7 @@ public final class FnResolveUri { @NonNull static final IFunction SIGNATURE_TWO_ARG = IFunction.builder() .name("resolve-uri") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnRound.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnRound.java index 047985842..5edef5cf5 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnRound.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnRound.java @@ -52,7 +52,7 @@ public final class FnRound { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name(NAME) - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() @@ -69,7 +69,7 @@ public final class FnRound { @NonNull static final IFunction SIGNATURE_WITH_PRECISION = IFunction.builder() .name(NAME) - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStartsWith.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStartsWith.java index 4b644bfce..33320a005 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStartsWith.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStartsWith.java @@ -47,7 +47,7 @@ public final class FnStartsWith { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name("starts-with") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .argument(IArgument.builder() .name("arg1").type(IStringItem.class) .zeroOrOne() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStaticBaseUri.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStaticBaseUri.java index 34a0d45dd..1fc6a1b73 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStaticBaseUri.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnStaticBaseUri.java @@ -45,7 +45,7 @@ public final class FnStaticBaseUri { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name("static-base-uri") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .argument(IArgument.builder() .name("arg1") .type(IStringItem.class) diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnSum.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnSum.java index 67107d46d..93c418e83 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnSum.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnSum.java @@ -55,7 +55,7 @@ public final class FnSum { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name(NAME) - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() @@ -72,7 +72,7 @@ public final class FnSum { @NonNull static final IFunction SIGNATURE_TWO_ARG = IFunction.builder() .name(NAME) - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnTrue.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnTrue.java index eca3577cd..4b67241bf 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnTrue.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/FnTrue.java @@ -41,7 +41,7 @@ public final class FnTrue { @NonNull static final IFunction SIGNATURE = IFunction.builder() .name("true") - .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) .deterministic() .contextIndependent() .focusIndependent() diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpRecurseDepth.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpRecurseDepth.java index 8e9a1de39..5e3e83139 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpRecurseDepth.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpRecurseDepth.java @@ -27,11 +27,11 @@ package gov.nist.secauto.metaschema.core.metapath.function.library; import gov.nist.secauto.metaschema.core.metapath.DynamicContext; -import gov.nist.secauto.metaschema.core.metapath.DynamicMetapathException; import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.MetapathConstants; import gov.nist.secauto.metaschema.core.metapath.MetapathException; import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; +import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException; 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; @@ -54,7 +54,7 @@ public final class MpRecurseDepth { @NonNull static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() .name("recurse-depth") - .namespace(MetapathConstants.NS_METAPATH) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS_EXTENDED) .deterministic() .contextDependent() .focusDependent() @@ -71,7 +71,7 @@ public final class MpRecurseDepth { @NonNull static final IFunction SIGNATURE_TWO_ARG = IFunction.builder() .name("recurse-depth") - .namespace(MetapathConstants.NS_METAPATH) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS_EXTENDED) .deterministic() .contextDependent() .focusIndependent() @@ -136,7 +136,7 @@ private static ISequence recurseDepth( try { recursionMetapath = MetapathExpression.compile(recursionPath.asString()); } catch (MetapathException ex) { - throw new DynamicMetapathException(DynamicMetapathException.INVALID_PATH_GRAMMAR, ex.getMessage(), ex); + throw new StaticMetapathException(StaticMetapathException.INVALID_PATH_GRAMMAR, ex.getMessage(), ex); } return recurseDepth(initialContext, recursionMetapath, dynamicContext); diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlModelParser.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlModelParser.java index 0e611ca10..1298a416b 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlModelParser.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlModelParser.java @@ -157,15 +157,16 @@ private static void append( container.getModelInstances().add(assembly); } - public void parseChoice( + // REFACTOR: move up to calling location + public static void parseChoice( @NonNull ChoiceType xmlObject, @NonNull IModelContainer parent, @NonNull IStandardModelContainerSupport container) { MODEL_PARSER.parse(xmlObject, Pair.of(parent, container)); } - // TODO: move back to calling location - public void parseModel( + // REFACTOR: move up to calling location + public static void parseModel( @NonNull AssemblyModelType xmlObject, @NonNull IModelContainer parent, @NonNull IStandardModelContainerSupport container) { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlModule.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlModule.java index a467f5bbb..f2a75efc8 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlModule.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlModule.java @@ -96,6 +96,7 @@ public XmlModule( // NOPMD - unavoidable METASCHEMA metaschemaNode = module.getMETASCHEMA(); // handle definitions in this module + // TODO: switch implementation to use the XmlObjectParser { // start with flag definitions try (XmlCursor cursor = metaschemaNode.newCursor()) { diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlObjectParser.java b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlObjectParser.java index 8a2d3ec43..72d63e388 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlObjectParser.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/model/xml/impl/XmlObjectParser.java @@ -43,6 +43,7 @@ import javax.xml.namespace.QName; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; public class XmlObjectParser { private final Map> elementNameToHandlerMap; @@ -104,6 +105,29 @@ private String getXpath() { return xpath; } + @Nullable + public static String getLocation(@NonNull XmlCursor cursor) { + String retval = null; + XmlBookmark bookmark = cursor.getBookmark(XmlLineNumber.class); + if (bookmark != null) { + StringBuilder locationBuilder = new StringBuilder(); + XmlLineNumber lineNumber = (XmlLineNumber) bookmark; + + String source = cursor.documentProperties().getSourceName(); + if (source != null) { + locationBuilder.append(source) + .append(':'); + } + + locationBuilder.append(lineNumber.getLine()) + .append(':') + .append(lineNumber.getColumn()); + + retval = locationBuilder.toString(); + } + return retval; + } + /** * Used to determine which parser {@link Handler} implementation to use to parse * the object. @@ -124,23 +148,15 @@ protected Handler identifyHandler(@NonNull XmlCursor cursor, @NonNull XmlObje QName qname = cursor.getName(); Handler retval = getElementNameToHandlerMap().get(qname); if (retval == null) { - String location = ""; - XmlBookmark bookmark = cursor.getBookmark(XmlLineNumber.class); - if (bookmark != null) { - StringBuilder locationBuilder = new StringBuilder(); - XmlLineNumber lineNumber = (XmlLineNumber) bookmark; - locationBuilder.append(" at location '"); - - String source = cursor.documentProperties().getSourceName(); - if (source != null) { - locationBuilder.append(source) - .append(':'); - } - - locationBuilder.append(lineNumber.getLine()) - .append(':') - .append(lineNumber.getColumn()) - .append('\''); + String location = getLocation(cursor); + if (location == null) { + location = ""; + } else { + location = new StringBuilder() + .append(" at location '") + .append(location) + .append('\'') + .toString(); } throw new IllegalStateException(String.format("Unhandled node '%s'%s.", qname, location)); } diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/MarkupParserTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/MarkupParserTest.java index 839536eb3..f9cd70861 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/MarkupParserTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/MarkupParserTest.java @@ -83,8 +83,7 @@ void test() throws XMLStreamException { assertDoesNotThrow(() -> { MarkupMultiline markupString = XmlMarkupParser.instance().parseMarkupMultiline(reader); - AstCollectingVisitor visitor = new AstCollectingVisitor(); - visitor.collect(markupString.getDocument()); + AstCollectingVisitor.asString(markupString.getDocument()); // System.out.println(html); // System.out.println(visitor.getAst()); // System.out.println(markupString.toMarkdown()); diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/MarkupXmlStreamWriterTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/MarkupXmlStreamWriterTest.java index bf3780a22..7692bf29d 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/MarkupXmlStreamWriterTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/markup/flexmark/MarkupXmlStreamWriterTest.java @@ -49,6 +49,15 @@ class MarkupXmlStreamWriterTest { @Test void testHTML() throws XMLStreamException { + + XMLOutputFactory2 factory = (XMLOutputFactory2) XMLOutputFactory.newInstance(); + assert factory instanceof WstxOutputFactory; + factory.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, false); + XMLStreamWriter2 xmlStreamWriter = (XMLStreamWriter2) factory.createXMLStreamWriter(System.out); + NamespaceContext nsContext = MergedNsContext.construct(xmlStreamWriter.getNamespaceContext(), + List.of(NamespaceEventImpl.constructNamespace(null, NS_PREFIX, NAMESPACE))); + xmlStreamWriter.setNamespaceContext(nsContext); + String html = "

Example

\n" + "

textquote1

\n" + "\n" @@ -63,17 +72,7 @@ void testHTML() throws XMLStreamException { + "

Some more text \"alt\"

\n"; MarkupMultiline ms = MarkupMultiline.fromHtml(html); - AstCollectingVisitor visitor = new AstCollectingVisitor(); - visitor.collect(ms.getDocument()); - // System.out.println(visitor.getAst()); - - XMLOutputFactory2 factory = (XMLOutputFactory2) XMLOutputFactory.newInstance(); - assert factory instanceof WstxOutputFactory; - factory.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, false); - XMLStreamWriter2 xmlStreamWriter = (XMLStreamWriter2) factory.createXMLStreamWriter(System.out); - NamespaceContext nsContext = MergedNsContext.construct(xmlStreamWriter.getNamespaceContext(), - List.of(NamespaceEventImpl.constructNamespace(null, NS_PREFIX, NAMESPACE))); - xmlStreamWriter.setNamespaceContext(nsContext); + // System.out.println(AstCollectingVisitor.asString(ms.getDocument())); ms.writeXHtml(NAMESPACE, xmlStreamWriter); xmlStreamWriter.close(); diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ExpressionTestBase.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ExpressionTestBase.java index b440caa5f..745ec8ca0 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ExpressionTestBase.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ExpressionTestBase.java @@ -62,7 +62,7 @@ protected static DynamicContext newDynamicContext() { return StaticContext.builder() .baseUri(baseUri) - .build().newDynamicContext(); + .build().dynamicContext(); } @NonNull diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ExpressionUtilsTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ExpressionUtilsTest.java index c1d24a8e7..1644be040 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ExpressionUtilsTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ExpressionUtilsTest.java @@ -28,6 +28,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import gov.nist.secauto.metaschema.core.metapath.cst.ExpressionUtils; +import gov.nist.secauto.metaschema.core.metapath.cst.IExpression; import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IFieldNodeItem; diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/TestUtils.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/TestUtils.java index 6c21eed9a..65da46bd5 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/TestUtils.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/TestUtils.java @@ -105,7 +105,7 @@ public static ISequence executeFunction( @Nullable ISequence focus, List> arguments) { - DynamicContext context = dynamicContext == null ? StaticContext.newInstance().newDynamicContext() : dynamicContext; + DynamicContext context = dynamicContext == null ? StaticContext.instance().dynamicContext() : dynamicContext; ISequence focusSeqence = function.isFocusDepenent() ? ObjectUtils.requireNonNull(focus, "Function call requires a focus") : ISequence.empty(); diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/AndTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/AndTest.java similarity index 92% rename from core/src/test/java/gov/nist/secauto/metaschema/core/metapath/AndTest.java rename to core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/AndTest.java index 1dbcde3ad..1630676b6 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/AndTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/AndTest.java @@ -24,10 +24,14 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import static org.junit.jupiter.api.Assertions.assertEquals; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +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.item.atomic.IBooleanItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/BuildAstVisitorTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildAstVisitorTest.java similarity index 91% rename from core/src/test/java/gov/nist/secauto/metaschema/core/metapath/BuildAstVisitorTest.java rename to core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildAstVisitorTest.java index 25c8b4c53..cc64f42aa 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/BuildAstVisitorTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/BuildAstVisitorTest.java @@ -24,7 +24,7 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; @@ -38,9 +38,17 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; import gov.nist.secauto.metaschema.core.metapath.MetapathExpression.ResultType; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Lexer; -import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Parser; +import gov.nist.secauto.metaschema.core.metapath.StaticContext; +import gov.nist.secauto.metaschema.core.metapath.antlr.FailingErrorListener; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10; +import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10Lexer; +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.AbstractComparison; +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.GeneralComparison; +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.ValueComparison; import gov.nist.secauto.metaschema.core.metapath.function.ComparisonFunctions; import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; import gov.nist.secauto.metaschema.core.metapath.item.IItem; @@ -91,21 +99,21 @@ private IDocumentNodeItem newTestDocument() { @NonNull private static DynamicContext newDynamicContext() { return StaticContext.builder() - .build().newDynamicContext(); + .build().dynamicContext(); } private static IExpression parseExpression(@NonNull String path) { - metapath10Lexer lexer = new metapath10Lexer(CharStreams.fromString(path)); + Metapath10Lexer lexer = new Metapath10Lexer(CharStreams.fromString(path)); CommonTokenStream tokens = new CommonTokenStream(lexer); - metapath10Parser parser = new metapath10Parser(tokens); + Metapath10 parser = new Metapath10(tokens); parser.addErrorListener(new FailingErrorListener()); ParseTree tree = parser.expr(); - // CSTPrinter cstPrinter = new CSTPrinter(System.out); + // ParseTreePrinter cstPrinter = new ParseTreePrinter(System.out); // cstPrinter.print(tree, Arrays.asList(parser.getRuleNames())); - return new BuildAstVisitor().visit(tree); + return new BuildCSTVisitor().visit(tree); } @Test diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/FlagTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/FlagTest.java similarity index 91% rename from core/src/test/java/gov/nist/secauto/metaschema/core/metapath/FlagTest.java rename to core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/FlagTest.java index 861c590b0..973e29692 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/FlagTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/FlagTest.java @@ -24,10 +24,14 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import static org.junit.jupiter.api.Assertions.assertEquals; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.path.Flag; import gov.nist.secauto.metaschema.core.metapath.item.node.IFlagNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.NodeItemType; diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/OrTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/OrTest.java similarity index 92% rename from core/src/test/java/gov/nist/secauto/metaschema/core/metapath/OrTest.java rename to core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/OrTest.java index f609453b3..0b3c87a72 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/OrTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/OrTest.java @@ -24,10 +24,14 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import static org.junit.jupiter.api.Assertions.assertEquals; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +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.item.atomic.IBooleanItem; import gov.nist.secauto.metaschema.core.util.ObjectUtils; diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/PredicateTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/PredicateTest.java similarity index 95% rename from core/src/test/java/gov/nist/secauto/metaschema/core/metapath/PredicateTest.java rename to core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/PredicateTest.java index 233b1f1b9..8e485412d 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/PredicateTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/PredicateTest.java @@ -24,10 +24,13 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import static org.junit.jupiter.api.Assertions.assertEquals; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase; +import gov.nist.secauto.metaschema.core.metapath.ISequence; import gov.nist.secauto.metaschema.core.metapath.item.node.IAssemblyNodeItem; import gov.nist.secauto.metaschema.core.util.CollectionUtil; diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/QuantifiedTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/QuantifiedTest.java new file mode 100644 index 000000000..ed36990da --- /dev/null +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/QuantifiedTest.java @@ -0,0 +1,62 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase; +import gov.nist.secauto.metaschema.core.metapath.MetapathExpression; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import edu.umd.cs.findbugs.annotations.NonNull; + +class QuantifiedTest + extends ExpressionTestBase { + private static Stream testQuantified() { // NOPMD - false positive + return Stream.of( + Arguments.of( + true, + MetapathExpression.compile("some $x in (1, 2, 3), $y in (2, 3, 4) satisfies $x + $y = 4")), + Arguments.of( + false, + MetapathExpression.compile("every $x in (1, 2, 3), $y in (2, 3, 4) satisfies $x + $y = 4"))); + } + + @ParameterizedTest + @MethodSource + void testQuantified(boolean expected, @NonNull MetapathExpression metapath) { + DynamicContext dynamicContext = newDynamicContext(); + + assertEquals(expected, metapath.evaluateAs(null, MetapathExpression.ResultType.BOOLEAN, dynamicContext)); + } +} diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/RangeTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/RangeTest.java new file mode 100644 index 000000000..a256436a8 --- /dev/null +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/RangeTest.java @@ -0,0 +1,67 @@ +/* + * Portions of this software was developed by employees of the National Institute + * of Standards and Technology (NIST), an agency of the Federal Government and is + * being made available as a public service. Pursuant to title 17 United States + * Code Section 105, works of NIST employees are not subject to copyright + * protection in the United States. This software may be subject to foreign + * copyright. Permission in the United States and in foreign countries, to the + * extent that NIST may hold copyright, to use, copy, modify, create derivative + * works, and distribute this software and its documentation without fee is hereby + * granted on a non-exclusive basis, provided that this notice and disclaimer + * of warranty appears in all copies. + * + * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER + * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY + * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM + * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE + * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT + * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, + * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, + * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, + * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR + * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT + * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. + */ + +package gov.nist.secauto.metaschema.core.metapath.cst; + +import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer; +import static org.junit.jupiter.api.Assertions.assertEquals; + +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 org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import edu.umd.cs.findbugs.annotations.NonNull; + +class RangeTest + extends ExpressionTestBase { + private static Stream provideValues() { // NOPMD - false positive + return Stream.of( + Arguments.of( + ISequence.of(integer(2), integer(3), integer(4), integer(5)), + MetapathExpression.compile("2 to 5")), + Arguments.of( + ISequence.empty(), + MetapathExpression.compile("() to 2")), + Arguments.of( + ISequence.empty(), + MetapathExpression.compile("2 to ()")), + Arguments.of( + ISequence.empty(), + MetapathExpression.compile("5 to 2"))); + } + + @ParameterizedTest + @MethodSource("provideValues") + void testRange(@NonNull ISequence expected, @NonNull MetapathExpression metapath) { + assertEquals(expected, metapath.evaluateAs(null, MetapathExpression.ResultType.SEQUENCE, newDynamicContext())); + } +} diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/RootSlashOnlyTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/RootSlashOnlyTest.java similarity index 89% rename from core/src/test/java/gov/nist/secauto/metaschema/core/metapath/RootSlashOnlyTest.java rename to core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/RootSlashOnlyTest.java index 36fa432c9..efb946be2 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/RootSlashOnlyTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/RootSlashOnlyTest.java @@ -24,10 +24,14 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import static org.junit.jupiter.api.Assertions.assertEquals; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.path.RootSlashOnlyPath; import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ValueComparisonTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/ValueComparisonTest.java similarity index 95% rename from core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ValueComparisonTest.java rename to core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/ValueComparisonTest.java index 3e99472bc..7e6233316 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/ValueComparisonTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/cst/ValueComparisonTest.java @@ -24,10 +24,14 @@ * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. */ -package gov.nist.secauto.metaschema.core.metapath; +package gov.nist.secauto.metaschema.core.metapath.cst; import static org.junit.jupiter.api.Assertions.assertEquals; +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase; +import gov.nist.secauto.metaschema.core.metapath.ISequence; +import gov.nist.secauto.metaschema.core.metapath.cst.comparison.ValueComparison; import gov.nist.secauto.metaschema.core.metapath.function.ComparisonFunctions; import gov.nist.secauto.metaschema.core.metapath.item.IItem; import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBooleanItem; diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidatorTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidatorTest.java index 79531a5ab..3e54f41c4 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidatorTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/model/constraint/DefaultConstraintValidatorTest.java @@ -96,7 +96,7 @@ void testAllowedValuesAllowOther() { }); DynamicContext dynamicContext = StaticContext.builder() - .build().newDynamicContext(); + .build().dynamicContext(); FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler(); DefaultConstraintValidator validator = new DefaultConstraintValidator(dynamicContext, handler); validator.validate(flag); @@ -149,7 +149,7 @@ void testAllowedValuesMultipleAllowOther() { }); DynamicContext dynamicContext = StaticContext.builder() - .build().newDynamicContext(); + .build().dynamicContext(); FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler(); DefaultConstraintValidator validator = new DefaultConstraintValidator(dynamicContext, handler); validator.validate(flag); @@ -210,7 +210,7 @@ void testMultipleAllowedValuesConflictingAllowOther() { }); DynamicContext dynamicContext = StaticContext.builder() - .build().newDynamicContext(); + .build().dynamicContext(); FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler(); DefaultConstraintValidator validator = new DefaultConstraintValidator(dynamicContext, handler); validator.validate(flag1); diff --git a/core/src/test/resources/log4j2-test.xml b/core/src/test/resources/log4j2-test.xml index 2999d73e4..84f3107d0 100644 --- a/core/src/test/resources/log4j2-test.xml +++ b/core/src/test/resources/log4j2-test.xml @@ -13,6 +13,11 @@ + diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java index dd833d240..f124ebaaa 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/IBindingContext.java @@ -287,7 +287,7 @@ default IConstraintValidator newValidator(@NonNull IConstraintValidationHandler IBoundLoader loader = newBoundLoader(); loader.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS); - DynamicContext context = StaticContext.newInstance().newDynamicContext(); + DynamicContext context = StaticContext.instance().dynamicContext(); context.setDocumentLoader(loader); return new DefaultConstraintValidator(context, handler); @@ -371,7 +371,7 @@ default IValidationResult validateWithConstraints(@NonNull Path target) throws I IBoundLoader loader = newBoundLoader(); loader.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS); - DynamicContext dynamicContext = StaticContext.newInstance().newDynamicContext(); + DynamicContext dynamicContext = StaticContext.instance().dynamicContext(); dynamicContext.setDocumentLoader(loader); IDocumentNodeItem nodeItem = loader.loadAsNodeItem(target); diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/AnnotationGenerator.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/AnnotationGenerator.java index 3c6b56b25..df14e8e2e 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/AnnotationGenerator.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/codegen/AnnotationGenerator.java @@ -432,7 +432,7 @@ private static void applyHasCardinalityConstraints( @NonNull AnnotationSpec.Builder annotation, @NonNull List constraints) { - DynamicContext dynamicContext = StaticContext.newInstance().newDynamicContext(); + DynamicContext dynamicContext = StaticContext.instance().dynamicContext(); dynamicContext.disablePredicateEvaluation(); for (ICardinalityConstraint constraint : constraints) { diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/AbstractDeserializer.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/AbstractDeserializer.java index dd71e0c91..47ea89fb7 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/AbstractDeserializer.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/AbstractDeserializer.java @@ -101,8 +101,8 @@ public INodeItem deserializeToNodeItem(Reader reader, URI documentUri) throws IO } if (isValidating()) { - StaticContext staticContext = StaticContext.newInstance(); - DynamicContext dynamicContext = staticContext.newDynamicContext(); + StaticContext staticContext = StaticContext.instance(); + DynamicContext dynamicContext = staticContext.dynamicContext(); dynamicContext.setDocumentLoader(getBindingContext().newBoundLoader()); DefaultConstraintValidator validator = new DefaultConstraintValidator( dynamicContext, diff --git a/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/DefaultBoundLoader.java b/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/DefaultBoundLoader.java index aa871213c..2eb77479b 100644 --- a/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/DefaultBoundLoader.java +++ b/databind/src/main/java/gov/nist/secauto/metaschema/databind/io/DefaultBoundLoader.java @@ -230,8 +230,8 @@ public IDocumentNodeItem loadAsNodeItem(URI uri) throws IOException { } } - @Override - public IDocumentNodeItem loadAsNodeItem(InputStream is, URI documentUri) throws IOException { + @NonNull + public IDocumentNodeItem loadAsNodeItem(@NonNull InputStream is, @NonNull URI documentUri) throws IOException { FormatDetector.Result formatMatch = getFormatDetector().detect(is); Format format = formatMatch.getFormat();