001    //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/graphics/sld/StyleUtils.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 java.util.ArrayList;
039    import java.util.Iterator;
040    import java.util.List;
041    import java.util.Map;
042    
043    import org.deegree.datatypes.QualifiedName;
044    import org.deegree.framework.util.StringTools;
045    import org.deegree.io.datastore.PropertyPathResolvingException;
046    import org.deegree.model.filterencoding.Expression;
047    import org.deegree.model.filterencoding.Filter;
048    import org.deegree.model.filterencoding.FilterTools;
049    import org.deegree.ogcbase.PropertyPath;
050    import org.deegree.ogcbase.PropertyPathFactory;
051    
052    /**
053     * Collects all property names used by a list of styles. E.g. this can be used to optimze GetFeature requests from a WMS
054     * against a WFS.
055     * 
056     * @version $Revision: 32310 $
057     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
058     * @author last edited by: $Author: apoth $
059     * 
060     * @version 1.0. $Revision: 32310 $, $Date: 2011-10-26 15:34:57 +0200 (Mi, 26 Okt 2011) $
061     * 
062     * @since 2.0
063     */
064    public class StyleUtils {
065    
066        /**
067         * @return a list of all
068         * 
069         * @param featureType
070         * @param styles
071         * @param scaleDen
072         * @throws PropertyPathResolvingException
073         */
074        public static List<PropertyPath> extractRequiredProperties( QualifiedName featureType, List<UserStyle> styles,
075                                                                    double scaleDen )
076                                throws PropertyPathResolvingException {
077            List<PropertyPath> pp = new ArrayList<PropertyPath>();
078    
079            for ( int i = 0; i < styles.size(); i++ ) {
080                FeatureTypeStyle[] fts = styles.get( i ).getFeatureTypeStyles();
081                for ( int j = 0; j < fts.length; j++ ) {
082                    Rule[] rules = fts[j].getRules();
083                    for ( int k = 0; k < rules.length; k++ ) {
084    //                    double minScale = rules[k].getMinScaleDenominator();
085    //                    double maxScale = rules[k].getMaxScaleDenominator();
086                        //if ( minScale <= scaleDen && maxScale > scaleDen ) {
087                            Filter filter = rules[k].getFilter();
088                            List<PropertyPath> list = FilterTools.extractPropertyPaths( filter );
089                            pp.addAll( list );
090                            Symbolizer[] sym = rules[k].getSymbolizers();
091                            for ( int d = 0; d < sym.length; d++ ) {
092                                if ( sym[d] instanceof PointSymbolizer ) {
093                                    pp = extractPPFromPointSymbolizer( featureType, (PointSymbolizer) sym[d], pp );
094                                } else if ( sym[d] instanceof LineSymbolizer ) {
095                                    pp = extractPPFromLineSymbolizer( (LineSymbolizer) sym[d], pp );
096                                } else if ( sym[d] instanceof PolygonSymbolizer ) {
097                                    pp = extractPPFromPolygonSymbolizer( (PolygonSymbolizer) sym[d], pp );
098                                } else if ( sym[d] instanceof TextSymbolizer ) {
099                                    pp = extractPPFromTextSymbolizer( (TextSymbolizer) sym[d], pp );
100                                }
101                            }
102                        //}
103                    }
104                }
105            }
106    
107            List<PropertyPath> tmp = new ArrayList<PropertyPath>( pp.size() );
108            for ( int i = 0; i < pp.size(); i++ ) {
109                if ( !tmp.contains( pp.get( i ) ) ) {
110                    tmp.add( pp.get( i ) );
111                }
112            }
113    
114            return tmp;
115        }
116    
117        private static List<PropertyPath> extractPPFromTextSymbolizer( TextSymbolizer symbolizer, List<PropertyPath> pp )
118                                throws PropertyPathResolvingException {
119    
120            ParameterValueType[] bbox = symbolizer.getBoundingBox();
121            if ( bbox != null ) {
122                pp = extractPPFromParamValueType( bbox[0], pp );
123                pp = extractPPFromParamValueType( bbox[1], pp );
124                pp = extractPPFromParamValueType( bbox[2], pp );
125                pp = extractPPFromParamValueType( bbox[3], pp );
126            }
127    
128            Map<?, ?> css = null;
129            if ( symbolizer.getFill() != null ) {
130                css = symbolizer.getFill().getCssParameters();
131                pp = extractPPFromCssParameter( css, pp );
132            }
133            if ( symbolizer.getFont() != null ) {
134                css = symbolizer.getFont().getCssParameters();
135                pp = extractPPFromCssParameter( css, pp );
136            }
137            if ( symbolizer.getGeometry() != null ) {
138                pp.add( symbolizer.getGeometry().getPropertyPath() );
139            }
140            Halo halo = symbolizer.getHalo();
141            ParameterValueType pvt = null;
142            if ( halo != null ) {
143                pvt = halo.getRadius();
144                pp = extractPPFromParamValueType( pvt, pp );
145    
146                if ( halo.getFill() != null ) {
147                    css = halo.getFill().getCssParameters();
148                    pp = extractPPFromCssParameter( css, pp );
149                }
150                if ( halo.getStroke() != null ) {
151                    css = halo.getStroke().getCssParameters();
152                    pp = extractPPFromCssParameter( css, pp );
153                }
154            }
155            pvt = symbolizer.getLabel();
156            pp = extractPPFromParamValueType( pvt, pp );
157    
158            // collect property names from line placement
159            LinePlacement lp = symbolizer.getLabelPlacement().getLinePlacement();
160            if ( lp != null ) {
161                pvt = lp.getGap();
162                pp = extractPPFromParamValueType( pvt, pp );
163                pvt = lp.getLineWidth();
164                pp = extractPPFromParamValueType( pvt, pp );
165                pvt = lp.getPerpendicularOffset();
166                pp = extractPPFromParamValueType( pvt, pp );
167            }
168    
169            // collect property names from line placement
170            PointPlacement ppl = symbolizer.getLabelPlacement().getPointPlacement();
171            if ( ppl != null ) {
172                pvt = ppl.getRotation();
173                pp = extractPPFromParamValueType( pvt, pp );
174                ParameterValueType[] pvta = ppl.getAnchorPoint();
175                if ( pvta != null ) {
176                    for ( int i = 0; i < pvta.length; i++ ) {
177                        pp = extractPPFromParamValueType( pvta[i], pp );
178                    }
179                }
180                pvta = ppl.getDisplacement();
181                if ( pvta != null ) {
182                    for ( int i = 0; i < pvta.length; i++ ) {
183                        pp = extractPPFromParamValueType( pvta[i], pp );
184                    }
185                }
186            }
187    
188            return pp;
189        }
190    
191        private static List<PropertyPath> extractPPFromPolygonSymbolizer( PolygonSymbolizer symbolizer,
192                                                                          List<PropertyPath> pp )
193                                throws PropertyPathResolvingException {
194    
195            Map<?, ?> css = null;
196            if ( symbolizer != null ) {
197                if ( symbolizer.getFill() != null ) {
198                    css = symbolizer.getFill().getCssParameters();
199                    pp = extractPPFromCssParameter( css, pp );
200                }
201    
202                if ( symbolizer.getGeometry() != null ) {
203                    pp.add( symbolizer.getGeometry().getPropertyPath() );
204                }
205    
206                if ( symbolizer.getStroke() != null ) {
207                    css = symbolizer.getStroke().getCssParameters();
208                    pp = extractPPFromCssParameter( css, pp );
209                }
210            }
211    
212            return pp;
213        }
214    
215        private static List<PropertyPath> extractPPFromLineSymbolizer( LineSymbolizer symbolizer, List<PropertyPath> pp )
216                                throws PropertyPathResolvingException {
217    
218            if ( symbolizer.getGeometry() != null ) {
219                pp.add( symbolizer.getGeometry().getPropertyPath() );
220            }
221    
222            Map<?, ?> css = symbolizer.getStroke().getCssParameters();
223            pp = extractPPFromCssParameter( css, pp );
224    
225            return pp;
226        }
227    
228        private static List<PropertyPath> extractPPFromPointSymbolizer( QualifiedName featureType,
229                                                                        PointSymbolizer symbolizer, List<PropertyPath> pp )
230                                throws PropertyPathResolvingException {
231    
232            Graphic graphic = symbolizer.getGraphic();
233            if ( graphic != null ) {
234                if ( graphic.getOpacity() != null ) {
235                    pp = extractPPFromParamValueType( graphic.getOpacity(), pp );
236                }
237    
238                if ( graphic.getRotation() != null ) {
239                    pp = extractPPFromParamValueType( graphic.getRotation(), pp );
240                }
241    
242                if ( graphic.getDisplacement() != null ) {
243                    pp = extractPPFromParamValueType( graphic.getDisplacement()[0], pp );
244                    pp = extractPPFromParamValueType( graphic.getDisplacement()[1], pp );
245                }
246    
247                if ( graphic.getSize() != null ) {
248                    pp = extractPPFromParamValueType( graphic.getSize(), pp );
249                }
250    
251                if ( symbolizer.getGeometry() != null ) {
252                    pp.add( symbolizer.getGeometry().getPropertyPath() );
253                }
254    
255                if ( graphic.getMarksAndExtGraphics().length > 0 ) {
256                    for ( Object obj : graphic.getMarksAndExtGraphics() ) {
257                        if ( obj instanceof ExternalGraphic ) {
258                            String file = ( (ExternalGraphic) obj ).getOnlineResource().toExternalForm();
259                            String[] tags = StringTools.extractStrings( file, "$", "$" );
260                            if ( tags != null ) {
261                                for ( int i = 0; i < tags.length; i++ ) {
262                                    String tag = tags[i].substring( 1, tags[i].length() - 1 );
263                                    QualifiedName pn = new QualifiedName( tag, featureType.getNamespace() );
264                                    pp.add( PropertyPathFactory.createPropertyPath( pn ) );
265                                }
266                            }
267                        }
268                    }
269                }
270    
271            }
272    
273            return pp;
274        }
275    
276        private static List<PropertyPath> extractPPFromCssParameter( Map<?, ?> css, List<PropertyPath> pp )
277                                throws PropertyPathResolvingException {
278            if ( css != null ) {
279                Iterator<?> iter = css.values().iterator();
280                while ( iter.hasNext() ) {
281                    ParameterValueType pvt = ( (CssParameter) iter.next() ).getValue();
282                    pp = extractPPFromParamValueType( pvt, pp );
283                }
284            }
285            return pp;
286        }
287    
288        private static List<PropertyPath> extractPPFromParamValueType( ParameterValueType pvt, List<PropertyPath> pp )
289                                throws PropertyPathResolvingException {
290            if ( pvt != null ) {
291                Object[] components = pvt.getComponents();
292                for ( int i = 0; i < components.length; i++ ) {
293                    if ( components[i] instanceof Expression ) {
294                        pp = FilterTools.extractPropertyPaths( (Expression) components[i], pp );
295                    }
296                }
297            }
298            return pp;
299        }
300    
301    }