001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.mappaint.mapcss;
003
004import java.util.Arrays;
005
006import org.openstreetmap.josm.gui.mappaint.Cascade;
007import org.openstreetmap.josm.gui.mappaint.Environment;
008import org.openstreetmap.josm.gui.mappaint.Keyword;
009import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
010import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
011import org.openstreetmap.josm.gui.mappaint.StyleKeys;
012
013abstract public class Instruction implements StyleKeys {
014
015    public abstract void execute(Environment env);
016
017    public static class RelativeFloat {
018        public final float val;
019
020        public RelativeFloat(float val) {
021            this.val = val;
022        }
023
024        @Override
025        public String toString() {
026            return "RelativeFloat{" + "val=" + val + '}';
027        }
028    }
029
030    public static class AssignmentInstruction extends Instruction {
031        public final String key;
032        public final Object val;
033
034        public AssignmentInstruction(String key, Object val) {
035            this.key = key;
036            if (val instanceof LiteralExpression) {
037                Object litValue = ((LiteralExpression) val).evaluate(null);
038                if (key.equals(TEXT)) {
039                    /* Special case for declaration 'text: ...'
040                     *
041                     * - Treat the value 'auto' as keyword.
042                     * - Treat any other literal value 'litval' as as reference to tag with key 'litval'
043                     *
044                     * - Accept function expressions as is. This allows for
045                     *     tag(a_tag_name)                 value of a tag
046                     *     eval("a static text")           a static text
047                     *     parent_tag(a_tag_name)          value of a tag of a parent relation
048                     */
049                    if (litValue.equals(Keyword.AUTO)) {
050                        this.val = Keyword.AUTO;
051                    } else {
052                        String s = Cascade.convertTo(litValue, String.class);
053                        if (s != null) {
054                            this.val = new MapPaintStyles.TagKeyReference(s);
055                        } else {
056                            this.val = litValue;
057                        }
058                    }
059                } else {
060                    this.val = litValue;
061                }
062            } else {
063                this.val = val;
064            }
065        }
066
067        @Override
068        public void execute(Environment env) {
069            Object value = null;
070            if (val instanceof Expression) {
071                value = ((Expression) val).evaluate(env);
072            } else {
073                value = val;
074            }
075            if (key.equals(ICON_IMAGE) || key.equals(FILL_IMAGE) || key.equals("pattern-image") || key.equals(REPEAT_IMAGE)) {
076                if (value instanceof String) {
077                    value = new IconReference((String) value, env.source);
078                }
079            }
080            env.mc.getOrCreateCascade(env.layer).putOrClear(key, value);
081        }
082
083        @Override
084        public String toString() {
085            return key + ':' + (val instanceof float[] ? Arrays.toString((float[]) val) : val) + ';';
086        }
087    }
088}