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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26