001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.gui.mappaint;
003    
004    import org.openstreetmap.josm.data.osm.OsmPrimitive;
005    import org.openstreetmap.josm.data.osm.Relation;
006    import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
007    import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector;
008    import org.openstreetmap.josm.tools.CheckParameterUtil;
009    
010    public class Environment {
011    
012        public OsmPrimitive osm;
013    
014        public MultiCascade mc;
015        public String layer;
016        public StyleSource source;
017        private Context context = Context.PRIMITIVE;
018    
019        /**
020         * If not null, this is the matching parent object if an condition or an expression
021         * is evaluated in a {@link LinkSelector} (within a child selector)
022         */
023        public OsmPrimitive parent;
024        /**
025         * The same for parent selector. Only one of the 2 fields (parent or child) is not null in any environment.
026         */
027        public OsmPrimitive child;
028    
029        /**
030         * index of node in parent way or member in parent relation. Must be != null in LINK context.
031         */
032        public Integer index = null;
033    
034        /**
035         * Creates a new uninitialized environment
036         */
037        public Environment() {}
038    
039        public Environment(OsmPrimitive osm, MultiCascade mc, String layer, StyleSource source) {
040            this.osm = osm;
041            this.mc = mc;
042            this.layer = layer;
043            this.source = source;
044        }
045    
046        /**
047         * Creates a clone of the environment {@code other}
048         * 
049         * @param other the other environment. Must not be null.
050         */
051        public Environment(Environment other) throws IllegalArgumentException{
052            CheckParameterUtil.ensureParameterNotNull(other);
053            this.osm = other.osm;
054            this.mc = other.mc;
055            this.layer = other.layer;
056            this.parent = other.parent;
057            this.child = other.child;
058            this.source = other.source;
059            this.index = other.index;
060            this.context = other.getContext();
061        }
062    
063        public Environment withPrimitive(OsmPrimitive osm) {
064            Environment e = new Environment(this);
065            e.osm = osm;
066            return e;
067        }
068    
069        public Environment withParent(OsmPrimitive parent) {
070            Environment e = new Environment(this);
071            e.parent = parent;
072            return e;
073        }
074    
075        public Environment withChild(OsmPrimitive child) {
076            Environment e = new Environment(this);
077            e.child = child;
078            return e;
079        }
080    
081        public Environment withIndex(int index) {
082            Environment e = new Environment(this);
083            e.index = index;
084            return e;
085        }
086    
087        public Environment withContext(Context context) {
088            Environment e = new Environment(this);
089            e.context = context == null ? Context.PRIMITIVE : context;
090            return e;
091        }
092    
093        public Environment withLinkContext() {
094            Environment e = new Environment(this);
095            e.context = Context.LINK;
096            return e;
097        }
098    
099        public boolean isLinkContext() {
100            return Context.LINK.equals(context);
101        }
102    
103        public boolean hasParentRelation() {
104            return parent != null && parent instanceof Relation;
105        }
106    
107        /**
108         * Replies the current context.
109         * 
110         * @return the current context
111         */
112        public Context getContext() {
113            return context == null ? Context.PRIMITIVE : context;
114        }
115    
116        public String getRole() {
117            if (getContext().equals(Context.PRIMITIVE))
118                return null;
119    
120            if (parent != null && parent instanceof Relation)
121                return ((Relation) parent).getMember(index).getRole();
122            if (child != null && osm instanceof Relation)
123                return ((Relation) osm).getMember(index).getRole();
124            return null;
125        }
126    
127        public void clearSelectorMatchingInformation() {
128            parent = null;
129            child = null;
130            index = null;
131        }
132    }