001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.gui.mappaint.mapcss;
003    
004    import java.util.Arrays;
005    
006    import org.openstreetmap.josm.gui.mappaint.Cascade;
007    import org.openstreetmap.josm.gui.mappaint.Environment;
008    import org.openstreetmap.josm.gui.mappaint.Keyword;
009    import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
010    import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
011    import org.openstreetmap.josm.gui.mappaint.StyleKeys;
012    
013    abstract 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 Expression.LiteralExpression) {
037                    Object litValue = ((Expression.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")) {
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    }