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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26