001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.tools.template_engine;
003
004import java.util.Collection;
005import java.util.Locale;
006import java.util.Objects;
007
008/**
009 * {@link TemplateEntry} that inserts the value of a variable.
010 * <p>
011 * Variables starting with "special:" form a separate namespace and
012 * provide actions other than simple key-value lookup.
013 * <p>
014 * A variable with no mapping for a given data provider will be considered not "valid"
015 * (see {@link TemplateEntry#isValid(TemplateEngineDataProvider)}).
016 */
017public class Variable implements TemplateEntry {
018
019    private static final String SPECIAL_VARIABLE_PREFIX = "special:";
020    private static final String SPECIAL_VALUE_EVERYTHING = "everything";
021
022    private final String variableName;
023    private final boolean special;
024
025    /**
026     * Constructs a new {@code Variable}.
027     * @param variableName the variable name (i.e. the key in the data provider key-value mapping);
028     * will be considered "special" if the variable name starts with {@link #SPECIAL_VARIABLE_PREFIX}
029     */
030    public Variable(String variableName) {
031        if (variableName.toLowerCase(Locale.ENGLISH).startsWith(SPECIAL_VARIABLE_PREFIX)) {
032            this.variableName = variableName.substring(SPECIAL_VARIABLE_PREFIX.length());
033            // special:special:key means that real key named special:key is needed, not special variable
034            this.special = !this.variableName.toLowerCase(Locale.ENGLISH).startsWith(SPECIAL_VARIABLE_PREFIX);
035        } else {
036            this.variableName = variableName;
037            this.special = false;
038        }
039    }
040
041    @Override
042    public void appendText(StringBuilder result, TemplateEngineDataProvider dataProvider) {
043        if (special && SPECIAL_VALUE_EVERYTHING.equals(variableName)) {
044            Collection<String> keys = dataProvider.getTemplateKeys();
045            boolean first = true;
046            for (String key: keys) {
047                if (!first) {
048                    result.append(", ");
049                } else {
050                    first = false;
051                }
052                result.append(key).append('=').append(dataProvider.getTemplateValue(key, false));
053            }
054        } else {
055            Object value = dataProvider.getTemplateValue(variableName, special);
056            if (value != null) {
057                result.append(value);
058            }
059        }
060    }
061
062    @Override
063    public boolean isValid(TemplateEngineDataProvider dataProvider) {
064        if (special && SPECIAL_VALUE_EVERYTHING.equals(variableName))
065            return true;
066        else
067            return dataProvider.getTemplateValue(variableName, special) != null;
068    }
069
070    @Override
071    public String toString() {
072        return '{' + (special ? SPECIAL_VARIABLE_PREFIX : "") + variableName + '}';
073    }
074
075    /**
076     * Check if this variable is special.
077     *
078     * @return true if this variable is special
079     */
080    public boolean isSpecial() {
081        return special;
082    }
083
084    @Override
085    public int hashCode() {
086        return Objects.hash(special, variableName);
087    }
088
089    @Override
090    public boolean equals(Object obj) {
091        if (this == obj)
092            return true;
093        if (obj == null || getClass() != obj.getClass())
094            return false;
095        Variable other = (Variable) obj;
096        if (special != other.special)
097            return false;
098        if (variableName == null) {
099            if (other.variableName != null)
100                return false;
101        } else if (!variableName.equals(other.variableName))
102            return false;
103        return true;
104    }
105}