1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.core.metapath.function;
7   
8   import gov.nist.secauto.metaschema.core.metapath.item.IItem;
9   import gov.nist.secauto.metaschema.core.util.ObjectUtils;
10  
11  import java.util.Objects;
12  
13  import edu.umd.cs.findbugs.annotations.NonNull;
14  
15  /**
16   * Represents a single function argument signature.
17   */
18  public interface IArgument {
19    /**
20     * Get the argument's name.
21     *
22     * @return the argument's name
23     */
24    @NonNull
25    String getName();
26  
27    /**
28     * Get information about the type of sequence supported by the argument.
29     *
30     * @return the sequence information
31     */
32    @NonNull
33    ISequenceType getSequenceType();
34  
35    /**
36     * Get the signature of the argument.
37     *
38     * @return the argument's signature
39     */
40    @NonNull
41    String toSignature();
42  
43    /**
44     * Get a new argument builder.
45     *
46     * @return the new argument builder
47     */
48    @NonNull
49    static Builder builder() {
50      return new Builder();
51    }
52  
53    /**
54     * Used to create an argument's signature using a builder pattern.
55     */
56    final class Builder {
57      private String name;
58      @NonNull
59      private Class<? extends IItem> type = IItem.class;
60      private Occurrence occurrence;
61  
62      private Builder() {
63        // construct a new non-initialized builder
64      }
65  
66      private Builder(@NonNull String name) {
67        this.name = name;
68      }
69  
70      /**
71       * Define the name of the function argument.
72       *
73       * @param name
74       *          the argument's name
75       * @return this builder
76       */
77      @NonNull
78      public Builder name(@NonNull String name) {
79        if (Objects.requireNonNull(name, "name").isBlank()) {
80          throw new IllegalArgumentException("the name must be non-blank");
81        }
82        this.name = name.trim();
83        return this;
84      }
85  
86      /**
87       * Define the type of the function argument.
88       * <p>
89       * By default an argument has the type {@link IItem}.
90       *
91       * @param type
92       *          the argument's type
93       * @return this builder
94       */
95      @NonNull
96      public Builder type(@NonNull Class<? extends IItem> type) {
97        this.type = Objects.requireNonNull(type, "type");
98        return this;
99      }
100 
101     /**
102      * Identifies the argument's cardinality as a single, optional item (zero or
103      * one).
104      *
105      * @return this builder
106      */
107     @NonNull
108     public Builder zeroOrOne() {
109       return occurrence(Occurrence.ZERO_OR_ONE);
110     }
111 
112     /**
113      * Identifies the argument's cardinality as a single, required item (one).
114      *
115      * @return this builder
116      */
117     @NonNull
118     public Builder one() {
119       return occurrence(Occurrence.ONE);
120     }
121 
122     /**
123      * Identifies the argument's cardinality as an optional series of items (zero or
124      * more).
125      *
126      * @return this builder
127      */
128     @NonNull
129     public Builder zeroOrMore() {
130       return occurrence(Occurrence.ZERO_OR_MORE);
131     }
132 
133     /**
134      * Identifies the argument's cardinality as a required series of items (one or
135      * more).
136      *
137      * @return this builder
138      */
139     @NonNull
140     public Builder oneOrMore() {
141       return occurrence(Occurrence.ONE_OR_MORE);
142     }
143 
144     @NonNull
145     private Builder occurrence(@NonNull Occurrence occurrence) {
146       Objects.requireNonNull(occurrence, "occurrence");
147       this.occurrence = occurrence;
148       return this;
149     }
150 
151     /**
152      * Builds the argument's signature.
153      *
154      * @return the argument's signature
155      */
156     @NonNull
157     public IArgument build() {
158       return new ArgumentImpl(
159           ObjectUtils.requireNonNull(name, "the argument name must not be null"),
160           ISequenceType.of(type, ObjectUtils.requireNonNull(occurrence, "occurrence")));
161     }
162   }
163 }