/[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 111 - (show annotations)
Tue May 12 23:33:14 2009 UTC (15 years, 9 months ago) by alfonx
File size: 29200 byte(s)
* Fixed some bugs with the SelectionListeners and the JMapPane. To make this work,  StyledFeatureLayerSelectionModel now extends StyledLayerSelectionModel<String>. So the selection is remembered as a Set of Feature-IDs. This change was needed, because Feature.java doesn't overwrite the equals method, and therefore the HashSet didn't function as expected.
* Added new Tools and BUttons to MapPaneToolBar.java to select features
* Changed a lot in MapPaneToolBar.java. It now allows to position Spaces, Actions and Tools via the ID field. (the new feature is to mix them)
* Fixed a bug in AV's ClickInfoPanel that would suddenly pop up an AtlasViewer if started from Geopublisher under special circumstances.
* Moving layers in the legend is using MapContext's move method instead of remove and insert.
* LayerPanel's remember* Maps now all have the MapLayer's ID as a key. 

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26