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