1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.databind.metapath.function;
7   
8   import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
9   import gov.nist.secauto.metaschema.core.metapath.ISequence;
10  import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
11  import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
12  import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
13  import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
14  import gov.nist.secauto.metaschema.core.metapath.item.IItem;
15  import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem;
16  import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
17  import gov.nist.secauto.metaschema.core.model.IDefinition;
18  import gov.nist.secauto.metaschema.core.model.INamedInstance;
19  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
20  import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingModelElement;
21  
22  import java.util.List;
23  
24  import edu.umd.cs.findbugs.annotations.NonNull;
25  
26  public final class Model {
27    @NonNull
28    static final IFunction SIGNATURE = IFunction.builder()
29        .name("model")
30        .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS_EXTENDED)
31        .argument(IArgument.builder()
32            .name("node")
33            .type(INodeItem.class)
34            .one()
35            .build())
36        .returnType(INodeItem.class)
37        .focusIndependent()
38        .contextIndependent()
39        .deterministic()
40        .returnZeroOrOne()
41        .functionHandler(Model::execute)
42        .build();
43  
44    private Model() {
45      // disable construction
46    }
47  
48    @SuppressWarnings({ "unused",
49        "PMD.OnlyOneReturn" // readability
50    })
51    @NonNull
52    public static ISequence<?> execute(
53        @NonNull IFunction function,
54        @NonNull List<ISequence<?>> arguments,
55        @NonNull DynamicContext dynamicContext,
56        IItem focus) {
57      assert arguments.size() == 1;
58      ISequence<? extends INodeItem> nodeSequence = FunctionUtils.asType(
59          ObjectUtils.notNull(arguments.get(0)));
60  
61      if (nodeSequence.isEmpty()) {
62        return ISequence.empty();
63      }
64  
65      // always not null, since the first item is required
66      INodeItem node = nodeSequence.getFirstItem(true);
67  
68      if (!(node instanceof IDefinitionNodeItem)) {
69        return ISequence.empty();
70      }
71  
72      node = getModel((IDefinitionNodeItem<?, ?>) node);
73      return ISequence.of(node);
74    }
75  
76    public static INodeItem getModel(@NonNull IDefinitionNodeItem<?, ?> definitionNodeItem) {
77      INamedInstance instance = definitionNodeItem.getInstance();
78  
79      INodeItem retval = null;
80      if (instance != null) {
81        if (instance instanceof IBindingModelElement) {
82          retval = ((IBindingModelElement) instance).getSourceNodeItem();
83        }
84      } else {
85        IDefinition definition = definitionNodeItem.getDefinition();
86        if (definition instanceof IBindingModelElement) {
87          retval = ((IBindingModelElement) definition).getSourceNodeItem();
88        }
89      }
90  
91      return retval;
92    }
93  }