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