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    *      https://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  package org.apache.commons.jexl3.parser;
18  
19  import java.util.Map;
20  
21  import org.apache.commons.jexl3.JexlFeatures;
22  import org.apache.commons.jexl3.internal.Frame;
23  import org.apache.commons.jexl3.internal.Scope;
24  
25  /**
26   * Enhanced script to allow parameter declaration.
27   */
28  public class ASTJexlScript extends JexlLexicalNode  {
29  
30      /** Serial uid.*/
31      private static final long serialVersionUID = 202112111533L;
32  
33      /** The pragmas. */
34      private Map<String, Object> pragmas;
35  
36      /** Features. */
37      private transient JexlFeatures features;
38  
39      /** The script scope. */
40      private transient Scope scope;
41  
42      public ASTJexlScript(final int id) {
43          super(id);
44      }
45  
46      public ASTJexlScript(final Parser p, final int id) {
47          super(id);
48      }
49  
50      /**
51       * Creates an array of arguments by copying values up to the number of parameters.
52       *
53       * @param caller the calling frame
54       * @param values the argument values
55       * @return the arguments array
56       */
57      public Frame createFrame(final Frame caller, final Object... values) {
58          return scope != null ? scope.createFrame(features.supportsReferenceCapture(), caller, values) : null;
59      }
60  
61      /**
62       * Creates an array of arguments by copying values up to the number of parameters.
63       *
64       * @param values the argument values
65       * @return the arguments array
66       */
67      public Frame createFrame(final Object... values) {
68          return createFrame(null, values);
69      }
70  
71      /**
72       * Gets the (maximum) number of arguments this script expects.
73       *
74       * @return the number of parameters
75       */
76      public int getArgCount() {
77          return scope != null ? scope.getArgCount() : 0;
78      }
79  
80      /**
81       * Gets this script captured variable, i.e. symbols captured from outer scopes.
82       *
83       * @return the captured variable names
84       */
85      public String[] getCapturedVariables() {
86          return scope != null ? scope.getCapturedVariables() : new String[0];
87      }
88  
89      /**
90       * @return this script scope
91       */
92      public JexlFeatures getFeatures() {
93          return features;
94      }
95  
96      /**
97       * Gets this script local variable, i.e. symbols assigned to local variables.
98       *
99       * @return the local variable names
100      */
101     public String[] getLocalVariables() {
102         return scope != null ? scope.getLocalVariables() : new String[0];
103     }
104 
105     /**
106      * Gets this script parameters, i.e. symbols assigned before creating local variables.
107      *
108      * @return the parameter names
109      */
110     public String[] getParameters() {
111         return scope != null ? scope.getParameters() : new String[0];
112     }
113 
114     /**
115      * @return this script pragmas.
116      */
117     public Map<String, Object> getPragmas() {
118         return pragmas;
119     }
120 
121     /**
122      * @return this script scope
123      */
124     public Scope getScope() {
125         return scope;
126     }
127 
128     /**
129      * Gets this script symbols, i.e. parameters and local variables.
130      *
131      * @return the symbol names
132      */
133     public String[] getSymbols() {
134         return scope != null ? scope.getSymbols() : null;
135     }
136 
137     /**
138      * Checks whether a given symbol is captured.
139      *
140      * @param symbol the symbol number
141      * @return true if captured, false otherwise
142      */
143     public boolean isCapturedSymbol(final int symbol) {
144         return scope != null && scope.isCapturedSymbol(symbol);
145     }
146 
147     @Override
148     public Object jjtAccept(final ParserVisitor visitor, final Object data) {
149         return visitor.visit(this, data);
150     }
151 
152     /**
153      * Consider script with no parameters that return lambda as parametric-scripts.
154      *
155      * @return the script
156      */
157     public ASTJexlScript script() {
158         if (scope == null && jjtGetNumChildren() == 1 && jjtGetChild(0) instanceof ASTJexlLambda) {
159             final ASTJexlLambda lambda = (ASTJexlLambda) jjtGetChild(0);
160             lambda.jjtSetParent(null);
161             lambda.setFeatures(getFeatures());
162             return lambda;
163         }
164         return this;
165     }
166 
167     /**
168      * Sets this script features.
169      *
170      * @param theFeatures the features
171      */
172     public void setFeatures(final JexlFeatures theFeatures) {
173         this.features = theFeatures;
174     }
175 
176     /**
177      * Sets this script pragmas.
178      *
179      * @param thePragmas the pragmas
180      */
181     public void setPragmas(final Map<String, Object> thePragmas) {
182         this.pragmas = thePragmas;
183     }
184 
185     /**
186      * Sets this script scope.
187      *
188      * @param theScope the scope
189      */
190     public void setScope(final Scope theScope) {
191         this.scope = theScope;
192         if (theScope != null) {
193             for(int a = 0; a < theScope.getArgCount(); ++a) {
194                 declareSymbol(a);
195             }
196         }
197     }
198 }