/[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 2 - (hide annotations)
Tue Feb 24 22:43:52 2009 UTC (16 years ago) by mojays
Original Path: trunk/src/skrueger/geotools/StyledMapUtil.java
File size: 28445 byte(s)
First Commit, corresponds to Revision 1008 of Wikisquare-SVN
includes:
- schmitzm.* (except schmitzm.test)
- org.geotools.* (all overridden classes)
- skrueger.geotools
- skrueger.i8n
- skrueger.swing
- appl.data.LateLoadable (dependency in SCHMITZM)
- appl.data.LoadingException (dependency in SCHMITZM)
- appl.util.RasterMetaData (dependency in SCHMITZM)

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     import org.geotools.styling.ColorMap;
15     import org.geotools.styling.ColorMapEntry;
16     import org.geotools.styling.Style;
17    
18     import org.apache.log4j.Logger;
19    
20     import org.jdom.Element;
21     import org.jdom.Document;
22     import org.jdom.input.SAXBuilder;
23     import org.jdom.output.XMLOutputter;
24    
25     import schmitzm.geotools.styling.StylingUtil;
26     import skrueger.AttributeMetaData;
27     import skrueger.RasterLegendData;
28     import skrueger.i8n.Translation;
29     import schmitzm.io.IOUtil;
30     import java.io.File;
31     import java.io.FileNotFoundException;
32     import schmitzm.lang.LangUtil;
33     import schmitzm.swing.SwingUtil;
34    
35     import java.io.FileWriter;
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    
155     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     * Parses a {@link AttributeMetaData} object from an JDOM-{@link Element}.
163     * This method works like {@link AMLImport#parseDataAttribute(org.w3c.dom.Node},
164     * but for JDOM.
165     * @param element {@link Element} to parse
166     */
167     public static AttributeMetaData parseAttributeMetaData(final Element element) {
168     final Integer col = Integer.valueOf(element.getAttributeValue("col"));
169     final Boolean visible = Boolean.valueOf(element.getAttributeValue("visible"));
170     final String unit = element.getAttributeValue("unit");
171    
172     Translation name = new Translation();
173     Translation desc = new Translation();
174     for (final Element childElement : (List<Element>)element.getChildren()) {
175     if (childElement.getName() == null)
176     continue;
177    
178     if (childElement.getName().equals("name"))
179     name = parseTranslation(childElement);
180     else if (childElement.getName().equals("desc"))
181     desc = parseTranslation(childElement);
182     }
183     return new AttributeMetaData(col, visible, name, desc, unit);
184     }
185    
186     /**
187     * Parses a {@link AttributeMetaData} map from an JDOM-{@link Element}
188     * with {@code <attribute>}-childs.
189     * @param element {@link Element} to parse
190     */
191     public static Map<Integer,AttributeMetaData> parseAttributeMetaDataMap(final Element element) {
192     HashMap<Integer,AttributeMetaData> metaData = new HashMap<Integer,AttributeMetaData>();
193     List<Element> attributesElements = element.getChildren( ELEM_NAME_ATTRIBUTE );
194     for (Element attibuteElement : attributesElements)
195     {
196     AttributeMetaData attrMetaData = parseAttributeMetaData( attibuteElement );
197     metaData.put( attrMetaData.getColIdx(), attrMetaData );
198     }
199     return metaData;
200     }
201    
202     /**
203     * Loads a {@link AttributeMetaData} object from an URL.
204     * @param documentUrl {@link URL} to parse
205     * @see #parseAttributeMetaData(Element)
206     */
207     public static Map<Integer,AttributeMetaData> loadAttributeMetaDataMap(final URL documentUrl) throws Exception {
208     Document document = SAX_BUILDER.build(documentUrl);
209     return parseAttributeMetaDataMap( document.getRootElement() );
210     }
211    
212     /**
213     * Creates an JDOM {@link Element} for the given {@link AttributeMetaData}
214     * object.
215     * @param amd meta data for one attribute
216     */
217     public static Element createAttributeMetaDataElement(final AttributeMetaData amd) {
218     final Element element = new Element( ELEM_NAME_ATTRIBUTE , AMLURI);
219     element.setAttribute("col", String.valueOf( amd.getColIdx() ) );
220     element.setAttribute("visible", String.valueOf( amd.isVisible() ) );
221     element.setAttribute("unit", amd.getUnit() );
222     // Creating a aml:name tag...
223     element.addContent( createTranslationElement("name", amd.getTitle()) );
224     // Creating a aml:desc tag...
225     element.addContent( createTranslationElement("desc", amd.getDesc()) );
226     return element;
227     }
228    
229     /**
230     * Creates an JDOM {@link Element} for the given {@link AttributeMetaData}
231     * map.
232     * @param amdMap map of attribute meta data
233     */
234     public static Element createAttributeMetaDataMapElement(final Map<Integer,AttributeMetaData> amdMap) {
235     final Element element = new Element( ELEM_NAME_AMD , AMLURI);
236     for (AttributeMetaData amd : amdMap.values())
237     element.addContent( createAttributeMetaDataElement( amd ) );
238     return element;
239     }
240    
241     /**
242     * Saves a {@link AttributeMetaData AttributeMetaData-Map} to an URL.
243     * @param amdMap map of {@link AttributeMetaData}
244     * @param documentUrl {@link URL} to store the XML
245     */
246     public static void saveAttributeMetaDataMap(final Map<Integer,AttributeMetaData> amdMap, final URL documentUrl) throws Exception {
247     // Create XML-Document
248     final FileWriter out = new FileWriter( new File(documentUrl.toURI()) );
249     XML_OUTPUTTER.output(
250     createAttributeMetaDataMapElement(amdMap),
251     out
252     );
253     out.flush();
254     out.close();
255     }
256    
257    
258    
259     /**
260     * Parses a {@link RasterLegendData} object from an JDOM-{@link Element}.
261     * This method works like {@link AMLImport#parseRasterLegendData(org.w3c.dom.Node},
262     * but for JDOM.
263     * @param element {@link Element} to parse
264     */
265     public static RasterLegendData parseRasterLegendData(Element element) {
266    
267     final boolean paintGaps = Boolean.valueOf( element.getAttributeValue("paintGaps") );
268    
269     RasterLegendData rld = new RasterLegendData(paintGaps);
270    
271     for ( Element childElement : (List<Element>)element.getChildren() ) {
272     final String name = childElement.getName();
273     // Cancel if it's an attribute
274     if ( childElement.getChildren().size() == 0 )
275     continue;
276    
277     if (name.equals( ELEM_NAME_RASTERLEGEND )) {
278     final String valueAttr = childElement.getAttributeValue("value");
279     if ( valueAttr == null )
280     throw new UnsupportedOperationException("Attribute 'value' missing for definition of <"+ELEM_NAME_RASTERLEGEND+">");
281     final double value = Double.valueOf(valueAttr);
282    
283     // first and only item should be the label
284     final Element labelElement = childElement.getChild("label");
285     // id label element is missing, the translation is searched directly
286     // as childs of the rasterLegendItem element
287     Translation label = parseTranslation( labelElement != null ? labelElement : childElement );
288     rld.put(value, label);
289     }
290     }
291    
292     return rld;
293     }
294    
295     /**
296     * Loads a {@link RasterLegendData} object from an URL.
297     * @param documentUrl {@link URL} to parse
298     * @see #parseAttributeMetaData(Element)
299     */
300     public static RasterLegendData loadRasterLegendData(final URL documentUrl) throws Exception {
301     Document document = SAX_BUILDER.build(documentUrl);
302     return parseRasterLegendData( document.getRootElement() );
303     }
304    
305     /**
306     * Creates an JDOM {@link Element} for the given {@link RasterLegendData}
307     * map.
308     * @param rld raster legend data
309     */
310     public static Element createRasterLegendDataElement(final RasterLegendData rld) {
311     final Element element = new Element( ELEM_NAME_RLD , AMLURI);
312     element.setAttribute("paintGaps", rld.isPaintGaps().toString());
313     for (Double key : rld.getSortedKeys()) {
314     Element item = new Element( ELEM_NAME_RASTERLEGEND, AMLURI);
315     item.setAttribute("value", key.toString());
316     item.addContent( createTranslationElement("label", rld.get(key)) );
317     element.addContent(item);
318     }
319     return element;
320     }
321    
322     /**
323     * Creates {@link RasterLegendData} from a {@link ColorMap}.
324     * @param colorMap a color map
325     * @param paintGaps indicated whether gaps are painted between the legend items
326     * @param digits number of digits the grid value classes (and legend) are
327     * rounded to (null means no round; >= 0 means digits after comma;
328     * < 0 means digits before comma) */
329     public static RasterLegendData generateRasterLegendData(ColorMap colorMap, boolean paintGaps, Integer digits) {
330     DecimalFormat decFormat = digits != null ? new DecimalFormat( SwingUtil.getNumberFormatPattern(digits) ) : null;
331     RasterLegendData rld = new RasterLegendData(paintGaps);
332     for (ColorMapEntry cme : colorMap.getColorMapEntries())
333     {
334     double value = StylingUtil.getQuantityFromColorMapEntry(cme);
335     String label = cme.getLabel();
336     // if no label is set (e.g. quantitative style),
337     // use the value as label
338     if ( label == null || label.equals("") )
339     if ( digits == null )
340     label = String.valueOf(value);
341     else
342     label = decFormat.format( LangUtil.round(value, digits) );
343     rld.put( value, new Translation(" "+label) );
344     }
345     return rld;
346     }
347    
348     /**
349     * Creates {@link RasterLegendData} from the {@link ColorMap} of a style.
350     * @param style a raster style (must contain a {@link RasterSymbolizer})
351     * @param paintGaps indicated whether gaps are painted between the legend items
352     * @param digits number of digits the grid value classes (and legend) are
353     * rounded to (null means no round; >= 0 means digits after comma;
354     * < 0 means digits before comma) */
355     public static RasterLegendData generateRasterLegendData(Style style, boolean paintGaps, Integer digits) {
356     ColorMap colorMap = StylingUtil.getColorMapFromStyle(style);
357     if ( colorMap == null)
358     throw new IllegalArgumentException("Color map can not be determined from style!");
359     return generateRasterLegendData(colorMap, paintGaps, digits);
360     }
361    
362     /**
363     * Saves a {@link RasterLegendData} to an URL.
364     * @param rld raster legend data
365     * @param documentUrl {@link URL} to store the XML
366     */
367     public static void saveRasterLegendData(final RasterLegendData rld, final URL documentUrl) throws Exception {
368     // Create XML-Document
369     final FileWriter out = new FileWriter( new File(documentUrl.toURI()) );
370     XML_OUTPUTTER.output(
371     createRasterLegendDataElement(rld),
372     out
373     );
374     out.flush();
375     out.close();
376     }
377    
378     /**
379     * Parses a {@link Translation} object from an JDOM-{@link Element}.
380     * This method works like {@link AMLImport#parseTranslation(org.w3c.dom.Node},
381     * but for JDOM.
382     * @param element {@link Element} to parse
383     */
384     public final static Translation parseTranslation(final Element element) {
385     Translation trans = new Translation();
386    
387     if (element == null)
388     return trans;
389    
390     for (final Element translationElement : (List<Element>)element.getChildren()) {
391     final String name = translationElement.getName();
392     if (name == null)
393     continue;
394    
395     // lang attribute
396     String lang = translationElement.getAttributeValue("lang");
397     // set the default, if no language code is set
398     if ( lang == null )
399     lang = Translation.DEFAULT_KEY;
400    
401     final String translationText = translationElement.getValue();
402     if (translationText == null)
403     trans.put(lang, "");
404     else
405     trans.put(lang, translationText);
406     }
407    
408     // if no <translation> is given, the value of the node should
409     // be used as a default translation
410     if (trans.size() == 0)
411     trans.put( Translation.DEFAULT_KEY, element.getValue() );
412     // trans = new Translation( ((List<Element>)element.getChildren()).get(0).getValue() );
413    
414     return trans;
415     }
416    
417     /**
418     * Creates an JDOM {@link Element} for the given {@link Translation}.
419     * @param tagname Name of the Element
420     * @param translation Translation to store in the Element
421     */
422     public final static Element createTranslationElement(String tagname, Translation translation) {
423     Element element = new Element(tagname, AMLURI);
424     if ( translation == null )
425     throw new UnsupportedOperationException("Translation element can not be created from null!");
426    
427     // If only a default translation is set, the <translation lang="..">..</tranlation>
428     // part is not used
429     if (translation.keySet().size() == 1 && translation.get(Translation.DEFAULT_KEY) != null) {
430     element.addContent( translation.get(Translation.DEFAULT_KEY) );
431     return element;
432     }
433    
434     // add a <translation lang="..">..</tranlation> part to the element for
435     // all languages
436     for (String lang : translation.keySet()) {
437     Element translationElement = new Element( ELEM_NAME_TRANSLATION , AMLURI);
438     translationElement.setAttribute("lang", lang);
439     String translationString = translation.get(lang);
440     if (translationString == null)
441     translationString = "";
442     translationElement.addContent( translationString );
443     element.addContent(translationElement);
444     }
445    
446     return element;
447     }
448    
449    
450     /**
451     * Sets a style to {@link StyledMapInterface}.
452     * @param styledObject a styled object
453     * @param style a Style
454     */
455     public static void setStyledMapStyle(StyledMapInterface styledObject, StyledMapStyle<?> style) {
456     // set SLD style
457     styledObject.setStyle( style.getGeoObjectStyle() );
458     // set meta data
459     if ( styledObject instanceof StyledGridCoverageInterface &&
460     (style.getMetaData() instanceof RasterLegendData || style.getMetaData() == null) ) {
461     RasterLegendData sourceRld = (RasterLegendData)style.getMetaData();
462     RasterLegendData destRld = ((StyledGridCoverageInterface)styledObject).getLegendMetaData();
463     if ( destRld != null && sourceRld != null ) {
464     destRld.setPaintGaps(sourceRld.isPaintGaps());
465     destRld.clear();
466     destRld.putAll( sourceRld );
467     }
468     return;
469     }
470     if ( styledObject instanceof StyledFeatureCollectionInterface &&
471     (style.getMetaData() instanceof Map || style.getMetaData() == null) ) {
472     Map<Integer, AttributeMetaData> sourceAmd = (Map<Integer, AttributeMetaData>)style.getMetaData();
473     Map<Integer, AttributeMetaData> destAmd = ((StyledFeatureCollectionInterface)styledObject).getAttributeMetaDataMap();
474     if ( destAmd != null && sourceAmd != null ) {
475     destAmd.clear();
476     destAmd.putAll( sourceAmd );
477     }
478     return;
479     }
480    
481     throw new UnsupportedOperationException("Style is not compatible to object: " +
482     (style.getMetaData() == null ? null : style.getMetaData().getClass().getSimpleName()) +
483     " <-> " +
484     (styledObject == null ? null : styledObject.getClass().getSimpleName()));
485     }
486    
487     /**
488     * Returns the style a {@link StyledMapInterface} as a {@link StyledMapStyle}.
489     * @param styledObject a styled object
490     * @return {@code StyledMapStyle<RasterLegendData>} for {@link StyledGridCoverageInterface}
491     * or {@code StyledMapStyle<Map<Integer,AttributeMetaData>>} for
492     * {@link StyledFeatureCollectionInterface}
493     */
494     public static StyledMapStyle<?> getStyledMapStyle(StyledMapInterface styledObject) {
495     if ( styledObject instanceof StyledGridCoverageInterface )
496     return getStyledMapStyle( (StyledGridCoverageInterface)styledObject );
497     if ( styledObject instanceof StyledFeatureCollectionInterface )
498     return getStyledMapStyle( (StyledFeatureCollectionInterface)styledObject );
499     throw new UnsupportedOperationException("Unknown type of StyledMapInterface: "+(styledObject == null ? null : styledObject.getClass().getSimpleName()));
500     }
501    
502     /**
503     * Returns the style and raster meta data of a {@link StyledGridCoverageInterface}
504     * as a {@link StyledMapStyle}.
505     * @param styledGC a styled grid coverage
506     */
507     public static StyledMapStyle<RasterLegendData> getStyledMapStyle(StyledGridCoverageInterface styledGC) {
508     return new StyledMapStyle<RasterLegendData>(
509     styledGC.getStyle(),
510     styledGC.getLegendMetaData()
511     );
512     }
513    
514     /**
515     * Returns the style and attribute meta data of a {@link StyledFeatureCollectionInterface}
516     * as a {@link StyledMapStyle}.
517     * @param styledFC a styled feature collection
518     */
519     public static StyledMapStyle<Map<Integer,AttributeMetaData>> getStyledMapStyle(StyledFeatureCollectionInterface styledFC) {
520     return new StyledMapStyle<Map<Integer,AttributeMetaData>>(
521     styledFC.getStyle(),
522     styledFC.getAttributeMetaDataMap()
523     );
524     }
525    
526     /**
527     * Loads a {@linkplain Style SLD-Style} and {@linkplain RasterLegendData Raster-LegendData}
528     * for a given geo-object (raster) source. The SLD file must be present. A missing
529     * raster legend-data file is tolerated.
530     * @param geoObjectURL URL of the (already read) raster object
531     * @param sldExt file extention for the SLD file
532     * @param rldExt file extention for the raster legend-data file
533     * @return {@code null} in case of any error
534     */
535     public static StyledMapStyle<RasterLegendData> loadStyledRasterStyle(URL geoObjectURL, String sldExt, String rldExt) {
536     RasterLegendData metaData = null;
537     Style sldStyle = null;
538     try {
539     Style[] styles = StylingUtil.loadSLD(IOUtil.changeUrlExt(geoObjectURL, sldExt));
540     // SLD must be present
541     if ( styles == null || styles.length == 0 )
542     return null;
543     sldStyle = styles[0];
544     }
545     catch (Exception err) {
546     // SLD must be present
547     LangUtil.logDebugError(LOGGER,err);
548     return null;
549     }
550    
551     try {
552     metaData = StyledMapUtil.loadRasterLegendData( IOUtil.changeUrlExt(geoObjectURL,rldExt) );
553     } catch (FileNotFoundException err) {
554     // ignore missing raster legend data
555     } catch (Exception err) {
556     // any other error during legend data creation leads to error
557     LangUtil.logDebugError(LOGGER,err);
558     return null;
559     }
560     return new StyledMapStyle<RasterLegendData>(sldStyle, metaData);
561     }
562    
563     /**
564     * Loads a {@linkplain Style SLD-Style} from a {@code .sld} file and
565     * {@linkplain RasterLegendData Raster-LegendData} from a {@code .rld} file
566     * for a given geo-object (raster) source. The SLD file must be present. A missing
567     * raster legend-data file is tolerated.
568     * @param geoObjectURL URL of the (already read) raster object
569     * @param sldExt file extention for the SLD file
570     * @param rldExt file extention for the raster legend-data file
571     * @return {@code null} in case of any error
572     */
573     public static StyledMapStyle<RasterLegendData> loadStyledRasterStyle(URL geoObjectURL) {
574     return loadStyledRasterStyle(geoObjectURL, "sld", "rld");
575     }
576    
577     /**
578     * Loads a {@linkplain Style SLD-Style} and a {@linkplain AttributeMetaData AttributeMetaData-Map}
579     * for a given geo-object (feature) source. The SLD file must be present. A missing
580     * attribute meta-data file is tolerated.
581     * @param geoObjectURL URL of the (already read) feature object
582     * @param sldExt file extention for the SLD file
583     * @param rldExt file extention for the raster legend-data file
584     * @return {@code null} in case of any error
585     */
586     public static StyledMapStyle<Map<Integer,AttributeMetaData>> loadStyledFeatureStyle(URL geoObjectURL, String sldExt, String rldExt) {
587     Map<Integer,AttributeMetaData> metaData = null;
588     Style sldStyle = null;
589     try {
590     Style[] styles = StylingUtil.loadSLD(IOUtil.changeUrlExt(geoObjectURL, sldExt));
591     // SLD must be present
592     if ( styles == null || styles.length == 0 )
593     return null;
594     sldStyle = styles[0];
595     } catch (Exception err) {
596     // SLD must be present
597     LangUtil.logDebugError(LOGGER,err);
598     return null;
599     }
600    
601     try {
602     metaData = StyledMapUtil.loadAttributeMetaDataMap( IOUtil.changeUrlExt(geoObjectURL,rldExt) );
603     } catch (FileNotFoundException err) {
604     // ignore missing attribute meta data
605     } catch (Exception err) {
606     // any other error during meta data creation leads to error
607     LangUtil.logDebugError(LOGGER,err);
608     return null;
609     }
610    
611     return new StyledMapStyle<Map<Integer,AttributeMetaData>>(sldStyle, metaData);
612     }
613    
614     /**
615     * Loads a {@linkplain Style SLD-Style} from a {@code .sld} file and
616     * {@linkplain AttributeMetaData AttributeMetaData-Map} from a {@code .amd} file
617     * for a given geo-object (feature) source. The SLD file must be present. A missing
618     * attribute meta-data file is tolerated.
619     * @param geoObjectURL URL of the (already read) feature object
620     * @param sldExt file extention for the SLD file
621     * @param rldExt file extention for the raster legend-data file
622     * @return {@code null} in case of any error
623     */
624     public static StyledMapStyle<Map<Integer,AttributeMetaData>> loadStyledFeatureStyle(URL geoObjectURL) {
625     return loadStyledFeatureStyle(geoObjectURL, "sld", "amd");
626     }
627    
628     /**
629     * Stores a {@linkplain Style SLD-Style} and {@linkplain RasterLegendData Raster-LegendData}
630     * for a given geo-object (raster) source.
631     * @param style style to save
632     * @param geoObjectURL URL of the raster object
633     * @param sldExt file extention for the SLD file
634     * @param mdExt file extention for the meta-data file
635     */
636     public static <T> void saveStyledMapStyle(StyledMapStyle<T> style, URL geoObjectURL, String sldExt, String mdExt) throws Exception {
637     // Store the SLD
638     Style sldStyle = style.getGeoObjectStyle();
639     if ( sldStyle != null ) {
640     StylingUtil.saveStyleToSLD(
641     sldStyle,
642     IOUtil.changeFileExt(
643     new File(geoObjectURL.toURI()),
644     sldExt
645     )
646     );
647     }
648    
649     // Store the meta data
650     T metaData = style.getMetaData();
651     if ( metaData != null ) {
652     if ( metaData instanceof RasterLegendData ) {
653     saveRasterLegendData(
654     (RasterLegendData)metaData,
655     IOUtil.changeUrlExt(geoObjectURL,mdExt)
656     );
657     // } else if ( metaData instanceof Map<Integer,AttributeMetaData> ) { // LEIDER NICHT KOMPILIERBAR!!
658     } else if ( metaData instanceof Map ) {
659     saveAttributeMetaDataMap(
660     (Map<Integer,AttributeMetaData>)metaData,
661     IOUtil.changeUrlExt(geoObjectURL,mdExt)
662     );
663     } else
664     throw new UnsupportedOperationException("Export for meta data not yet supported: "+metaData.getClass().getSimpleName());
665     }
666     }
667    
668     /**
669     * Stores the {@linkplain Style SLD-Style} to a {@code .sld} file and
670     * the meta data ({@link RasterLegendData} or {@link AttributeMetaData})
671     * to a {@code .rld} or {@code .amd} file.
672     * for a given geo-object source.
673     * @param style style to save
674     * @param geoObjectURL URL of the (already read) raster object
675     */
676     public static void saveStyledMapStyle(StyledMapStyle<?> style, URL geoObjectURL) throws Exception {
677     if ( style.getMetaData() instanceof RasterLegendData )
678     saveStyledMapStyle(style,geoObjectURL, "sld", "rld");
679     else
680     saveStyledMapStyle(style,geoObjectURL, "sld", "amd");
681     }
682    
683     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26