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

nl.hsac.fitnesse.fixture.util.MapHelper Maven / Gradle / Ivy

There is a newer version: 5.3.17
Show newest version
package nl.hsac.fitnesse.fixture.util;

import nl.hsac.fitnesse.fixture.slim.ListFixture;
import nl.hsac.fitnesse.fixture.slim.SlimFixtureException;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MapHelper {
    private static final Pattern LIST_INDEX_PATTERN = Pattern.compile("(\\S+)\\[(\\d+)\\]");
    private HtmlCleaner htmlCleaner = new HtmlCleaner();

    /**
     * Gets value from map.
     * @param map map to get value from.
     * @param name name of (possibly nested) property to get value from.
     * @return value found, if it could be found, null otherwise.
     */
    public Object getValue(Map map, String name) {
        String cleanName = htmlCleaner.cleanupValue(name);
        return getValueImpl(map, cleanName);
    }

    protected Object getValueImpl(Map map, String name) {
        Object value = null;
        if (map.containsKey(name)) {
            value = map.get(name);
        } else {
            String[] parts = name.split("\\.", 2);
            if (parts.length > 1) {
                Object nested = getValueImpl(map, parts[0]);
                if (nested instanceof Map) {
                    Map nestedMap = (Map) nested;
                    value = getValueImpl(nestedMap, parts[1]);
                }
            } else if (isListName(name)) {
                value = getListValue(map, name);
            } else if (isListIndexExpr(name)) {
                value = getIndexedListValue(map, name);
            }
        }
        return value;
    }

    /**
     * Stores value in map.
     * @param value value to be passed.
     * @param name name to use this value for.
     * @param map map to store value in.
     */
    public void setValueForIn(Object value, String name, Map map) {
        if (isListName(name)) {
            String valueStr = null;
            if (value != null) {
                valueStr = value.toString();
            }
            setValuesForIn(valueStr, stripListIndicator(name), map);
        } else {
            if (name.endsWith("\\[]")) {
                name = name.replace("\\[]", "[]");
            }
            String cleanName = htmlCleaner.cleanupValue(name);
            Object cleanValue = value;
            if (value instanceof String) {
                cleanValue = htmlCleaner.cleanupValue((String) value);
            }
            if (map.containsKey(cleanName)) {
                // overwrite current value
                map.put(cleanName, cleanValue);
            } else {
                int lastDot = cleanName.lastIndexOf(".");
                if (lastDot > -1) {
                    String key = cleanName.substring(0, lastDot);
                    Object nested = getValue(map, key);
                    if (nested instanceof Map) {
                        Map nestedMap = (Map) nested;
                        String lastPart = cleanName.substring(lastDot + 1);
                        setValueForIn(cleanValue, lastPart, nestedMap);
                    } else {
                        throw new SlimFixtureException(false, key + " is not a map, but " + nested.getClass());
                    }
                } else if (isListIndexExpr(name)) {
                    setIndexedListValue(map, cleanName, cleanValue);
                } else {
                    map.put(cleanName, cleanValue);
                }
            }
        }
    }

    /**
     * Stores list of values in map.
     * @param values comma separated list of values.
     * @param name name to use this list for.
     * @param map map to store values in.
     */
    public void setValuesForIn(String values, String name, Map map) {
        String cleanName = htmlCleaner.cleanupValue(name);
        String[] valueArrays = values.split("\\s*,\\s*");
        List valueObjects = new ArrayList(valueArrays.length);
        for (int i = 0; i < valueArrays.length; i++) {
            String cleanValue = htmlCleaner.cleanupValue(valueArrays[i]);
            valueObjects.add(cleanValue);
        }
        setValueForIn(valueObjects, cleanName, map);
    }

    /**
     * Determines whether map one's content matches two.
     * @param one map the check content of.
     * @param two other map to check.
     * @return true if both maps are equal.
     */
    public boolean contentOfEquals(Map one, Object two) {
        if (one == null) {
            return two == null;
        } else {
            return one.equals(two);
        }
    }

    /**
     * Determines size of either (Map or Collection) value in the map.
     * @param expr expression indicating which (possibly nested) value in the map to determine size of.
     * @param map map to find value in.
     * @return size of value.
     * @throws SlimFixtureException if the value found is not a Map or Collection.
     */
    public int sizeOfIn(String expr, Map map) {
        int result;
        Object val = getValue(map, expr);
        if (val instanceof Map) {
            result = ((Map) val).size();
        } else if (val instanceof Collection) {
            result = ((Collection) val).size();
        } else {
            throw new SlimFixtureException(false, expr + " is not a collection");
        }
        return result;
    }

    protected Object getListValue(Map map, String name) {
        return getValue(map, stripListIndicator(name));
    }

    protected Object getIndexedListValue(Map map, String name) {
        Object value;
        String prop = getListKeyName(name);
        Object val = getValue(map, prop);
        if (val instanceof List) {
            List list = (List) val;
            int index = getListIndex(name);
            if (index < list.size()) {
                value = list.get(index);
            } else {
                value = null;
            }
        } else {
            throw new SlimFixtureException(false, prop + " is not a list, but " + val);
        }
        return value;
    }

    protected void setIndexedListValue(Map map, String name, Object value) {
        String prop = getListKeyName(name);
        Object val = getValue(map, prop);
        if (val == null) {
            val = new ArrayList();
            setValueForIn(val, prop, map);
        }
        if (val instanceof List) {
            List list = (List) val;
            int index = getListIndex(name);
            while (list.size() <= index) {
                list.add(null);
            }
            list.set(index, value);
        } else {
            throw new SlimFixtureException(false, prop + " is not a list, but " + val);
        }
    }

    protected boolean isListName(String name) {
        return name.endsWith("[]") && !name.endsWith("\\[]");
    }

    protected String stripListIndicator(String key) {
        return key.substring(0, key.length() - 2);
    }

    protected boolean isListIndexExpr(String key) {
        return getListIndexMatcher(key).matches();
    }

    protected String getListKeyName(String key) {
        Matcher matcher = getListIndexMatcher(key);
        matcher.matches();
        return matcher.group(1);
    }

    protected int getListIndex(String key) {
        Matcher matcher = getListIndexMatcher(key);
        matcher.matches();
        return Integer.parseInt(matcher.group(2));
    }

    protected Matcher getListIndexMatcher(String key) {
        return LIST_INDEX_PATTERN.matcher(key);
    }

    public void setHtmlCleaner(HtmlCleaner htmlCleaner) {
        this.htmlCleaner = htmlCleaner;
    }
}