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

Contents of /trunk/src/skrueger/geotools/StyledLayerUtil.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (show 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 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.data.FeatureSource;
15 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
156 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