001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/graphics/displayelements/DisplayElementFactory.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.displayelements;
037    
038    import java.lang.reflect.Constructor;
039    import java.lang.reflect.InvocationTargetException;
040    import java.util.ArrayList;
041    import java.util.List;
042    import java.util.Locale;
043    import java.util.UUID;
044    
045    import org.deegree.datatypes.QualifiedName;
046    import org.deegree.framework.log.ILogger;
047    import org.deegree.framework.log.LoggerFactory;
048    import org.deegree.graphics.sld.FeatureTypeStyle;
049    import org.deegree.graphics.sld.Geometry;
050    import org.deegree.graphics.sld.LineSymbolizer;
051    import org.deegree.graphics.sld.PointSymbolizer;
052    import org.deegree.graphics.sld.PolygonSymbolizer;
053    import org.deegree.graphics.sld.RasterSymbolizer;
054    import org.deegree.graphics.sld.Rule;
055    import org.deegree.graphics.sld.Symbolizer;
056    import org.deegree.graphics.sld.TextSymbolizer;
057    import org.deegree.graphics.sld.UserStyle;
058    import org.deegree.i18n.Messages;
059    import org.deegree.io.datastore.PropertyPathResolvingException;
060    import org.deegree.model.coverage.grid.GridCoverage;
061    import org.deegree.model.feature.Feature;
062    import org.deegree.model.feature.FeatureFactory;
063    import org.deegree.model.feature.FeatureProperty;
064    import org.deegree.model.feature.schema.FeatureType;
065    import org.deegree.model.feature.schema.PropertyType;
066    import org.deegree.model.filterencoding.Filter;
067    import org.deegree.model.filterencoding.FilterEvaluationException;
068    import org.deegree.model.spatialschema.Curve;
069    import org.deegree.model.spatialschema.GeometryException;
070    import org.deegree.model.spatialschema.GeometryFactory;
071    import org.deegree.model.spatialschema.MultiCurve;
072    import org.deegree.model.spatialschema.MultiGeometry;
073    import org.deegree.model.spatialschema.MultiPoint;
074    import org.deegree.model.spatialschema.MultiPrimitive;
075    import org.deegree.model.spatialschema.MultiSurface;
076    import org.deegree.model.spatialschema.Point;
077    import org.deegree.model.spatialschema.Position;
078    import org.deegree.model.spatialschema.Surface;
079    import org.deegree.ogcwebservices.wms.operation.GetMap;
080    
081    /**
082     * Factory class for the different kinds of {@link DisplayElement}s.
083     *
084     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
085     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider</a>
086     * @author last edited by: $Author: mschneider $
087     *
088     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
089     */
090    public class DisplayElementFactory {
091    
092        private static final ILogger LOG = LoggerFactory.getLogger( DisplayElementFactory.class );
093    
094        /**
095         * @param o
096         * @param styles
097         * @return the display elements
098         * @throws ClassNotFoundException
099         * @throws IllegalAccessException
100         * @throws InstantiationException
101         * @throws NoSuchMethodException
102         * @throws InvocationTargetException
103         * @throws GeometryException
104         * @throws PropertyPathResolvingException
105         */
106        public DisplayElement[] createDisplayElement( Object o, UserStyle[] styles )
107                                throws ClassNotFoundException, IllegalAccessException, InstantiationException,
108                                NoSuchMethodException, InvocationTargetException, GeometryException,
109                                PropertyPathResolvingException {
110            return createDisplayElement( o, styles, null );
111        }
112    
113        /**
114         * Returns the display elements for a {@link Feature} or {@link GridCoverage}.
115         *
116         * @param o
117         * @param styles
118         * @param request
119         * @return the display elements
120         * @throws ClassNotFoundException
121         * @throws IllegalAccessException
122         * @throws InstantiationException
123         * @throws NoSuchMethodException
124         * @throws InvocationTargetException
125         * @throws GeometryException
126         *
127         * @throws PropertyPathResolvingException
128         */
129        public DisplayElement[] createDisplayElement( Object o, UserStyle[] styles, GetMap request )
130                                throws ClassNotFoundException, IllegalAccessException, InstantiationException,
131                                NoSuchMethodException, InvocationTargetException, GeometryException,
132                                PropertyPathResolvingException {
133    
134            ArrayList<DisplayElement> list = new ArrayList<DisplayElement>( 20 );
135    
136            if ( o instanceof Feature ) {
137                Feature tmp = (Feature) o;
138    
139                List<Feature> features = splitFeature( tmp );
140                for ( Feature feature : features ) {
141    
142                    try {
143                        String featureTypeName = feature.getFeatureType().getName().getPrefixedName();
144                        String qfeatureTypeName = feature.getFeatureType().getName().getFormattedString();
145    
146                        for ( int i = 0; i < styles.length; i++ ) {
147    
148                            if ( styles[i] == null ) {
149                                // create display element from default style
150                                DisplayElement de = buildDisplayElement( feature );
151                                if ( de != null ) {
152                                    list.add( de );
153                                }
154                            } else {
155                                FeatureTypeStyle[] fts = styles[i].getFeatureTypeStyles();
156                                for ( int k = 0; k < fts.length; k++ ) {
157                                    if ( fts[k].getFeatureTypeName() == null
158                                         || featureTypeName.equals( fts[k].getFeatureTypeName() )
159                                         || qfeatureTypeName.equals( fts[k].getFeatureTypeName() ) ) {
160                                        Rule[] rules = fts[k].getRules();
161                                        for ( int n = 0; n < rules.length; n++ ) {
162                                            // does the filter rule apply?
163                                            Filter filter = rules[n].getFilter();
164                                            if ( filter != null ) {
165                                                try {
166                                                    if ( !filter.evaluate( feature ) ) {
167                                                        continue;
168                                                    }
169                                                } catch ( FilterEvaluationException e ) {
170                                                    LOG.logDebug( "Error evaluating filter: ", e );
171                                                    continue;
172                                                }
173                                            }
174    
175                                            // Filter expression is true for this feature, so a
176                                            // corresponding DisplayElement has to be added to the
177                                            // list
178                                            Symbolizer[] symbolizers = rules[n].getSymbolizers();
179    
180                                            for ( int u = 0; u < symbolizers.length; u++ ) {
181                                                DisplayElement displayElement = buildDisplayElement( feature,
182                                                                                                     symbolizers[u] );
183                                                if ( displayElement != null ) {
184                                                    list.add( displayElement );
185                                                }
186                                            }
187                                        }
188                                    }
189                                }
190                            }
191                        }
192                    } catch ( IncompatibleGeometryTypeException e ) {
193                        LOG.logWarning( e.getLocalizedMessage() );
194                        LOG.logDebug( "Stack trace", e );
195                    }
196                }
197            } else {
198                for ( UserStyle style : styles ) {
199                    if ( style == null ) {
200                        list.add( buildRasterDisplayElement( (GridCoverage) o, new RasterSymbolizer(), request ) );
201                        continue;
202                    }
203                    for ( FeatureTypeStyle fts : style.getFeatureTypeStyles() ) {
204                        for ( Rule rule : fts.getRules() ) {
205                            for ( Symbolizer symbolizer : rule.getSymbolizers() ) {
206                                list.add( buildRasterDisplayElement( (GridCoverage) o, (RasterSymbolizer) symbolizer,
207                                                                     request ) );
208                            }
209                        }
210                    }
211                }
212            }
213    
214            DisplayElement[] de = new DisplayElement[list.size()];
215            return list.toArray( de );
216        }
217    
218        /**
219         * splits a feature into n-Features if at least one of a features geometries are a {@link MultiGeometry}
220         *
221         * @param feature
222         * @return list of {@link Feature}
223         */
224        private List<Feature> splitFeature( Feature feature ) {
225            List<Feature> list = new ArrayList<Feature>();
226            FeatureType ft = feature.getFeatureType();
227            PropertyType[] pt = ft.getProperties();
228    
229            for ( PropertyType type : pt ) {
230                FeatureProperty[] fp = feature.getProperties( type.getName() );
231                if ( fp == null ) {
232                    continue;
233                }
234                for ( FeatureProperty property : fp ) {
235                    if ( property == null ) {
236                        continue;
237                    }
238                    Object value = property.getValue();
239                    if ( value instanceof MultiGeometry ) {
240                        MultiGeometry mg = (MultiGeometry) value;
241                        org.deegree.model.spatialschema.Geometry[] g = mg.getAll();
242                        for ( org.deegree.model.spatialschema.Geometry geometry : g ) {
243                            list.add( cloneFeature( feature, geometry, property.getName() ) );
244                        }
245                    }
246                }
247    
248            }
249            if ( list.size() == 0 ) {
250                list.add( feature );
251            }
252    
253            return list;
254        }
255    
256        private Feature cloneFeature( Feature feature, org.deegree.model.spatialschema.Geometry geometry, QualifiedName name ) {
257            FeatureType ft = feature.getFeatureType();
258            PropertyType[] pt = ft.getProperties();
259            List<FeatureProperty> properties = new ArrayList<FeatureProperty>( pt.length );
260            for ( PropertyType type : pt ) {
261                if ( type.getName().equals( name ) ) {
262                    properties.add( FeatureFactory.createFeatureProperty( name, geometry ) );
263                } else {
264                    FeatureProperty[] tmp = feature.getProperties( type.getName() );
265                    for ( FeatureProperty property : tmp ) {
266                        properties.add( property );
267                    }
268                }
269            }
270            FeatureProperty[] fp = properties.toArray( new FeatureProperty[properties.size()] );
271            return FeatureFactory.createFeature( UUID.randomUUID().toString(), ft, fp );
272        }
273    
274        /**
275         * Builds a {@link DisplayElement} using the given {@link Feature} or {@link GridCoverage} and {@link Symbolizer}.
276         *
277         * @param o
278         *            contains the geometry or raster information (Feature or GridCoverage)
279         * @param symbolizer
280         *            contains the drawing (style) information and selects the geometry property of the <code>Feature</code>
281         *            to be drawn
282         * @throws IncompatibleGeometryTypeException
283         *             if the selected geometry of the <code>Feature</code> is not compatible with the
284         *             <code>Symbolizer</code>
285         * @return constructed <code>DisplayElement</code>
286         * @throws ClassNotFoundException
287         * @throws IllegalAccessException
288         * @throws InstantiationException
289         * @throws NoSuchMethodException
290         * @throws InvocationTargetException
291         * @throws GeometryException
292         * @throws PropertyPathResolvingException
293         */
294        public static DisplayElement buildDisplayElement( Object o, Symbolizer symbolizer )
295                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
296                                InstantiationException, NoSuchMethodException, InvocationTargetException,
297                                GeometryException, PropertyPathResolvingException {
298            DisplayElement displayElement = null;
299    
300            if ( o instanceof Feature ) {
301                Feature feature = (Feature) o;
302    
303                // determine the geometry property to be used
304                org.deegree.model.spatialschema.Geometry geometry = null;
305                Geometry symbolizerGeometry = symbolizer.getGeometry();
306    
307                if ( symbolizerGeometry != null ) {
308                    FeatureProperty property = feature.getDefaultProperty( symbolizerGeometry.getPropertyPath() );
309                    if ( property != null ) {
310                        geometry = (org.deegree.model.spatialschema.Geometry) property.getValue();
311                    }
312                } else {
313                    geometry = feature.getDefaultGeometryPropertyValue();
314                }
315    
316                // if the geometry is null, do not build a DisplayElement
317                if ( geometry == null ) {
318                    return null;
319                }
320                if ( symbolizer instanceof PointSymbolizer ) {
321                    displayElement = buildPointDisplayElement( feature, geometry, (PointSymbolizer) symbolizer );
322                } else if ( symbolizer instanceof LineSymbolizer ) {
323                    displayElement = buildLineStringDisplayElement( feature, geometry, (LineSymbolizer) symbolizer );
324                } else if ( symbolizer instanceof PolygonSymbolizer ) {
325                    displayElement = buildPolygonDisplayElement( feature, geometry, (PolygonSymbolizer) symbolizer );
326                } else if ( symbolizer instanceof TextSymbolizer ) {
327                    displayElement = buildLabelDisplayElement( feature, geometry, (TextSymbolizer) symbolizer );
328                }
329            } else {
330                if ( symbolizer instanceof RasterSymbolizer ) {
331                    LOG.logDebug( "Building RasterDisplayElement" );
332                    displayElement = buildRasterDisplayElement( (GridCoverage) o, (RasterSymbolizer) symbolizer );
333                }
334            }
335    
336            return displayElement;
337        }
338    
339        /**
340         * Builds a {@link DisplayElement} using the given {@link Feature} or {@link GridCoverage} and the default
341         * {@link Symbolizer}.
342         *
343         * @param o
344         *            contains the geometry or raster information (Feature or GridCoverage)
345         * @throws IncompatibleGeometryTypeException
346         *             if the selected geometry of the <code>Feature</code> is not compatible with the
347         *             <code>Symbolizer</code>
348         * @return constructed <code>DisplayElement</code>
349         * @throws ClassNotFoundException
350         * @throws IllegalAccessException
351         * @throws InstantiationException
352         * @throws NoSuchMethodException
353         * @throws InvocationTargetException
354         * @throws GeometryException
355         */
356        public static DisplayElement buildDisplayElement( Object o )
357                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
358                                InstantiationException, NoSuchMethodException, InvocationTargetException, GeometryException {
359    
360            DisplayElement displayElement = null;
361    
362            if ( o instanceof GridCoverage ) {
363                RasterSymbolizer symbolizer = new RasterSymbolizer();
364                displayElement = buildRasterDisplayElement( (GridCoverage) o, symbolizer );
365            } else {
366                Feature feature = (Feature) o;
367                // determine the geometry property to be used
368                org.deegree.model.spatialschema.Geometry geoProperty = feature.getDefaultGeometryPropertyValue();
369    
370                // if the geometry property is null, do not build a DisplayElement
371                if ( geoProperty == null ) {
372                    return null;
373                }
374                // PointSymbolizer
375                if ( geoProperty instanceof Point || geoProperty instanceof MultiPoint ) {
376                    PointSymbolizer symbolizer = new PointSymbolizer();
377                    displayElement = buildPointDisplayElement( feature, geoProperty, symbolizer );
378                } // LineSymbolizer
379                else if ( geoProperty instanceof Curve || geoProperty instanceof MultiCurve ) {
380                    LineSymbolizer symbolizer = new LineSymbolizer();
381                    displayElement = buildLineStringDisplayElement( feature, geoProperty, symbolizer );
382                } // PolygonSymbolizer
383                else if ( geoProperty instanceof Surface || geoProperty instanceof MultiSurface ) {
384                    PolygonSymbolizer symbolizer = new PolygonSymbolizer();
385                    displayElement = buildPolygonDisplayElement( feature, geoProperty, symbolizer );
386                } else {
387                    throw new IncompatibleGeometryTypeException( "not a valid geometry type" );
388                }
389            }
390    
391            return displayElement;
392        }
393    
394        /**
395         * Creates a {@link PointDisplayElement} using the given geometry and style information.
396         *
397         * @param feature
398         *            associated feature (source of the geometry information)
399         * @param geom
400         *            geometry information
401         * @param sym
402         *            style information
403         * @return constructed <code>PointDisplayElement</code>
404         * @throws ClassNotFoundException
405         * @throws IllegalAccessException
406         * @throws InstantiationException
407         * @throws NoSuchMethodException
408         * @throws InvocationTargetException
409         */
410        public static PointDisplayElement buildPointDisplayElement( Feature feature,
411                                                                    org.deegree.model.spatialschema.Geometry geom,
412                                                                    PointSymbolizer sym )
413                                throws ClassNotFoundException, IllegalAccessException, InstantiationException,
414                                NoSuchMethodException, InvocationTargetException {
415    
416            // if the geometry is not a point geometry, the centroid(s) of the
417            // geometry will be used
418            PointDisplayElement displayElement = null;
419            String className = sym.getResponsibleClass();
420            Class<?> clss = Class.forName( className );
421            Object[] values = new Object[] { feature, geom, sym };
422            if ( geom instanceof Point ) {
423                Class<?>[] param = new Class[] { Feature.class, Point.class, PointSymbolizer.class };
424                Constructor<?> constructor = clss.getConstructor( param );
425                displayElement = (PointDisplayElement) constructor.newInstance( values );
426            } else if ( geom instanceof MultiPoint ) {
427                Class<?>[] param = new Class[] { Feature.class, MultiPoint.class, PointSymbolizer.class };
428                Constructor<?> constructor = clss.getConstructor( param );
429                displayElement = (PointDisplayElement) constructor.newInstance( values );
430            } else if ( geom instanceof MultiPrimitive ) {
431                // Primitive[] primitives = ( (MultiPrimitive) geom ).getAllPrimitives();
432                // Point[] centroids = new Point[primitives.length];
433                Point[] centroids = new Point[1];
434                centroids[0] = geom.getCentroid();
435    
436                // for ( int i = 0; i < primitives.length; i++ ) {
437                // centroids[i] = primitives[i].getCentroid();
438                // }
439    
440                try {
441                    Class<?>[] param = new Class[] { Feature.class, MultiPoint.class, PointSymbolizer.class };
442                    Constructor<?> constructor = clss.getConstructor( param );
443                    values[1] = GeometryFactory.createMultiPoint( centroids );
444                    displayElement = (PointDisplayElement) constructor.newInstance( values );
445                } catch ( Exception e ) {
446                    e.printStackTrace();
447                }
448            } else {
449                Class<?>[] param = new Class[] { Feature.class, Point.class, PointSymbolizer.class };
450                Constructor<?> constructor = clss.getConstructor( param );
451                values[1] = geom.getCentroid();
452                displayElement = (PointDisplayElement) constructor.newInstance( values );
453            }
454    
455            return displayElement;
456        }
457    
458        /**
459         * Creates a {@link LineStringDisplayElement} using the given geometry and style information.
460         *
461         * @param feature
462         *            associated feature (source of the geometry information)
463         * @param geom
464         *            geometry information
465         * @param sym
466         *            style information
467         * @throws IncompatibleGeometryTypeException
468         *             if the geometry property is not a <code>Curve</code> or <code>MultiCurve</code>
469         * @return constructed <code>LineStringDisplayElement</code>
470         * @throws ClassNotFoundException
471         * @throws IllegalAccessException
472         * @throws InstantiationException
473         * @throws NoSuchMethodException
474         * @throws InvocationTargetException
475         * @throws GeometryException
476         */
477        public static LineStringDisplayElement buildLineStringDisplayElement(
478                                                                              Feature feature,
479                                                                              org.deegree.model.spatialschema.Geometry geom,
480                                                                              LineSymbolizer sym )
481                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
482                                InstantiationException, NoSuchMethodException, InvocationTargetException, GeometryException {
483            LineStringDisplayElement displayElement = null;
484    
485            String className = sym.getResponsibleClass();
486            Class<?> clss = Class.forName( className );
487            Object[] values = new Object[] { feature, geom, sym };
488    
489            if ( geom instanceof Curve ) {
490                Class<?>[] param = new Class[] { Feature.class, Curve.class, LineSymbolizer.class };
491                Constructor<?> constructor = clss.getConstructor( param );
492                displayElement = (LineStringDisplayElement) constructor.newInstance( values );
493            } else if ( geom instanceof MultiCurve ) {
494                Class<?>[] param = new Class[] { Feature.class, MultiCurve.class, LineSymbolizer.class };
495                Constructor<?> constructor = clss.getConstructor( param );
496                displayElement = (LineStringDisplayElement) constructor.newInstance( values );
497            } else if ( geom instanceof Surface ) {
498                // according to OGC SLD specification it is possible to assign a
499                // LineSymbolizer to a polygon. To handle this the border of the
500                // polygon will be transformed into a lines (curves)
501                MultiCurve mc = surfaceToCurve( (Surface) geom );
502                displayElement = buildLineStringDisplayElement( feature, mc, sym );
503            } else if ( geom instanceof MultiSurface ) {
504                // according to OGC SLD specification it is possible to assign a
505                // LineSymbolizer to a multipolygon. To handle this the borders of the
506                // multipolygons will be transformed into a lines (curves)
507                MultiSurface ms = (MultiSurface) geom;
508                List<Curve> list = new ArrayList<Curve>( 500 );
509                for ( int i = 0; i < ms.getSize(); i++ ) {
510                    MultiCurve mc = surfaceToCurve( ms.getSurfaceAt( i ) );
511                    for ( int j = 0; j < mc.getSize(); j++ ) {
512                        list.add( mc.getCurveAt( j ) );
513                    }
514                }
515                Curve[] curves = list.toArray( new Curve[list.size()] );
516                MultiCurve mc = GeometryFactory.createMultiCurve( curves );
517                displayElement = buildLineStringDisplayElement( feature, mc, sym );
518            } else {
519                throw new IncompatibleGeometryTypeException( "Tried to create a LineStringDisplayElement from a geometry "
520                                                             + "with an incompatible / unsupported type: '"
521                                                             + geom.getClass().getName() + "'!" );
522            }
523    
524            return displayElement;
525        }
526    
527        /**
528         * Transforms a {@link Surface} into a {@link MultiCurve}.
529         *
530         * @param geom
531         * @return MultiCurve
532         */
533        private static MultiCurve surfaceToCurve( Surface geom )
534                                throws GeometryException {
535            List<Curve> list = new ArrayList<Curve>( 100 );
536            int num = geom.getNumberOfSurfacePatches();
537            for ( int i = 0; i < num; i++ ) {
538                Position[] pos = geom.getSurfacePatchAt( i ).getExteriorRing();
539                Curve curve = GeometryFactory.createCurve( pos, geom.getCoordinateSystem() );
540                list.add( curve );
541                Position[][] inn = geom.getSurfacePatchAt( i ).getInteriorRings();
542                if ( inn != null ) {
543                    for ( int j = 0; j < inn.length; j++ ) {
544                        curve = GeometryFactory.createCurve( inn[j], geom.getCoordinateSystem() );
545                        list.add( curve );
546                    }
547                }
548            }
549            Curve[] curves = list.toArray( new Curve[list.size()] );
550            MultiCurve mc = GeometryFactory.createMultiCurve( curves );
551            return mc;
552        }
553    
554        /**
555         * Creates a {@link PolygonDisplayElement} using the given geometry and style information.
556         *
557         * @param feature
558         *            associated feature (source of the geometry information)
559         * @param geom
560         *            geometry information
561         * @param sym
562         *            style information
563         * @throws IncompatibleGeometryTypeException
564         *             if the geometry property is not a <code>Surface</code> or <code>MultiSurface</code>
565         * @return constructed <code>PolygonDisplayElement</code>
566         * @throws ClassNotFoundException
567         * @throws IllegalAccessException
568         * @throws InstantiationException
569         * @throws NoSuchMethodException
570         * @throws InvocationTargetException
571         */
572        public static PolygonDisplayElement buildPolygonDisplayElement( Feature feature,
573                                                                        org.deegree.model.spatialschema.Geometry geom,
574                                                                        PolygonSymbolizer sym )
575                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
576                                InstantiationException, NoSuchMethodException, InvocationTargetException {
577            PolygonDisplayElement displayElement = null;
578    
579            String className = sym.getResponsibleClass();
580            Class<?> clss = Class.forName( className );
581            Object[] values = new Object[] { feature, geom, sym };
582            if ( geom instanceof Surface ) {
583                Class<?>[] param = new Class[] { Feature.class, Surface.class, PolygonSymbolizer.class };
584                Constructor<?> constructor = clss.getConstructor( param );
585                displayElement = (PolygonDisplayElement) constructor.newInstance( values );
586            } else if ( geom instanceof MultiSurface ) {
587                Class<?>[] param = new Class[] { Feature.class, MultiSurface.class, PolygonSymbolizer.class };
588                Constructor<?> constructor = clss.getConstructor( param );
589                displayElement = (PolygonDisplayElement) constructor.newInstance( values );
590            } else {
591                String s = Messages.get( Locale.getDefault(), "INVALID_GEOM_TYPE_FOR_POLYGON_DE", geom.getClass().getName() );
592                throw new IncompatibleGeometryTypeException( s );
593            }
594    
595            return displayElement;
596        }
597    
598        /**
599         * Creates a {@link LabelDisplayElement} using the given geometry and style information.
600         *
601         * @param feature
602         *            associated feature (source of the geometry information and label caption)
603         * @param geom
604         *            geometry information
605         * @param sym
606         *            style information
607         * @throws IncompatibleGeometryTypeException
608         *             if the geometry property is not a <code>Point</code>, a <code>Surface</code> or
609         *             <code>MultiSurface</code>
610         * @return constructed <code>LabelDisplayElement</code>
611         * @throws ClassNotFoundException
612         * @throws IllegalAccessException
613         * @throws InstantiationException
614         * @throws NoSuchMethodException
615         * @throws InvocationTargetException
616         */
617        public static LabelDisplayElement buildLabelDisplayElement( Feature feature,
618                                                                    org.deegree.model.spatialschema.Geometry geom,
619                                                                    TextSymbolizer sym )
620                                throws IncompatibleGeometryTypeException, ClassNotFoundException, IllegalAccessException,
621                                InstantiationException, NoSuchMethodException, InvocationTargetException {
622    
623            LabelDisplayElement displayElement = null;
624    
625            if ( geom instanceof Point || geom instanceof MultiPoint || geom instanceof Surface
626                 || geom instanceof MultiSurface || geom instanceof Curve || geom instanceof MultiCurve ) {
627                String className = sym.getResponsibleClass();
628                Class<?> clss = Class.forName( className );
629                Class<?>[] param = new Class[] { Feature.class, org.deegree.model.spatialschema.Geometry.class,
630                                                TextSymbolizer.class };
631                Object[] values = new Object[] { feature, geom, sym };
632                Constructor<?> constructor = clss.getConstructor( param );
633                displayElement = (LabelDisplayElement) constructor.newInstance( values );
634            } else {
635                throw new IncompatibleGeometryTypeException( "Tried to create a LabelDisplayElement from a geometry with "
636                                                             + "an incompatible / unsupported type: '"
637                                                             + geom.getClass().getName() + "'!" );
638            }
639    
640            return displayElement;
641        }
642    
643        /**
644         * Creates a {@link RasterDisplayElement} from the given {@link GridCoverage}.
645         *
646         * @param gc
647         *            grid coverage (source of the raster data)
648         * @param sym
649         *            raster symbolizer
650         *
651         * @return RasterDisplayElement
652         */
653        public static RasterDisplayElement buildRasterDisplayElement( GridCoverage gc, RasterSymbolizer sym ) {
654            return new RasterDisplayElement( gc, sym );
655        }
656    
657        /**
658         * @param gc
659         * @param sym
660         * @param request
661         * @return the new raster display element
662         */
663        public static RasterDisplayElement buildRasterDisplayElement( GridCoverage gc, RasterSymbolizer sym, GetMap request ) {
664            return new RasterDisplayElement( gc, sym, request );
665        }
666    
667    }