1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5  * the License. A copy of the License is located at
6  *
7  * http://aws.amazon.com/apache2.0
8  *
9  * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10  * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11  * and limitations under the License.
12  */
13 
14 package software.amazon.awssdk.services.kms.endpoints.internal;
15 
16 import java.util.List;
17 import java.util.stream.Collectors;
18 import software.amazon.awssdk.annotations.SdkInternalApi;
19 import software.amazon.awssdk.utils.Pair;
20 
21 @SdkInternalApi
22 public abstract class Fn extends Expr implements Into<Condition> {
23     protected FnNode fnNode;
24 
Fn(FnNode fnNode)25     public Fn(FnNode fnNode) {
26         this.fnNode = fnNode;
27     }
28 
29     /**
30      * Convert this fn into a condition
31      */
condition()32     public Condition condition() {
33         return new Condition.Builder().fn(this).build();
34     }
35 
condition(String result)36     public Condition condition(String result) {
37         return new Condition.Builder().fn(this).result(result).build();
38     }
39 
acceptFnVisitor(FnVisitor<T> visitor)40     public abstract <T> T acceptFnVisitor(FnVisitor<T> visitor);
41 
accept(ExprVisitor<R> visitor)42     public <R> R accept(ExprVisitor<R> visitor) {
43         return visitor.visitFn(this);
44     }
45 
46     /**
47      * Returns the name of this function, eg. {@code isSet}, {@code parseUrl}
48      *
49      * @return The name
50      */
getName()51     public String getName() {
52         return fnNode.getId();
53     }
54 
55     /**
56      * @return The arguments to this function
57      */
getArgv()58     public List<Expr> getArgv() {
59         return fnNode.getArgv();
60     }
61 
62     @Override
equals(Object o)63     public boolean equals(Object o) {
64         if (this == o) {
65             return true;
66         }
67         if (o == null || getClass() != o.getClass()) {
68             return false;
69         }
70         if (!super.equals(o)) {
71             return false;
72         }
73 
74         Fn fn = (Fn) o;
75 
76         return fnNode != null ? fnNode.equals(fn.fnNode) : fn.fnNode == null;
77     }
78 
79     @Override
hashCode()80     public int hashCode() {
81         return fnNode != null ? fnNode.hashCode() : 0;
82     }
83 
84     @Override
toString()85     public String toString() {
86         return String.format("%s(%s)", fnNode.getId(),
87                 fnNode.getArgv().stream().map(Expr::toString).collect(Collectors.joining(", ")));
88     }
89 
expectOneArg()90     protected Expr expectOneArg() {
91         List<Expr> argv = this.fnNode.getArgv();
92         if (argv.size() == 1) {
93             return argv.get(0);
94         } else {
95             throw RuleError.builder()
96                     .cause(SourceException.builder().message("expected 1 argument but found " + argv.size()).build()).build();
97         }
98     }
99 
expectTwoArgs()100     protected Pair<Expr, Expr> expectTwoArgs() {
101         List<Expr> argv = this.fnNode.getArgv();
102         if (argv.size() == 2) {
103             return Pair.of(argv.get(0), argv.get(1));
104         } else {
105             throw RuleError.builder()
106                     .cause(SourceException.builder().message("expected 2 arguments but found " + argv.size()).build()).build();
107         }
108 
109     }
110 
expectVariableArgs(int expectedNumberArgs)111     protected List<Expr> expectVariableArgs(int expectedNumberArgs) {
112         List<Expr> argv = this.fnNode.getArgv();
113         if (argv.size() == expectedNumberArgs) {
114             return argv;
115         } else {
116             throw RuleError
117                     .builder()
118                     .cause(SourceException.builder()
119                             .message(String.format("expected %d arguments but found %d", expectedNumberArgs, argv.size()))
120                             .build()).build();
121         }
122 
123     }
124 
125     @Override
into()126     public Condition into() {
127         return this.condition();
128     }
129 }
130