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.ArrayList; 17 import java.util.HashMap; 18 import java.util.List; 19 import java.util.Map; 20 import java.util.stream.Collectors; 21 import software.amazon.awssdk.annotations.SdkInternalApi; 22 import software.amazon.awssdk.core.exception.SdkClientException; 23 import software.amazon.awssdk.protocols.jsoncore.JsonNode; 24 25 @SdkInternalApi 26 public class Literal extends Expr { 27 public interface Visitor<T> { 28 visitBool(boolean b)29 T visitBool(boolean b); 30 visitStr(Template value)31 T visitStr(Template value); 32 visitObject(Map<Identifier, Literal> members)33 T visitObject(Map<Identifier, Literal> members); 34 visitTuple(List<Literal> members)35 T visitTuple(List<Literal> members); 36 visitInt(int value)37 T visitInt(int value); 38 } 39 40 private final Lit source; 41 Literal(Lit source)42 private Literal(Lit source) { 43 this.source = source; 44 } 45 accept(Visitor<T> visitor)46 public <T> T accept(Visitor<T> visitor) { 47 return this.source.accept(visitor); 48 } 49 expectLiteralString()50 public String expectLiteralString() { 51 if (source instanceof Str) { 52 Str s = (Str) source; 53 54 return s.value.expectLiteral(); 55 } else { 56 throw RuleError.builder() 57 .cause(SourceException.builder().message("Expected a literal string, got " + source).build()).build(); 58 } 59 } 60 61 @Override accept(ExprVisitor<R> visitor)62 public <R> R accept(ExprVisitor<R> visitor) { 63 return visitor.visitLiteral(this); 64 } 65 66 @Override eval(Scope<Value> scope)67 public Value eval(Scope<Value> scope) { 68 return source.accept(new Visitor<Value>() { 69 @Override 70 public Value visitInt(int value) { 71 return Value.fromInteger(value); 72 } 73 74 @Override 75 public Value visitBool(boolean b) { 76 return Value.fromBool(b); 77 } 78 79 @Override 80 public Value visitStr(Template value) { 81 return value.eval(scope); 82 } 83 84 @Override 85 public Value visitObject(Map<Identifier, Literal> members) { 86 Map<Identifier, Value> tpe = new HashMap<>(); 87 members.forEach((k, v) -> { 88 tpe.put(k, v.eval(scope)); 89 }); 90 return Value.fromRecord(tpe); 91 } 92 93 @Override 94 public Value visitTuple(List<Literal> members) { 95 List<Value> tuples = new ArrayList<>(); 96 for (Literal el : ((Tuple) source).members) { 97 tuples.add(el.eval(scope)); 98 } 99 return Value.fromArray(tuples); 100 } 101 }); 102 } 103 104 @Override 105 public boolean equals(Object o) { 106 if (this == o) { 107 return true; 108 } 109 if (o == null || getClass() != o.getClass()) { 110 return false; 111 } 112 if (!super.equals(o)) { 113 return false; 114 } 115 116 Literal literal = (Literal) o; 117 118 return source != null ? source.equals(literal.source) : literal.source == null; 119 } 120 121 @Override 122 public int hashCode() { 123 return source != null ? source.hashCode() : 0; 124 } 125 126 public String toString() { 127 return source.toString(); 128 } 129 130 public static Literal fromNode(JsonNode node) { 131 Lit lit; 132 if (node.isArray()) { 133 List<Literal> array = node.asArray().stream().map(Literal::fromNode).collect(Collectors.toList()); 134 lit = new Tuple(array); 135 } else if (node.isBoolean()) { 136 lit = new Bool(node.asBoolean()); 137 } else if (node.isNull()) { 138 throw SdkClientException.create("null node not supported"); 139 } else if (node.isNumber()) { 140 lit = new Int(Integer.parseInt(node.asNumber())); 141 } else if (node.isObject()) { 142 Map<Identifier, Literal> obj = new HashMap<>(); 143 node.asObject().forEach((k, v) -> obj.put(Identifier.of(k), fromNode(v))); 144 lit = new Obj(obj); 145 } else if (node.isString()) { 146 lit = new Str(new Template(node.asString())); 147 } else { 148 throw SdkClientException.create("Unable to create literal from " + node); 149 } 150 return new Literal(lit); 151 } 152 153 public static Literal fromTuple(List<Literal> authSchemes) { 154 return new Literal(new Tuple(authSchemes)); 155 } 156 157 public static Literal fromRecord(Map<Identifier, Literal> record) { 158 return new Literal(new Obj(record)); 159 } 160 161 public static Literal fromStr(Template value) { 162 return new Literal(new Str(value)); 163 } 164 165 public static Literal fromStr(String s) { 166 return fromStr(new Template(s)); 167 } 168 169 public static Literal fromInteger(int value) { 170 return new Literal(new Int(value)); 171 } 172 173 public static Literal fromBool(boolean value) { 174 return new Literal(new Bool(value)); 175 } 176 177 private interface Lit { 178 <T> T accept(Visitor<T> visitor); 179 } 180 181 static final class Int implements Lit { 182 private final Integer value; 183 184 Int(Integer value) { 185 this.value = value; 186 } 187 188 @Override 189 public <T> T accept(Visitor<T> visitor) { 190 return visitor.visitInt(value); 191 } 192 193 @Override 194 public String toString() { 195 return Integer.toString(value); 196 } 197 198 @Override 199 public boolean equals(Object o) { 200 if (this == o) { 201 return true; 202 } 203 if (o == null || getClass() != o.getClass()) { 204 return false; 205 } 206 207 Int anInt = (Int) o; 208 209 return value != null ? value.equals(anInt.value) : anInt.value == null; 210 } 211 212 @Override 213 public int hashCode() { 214 return value != null ? value.hashCode() : 0; 215 } 216 } 217 218 static final class Tuple implements Lit { 219 private final List<Literal> members; 220 221 Tuple(List<Literal> members) { 222 this.members = members; 223 } 224 225 @Override 226 public <T> T accept(Visitor<T> visitor) { 227 return visitor.visitTuple(members); 228 } 229 230 @Override 231 public String toString() { 232 return members.stream().map(Literal::toString).collect(Collectors.joining(", ", "[", "]")); 233 } 234 235 public List<Literal> members() { 236 return members; 237 } 238 239 @Override 240 public boolean equals(Object o) { 241 if (this == o) { 242 return true; 243 } 244 if (o == null || getClass() != o.getClass()) { 245 return false; 246 } 247 248 Tuple tuple = (Tuple) o; 249 250 return members != null ? members.equals(tuple.members) : tuple.members == null; 251 } 252 253 @Override 254 public int hashCode() { 255 return members != null ? members.hashCode() : 0; 256 } 257 } 258 259 static final class Obj implements Lit { 260 private final Map<Identifier, Literal> members; 261 262 Obj(Map<Identifier, Literal> members) { 263 this.members = members; 264 } 265 266 @Override 267 public <T> T accept(Visitor<T> visitor) { 268 return visitor.visitObject(members); 269 } 270 271 @Override 272 public String toString() { 273 return members.toString(); 274 } 275 276 public Map<Identifier, Literal> members() { 277 return members; 278 } 279 280 @Override 281 public boolean equals(Object o) { 282 if (this == o) { 283 return true; 284 } 285 if (o == null || getClass() != o.getClass()) { 286 return false; 287 } 288 289 Obj obj = (Obj) o; 290 291 return members != null ? members.equals(obj.members) : obj.members == null; 292 } 293 294 @Override 295 public int hashCode() { 296 return members != null ? members.hashCode() : 0; 297 } 298 } 299 300 static final class Bool implements Lit { 301 private final boolean value; 302 303 Bool(boolean value) { 304 this.value = value; 305 } 306 307 @Override 308 public <T> T accept(Visitor<T> visitor) { 309 return visitor.visitBool(value); 310 } 311 312 @Override 313 public String toString() { 314 return Boolean.toString(value); 315 } 316 317 public Boolean value() { 318 return value; 319 } 320 321 @Override 322 public boolean equals(Object o) { 323 if (this == o) { 324 return true; 325 } 326 if (o == null || getClass() != o.getClass()) { 327 return false; 328 } 329 330 Bool bool = (Bool) o; 331 332 return value == bool.value; 333 } 334 335 @Override 336 public int hashCode() { 337 return value ? 1 : 0; 338 } 339 } 340 341 static final class Str implements Lit { 342 private final Template value; 343 344 Str(Template value) { 345 this.value = value; 346 } 347 348 @Override 349 public <T> T accept(Visitor<T> visitor) { 350 return visitor.visitStr(value); 351 } 352 353 @Override 354 public String toString() { 355 return value.toString(); 356 } 357 358 public Template value() { 359 return value; 360 } 361 362 @Override 363 public boolean equals(Object o) { 364 if (this == o) { 365 return true; 366 } 367 if (o == null || getClass() != o.getClass()) { 368 return false; 369 } 370 371 Str str = (Str) o; 372 373 return value != null ? value.equals(str.value) : str.value == null; 374 } 375 376 @Override 377 public int hashCode() { 378 return value != null ? value.hashCode() : 0; 379 } 380 } 381 } 382