View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shardingsphere.infra.expr.espresso;
19  
20  import lombok.SneakyThrows;
21  
22  import java.util.stream.Stream;
23  
24  /**
25   * Reflect Value.
26   * Avoid using JDK21 bytecode during compilation. Refer to `org.graalvm.polyglot.Value`.
27   */
28  public class ReflectValue {
29      
30      private static final String VALUE_CLASS_NAME = "org.graalvm.polyglot.Value";
31      
32      private final Object valueInstance;
33      
34      public ReflectValue(final Object valueInstance) {
35          this.valueInstance = valueInstance;
36      }
37      
38      /**
39       * Returns the member with a given identifier or null if the member does not exist.
40       * @param identifier the member identifier
41       * @return {@link org.apache.shardingsphere.infra.expr.espresso.ReflectValue}
42       */
43      @SneakyThrows
44      public ReflectValue getMember(final String identifier) {
45          Object resultValueInstance = Class.forName(VALUE_CLASS_NAME)
46                  .getMethod("getMember", String.class)
47                  .invoke(valueInstance, identifier);
48          return new ReflectValue(resultValueInstance);
49      }
50      
51      /**
52       * Instantiates this value if it can be instantiated.
53       * @param arguments the arguments
54       * @return {@link org.apache.shardingsphere.infra.expr.espresso.ReflectValue}
55       */
56      @SneakyThrows
57      public ReflectValue newInstance(final Object... arguments) {
58          Object resultValueInstance = Class.forName(VALUE_CLASS_NAME)
59                  .getMethod("newInstance", Object[].class)
60                  .invoke(valueInstance, new Object[]{Stream.of(arguments).toArray()});
61          return new ReflectValue(resultValueInstance);
62      }
63      
64      /**
65       * Invokes the given member of this value.
66       * @param identifier the member identifier to invoke
67       * @param arguments the invocation arguments
68       * @return {@link org.apache.shardingsphere.infra.expr.espresso.ReflectValue}
69       */
70      @SneakyThrows
71      public ReflectValue invokeMember(final String identifier, final Object... arguments) {
72          Object resultValueInstance = Class.forName(VALUE_CLASS_NAME)
73                  .getMethod("invokeMember", String.class, Object[].class)
74                  .invoke(valueInstance, identifier, arguments);
75          return new ReflectValue(resultValueInstance);
76      }
77      
78      /**
79       * Returns true if this value represents a string.
80       * @return Returns true if this value represents a string.
81       */
82      @SneakyThrows
83      public boolean isString() {
84          return (boolean) Class.forName(VALUE_CLASS_NAME)
85                  .getMethod("isString")
86                  .invoke(valueInstance);
87      }
88      
89      /**
90       * Maps a polyglot value to a value with a given Java target type.
91       * @param targetType the target Java type to map
92       * @param <T> target type
93       * @return target type
94       */
95      @SneakyThrows
96      @SuppressWarnings("unchecked")
97      public <T> T as(final Class<T> targetType) {
98          return (T) Class.forName(VALUE_CLASS_NAME)
99                  .getMethod("as", Class.class)
100                 .invoke(valueInstance, targetType);
101     }
102 }