001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/graphics/sld/Rule.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2006 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     
043     ---------------------------------------------------------------------------*/
044    package org.deegree.graphics.sld;
045    
046    import java.util.ArrayList;
047    import java.util.List;
048    
049    import org.deegree.framework.xml.Marshallable;
050    import org.deegree.model.filterencoding.Filter;
051    
052    /**
053     * A rule is used to attach a condition to and group the individual symbolizers used for rendering.
054     * The Title and Abstract describe the rule and may be used to generate a legend, as may the
055     * LegendGraphic. The Filter, ElseFilter, MinScale, and MaxScale elements allow the selection of
056     * features and rendering scales for a rule. The scale selection works as follows. When a map is to
057     * be rendered, the scale denominator is computed and all rules in all UserStyles that have a scale
058     * outside of the request range are dropped. (This also includes Rules that have an ElseFilter.) An
059     * ElseFilter is simply an ELSE condition to the conditions (Filters) of all other rules in the same
060     * UserStyle. The exact meaning of the ElseFilter is determined after Rules have been eliminated for
061     * not fitting the rendering scale. This definition of the behaviour of ElseFilters may seem a
062     * little strange, but it allows for scale- dependent and scale-independent ELSE conditions. For the
063     * Filter, only SqlExpression is available for specification, but this is a hack and should be
064     * replaced with Filter as defined in WFS. A missing Filter element means "always true". If a set of
065     * Rules has no ElseFilters, then some features may not be rendered (which is presumably the desired
066     * behavior). The Scales are actually scale denominators (as double floats), so "10e6" would be
067     * interpreted as 1:10M. A missing MinScale means there is no lower bound to the scale- denominator
068     * range (lim[x->0+](x)), and a missing MaxScale means there is no upper bound (infinity). 0.28mm
069     * 
070     * 
071     * @author <a href="mailto:k.lupp@web.de">Katharina Lupp </a>
072     * @author last edited by: $Author: apoth $
073     * @version $Revision: 6698 $ $Date: 2007-04-26 11:40:11 +0200 (Do, 26 Apr 2007) $
074     */
075    
076    public class Rule implements Marshallable {
077    
078        private List<Symbolizer> symbolizers = null;
079    
080        /**
081         * 
082         */
083        private Filter filter = null;
084    
085        /**
086         * 
087         */
088        private LegendGraphic legendGraphic = null;
089    
090        private String abstract_ = null;
091    
092        private String name = null;
093    
094        private String title = null;
095    
096        private boolean elseFilter = false;
097    
098        private double maxScaleDenominator = 0;
099    
100        private double minScaleDenominator = 0;
101    
102        /**
103         * default constructor
104         */
105        Rule() {
106            symbolizers = new ArrayList<Symbolizer>();
107        }
108    
109        /**
110         * constructor initializing the class with the <Rule>
111         */
112        Rule( Symbolizer[] symbolizers, String name, String title, String abstract_, LegendGraphic legendGraphic,
113              Filter filter, boolean elseFilter, double minScaleDenominator, double maxScaleDenominator ) {
114            this();
115            setSymbolizers( symbolizers );
116            setName( name );
117            setTitle( title );
118            setAbstract( abstract_ );
119            setLegendGraphic( legendGraphic );
120            setFilter( filter );
121            setElseFilter( elseFilter );
122            setMinScaleDenominator( minScaleDenominator );
123            setMaxScaleDenominator( maxScaleDenominator );
124        }
125    
126        /**
127         * returns the name of the rule. this for machine interpreting.
128         * 
129         * @return the name of the rule
130         * 
131         */
132        public String getName() {
133            return name;
134        }
135    
136        /**
137         * sets the name of the rule. this for machine interpreting.
138         * 
139         * @param name
140         *            the name of the rule
141         * 
142         */
143        public void setName( String name ) {
144            this.name = name;
145        }
146    
147        /**
148         * returns the human readable title of the rule
149         * 
150         * @return the title of the rule
151         * 
152         */
153        public String getTitle() {
154            return title;
155        }
156    
157        /**
158         * sets the human readable title of the rule
159         * 
160         * @param title
161         *            the title of the rule
162         * 
163         */
164        public void setTitle( String title ) {
165            this.title = title;
166        }
167    
168        /**
169         * returns the human readable abstract of the rule
170         * 
171         * @return the abstract of the rule
172         */
173        public String getAbstract() {
174            return abstract_;
175        }
176    
177        /**
178         * sets the human readable abstract of the rule
179         * 
180         * @param abstract_
181         *            the abstract of the rule
182         */
183        public void setAbstract( String abstract_ ) {
184            this.abstract_ = abstract_;
185        }
186    
187        /**
188         * The LegendGraphic element gives an optional explicit Graphic symbol to be displayed in a
189         * legend for this rule.
190         * 
191         * @return the legendGraphic of the rule
192         * 
193         */
194        public LegendGraphic getLegendGraphic() {
195            return legendGraphic;
196        }
197    
198        /**
199         * sets the LegendGraphic element
200         * 
201         * @param legendGraphic
202         *            the legendGraphic of the rule
203         * 
204         */
205        public void setLegendGraphic( LegendGraphic legendGraphic ) {
206            this.legendGraphic = legendGraphic;
207        }
208    
209        /**
210         * The Filter element has a relatively straightforward meaning. The syntax of the Filter element
211         * is defined in the WFS specification and allows both attribute (property) and spatial
212         * filtering.
213         * 
214         * @return the filter element
215         * 
216         */
217        public Filter getFilter() {
218            return filter;
219        }
220    
221        /**
222         * sets the <Filter>
223         * 
224         * @param filter
225         *            the filter element
226         * 
227         */
228        public void setFilter( Filter filter ) {
229            this.filter = filter;
230        }
231    
232        /**
233         * The ElseFilter allows rules to be specified that are activated for features are not selected
234         * by any other rule in a feature-type style.
235         * 
236         * @return true if the rule has an elseFilter
237         */
238        public boolean hasElseFilter() {
239            return elseFilter;
240        }
241    
242        /**
243         * sets the <ElseFilter>
244         * 
245         * @param elseFilter
246         *            an elseFilter
247         * 
248         */
249        public void setElseFilter( boolean elseFilter ) {
250            this.elseFilter = elseFilter;
251        }
252    
253        /**
254         * The MinScaleDenominator and MaxScaleDenominator elements of a Rule define the range of
255         * map-rendering scales for which the rule should be applied. The MinScaleDenominator and
256         * MaxScaleDenominator elements, as their names suggest, are simply the minimum and maximum
257         * ranges of scale (denominators) of maps for which a rule should apply.
258         * 
259         * @return the MinScaleDenominator for the rule
260         * 
261         */
262        public double getMinScaleDenominator() {
263            return minScaleDenominator;
264        }
265    
266        /**
267         * sets the <MinScaleDenominator>
268         * 
269         * @param minScaleDenominator
270         *            the MinScaleDenominator for the rule
271         * 
272         */
273        public void setMinScaleDenominator( double minScaleDenominator ) {
274            this.minScaleDenominator = minScaleDenominator;
275        }
276    
277        /**
278         * The MinScaleDenominator and MaxScaleDenominator elements of a Rule define the range of
279         * map-rendering scales for which the rule should be applied. The MinScaleDenominator and
280         * MaxScaleDenominator elements, as their names suggest, are simply the minimum and maximum
281         * ranges of scale (denominators) of maps for which a rule should apply.
282         * 
283         * @return the MaxScaleDenominator for the rule
284         * 
285         */
286        public double getMaxScaleDenominator() {
287            return maxScaleDenominator;
288        }
289    
290        /**
291         * sets the <MaxScaleDenominator>
292         * 
293         * @param maxScaleDenominator
294         *            the MaxScaleDenominator for the rule
295         * 
296         */
297        public void setMaxScaleDenominator( double maxScaleDenominator ) {
298            this.maxScaleDenominator = maxScaleDenominator;
299        }
300    
301        /**
302         * Embedded inside of Rules, which group conditions for styling features, are Symbolizers. A
303         * symbolizer describes how a feature is to appear on a map. The symbolizer describes not just
304         * the shape that should appear but also such graphical properties as color and opacity. A
305         * symbol is obtained by specifying one of a small number of different types of symbolizer and
306         * then supplying parameters to override its default behaviour. Currently, five types of
307         * symbolizers are defined.
308         * <p>
309         * </p>
310         * The Symbolizers will be returned in the sequece of their occurence with in the rule
311         * definition. Its the users function to determine what type of Symbolizer(s) are returned. This
312         * can be done for example by using the <tt>instanceof</tt> operator of Java.
313         * 
314         * @return the Symbolizer for the rule
315         * 
316         */
317        public Symbolizer[] getSymbolizers() {
318            return symbolizers.toArray( new Symbolizer[symbolizers.size()] );
319        }
320    
321        /**
322         * sets the <Symbolizer>
323         * 
324         * @param symbolizers
325         *            symbolizers for the rule
326         */
327        public void setSymbolizers( Symbolizer[] symbolizers ) {
328            this.symbolizers.clear();
329    
330            if ( symbolizers != null ) {
331                for ( int i = 0; i < symbolizers.length; i++ ) {
332                    this.symbolizers.add( symbolizers[i] );
333                }
334            }
335        }
336    
337        /**
338         * adds a <Symbolizer>
339         * 
340         * @param symbolizer
341         *            symbolizer to add
342         */
343        public void addSymbolizer( Symbolizer symbolizer ) {
344            symbolizers.add( symbolizer );
345        }
346    
347        /**
348         * Removes a <Symbolizer>from a set of Symbolizers.
349         * 
350         * @param symbolizer
351         *            symbolizer to remove
352         */
353        public void removeSymbolizer( Symbolizer symbolizer ) {
354            if ( symbolizers.indexOf( symbolizer ) != -1 ) {
355                symbolizers.remove( symbolizers.indexOf( symbolizer ) );
356            }
357        }
358    
359        /**
360         * exports the content of the Rule as XML formated String
361         * 
362         * @return xml representation of the Rule
363         */
364        public String exportAsXML() {
365    
366            StringBuffer sb = new StringBuffer( 1000 );
367            sb.append( "<Rule>" );
368            if ( name != null && !name.equals( "" ) ) {
369                sb.append( "<Name>" ).append( name ).append( "</Name>" );
370            }
371            if ( title != null && !title.equals( "" ) ) {
372                sb.append( "<Title>" ).append( title ).append( "</Title>" );
373            }
374            if ( abstract_ != null && !abstract_.equals( "" ) ) {
375                sb.append( "<Abstract>" ).append( abstract_ ).append( "</Abstract>" );
376            }
377            if ( legendGraphic != null ) {
378                sb.append( "<LegendGraphic>" ).append( ( (Marshallable) legendGraphic ).exportAsXML() ).append(
379                                                                                                                "</LegendGraphic>" );
380            }
381            if ( filter != null ) {
382                sb.append( filter.toXML() );
383            }
384            if ( elseFilter ) {
385                sb.append( "<ElseFilter/>" );
386            }
387            sb.append( "<MinScaleDenominator>" ).append( minScaleDenominator );
388            sb.append( "</MinScaleDenominator>" );
389            sb.append( "<MaxScaleDenominator>" ).append( maxScaleDenominator );
390            sb.append( "</MaxScaleDenominator>" );
391            for ( int i = 0; i < symbolizers.size(); i++ ) {
392                sb.append( ( (Marshallable) symbolizers.get( i ) ).exportAsXML() );
393            }
394            sb.append( "</Rule>" );
395    
396            return sb.toString();
397        }
398    }