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