Package simpleserver.events

Source Code of simpleserver.events.PostfixEvaluator

/*
* Copyright (c) 2010 SimpleServer authors (see CONTRIBUTORS)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package simpleserver.events;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

import simpleserver.Player;
import simpleserver.config.GiveAliasList.Item;
import simpleserver.config.xml.Area;

@SuppressWarnings("unused")
public class PostfixEvaluator {
  private RunningEvent e;
  private ArrayList<String> expstack;
  private static HashMap<String, String> ops;

  PostfixEvaluator(RunningEvent context) {
    e = context;
    expstack = new ArrayList<String>();

    if (ops == null) {
      initOps();
    }
  }

  private void initOps() {
    ops = new HashMap<String, String>(); // maps operator token -> method name

    ops.put("not", "not");
    ops.put("and", "and");
    ops.put("or", "or");

    ops.put("+", "add");
    ops.put("-", "sub");
    ops.put("*", "mul");
    ops.put("/", "div");
    ops.put("%", "mod");

    ops.put("gt", "gt");
    ops.put("lt", "lt");
    ops.put("eq", "eq");

    ops.put(".", "strcat");
    ops.put("..", "strcatspace");
    ops.put("isempty", "isempty");
    ops.put("length", "length");

    ops.put("int", "str2num");
    ops.put("bool", "str2bool");
    ops.put("rand", "rand");
    ops.put("currtime", "currtime");
    ops.put("totime", "int2timestr");
    ops.put("evalvar", "evalvar");
    ops.put("getitemalias", "id2alias");
    ops.put("getitemid", "alias2id");

    ops.put("dup", "dup");
    ops.put("drop", "drop");
    ops.put("flip", "flip");

    ops.put("getgroup", "getgroup");
    ops.put("getplayers", "getplayers");
    ops.put("isinarea", "isinarea");
    ops.put("getcoord", "getcoord");

    /* array ops */

    ops.put("Anew", "arraynew");
    ops.put("Acreate", "arraycreate");

    ops.put("Apush", "arraypush");
    ops.put("Apop", "arraypop");
    ops.put("Ainsert", "arrayinsert");
    ops.put("Aremove", "arrayremove");
    ops.put("Asize", "arraysize");
    ops.put("Aisempty", "arrayisempty");
    ops.put("Acontains", "arraycontains");
    ops.put("Aget", "arrayget");
    ops.put("Agetlast", "arraygetlast");
    ops.put("Ajoin", "arrayjoin");
    ops.put("Aexplode", "arrayexplode");

    /* hash ops */
    ops.put("Hnew", "hashnew");
    ops.put("Hcreate", "hashcreate");

    ops.put("Hput", "hashput");
    ops.put("Hget", "hashget");
    ops.put("Hremove", "hashremove");
    ops.put("Hcontainskey", "hashcontainskey");
    ops.put("Hcontainsvalue", "hashcontainsval");
    ops.put("Hisempty", "hashisempty");
    ops.put("Hsize", "hashsize");
    ops.put("Hkeys", "hashkeys");
    ops.put("Hvalues", "hashvalues");

    /* check that all methods really exist... */
    try {
      for (String name : ops.values()) {
        java.lang.reflect.Method m = this.getClass().getDeclaredMethod(name, new Class[] {});
      }
    } catch (NoSuchMethodException e) {
      System.out.println("Error in event interpreter - stack operator method mappings faulty!");
      System.out.println("Please file a bug report!");
    }

  }

  /*---- push + pop helpers ----*/

  private String pop() throws IndexOutOfBoundsException {
    return expstack.remove(0);
  }

  private Long popNum() throws IndexOutOfBoundsException {
    return toNum(expstack.remove(0));

  }

  private Boolean popBool() throws IndexOutOfBoundsException {
    return toBool(expstack.remove(0));
  }

  private ArrayList<String> popArray() throws IndexOutOfBoundsException {
    return toArray(expstack.remove(0));
  }

  private HashMap<String, String> popHash() throws IndexOutOfBoundsException {
    return toHash(expstack.remove(0));
  }

  private void push(String val) {
    expstack.add(0, String.valueOf(val));
  }

  private void push(long val) {
    expstack.add(0, String.valueOf(val));
  }

  private void push(boolean val) {
    expstack.add(0, String.valueOf(val));
  }

  private void push(ArrayList<String> val) {
    expstack.add(0, fromArray(val));
  }

  private void push(HashMap<String, String> val) {
    expstack.add(0, fromHash(val));
  }

  /*---- interface ----*/

  /* evaluate, return all elements left at the end */
  public ArrayList<String> evaluate(ArrayList<String> tokens) {

    try {
      while (tokens.size() > 0) {
        String elem = tokens.remove(0);
        if (elem.charAt(0) == RunningEvent.REFERENCEOP) { // escape->as string
          elem = elem.substring(1);
          push(elem);
          continue;
        }

        if (ops.containsKey(elem)) { // look through methods
          this.getClass().getDeclaredMethod(ops.get(elem), new Class[] {}).invoke(this);
        } else { // no method in hash -> regular value
          push(elem);
        }
      }
    } catch (Exception ex) {
      e.notifyError("Invalid expression!");
      return null;
    }

    ArrayList<String> ret = new ArrayList<String>();
    for (String s : expstack) {
      ret.add(0, s);
    }

    return ret;
  }

  /* evaluate, return top element */
  public String evaluateSingle(ArrayList<String> tokens) {
    tokens = evaluate(tokens);

    if (expstack.size() == 0) {
      e.notifyError("Expression returns no value! Returning null.");
      return null;
    } else if (expstack.size() > 1) {
      e.notifyError("Expression returns multiple values! Returning last.");
    }

    return pop(); // one element left -> correct evaluated result
  }

  /* evaluate stack, use as boolean expression */
  public boolean evaluateCondition(ArrayList<String> tokens) {
    return toBool(evaluateSingle(tokens));
  }

  /*---- Common data type methods ----*/

  public static boolean toBool(String bool) {
    if (bool.equals("false") || bool.equals("null") || bool.equals("") || bool.equals("0")) {
      return false;
    }
    return true;
  }

  public static long toNum(String num) {
    long ret = 0;
    try {
      ret = Long.valueOf(num);
    } catch (Exception e) {
      if (num.equals("true")) {
        return 1;
      } else {
        return 0;
      }
    }

    return ret;
  }

  /* format time string from milliseconds (max. unit=days) */
  public static String fmtTime(long ms) {
    long millis = ms % 1000;
    ms -= millis;
    ms /= 1000;
    long secs = ms % 60;
    ms -= secs;
    ms /= 60;
    long mins = ms % 60;
    ms -= mins;
    ms /= 60;
    long hrs = ms % 24;
    ms -= hrs;
    ms /= 24;
    long days = ms;

    String time = "";
    if (days != 0) {
      time += String.valueOf(days) + "d ";
    }
    if (hrs != 0) {
      time += String.valueOf(hrs) + "h ";
    }
    if (mins != 0) {
      time += String.valueOf(mins) + "m ";
    }
    if (secs != 0) {
      time += String.valueOf(secs) + "s ";
    }
    if (millis != 0) {
      time += String.valueOf(millis) + "ms ";
    }

    return time;
  }

  public static ArrayList<String> toArray(String val) {
    if (val == null || val.length() < 2 || val.charAt(0) != '[' || val.charAt(val.length() - 1) != ']') {
      return new ArrayList<String>(); // not valid array -> return empty one
    }

    ArrayList<String> arr = new ArrayList<String>();
    val = val.substring(1, val.length() - 1);
    for (String s : val.split("(?<!\\\\),")) {
      s = unescape(s, ",");
      if (!s.equals("")) {
        arr.add(s);
      }
    }

    return arr;
  }

  public static String fromArray(ArrayList<String> val) {
    String s = "[";
    while (val.size() != 0) {
      String t = val.remove(0);
      t = escape(t, ",");
      s += t;

      if (val.size() != 0) {
        s += ",";
      }
    }
    s += "]";
    return s;
  }

  public static String fromHash(HashMap<String, String> val) {
    String s = "{";

    if (val.size() > 0) {
      for (String key : val.keySet()) {
        String t = val.get(key);
        key = escape(key, ",:");
        t = escape(t, ",:");
        s += key + ":" + t + ",";
      }
      s = s.substring(0, s.length() - 1);
    }

    s += "}";
    return s;
  }

  public static HashMap<String, String> toHash(String val) {
    if (val == null || val.length() < 2 || val.charAt(0) != '{' || val.charAt(val.length() - 1) != '}') {
      return new HashMap<String, String>(); // not valid hash -> return empty
                                            // one
    }

    HashMap<String, String> ret = new HashMap<String, String>();
    val = val.substring(1, val.length() - 1);
    for (String s : val.split("(?<!\\\\),")) {
      String[] toks = s.split("(?<!\\\\):");
      if (toks.length != 2) {
        return new HashMap<String, String>();
      }
      ret.put(unescape(toks[0], ",:"), unescape(toks[1], ",:"));
    }

    return ret;
  }

  /*---- generic (un)escape for array/hash/etc ----*/
  public static String escape(String str, String chars) {
    String ret = str;
    for (int i = 0; i < chars.length(); i++) {
      String c = chars.substring(i, i + 1);
      ret = ret.replaceAll(c, "\\\\" + c);
    }
    return ret;
  }

  public static String unescape(String str, String chars) {
    String ret = str;
    for (int i = 0; i < chars.length(); i++) {
      String c = chars.substring(i, i + 1);
      ret = ret.replaceAll("\\\\" + c, c);
    }
    return ret;
  }

  /*---- Operators ----*/

  /* boolean ops */

  private void not() {
    push(!popBool());
  }

  private void and() {
    boolean b2 = popBool();
    boolean b1 = popBool();
    push(b1 && b2);
  }

  private void or() {
    boolean b2 = popBool();
    boolean b1 = popBool();
    push(b1 || b2);
  }

  /* number ops */

  private void add() {
    long d2 = popNum();
    long d1 = popNum();
    push(d1 + d2);
  }

  private void sub() {
    long d2 = popNum();
    long d1 = popNum();
    push(d1 - d2);
  }

  private void mul() {
    long d2 = popNum();
    long d1 = popNum();
    push(d1 * d2);
  }

  private void div() {
    long d2 = popNum();
    long d1 = popNum();
    push(d1 / d2);
  }

  private void mod() {
    long d2 = popNum();
    long d1 = popNum();
    push(d1 % d2);
  }

  private void rand() {
    long d = popNum();
    push(e.eventHost.rng.nextInt((int) d));
  }

  /* comparison ops */

  private void gt() {
    long d2 = popNum();
    long d1 = popNum();
    push(d1 > d2);
  }

  private void lt() {
    long d2 = popNum();
    long d1 = popNum();
    push(d1 < d2);
  }

  private void eq() {
    String v2 = pop();
    String v1 = pop();
    push(v1.equals(v2));
  }

  /* string ops */

  private void strcat() {
    String s2 = pop();
    String s1 = pop();
    push(s1 + s2);
  }

  private void strcatspace() {
    String s2 = pop();
    String s1 = pop();
    push(s1 + " " + s2);
  }

  private void isempty() {
    push(pop().equals(""));
  }

  private void length() {
    push(pop().length());
  }

  /* other ops */

  private void str2num() {
    push(popNum());
  }

  private void str2bool() {
    push(popBool());
  }

  private void currtime() {
    push(String.valueOf(System.currentTimeMillis()));
  }

  private void int2timestr() {
    push(fmtTime(popNum()));
  }

  private void evalvar() {
    String s = pop();
    String v = e.evaluateVar(s);
    if (v != null) {
      push(v);
    } else {
      e.notifyError("Warning: Invalid variable: " + s + "! Returning null");
      push("null");
    }
  }

  private void id2alias() {
    String[] id = pop().split(":");
    String alias = "null";
    if (id.length == 1) {
      alias = e.server.giveAliasList.getAlias(Integer.valueOf(id[0]), 0);
    }
    else {
      alias = e.server.giveAliasList.getAlias(Integer.valueOf(id[0]), Integer.valueOf(id[1]));
    }
    push(alias);
  }

  private void alias2id() {
    String alias = pop();
    Item i = e.server.giveAliasList.getItemId(alias);
    if (i != null) {
      String id = String.valueOf(i.id);
      if (i.damage != 0) {
        id += ":" + String.valueOf(i.damage);
      }
      push(id);
    } else {
      push("null");
    }
  }

  private void dup() {
    String s = pop();
    push(s);
    push(s);
  }

  private void drop() {
    pop();
  }

  private void flip() {
    if (expstack.size() < 2) {
      return;
    }

    String b = pop();
    String a = pop();
    push(b);
    push(a);
  }

  private void getgroup() {
    String s = pop();
    Player tmp = e.server.findPlayer(s);
    if (tmp == null) {
      e.notifyError("getgroup: Player not found! Returning group -1");
      push(-1);
    } else {
      push(tmp.getGroupId());
    }
  }

  private void getplayers() {
    ArrayList<String> players = new ArrayList<String>();
    for (Player p : e.server.playerList.getArray()) {
      players.add(p.getName());
    }
    push(players);

  }

  private void isinarea() {
    String area = pop();
    String player = pop();
    Player p = e.server.findPlayer(player);
    if (p == null) {
      e.notifyError("isarea: Player not found!");
      push(false);
    }
    HashSet<Area> areas = new HashSet<Area>(e.server.config.dimensions.areas(p.position()));
    for (Area a : areas) {
      if (a.name.equals(area)) {
        push(true);
        return;
      }
    }
    push(false);
    return;
  }

  private void getcoord() {
    String player = pop();
    Player p = e.server.findPlayer(player);
    if (p == null) {
      e.notifyError("isarea: Player not found!");
      push(false);
    }

    ArrayList<String> c = new ArrayList<String>();
    c.add(String.valueOf(p.position().x()));
    c.add(String.valueOf(p.position().y()));
    c.add(String.valueOf(p.position().z()));
    push(c);
  }

  /* array ops */

  private void arraynew() {
    push(new ArrayList<String>());
  }

  private void arraycreate() {
    long num = popNum();
    ArrayList<String> arr = new ArrayList<String>();
    for (int i = 0; i < num; i++) {
      arr.add(0, pop());
    }

    push(arr);
  }

  private void arraypush() {
    String val = pop();
    ArrayList<String> arr = popArray();
    arr.add(val);
    push(arr);
  }

  private void arraypop() {
    ArrayList<String> arr = popArray();
    if (arr.size() != 0) {
      arr.remove(arr.size() - 1);
      push(arr);

    } else {
      e.notifyError("Popping empty array!");
    }
  }

  private void arrayinsert() {
    String val = pop();
    int index = popNum().intValue();
    ArrayList<String> arr = popArray();

    if (index >= 0 && arr.size() >= index) {
      arr.add(index, val);
    } else {
      e.notifyError("Index out of range!");
    }
    push(arr);
  }

  private void arrayremove() {
    int index = popNum().intValue();
    ArrayList<String> arr = popArray();

    if (index >= 0 && arr.size() > index) {
      arr.remove(index);
    } else {
      e.notifyError("Index out of range!");
    }
    push(arr);
  }

  private void arrayget() {
    int index = popNum().intValue();
    ArrayList<String> arr = popArray();

    if (index >= 0 && arr.size() > index) {
      push(unescape(arr.get(index), ","));
    } else {
      e.notifyError("Index out of range!");
      push("null");
    }
  }

  private void arraycontains() {
    String val = pop();
    ArrayList<String> arr = popArray();
    push(arr.contains(val));
  }

  private void arraygetlast() {
    ArrayList<String> arr = popArray();

    if (arr.size() != 0) {
      push(arr.remove(arr.size() - 1));
    } else {
      e.notifyError("Popping empty array!");
      push("null");
    }
  }

  private void arraysize() {
    ArrayList<String> arr = popArray();
    push(arr.size());
  }

  private void arrayisempty() {
    ArrayList<String> arr = popArray();
    push(arr.size() == 0);
  }

  private void arrayjoin() {
    String delimeter = pop();
    ArrayList<String> arr = popArray();

    String s = "";
    while (arr.size() != 0) {
      s += unescape(arr.remove(0), ",");
      if (arr.size() != 0) {
        s += delimeter;
      }
    }
    push(s);
  }

  private void arrayexplode() {
    ArrayList<String> arr = popArray();
    if (arr.size() > 0) {
      for (String e : arr) {
        push(e);
      }
    } else {
      push("null");
    }
  }

  /* hash ops */

  private void hashnew() {
    push(new HashMap<String, String>());
  }

  private void hashcreate() {
    long num = popNum();
    HashMap<String, String> h = new HashMap<String, String>();

    for (int i = 0; i < num; i++) {
      String val = pop();
      String key = pop();
      if (!key.equals("") && !key.equals("null")) {
        h.put(key, val);
      } else {
        e.notifyError("Invalid hash key! Ignoring hash pair...");
      }
    }

    push(h);
  }

  private void hashput() {
    String val = pop();
    String key = pop();
    HashMap<String, String> h = popHash();

    if (!key.equals("") && !key.equals("null")) {
      h.put(key, val);
    } else {
      e.notifyError("Invalid hash key!");
    }

    push(h);
  }

  private void hashget() {
    String key = pop();
    HashMap<String, String> h = popHash();

    if (!key.equals("") && !key.equals("null")) {
      String val = h.get(key);
      if (val == null) {
        val = "null";
      }
      push(val);
    } else {
      e.notifyError("Invalid hash key!");
      push("null");
    }
  }

  private void hashremove() {
    String key = pop();
    HashMap<String, String> h = popHash();

    if (!key.equals("") && !key.equals("null")) {
      h.remove(key);
    } else {
      e.notifyError("Invalid hash key!");
    }
    push(h);
  }

  private void hashcontainskey() {
    String key = pop();
    HashMap<String, String> h = popHash();

    if (!key.equals("") && !key.equals("null")) {
      push(h.containsKey(key));
    } else {
      e.notifyError("Invalid hash key!");
      push(false);
    }
  }

  private void hashcontainsval() {
    String val = pop();
    HashMap<String, String> h = popHash();
    push(h.containsValue(val));
  }

  private void hashisempty() {
    HashMap<String, String> h = popHash();
    push(h.size() == 0);
  }

  private void hashsize() {
    HashMap<String, String> h = popHash();
    push(h.size());
  }

  private void hashkeys() {
    HashMap<String, String> h = popHash();
    push(new ArrayList<String>(h.keySet()));
  }

  private void hashvalues() {
    HashMap<String, String> h = popHash();
    push(new ArrayList<String>(h.values()));
  }

}
TOP

Related Classes of simpleserver.events.PostfixEvaluator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.