/[schmitzm]/branches/1.0-gt2-2.6/src/skrueger/geotools/StyledLayerUtil.java
ViewVC logotype

Annotation of /branches/1.0-gt2-2.6/src/skrueger/geotools/StyledLayerUtil.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 127 - (hide annotations)
Sat May 30 14:29:58 2009 UTC (15 years, 9 months ago) by mojays
Original Path: trunk/src/skrueger/geotools/StyledMapUtil.java
File size: 29200 byte(s)
Many many many new JFreeChart stuff (selection panel and renderer, etc.)
- schmitzm.jfree.chart.SelectableChartPanel
- schmitzm.jfree.chart.ChartMouseSelectionTracker
- schmitzm.jfree.chart.selection.*
- schmitzm.jfree.chart.renderer.*
Plus: Imports organized!
1 mojays 2 package skrueger.geotools;
2    
3 mojays 127 import java.io.File;
4     import java.io.FileNotFoundException;
5     import java.io.FileWriter;
6     import java.net.URL;
7 mojays 2 import java.text.DecimalFormat;
8     import java.util.HashMap;
9     import java.util.List;
10 mojays 127 import java.util.Map;
11 mojays 52 import java.util.SortedMap;
12     import java.util.TreeMap;
13 mojays 2
14 mojays 127 import org.apache.log4j.Logger;
15     import org.geotools.coverage.grid.GridCoverage2D;
16     import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
17 mojays 2 import org.geotools.feature.FeatureCollection;
18 mojays 127 import org.geotools.map.DefaultMapLayer;
19 mojays 2 import org.geotools.map.MapLayer;
20     import org.geotools.styling.ColorMap;
21     import org.geotools.styling.ColorMapEntry;
22 mojays 127 import org.geotools.styling.RasterSymbolizer;
23 mojays 2 import org.geotools.styling.Style;
24 mojays 127 import org.jdom.Document;
25 mojays 2 import org.jdom.Element;
26     import org.jdom.input.SAXBuilder;
27     import org.jdom.output.XMLOutputter;
28    
29     import schmitzm.geotools.styling.StylingUtil;
30 mojays 127 import schmitzm.io.IOUtil;
31     import schmitzm.lang.LangUtil;
32     import schmitzm.swing.SwingUtil;
33 mojays 2 import skrueger.AttributeMetaData;
34     import skrueger.RasterLegendData;
35     import skrueger.i8n.Translation;
36    
37     /**
38     * This class provides static helper methods for dealing with
39     * {@link StyledMapInterface} stuff.
40     * @author <a href="mailto:[email protected]">Martin Schmitz</a> (University of Bonn/Germany)
41     * @version 1.0
42     */
43     public class StyledMapUtil {
44     private static final Logger LOGGER = Logger.getLogger(StyledMapUtil.class.getName());
45     private static final SAXBuilder SAX_BUILDER = new SAXBuilder();
46     private static final XMLOutputter XML_OUTPUTTER = new XMLOutputter();
47    
48     /** URL for Atlas XML schema */
49     public static final String AMLURI = "http://www.wikisquare.de/AtlasML";
50     /** Name of the XML Element for the attribute meta data map */
51     public static final String ELEM_NAME_AMD = "attributeMetaData";
52     /** Name of the XML Element for the raster legend data */
53     public static final String ELEM_NAME_RLD = "rasterLegendData";
54     /** Name of the XML Element for an attribute meta data map entry */
55     public static final String ELEM_NAME_ATTRIBUTE = "dataAttribute";
56     /** Name of the XML Element for an raster legend data entry */
57     public static final String ELEM_NAME_RASTERLEGEND = "rasterLegendItem";
58     /** Name of the XML Element for a translation */
59     public static final String ELEM_NAME_TRANSLATION = "translation";
60    
61     /**
62     * Creates a Geotools {@link MapLayer} from an object. If the object is a
63     * {@link StyledMapInterface} then its sytle is used. In case of direct
64     * Geotools objects ({@link GridCoverage2D}, {@link AbstractGridCoverage2DReader},
65     * {@link FeatureCollection}) a default style is generated.
66     * @param object an Object
67     * @exception Exception if {@code null} is given as object or an error occurs during layer creation
68     */
69     public static MapLayer createMapLayer(Object object) throws Exception {
70     return createMapLayer(object,null);
71     }
72    
73     /**
74     * Creates a Geotools {@link MapLayer} from an object. If the object is a
75     * {@link StyledMapInterface} then its sytle is used. In case of direct
76     * Geotools objects ({@link GridCoverage2D}, {@link AbstractGridCoverage2DReader},
77     * {@link FeatureCollection}) a default style is generated.
78     * @param object an Object
79     * @param forcedStyle (SLD-)Style to force for the object
80     * @exception Exception if {@code null} is given as object or an error occurs during layer creation
81     */
82     public static MapLayer createMapLayer(Object object, Style forcedStyle) throws Exception {
83     MapLayer layer = null;
84     Style style = null;
85     if ( object instanceof StyledMapInterface ) {
86     style = ((StyledMapInterface<?>)object).getStyle();
87     object = ((StyledMapInterface<?>)object).getGeoObject();
88     }
89     if ( forcedStyle != null )
90     style = forcedStyle;
91     if ( style == null )
92     style = StylingUtil.createDefaultStyle(object);
93    
94     if (object instanceof GridCoverage2D)
95     layer = new DefaultMapLayer( (GridCoverage2D) object, style);
96     if (object instanceof AbstractGridCoverage2DReader)
97     layer = new DefaultMapLayer( (AbstractGridCoverage2DReader) object, style);
98     if (object instanceof FeatureCollection)
99     layer = new DefaultMapLayer( (FeatureCollection) object, style);
100    
101     if ( layer == null )
102     throw new Exception("Can not create MapLayer from "+(object == null ? "null" : object.getClass()));
103    
104     return layer;
105     }
106    
107     /**
108     * Creates an default instance of {@link StyledMapInterface} for a Geotools
109     * object ({@link GridCoverage2D}, {@link FeatureCollection}) with a default
110     * style.
111     * @param object an Object
112     * @param title title for the object
113     * @exception UnsupportedOperationException if {@code null} is given as object or an error occurs during creation
114     */
115     public static StyledMapInterface<?> createStyledMap(Object object, String title) {
116     return createStyledMap(object, title, null);
117     }
118    
119     /**
120     * Creates an default instance of {@link StyledMapInterface} for a Geotools
121     * object ({@link GridCoverage2D}, {@link FeatureCollection}) with a given
122     * style.
123     * @param object an Object
124     * @param title title for the object
125     * @param style style and meta data for the object
126     * @exception UnsupportedOperationException if {@code null} is given as object or an error occurs during creation
127     */
128     public static StyledMapInterface<?> createStyledMap(Object object, String title, StyledMapStyle style) {
129     StyledMapInterface<?> styledObject = null;
130    
131     String id = (title != null) ? title : "defaultID";
132    
133     if ( object instanceof GridCoverage2D )
134     styledObject = new StyledGridCoverage(
135     (GridCoverage2D)object,
136     id,
137     title,
138     style
139     );
140     else if ( object instanceof AbstractGridCoverage2DReader )
141     styledObject = new StyledGridCoverageReader(
142     (AbstractGridCoverage2DReader)object,
143     id,
144     title,
145     style
146     );
147     else if ( object instanceof FeatureCollection )
148     styledObject = new StyledFeatureCollection(
149     (FeatureCollection)object,
150     id,
151     title,
152     style
153     );
154 alfonx 43
155 mojays 2 if ( styledObject == null )
156     throw new UnsupportedOperationException("Can not create StyledMapInterface object from "+(object == null ? "null" : object.getClass()));
157    
158     return styledObject;
159     }
160    
161     /**
162 mojays 52 * Return only the visible or invisible entries of an AttributeMetaData-Map.
163     * @param amdMap AttributeMetaData-Map
164     * @param visible indicated whether the visible or invisible entries are
165     * returned
166     */
167 alfonx 111 public static SortedMap<Integer,AttributeMetaData> getVisibleAttributeMetaData(Map<Integer,AttributeMetaData> amdMap, boolean visible) {
168 mojays 52 SortedMap<Integer,AttributeMetaData> filteredMap = new TreeMap<Integer,AttributeMetaData>();
169     for (AttributeMetaData amd : amdMap.values())
170     if ( amd.isVisible() )
171     filteredMap.put(amd.getColIdx(), amd);
172    
173     return filteredMap;
174     }
175    
176    
177     /**
178 mojays 2 * Parses a {@link AttributeMetaData} object from an JDOM-{@link Element}.
179     * This method works like {@link AMLImport#parseDataAttribute(org.w3c.dom.Node},
180     * but for JDOM.
181     * @param element {@link Element} to parse
182     */
183     public static AttributeMetaData parseAttributeMetaData(final Element element) {
184     final Integer col = Integer.valueOf(element.getAttributeValue("col"));
185     final Boolean visible = Boolean.valueOf(element.getAttributeValue("visible"));
186     final String unit = element.getAttributeValue("unit");
187    
188     Translation name = new Translation();
189     Translation desc = new Translation();
190     for (final Element childElement : (List<Element>)element.getChildren()) {
191     if (childElement.getName() == null)
192     continue;
193    
194     if (childElement.getName().equals("name"))
195     name = parseTranslation(childElement);
196     else if (childElement.getName().equals("desc"))
197     desc = parseTranslation(childElement);
198     }
199     return new AttributeMetaData(col, visible, name, desc, unit);
200     }
201    
202     /**
203     * Parses a {@link AttributeMetaData} map from an JDOM-{@link Element}
204     * with {@code <attribute>}-childs.
205     * @param element {@link Element} to parse
206     */
207     public static Map<Integer,AttributeMetaData> parseAttributeMetaDataMap(final Element element) {
208     HashMap<Integer,AttributeMetaData> metaData = new HashMap<Integer,AttributeMetaData>();
209     List<Element> attributesElements = element.getChildren( ELEM_NAME_ATTRIBUTE );
210     for (Element attibuteElement : attributesElements)
211     {
212     AttributeMetaData attrMetaData = parseAttributeMetaData( attibuteElement );
213     metaData.put( attrMetaData.getColIdx(), attrMetaData );
214     }
215     return metaData;
216     }
217    
218     /**
219     * Loads a {@link AttributeMetaData} object from an URL.
220     * @param documentUrl {@link URL} to parse
221     * @see #parseAttributeMetaData(Element)
222     */
223     public static Map<Integer,AttributeMetaData> loadAttributeMetaDataMap(final URL documentUrl) throws Exception {
224     Document document = SAX_BUILDER.build(documentUrl);
225     return parseAttributeMetaDataMap( document.getRootElement() );
226     }
227    
228     /**
229     * Creates an JDOM {@link Element} for the given {@link AttributeMetaData}
230     * object.
231     * @param amd meta data for one attribute
232     */
233     public static Element createAttributeMetaDataElement(final AttributeMetaData amd) {
234     final Element element = new Element( ELEM_NAME_ATTRIBUTE , AMLURI);
235     element.setAttribute("col", String.valueOf( amd.getColIdx() ) );
236     element.setAttribute("visible", String.valueOf( amd.isVisible() ) );
237     element.setAttribute("unit", amd.getUnit() );
238     // Creating a aml:name tag...
239     element.addContent( createTranslationElement("name", amd.getTitle()) );
240     // Creating a aml:desc tag...
241     element.addContent( createTranslationElement("desc", amd.getDesc()) );
242     return element;
243     }
244    
245     /**
246     * Creates an JDOM {@link Element} for the given {@link AttributeMetaData}
247     * map.
248     * @param amdMap map of attribute meta data
249     */
250     public static Element createAttributeMetaDataMapElement(final Map<Integer,AttributeMetaData> amdMap) {
251     final Element element = new Element( ELEM_NAME_AMD , AMLURI);
252     for (AttributeMetaData amd : amdMap.values())
253     element.addContent( createAttributeMetaDataElement( amd ) );
254     return element;
255     }
256    
257     /**
258     * Saves a {@link AttributeMetaData AttributeMetaData-Map} to an URL.
259     * @param amdMap map of {@link AttributeMetaData}
260     * @param documentUrl {@link URL} to store the XML
261     */
262     public static void saveAttributeMetaDataMap(final Map<Integer,AttributeMetaData> amdMap, final URL documentUrl) throws Exception {
263     // Create XML-Document
264     final FileWriter out = new FileWriter( new File(documentUrl.toURI()) );
265     XML_OUTPUTTER.output(
266     createAttributeMetaDataMapElement(amdMap),
267     out
268     );
269     out.flush();
270     out.close();
271     }
272    
273    
274    
275     /**
276     * Parses a {@link RasterLegendData} object from an JDOM-{@link Element}.
277     * This method works like {@link AMLImport#parseRasterLegendData(org.w3c.dom.Node},
278     * but for JDOM.
279     * @param element {@link Element} to parse
280     */
281     public static RasterLegendData parseRasterLegendData(Element element) {
282    
283     final boolean paintGaps = Boolean.valueOf( element.getAttributeValue("paintGaps") );
284    
285     RasterLegendData rld = new RasterLegendData(paintGaps);
286    
287     for ( Element childElement : (List<Element>)element.getChildren() ) {
288     final String name = childElement.getName();
289     // Cancel if it's an attribute
290     if ( childElement.getChildren().size() == 0 )
291     continue;
292    
293     if (name.equals( ELEM_NAME_RASTERLEGEND )) {
294     final String valueAttr = childElement.getAttributeValue("value");
295     if ( valueAttr == null )
296     throw new UnsupportedOperationException("Attribute 'value' missing for definition of <"+ELEM_NAME_RASTERLEGEND+">");
297     final double value = Double.valueOf(valueAttr);
298    
299     // first and only item should be the label
300     final Element labelElement = childElement.getChild("label");
301     // id label element is missing, the translation is searched directly
302     // as childs of the rasterLegendItem element
303     Translation label = parseTranslation( labelElement != null ? labelElement : childElement );
304     rld.put(value, label);
305     }
306     }
307    
308     return rld;
309     }
310    
311     /**
312     * Loads a {@link RasterLegendData} object from an URL.
313     * @param documentUrl {@link URL} to parse
314     * @see #parseAttributeMetaData(Element)
315     */
316     public static RasterLegendData loadRasterLegendData(final URL documentUrl) throws Exception {
317     Document document = SAX_BUILDER.build(documentUrl);
318     return parseRasterLegendData( document.getRootElement() );
319     }
320    
321     /**
322     * Creates an JDOM {@link Element} for the given {@link RasterLegendData}
323     * map.
324     * @param rld raster legend data
325     */
326     public static Element createRasterLegendDataElement(final RasterLegendData rld) {
327     final Element element = new Element( ELEM_NAME_RLD , AMLURI);
328     element.setAttribute("paintGaps", rld.isPaintGaps().toString());
329     for (Double key : rld.getSortedKeys()) {
330     Element item = new Element( ELEM_NAME_RASTERLEGEND, AMLURI);
331     item.setAttribute("value", key.toString());
332     item.addContent( createTranslationElement("label", rld.get(key)) );
333     element.addContent(item);
334     }
335     return element;
336     }
337    
338     /**
339     * Creates {@link RasterLegendData} from a {@link ColorMap}.
340     * @param colorMap a color map
341     * @param paintGaps indicated whether gaps are painted between the legend items
342     * @param digits number of digits the grid value classes (and legend) are
343     * rounded to (null means no round; >= 0 means digits after comma;
344     * < 0 means digits before comma) */
345     public static RasterLegendData generateRasterLegendData(ColorMap colorMap, boolean paintGaps, Integer digits) {
346     DecimalFormat decFormat = digits != null ? new DecimalFormat( SwingUtil.getNumberFormatPattern(digits) ) : null;
347     RasterLegendData rld = new RasterLegendData(paintGaps);
348     for (ColorMapEntry cme : colorMap.getColorMapEntries())
349     {
350     double value = StylingUtil.getQuantityFromColorMapEntry(cme);
351     String label = cme.getLabel();
352     // if no label is set (e.g. quantitative style),
353     // use the value as label
354     if ( label == null || label.equals("") )
355     if ( digits == null )
356     label = String.valueOf(value);
357     else
358     label = decFormat.format( LangUtil.round(value, digits) );
359     rld.put( value, new Translation(" "+label) );
360     }
361     return rld;
362     }
363    
364     /**
365     * Creates {@link RasterLegendData} from the {@link ColorMap} of a style.
366     * @param style a raster style (must contain a {@link RasterSymbolizer})
367     * @param paintGaps indicated whether gaps are painted between the legend items
368     * @param digits number of digits the grid value classes (and legend) are
369     * rounded to (null means no round; >= 0 means digits after comma;
370     * < 0 means digits before comma) */
371     public static RasterLegendData generateRasterLegendData(Style style, boolean paintGaps, Integer digits) {
372     ColorMap colorMap = StylingUtil.getColorMapFromStyle(style);
373     if ( colorMap == null)
374     throw new IllegalArgumentException("Color map can not be determined from style!");
375     return generateRasterLegendData(colorMap, paintGaps, digits);
376     }
377    
378     /**
379     * Saves a {@link RasterLegendData} to an URL.
380     * @param rld raster legend data
381     * @param documentUrl {@link URL} to store the XML
382     */
383     public static void saveRasterLegendData(final RasterLegendData rld, final URL documentUrl) throws Exception {
384     // Create XML-Document
385     final FileWriter out = new FileWriter( new File(documentUrl.toURI()) );
386     XML_OUTPUTTER.output(
387     createRasterLegendDataElement(rld),
388     out
389     );
390     out.flush();
391     out.close();
392     }
393    
394     /**
395     * Parses a {@link Translation} object from an JDOM-{@link Element}.
396     * This method works like {@link AMLImport#parseTranslation(org.w3c.dom.Node},
397     * but for JDOM.
398     * @param element {@link Element} to parse
399     */
400     public final static Translation parseTranslation(final Element element) {
401     Translation trans = new Translation();
402    
403     if (element == null)
404     return trans;
405    
406     for (final Element translationElement : (List<Element>)element.getChildren()) {
407     final String name = translationElement.getName();
408     if (name == null)
409     continue;
410    
411     // lang attribute
412     String lang = translationElement.getAttributeValue("lang");
413     // set the default, if no language code is set
414     if ( lang == null )
415     lang = Translation.DEFAULT_KEY;
416    
417     final String translationText = translationElement.getValue();
418     if (translationText == null)
419     trans.put(lang, "");
420     else
421     trans.put(lang, translationText);
422     }
423    
424     // if no <translation> is given, the value of the node should
425     // be used as a default translation
426     if (trans.size() == 0)
427     trans.put( Translation.DEFAULT_KEY, element.getValue() );
428     // trans = new Translation( ((List<Element>)element.getChildren()).get(0).getValue() );
429    
430     return trans;
431     }
432    
433     /**
434     * Creates an JDOM {@link Element} for the given {@link Translation}.
435     * @param tagname Name of the Element
436     * @param translation Translation to store in the Element
437     */
438     public final static Element createTranslationElement(String tagname, Translation translation) {
439     Element element = new Element(tagname, AMLURI);
440     if ( translation == null )
441     throw new UnsupportedOperationException("Translation element can not be created from null!");
442    
443     // If only a default translation is set, the <translation lang="..">..</tranlation>
444     // part is not used
445     if (translation.keySet().size() == 1 && translation.get(Translation.DEFAULT_KEY) != null) {
446     element.addContent( translation.get(Translation.DEFAULT_KEY) );
447     return element;
448     }
449    
450     // add a <translation lang="..">..</tranlation> part to the element for
451     // all languages
452     for (String lang : translation.keySet()) {
453     Element translationElement = new Element( ELEM_NAME_TRANSLATION , AMLURI);
454     translationElement.setAttribute("lang", lang);
455     String translationString = translation.get(lang);
456     if (translationString == null)
457     translationString = "";
458     translationElement.addContent( translationString );
459     element.addContent(translationElement);
460     }
461    
462     return element;
463     }
464    
465    
466     /**
467     * Sets a style to {@link StyledMapInterface}.
468     * @param styledObject a styled object
469     * @param style a Style
470     */
471     public static void setStyledMapStyle(StyledMapInterface styledObject, StyledMapStyle<?> style) {
472     // set SLD style
473     styledObject.setStyle( style.getGeoObjectStyle() );
474     // set meta data
475     if ( styledObject instanceof StyledGridCoverageInterface &&
476     (style.getMetaData() instanceof RasterLegendData || style.getMetaData() == null) ) {
477     RasterLegendData sourceRld = (RasterLegendData)style.getMetaData();
478     RasterLegendData destRld = ((StyledGridCoverageInterface)styledObject).getLegendMetaData();
479     if ( destRld != null && sourceRld != null ) {
480     destRld.setPaintGaps(sourceRld.isPaintGaps());
481     destRld.clear();
482     destRld.putAll( sourceRld );
483     }
484     return;
485     }
486     if ( styledObject instanceof StyledFeatureCollectionInterface &&
487     (style.getMetaData() instanceof Map || style.getMetaData() == null) ) {
488     Map<Integer, AttributeMetaData> sourceAmd = (Map<Integer, AttributeMetaData>)style.getMetaData();
489     Map<Integer, AttributeMetaData> destAmd = ((StyledFeatureCollectionInterface)styledObject).getAttributeMetaDataMap();
490     if ( destAmd != null && sourceAmd != null ) {
491     destAmd.clear();
492     destAmd.putAll( sourceAmd );
493     }
494     return;
495     }
496    
497     throw new UnsupportedOperationException("Style is not compatible to object: " +
498     (style.getMetaData() == null ? null : style.getMetaData().getClass().getSimpleName()) +
499     " <-> " +
500     (styledObject == null ? null : styledObject.getClass().getSimpleName()));
501     }
502    
503     /**
504     * Returns the style a {@link StyledMapInterface} as a {@link StyledMapStyle}.
505     * @param styledObject a styled object
506     * @return {@code StyledMapStyle<RasterLegendData>} for {@link StyledGridCoverageInterface}
507     * or {@code StyledMapStyle<Map<Integer,AttributeMetaData>>} for
508     * {@link StyledFeatureCollectionInterface}
509     */
510     public static StyledMapStyle<?> getStyledMapStyle(StyledMapInterface styledObject) {
511     if ( styledObject instanceof StyledGridCoverageInterface )
512     return getStyledMapStyle( (StyledGridCoverageInterface)styledObject );
513     if ( styledObject instanceof StyledFeatureCollectionInterface )
514     return getStyledMapStyle( (StyledFeatureCollectionInterface)styledObject );
515     throw new UnsupportedOperationException("Unknown type of StyledMapInterface: "+(styledObject == null ? null : styledObject.getClass().getSimpleName()));
516     }
517    
518     /**
519     * Returns the style and raster meta data of a {@link StyledGridCoverageInterface}
520     * as a {@link StyledMapStyle}.
521     * @param styledGC a styled grid coverage
522     */
523     public static StyledMapStyle<RasterLegendData> getStyledMapStyle(StyledGridCoverageInterface styledGC) {
524     return new StyledMapStyle<RasterLegendData>(
525     styledGC.getStyle(),
526     styledGC.getLegendMetaData()
527     );
528     }
529    
530     /**
531     * Returns the style and attribute meta data of a {@link StyledFeatureCollectionInterface}
532     * as a {@link StyledMapStyle}.
533     * @param styledFC a styled feature collection
534     */
535     public static StyledMapStyle<Map<Integer,AttributeMetaData>> getStyledMapStyle(StyledFeatureCollectionInterface styledFC) {
536     return new StyledMapStyle<Map<Integer,AttributeMetaData>>(
537     styledFC.getStyle(),
538     styledFC.getAttributeMetaDataMap()
539     );
540     }
541    
542     /**
543     * Loads a {@linkplain Style SLD-Style} and {@linkplain RasterLegendData Raster-LegendData}
544     * for a given geo-object (raster) source. The SLD file must be present. A missing
545     * raster legend-data file is tolerated.
546     * @param geoObjectURL URL of the (already read) raster object
547     * @param sldExt file extention for the SLD file
548     * @param rldExt file extention for the raster legend-data file
549     * @return {@code null} in case of any error
550     */
551     public static StyledMapStyle<RasterLegendData> loadStyledRasterStyle(URL geoObjectURL, String sldExt, String rldExt) {
552     RasterLegendData metaData = null;
553     Style sldStyle = null;
554     try {
555     Style[] styles = StylingUtil.loadSLD(IOUtil.changeUrlExt(geoObjectURL, sldExt));
556     // SLD must be present
557     if ( styles == null || styles.length == 0 )
558     return null;
559     sldStyle = styles[0];
560     }
561     catch (Exception err) {
562     // SLD must be present
563     LangUtil.logDebugError(LOGGER,err);
564     return null;
565     }
566    
567     try {
568     metaData = StyledMapUtil.loadRasterLegendData( IOUtil.changeUrlExt(geoObjectURL,rldExt) );
569     } catch (FileNotFoundException err) {
570     // ignore missing raster legend data
571     } catch (Exception err) {
572     // any other error during legend data creation leads to error
573     LangUtil.logDebugError(LOGGER,err);
574     return null;
575     }
576     return new StyledMapStyle<RasterLegendData>(sldStyle, metaData);
577     }
578    
579     /**
580     * Loads a {@linkplain Style SLD-Style} from a {@code .sld} file and
581     * {@linkplain RasterLegendData Raster-LegendData} from a {@code .rld} file
582     * for a given geo-object (raster) source. The SLD file must be present. A missing
583     * raster legend-data file is tolerated.
584     * @param geoObjectURL URL of the (already read) raster object
585     * @param sldExt file extention for the SLD file
586     * @param rldExt file extention for the raster legend-data file
587     * @return {@code null} in case of any error
588     */
589     public static StyledMapStyle<RasterLegendData> loadStyledRasterStyle(URL geoObjectURL) {
590     return loadStyledRasterStyle(geoObjectURL, "sld", "rld");
591     }
592    
593     /**
594     * Loads a {@linkplain Style SLD-Style} and a {@linkplain AttributeMetaData AttributeMetaData-Map}
595     * for a given geo-object (feature) source. The SLD file must be present. A missing
596     * attribute meta-data file is tolerated.
597     * @param geoObjectURL URL of the (already read) feature object
598     * @param sldExt file extention for the SLD file
599     * @param rldExt file extention for the raster legend-data file
600     * @return {@code null} in case of any error
601     */
602     public static StyledMapStyle<Map<Integer,AttributeMetaData>> loadStyledFeatureStyle(URL geoObjectURL, String sldExt, String rldExt) {
603     Map<Integer,AttributeMetaData> metaData = null;
604     Style sldStyle = null;
605     try {
606     Style[] styles = StylingUtil.loadSLD(IOUtil.changeUrlExt(geoObjectURL, sldExt));
607     // SLD must be present
608     if ( styles == null || styles.length == 0 )
609     return null;
610     sldStyle = styles[0];
611     } catch (Exception err) {
612     // SLD must be present
613     LangUtil.logDebugError(LOGGER,err);
614     return null;
615     }
616    
617     try {
618     metaData = StyledMapUtil.loadAttributeMetaDataMap( IOUtil.changeUrlExt(geoObjectURL,rldExt) );
619     } catch (FileNotFoundException err) {
620     // ignore missing attribute meta data
621     } catch (Exception err) {
622     // any other error during meta data creation leads to error
623     LangUtil.logDebugError(LOGGER,err);
624     return null;
625     }
626    
627     return new StyledMapStyle<Map<Integer,AttributeMetaData>>(sldStyle, metaData);
628     }
629    
630     /**
631     * Loads a {@linkplain Style SLD-Style} from a {@code .sld} file and
632     * {@linkplain AttributeMetaData AttributeMetaData-Map} from a {@code .amd} file
633     * for a given geo-object (feature) source. The SLD file must be present. A missing
634     * attribute meta-data file is tolerated.
635     * @param geoObjectURL URL of the (already read) feature object
636     * @param sldExt file extention for the SLD file
637     * @param rldExt file extention for the raster legend-data file
638     * @return {@code null} in case of any error
639     */
640     public static StyledMapStyle<Map<Integer,AttributeMetaData>> loadStyledFeatureStyle(URL geoObjectURL) {
641     return loadStyledFeatureStyle(geoObjectURL, "sld", "amd");
642     }
643    
644     /**
645     * Stores a {@linkplain Style SLD-Style} and {@linkplain RasterLegendData Raster-LegendData}
646     * for a given geo-object (raster) source.
647     * @param style style to save
648     * @param geoObjectURL URL of the raster object
649     * @param sldExt file extention for the SLD file
650     * @param mdExt file extention for the meta-data file
651     */
652     public static <T> void saveStyledMapStyle(StyledMapStyle<T> style, URL geoObjectURL, String sldExt, String mdExt) throws Exception {
653     // Store the SLD
654     Style sldStyle = style.getGeoObjectStyle();
655     if ( sldStyle != null ) {
656     StylingUtil.saveStyleToSLD(
657     sldStyle,
658     IOUtil.changeFileExt(
659     new File(geoObjectURL.toURI()),
660     sldExt
661     )
662     );
663     }
664    
665     // Store the meta data
666     T metaData = style.getMetaData();
667     if ( metaData != null ) {
668     if ( metaData instanceof RasterLegendData ) {
669     saveRasterLegendData(
670     (RasterLegendData)metaData,
671     IOUtil.changeUrlExt(geoObjectURL,mdExt)
672     );
673     // } else if ( metaData instanceof Map<Integer,AttributeMetaData> ) { // LEIDER NICHT KOMPILIERBAR!!
674     } else if ( metaData instanceof Map ) {
675     saveAttributeMetaDataMap(
676     (Map<Integer,AttributeMetaData>)metaData,
677     IOUtil.changeUrlExt(geoObjectURL,mdExt)
678     );
679     } else
680     throw new UnsupportedOperationException("Export for meta data not yet supported: "+metaData.getClass().getSimpleName());
681     }
682     }
683    
684     /**
685     * Stores the {@linkplain Style SLD-Style} to a {@code .sld} file and
686     * the meta data ({@link RasterLegendData} or {@link AttributeMetaData})
687     * to a {@code .rld} or {@code .amd} file.
688     * for a given geo-object source.
689     * @param style style to save
690     * @param geoObjectURL URL of the (already read) raster object
691     */
692     public static void saveStyledMapStyle(StyledMapStyle<?> style, URL geoObjectURL) throws Exception {
693     if ( style.getMetaData() instanceof RasterLegendData )
694     saveStyledMapStyle(style,geoObjectURL, "sld", "rld");
695     else
696     saveStyledMapStyle(style,geoObjectURL, "sld", "amd");
697     }
698    
699     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26