/[schmitzm]/trunk/src/skrueger/geotools/StyledMapUtil.java
ViewVC logotype

Annotation of /trunk/src/skrueger/geotools/StyledMapUtil.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 52 - (hide annotations)
Fri Apr 17 13:57:14 2009 UTC (15 years, 10 months ago) by mojays
File size: 29194 byte(s)


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26