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