All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.lucene.expressions.js.VariableContext Maven / Gradle / Ivy

There is a newer version: 10.0.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.lucene.expressions.js;


import java.util.ArrayList;
import java.util.List;

/**
 * A helper to parse the context of a variable name, which is the base variable, followed by the
 * sequence of array (integer or string indexed) and member accesses.
 */
public class VariableContext {

  /**
   * Represents what a piece of a variable does.
   */
  public static enum Type {
    /**
     * A member of the previous context (ie "dot" access).
     */ 
    MEMBER,

    /**
     * Brackets containing a string as the "index".
     */ 
    STR_INDEX,

    /**
     * Brackets containing an integer index (ie an array).
     */
    INT_INDEX,

    /**
     * Parenthesis represent a member method to be called.
     */
    METHOD
  }

  /**
   * The type of this piece of a variable.
   */ 
  public final Type type;

  /**
   * The text of this piece of the variable. Used for {@link Type#MEMBER} and {@link Type#STR_INDEX} types.
   */ 
  public final String text;

  /**
   * The integer value for this piece of the variable. Used for {@link Type#INT_INDEX}.
   */ 
  public final int integer;

  private VariableContext(Type c, String s, int i) {
    type = c;
    text = s;
    integer = i;
  }

  /**
   * Parses a normalized javascript variable. All strings in the variable should be single quoted,
   * and no spaces (except possibly within strings).
   */
  public static final VariableContext[] parse(String variable) {
    char[] text = variable.toCharArray();
    List contexts = new ArrayList<>();
    int i = addMember(text, 0, contexts); // base variable is a "member" of the global namespace
    while (i < text.length) {
      if (text[i] == '[') {
        if (text[++i] == '\'') {
          i = addStringIndex(text, i, contexts);
        } else {
          i = addIntIndex(text, i, contexts);
        }
        ++i; // move past end bracket
      } else { // text[i] == '.', ie object member
        i = addMember(text, i + 1, contexts);
      }
    }
    return contexts.toArray(new VariableContext[contexts.size()]);
  }

  // i points to start of member name
  private static int addMember(final char[] text, int i, List contexts) {
    int j = i + 1;
    while (j < text.length && text[j] != '[' && text[j] != '.' && text[j] != '(') ++j; // find first array, member access, or method call
    if (j + 1 < text.length && text[j] == '(' && text[j + 1] == ')') {
      contexts.add(new VariableContext(Type.METHOD, new String(text, i, j - i), -1));
      j += 2; //move past the parenthesis
    } else {
      contexts.add(new VariableContext(Type.MEMBER, new String(text, i, j - i), -1));
    }
    return j;
  }

  // i points to start of single quoted index
  private static int addStringIndex(final char[] text, int i, List contexts) {
    ++i; // move past quote
    int j = i;
    while (text[j] != '\'') { // find end of single quoted string
      if (text[j] == '\\') ++j; // skip over escapes
      ++j;
    }
    StringBuffer buf = new StringBuffer(j - i); // space for string, without end quote
    while (i < j) { // copy string to buffer (without begin/end quotes)
      if (text[i] == '\\') ++i; // unescape escapes
      buf.append(text[i]);
      ++i;
    }
    contexts.add(new VariableContext(Type.STR_INDEX, buf.toString(), -1));
    return j + 1; // move past quote, return end bracket location
  }

  // i points to start of integer index
  private static int addIntIndex(final char[] text, int i, List contexts) {
    int j = i + 1;
    while (text[j] != ']') ++j; // find end of array access
    int index = Integer.parseInt(new String(text, i, j - i));
    contexts.add(new VariableContext(Type.INT_INDEX, null, index));
    return j ;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy