org.ocsoft.rosetto.models.base.elements.values.ListValue.java Source code

Java tutorial

Introduction

Here is the source code for org.ocsoft.rosetto.models.base.elements.values.ListValue.java

Source

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.ocsoft.rosetto.models.base.elements.values;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.apache.commons.lang3.StringUtils;
import org.ocsoft.rosetto.contexts.base.Rosetto;
import org.ocsoft.rosetto.models.base.elements.RosettoValue;
import org.ocsoft.rosetto.models.base.elements.ValueType;
import org.ocsoft.rosetto.models.system.Parser;
import org.ocsoft.rosetto.models.system.Scope;
import org.ocsoft.rosetto.system.exceptions.NotConvertibleException;
import org.ocsoft.rosetto.utils.base.TextUtils;
import org.ocsoft.rosetto.utils.base.Values;

/**
 * ?????????????.<br>
 * Rosetto??????????ListValue???.<br>
 * ?????????????.<br>
 * <br>
 * (foo=10 bar=100 2 6 a=1 9 3)<br>
 * <br>
 * Rosetto?????????.<br>
 * <br>
 * Map {foo=10, bar=100, a=1}<br>
 * List (2,6,9,3)<br>
 * <br>
 * ???????????????????????????.<br>
 * ??????????.<br>
 * [size (a=1 b=2 c=3)] => 0
 * @author tohhy
 */
public class ListValue implements RosettoValue {
    private static final long serialVersionUID = -5778537199758610111L;

    public static final ListValue EMPTY = new ListValue(new LinkedList<RosettoValue>(),
            new TreeMap<String, RosettoValue>());

    /**
     * ?.<br>
     * Lisp?????LinkedList?.
     */
    private final LinkedList<RosettoValue> list;

    /**
     * ?.<br>
     * ???????TreeMap?.
     */
    private final TreeMap<String, RosettoValue> map;

    /**
     * ?????????HashedList??.
     * @param args ??
     */
    public static ListValue createFromString(String args) {
        if (args == null)
            throw new IllegalArgumentException("?null??");
        List<RosettoValue> list = new ArrayList<RosettoValue>();
        Map<String, RosettoValue> map = new HashMap<String, RosettoValue>();
        //???????
        //??????????????
        List<String> splited = Rosetto.getParser().splitElements(args);
        Parser parser = Rosetto.getParser();
        for (String str : splited) {
            int equalPosition = str.indexOf("=");
            if (equalPosition == -1) {
                list.add(parser.parseElement(TextUtils.removeDoubleQuote(str)));
            } else {
                String key = str.substring(0, equalPosition);
                String value = TextUtils.removeDoubleQuote(str.substring(equalPosition + 1));
                map.put(key, parser.parseElement(value));
            }
        }
        return new ListValue(list, map);
    }

    public static ListValue createFromString(String[] args) {
        List<RosettoValue> list = new LinkedList<RosettoValue>();
        Map<String, RosettoValue> map = new HashMap<String, RosettoValue>();
        for (String str : args) {
            int equalPosition = str.indexOf("=");
            if (equalPosition == -1) {
                list.add(Values.create(TextUtils.removeDoubleQuote(str)));
            } else {
                String key = str.substring(0, equalPosition);
                String value = TextUtils.removeDoubleQuote(str.substring(equalPosition + 1));
                map.put(key, Values.create(value));
            }
        }
        return new ListValue(list, map);
    }

    public static ListValue createFromString(List<String> elements) {
        List<RosettoValue> list = new ArrayList<RosettoValue>();
        Map<String, RosettoValue> map = new HashMap<String, RosettoValue>();
        for (String element : elements) {
            int equalPosition = element.indexOf("=");
            if (equalPosition == -1) {
                list.add(Values.create(TextUtils.removeDoubleQuote(element)));
            } else {
                String key = element.substring(0, equalPosition);
                String value = TextUtils.removeDoubleQuote(element.substring(equalPosition + 1));
                map.put(key, Values.create(value));
            }
        }
        return new ListValue(list, map);
    }

    public static ListValue createFromValue(List<RosettoValue> list, Map<String, RosettoValue> map) {
        return new ListValue(new LinkedList<RosettoValue>(list), new HashMap<String, RosettoValue>(map));
    }

    public static ListValue createFromValue(ListValue list) {
        return new ListValue(new LinkedList<RosettoValue>(list.getList()),
                new HashMap<String, RosettoValue>(list.getMap()));
    }

    private ListValue(List<RosettoValue> list, Map<String, RosettoValue> map) {
        this.list = (list instanceof LinkedList) ? (LinkedList<RosettoValue>) list
                : new LinkedList<RosettoValue>(list);
        this.map = (map instanceof TreeMap) ? (TreeMap<String, RosettoValue>) map
                : new TreeMap<String, RosettoValue>(map);
    }

    public ListValue(List<RosettoValue> list) {
        this((list instanceof LinkedList) ? (LinkedList<RosettoValue>) list : new LinkedList<RosettoValue>(list),
                new TreeMap<String, RosettoValue>());
    }

    public ListValue(RosettoValue... values) {
        this(toList(values));

    }

    public ListValue(String... values) {
        this(toList(values));
    }

    private static List<RosettoValue> toList(RosettoValue... values) {
        LinkedList<RosettoValue> list = new LinkedList<RosettoValue>();
        for (RosettoValue v : values)
            list.add(v);
        return list;
    }

    private static List<RosettoValue> toList(String... values) {
        Parser parser = Rosetto.getParser();
        LinkedList<RosettoValue> list = new LinkedList<RosettoValue>();
        for (String s : values)
            list.add(parser.parseElement(s));
        return list;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof RosettoValue) {
            return ((RosettoValue) obj).asString().equals(this.asString());
        }
        return false;
    }

    @Override
    public String toString() {
        return asString();
    }

    /**
     * ??????????.<br>
     * ??????.????asString??.
     */
    public String toArgsExpression() {
        StringBuilder sb = new StringBuilder();
        sb.append(StringUtils.join(list, ' '));
        int mapLen = map.size();
        if (mapLen > 0)
            sb.append(" ");
        sb.append(StringUtils.join(map.entrySet(), ' '));
        return sb.toString();
    }

    @Override
    public RosettoValue evaluate(Scope scope) {
        return this;
    }

    /**
     * ?????????????????.
     * @return
     */
    public ListValue evaluateChildren(Scope parentScope) {
        List<RosettoValue> list = new ArrayList<RosettoValue>();
        Map<String, RosettoValue> map = new TreeMap<String, RosettoValue>();
        for (RosettoValue v : this.list) {
            if (v instanceof ActionCall) {
                list.add(((ActionCall) v).evaluate(parentScope));
            } else {
                list.add(v);
            }
        }
        for (Entry<String, RosettoValue> e : this.map.entrySet()) {
            if (e.getValue() instanceof ActionCall) {
                map.put(e.getKey(), ((ActionCall) e.getValue()).evaluate(parentScope));
            } else {
                map.put(e.getKey(), e.getValue());
            }
        }
        return new ListValue(list, map);
    }

    /**
     * ????????.
     * ????????????????.
     * ???????????.
     * ????ActionCall??.
     * @param func ??
     * @return ????
     */
    public Map<String, RosettoValue> bind(RosettoFunction func, Scope currentScope) {
        if (func == null)
            throw new IllegalArgumentException("???null??");

        //??
        Map<String, RosettoValue> result = new HashMap<String, RosettoValue>();
        //????
        LinkedList<String> funcArgs = new LinkedList<String>();

        //???????????
        int requiredArgsCount = 0;

        //????????
        for (String s : func.getArguments()) {
            int eqIndex = s.indexOf("=");
            if (eqIndex == -1) {
                //?????????
                funcArgs.add(s);
                //????????
                requiredArgsCount++;
            } else {
                //????
                String key = s.substring(0, eqIndex);
                RosettoValue value = Values.create(s.substring(eqIndex + 1, s.length()));
                //?
                funcArgs.add(key);
                //???????
                result.put(key, value);
            }
        }

        //??????

        //??
        for (Entry<String, RosettoValue> e : getMap().entrySet()) {
            //?Entry??funcArgs?????funcArg
            boolean removed = funcArgs.remove(e.getKey());
            //????
            if (removed)
                requiredArgsCount--;
            //??
            result.put(e.getKey(), e.getValue());
        }

        //??
        String mutableArg = searchMutableArg(funcArgs);
        if (mutableArg != null) {
            //????????

            //????????
            //??????????-1
            if (requiredArgsCount - 1 > getList().size()) {
                throw new IllegalArgumentException("???????: "
                        + getList().toString() + "|" + func.getArguments());
            }

            //????????????????
            //??
            List<RosettoValue> margs = new LinkedList<RosettoValue>();
            for (int i = 0; i < getList().size(); i++) {
                RosettoValue v = getList().get(i);
                if (!funcArgs.isEmpty()) {
                    //???????????pop?????????
                    String farg = funcArgs.pollFirst();
                    //??????????
                    if (farg.equals(mutableArg)) {
                        //??????????????
                        if (!funcArgs.isEmpty()) {
                            throw new IllegalArgumentException("mutable args must be last element");
                        }
                        //??
                        margs.add(v);
                    }
                    //????????
                    result.put(farg, v);
                } else {
                    //??
                    margs.add(v);
                }
            }

            //?????
            if (margs.size() > 0) {
                //?????
                String margName = mutableArg.substring(1);
                //listvalue???
                result.put(margName, new ListValue(margs));
            }

        } else {
            //???????
            if (requiredArgsCount > getList().size()) {
                throw new IllegalArgumentException("???????: "
                        + getList().toString() + "|" + func.getArguments());
            } else if (funcArgs.size() < getList().size()) {
                throw new IllegalArgumentException(
                        "?????: " + getList().toString() + "|" + func.getArguments());
            }
            for (RosettoValue value : getList()) {
                //?????????
                if (value.getType() == ValueType.ACTION_CALL) {
                    //ActionCall??????
                    result.put(funcArgs.pollFirst(), ((ActionCall) value).evaluate(currentScope));
                } else {
                    result.put(funcArgs.pollFirst(), value);
                }
            }
        }
        return result;
    }

    public boolean hasMappedValue() {
        return map.size() > 0;
    }

    /**
     * ??????.
     */
    public boolean containsKey(String key) {
        return map.containsKey(key);
    }

    @Override
    public RosettoValue first() {
        return list.getFirst();
    }

    @Override
    public RosettoValue rest() {
        if (list.size() == 0 || list.size() == 1)
            return Values.NULL;
        if (list.size() == 2)
            return list.get(1);
        return new ListValue(list.subList(1, list.size()), map);
    }

    @Override
    public RosettoValue cons(RosettoValue head) {
        return null;
    }

    /**
     * List?????.
     */
    public RosettoValue getAt(int listIndex) {
        return list.get(listIndex);
    }

    /**
     * List????.
     */
    @Override
    public int size() {
        return list.size();
    }

    /**
     * ???????.
     */
    public RosettoValue get(String mapKey) {
        return map.containsKey(mapKey) ? map.get(mapKey) : Values.NULL;
    }

    public int optionSize() {
        return map.size();
    }

    public List<RosettoValue> getList() {
        return Collections.unmodifiableList(list);
    }

    public Map<String, RosettoValue> getMap() {
        return Collections.unmodifiableMap(map);
    }

    /**
     * ?????.
     * @return ????????null
     */
    private String searchMutableArg(List<String> args) {
        String result = null;
        for (String s : args) {
            if (s.startsWith("*") && s.length() >= 2) {
                if (result != null)
                    throw new IllegalArgumentException("multiple mutablearg found");
                result = s;
            }
        }
        return result;
    }

    @Override
    public ValueType getType() {
        return ValueType.LIST;
    }

    @Override
    public Object getValue() {
        return this;
    }

    @Override
    public String asString() throws NotConvertibleException {
        return "(" + toArgsExpression() + ")";
    }

    @Override
    public String asString(String defaultValue) {
        return "(" + toArgsExpression() + ")";
    }

    @Override
    public boolean asBool() throws NotConvertibleException {
        throw new NotConvertibleException();
    }

    @Override
    public boolean asBool(boolean defaultValue) {
        return defaultValue;
    }

    @Override
    public int asInt() throws NotConvertibleException {
        throw new NotConvertibleException();
    }

    @Override
    public int asInt(int defaultValue) {
        return defaultValue;
    }

    @Override
    public long asLong() throws NotConvertibleException {
        throw new NotConvertibleException();
    }

    @Override
    public long asLong(long defaultValue) {
        return defaultValue;
    }

    @Override
    public double asDouble() throws NotConvertibleException {
        throw new NotConvertibleException();
    }

    @Override
    public double asDouble(double defaultValue) {
        return defaultValue;
    }

}