001/* 002 * Portions of this software was developed by employees of the National Institute 003 * of Standards and Technology (NIST), an agency of the Federal Government and is 004 * being made available as a public service. Pursuant to title 17 United States 005 * Code Section 105, works of NIST employees are not subject to copyright 006 * protection in the United States. This software may be subject to foreign 007 * copyright. Permission in the United States and in foreign countries, to the 008 * extent that NIST may hold copyright, to use, copy, modify, create derivative 009 * works, and distribute this software and its documentation without fee is hereby 010 * granted on a non-exclusive basis, provided that this notice and disclaimer 011 * of warranty appears in all copies. 012 * 013 * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER 014 * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY 015 * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF 016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM 017 * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE 018 * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT 019 * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, 020 * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, 021 * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, 022 * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR 023 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT 024 * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. 025 */ 026 027package gov.nist.secauto.metaschema.core.metapath; 028 029import gov.nist.secauto.metaschema.core.metapath.antlr.metapath10Lexer; 030import gov.nist.secauto.metaschema.core.metapath.item.ItemUtils; 031import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; 032import gov.nist.secauto.metaschema.core.util.CollectionUtil; 033import gov.nist.secauto.metaschema.core.util.ObjectUtils; 034 035import java.util.List; 036import java.util.function.Function; 037import java.util.stream.Stream; 038 039import edu.umd.cs.findbugs.annotations.NonNull; 040 041@SuppressWarnings("PMD.ShortClassName") // intentional 042public enum Axis implements IExpression { 043 SELF(metapath10Lexer.KW_SELF, focus -> Stream.of(focus)), 044 PARENT(metapath10Lexer.KW_PARENT, focus -> Stream.ofNullable(focus.getParentNodeItem())), 045 ANCESTOR(metapath10Lexer.KW_ANCESTOR, INodeItem::ancestor), 046 ANCESTOR_OR_SELF(metapath10Lexer.KW_ANCESTOR_OR_SELF, INodeItem::ancestorOrSelf), 047 CHILDREN(metapath10Lexer.KW_CHILD, INodeItem::modelItems), 048 DESCENDANT(metapath10Lexer.KW_DESCENDANT, INodeItem::descendant), 049 DESCENDANT_OR_SELF(metapath10Lexer.KW_DESCENDANT_OR_SELF, INodeItem::descendantOrSelf); 050 051 private final int keywordIndex; 052 @NonNull 053 private final Function<INodeItem, Stream<? extends INodeItem>> action; 054 055 Axis(int keywordIndex, @NonNull Function<INodeItem, Stream<? extends INodeItem>> action) { 056 this.keywordIndex = keywordIndex; 057 this.action = action; 058 } 059 060 /** 061 * The ANTLR keyword for this axis type. 062 * 063 * @return the keyword 064 */ 065 public int getKeywordIndex() { 066 return keywordIndex; 067 } 068 069 /** 070 * Execute the axis operation on the provided {@code focus}. 071 * 072 * @param focus 073 * the node to operate on 074 * @return the result of the axis operation 075 */ 076 @NonNull 077 public Stream<? extends INodeItem> execute(@NonNull INodeItem focus) { 078 return ObjectUtils.notNull(action.apply(focus)); 079 } 080 081 @Override 082 public List<? extends IExpression> getChildren() { 083 return CollectionUtil.emptyList(); 084 } 085 086 @Override 087 public Class<INodeItem> getBaseResultType() { 088 return INodeItem.class; 089 } 090 091 @Override 092 public Class<INodeItem> getStaticResultType() { 093 return getBaseResultType(); 094 } 095 096 @Override 097 public <RESULT, CONTEXT> RESULT accept(IExpressionVisitor<RESULT, CONTEXT> visitor, CONTEXT context) { 098 return visitor.visitAxis(this, context); 099 } 100 101 @Override 102 public ISequence<? extends INodeItem> accept( 103 DynamicContext dynamicContext, 104 ISequence<?> outerFocus) { 105 ISequence<? extends INodeItem> retval; 106 if (outerFocus.isEmpty()) { 107 retval = ISequence.empty(); 108 } else { 109 retval = ISequence.of(outerFocus.asStream() 110 .map(item -> ItemUtils.checkItemIsNodeItemForStep(item)) 111 .flatMap(item -> { 112 assert item != null; 113 return execute(item); 114 }).distinct()); 115 } 116 return retval; 117 } 118}