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  package org.apache.commons.jexl3.parser;
18  
19  /**
20   * Identifiers, variables and registers.
21   */
22  public class ASTIdentifierAccess extends JexlNode {
23      /**
24       */
25      private static final long serialVersionUID = 1L;
26      /**
27       * Parse an identifier which must be of the form:
28       * 0|([1-9][0-9]*)
29       * @param id the identifier
30       * @return an integer or null
31       */
32      public static Integer parseIdentifier(final String id) {
33          // hand coded because the was no way to fail on leading '0's using NumberFormat
34          if (id != null) {
35              final int length = id.length();
36              int val = 0;
37              for (int i = 0; i < length; ++i) {
38                  final char c = id.charAt(i);
39                  // leading 0s but no just 0, NaN
40                  if (c == '0') {
41                      if (length == 1) {
42                          return 0;
43                      }
44                      if (val == 0) {
45                          return null;
46                      }
47                  } // any non numeric, NaN
48                  else if (c < '0' || c > '9') {
49                      return null;
50                  }
51                  val *= 10;
52                  val += c - '0';
53              }
54              return val;
55          }
56          return null;
57      }
58      private String name;
59  
60      private Integer identifier;
61  
62      ASTIdentifierAccess(final int id) {
63          super(id);
64      }
65  
66      public Object getIdentifier() {
67          return identifier != null ? identifier : name;
68      }
69  
70      public String getName() {
71          return name;
72      }
73  
74      /**
75       * Whether this is a Jxlt based identifier.
76       * @return true if `..${...}...`, false otherwise
77       */
78      public boolean isExpression() {
79          return false;
80      }
81  
82      @Override
83      public boolean isGlobalVar() {
84          return !isSafe() && !isExpression();
85      }
86  
87      /**
88       * Whether this is a dot or a question-mark-dot aka safe-navigation access.
89       * @return true is ?., false if .
90       */
91      public boolean isSafe() {
92          return false;
93      }
94  
95      @Override
96      public Object jjtAccept(final ParserVisitor visitor, final Object data) {
97          return visitor.visit(this, data);
98      }
99  
100     void setIdentifier(final String id) {
101         name = id;
102         identifier = parseIdentifier(id);
103     }
104 
105     @Override
106     public String toString() {
107         return name;
108     }
109 }