[Schmitzm-commits] r1174 - in trunk: src/schmitzm/geotools/styling src_junit/schmitzm/lang

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Tue Oct 26 12:00:34 CEST 2010


Author: alfonx
Date: 2010-10-26 12:00:34 +0200 (Tue, 26 Oct 2010)
New Revision: 1174

Modified:
   trunk/src/schmitzm/geotools/styling/StylingUtil.java
   trunk/src_junit/schmitzm/lang/ResourceProviderTest.java
Log:
Added comments and sorted StylingUtil.java

Modified: trunk/src/schmitzm/geotools/styling/StylingUtil.java
===================================================================
--- trunk/src/schmitzm/geotools/styling/StylingUtil.java	2010-10-26 10:00:10 UTC (rev 1173)
+++ trunk/src/schmitzm/geotools/styling/StylingUtil.java	2010-10-26 10:00:34 UTC (rev 1174)
@@ -88,7 +88,6 @@
 import org.geotools.resources.i18n.VocabularyKeys;
 import org.geotools.styling.ColorMap;
 import org.geotools.styling.ColorMapEntry;
-import org.geotools.styling.ColorMapEntryImpl;
 import org.geotools.styling.ColorMapImpl;
 import org.geotools.styling.ExternalGraphic;
 import org.geotools.styling.FeatureTypeStyle;
@@ -116,6 +115,7 @@
 import org.geotools.util.NumberRange;
 import org.jdom.Element;
 import org.jdom.output.XMLOutputter;
+import org.jfree.util.Log;
 import org.opengis.coverage.grid.Grid;
 import org.opengis.coverage.grid.GridCoverage;
 import org.opengis.feature.simple.SimpleFeature;
@@ -131,7 +131,6 @@
 import org.opengis.filter.expression.Literal;
 import org.opengis.filter.expression.PropertyName;
 
-import schmitzm.data.DataUtil;
 import schmitzm.geotools.FilterUtil;
 import schmitzm.geotools.feature.FeatureUtil;
 import schmitzm.geotools.feature.FeatureUtil.GeometryForm;
@@ -160,16 +159,13 @@
  * @version 1.1
  */
 public class StylingUtil {
-	private static final FilterFactory FILTER_FACTORY = FeatureUtil.FILTER_FACTORY;
 	private static final Logger LOGGER = Logger.getLogger(StylingUtil.class);
-	/** transparent color */
-	public static final Color TRANSPARENT_COLOR = new Color(0, 0, 0, 0);
 
-	/** Standard-Instanz eines {@link StyleBuilder}. */
-	public static final StyleBuilder STYLE_BUILDER = new StyleBuilder();
+	static final Literal zeroLit = FeatureUtil.FILTER_FACTORY2.literal(0);
 
 	/** Standard-Instanz eines {@link SLDTransformer}. */
 	public final static SLDTransformer SLDTRANSFORMER = new SLDTransformer();
+
 	static {
 		SLDTRANSFORMER.setEncoding(Charset.defaultCharset());
 	}
@@ -178,19 +174,38 @@
 	public static final StyleFactory STYLE_FACTORY = CommonFactoryFinder
 			.getStyleFactory(GeoTools.getDefaultHints());
 
+	/** Standard-Instanz eines {@link StyleBuilder}. */
+	public static final StyleBuilder STYLE_BUILDER = new StyleBuilder(
+			STYLE_FACTORY);
+
 	/**
-	 * TODO SK The following constants are used to speed up
-	 * {@link #createSelectionStyle(Object)}. I will "redo" them soon and also
-	 * document them. This is still under construction. TODO SK
+	 * Lists a few predefined {@link Style}s usefull to mark selected features.
 	 */
+	public enum SelectionStylesTypes {
+		LeftTop2RightBottom_lines, LeftTop2RightBottom_lines_biggaps, LeftTop2RightBottom_lines_smallgaps, Outline_only, RightTop2LeftBottom_lines, RightTop2LeftBottom_lines_biggaps, RightTop2LeftBottom_lines_smallgaps
+	}
 
+	/**
+	 * RegEx Patter to read palette information from gdalinfo output, for images
+	 * wir <code>RGB</code>, @see {@link #parseColormapToSld(URL)} @see
+	 * {@link #parseColormapToSld(File)}
+	 **/
+	public static final Pattern GDALINFO_COLORMAP_RGB = Pattern
+			.compile("^.*(\\d+): (\\d+),(\\d+),(\\d+).*$");
+
+	/**
+	 * RegEx Patter to read palette information from gdalinfo output, for images
+	 * wir <code>RGBA</code> @see {@link #parseColormapToSld(URL)} @see
+	 * {@link #parseColormapToSld(File)}
+	 **/
+	public static final Pattern GDALINFO_COLORMAP_RGBA = Pattern
+			.compile("^.*(\\d+): (\\d+),(\\d+),(\\d+),(\\d+).*$");
+	
+	static final Literal halfLit = FeatureUtil.FILTER_FACTORY2.literal(.5);
 	static final Literal size0 = FeatureUtil.FILTER_FACTORY2.literal(26);
-
 	static final Literal size1 = FeatureUtil.FILTER_FACTORY2.literal(9);
 	static final Literal size2 = FeatureUtil.FILTER_FACTORY2.literal(7);
 	static final Literal size3 = FeatureUtil.FILTER_FACTORY2.literal(3);
-	static final Literal zeroLit = FeatureUtil.FILTER_FACTORY2.literal(0);
-	static final Literal halfLit = FeatureUtil.FILTER_FACTORY2.literal(.5);
 
 	static final Graphic SELECTION_GRAPHIC1 = STYLE_FACTORY.createGraphic(
 			new ExternalGraphic[0], new Mark[] { STYLE_FACTORY.createMark(
@@ -200,14 +215,6 @@
 			new org.geotools.styling.Symbol[0], FeatureUtil.FILTER_FACTORY2
 					.literal(1), size1, zeroLit);
 
-	static final Graphic BLINK_GRAPHIC1 = STYLE_FACTORY.createGraphic(
-			new ExternalGraphic[0], new Mark[] { STYLE_FACTORY.createMark(
-					FeatureUtil.FILTER_FACTORY2.literal("circle"), null,
-					STYLE_FACTORY.createFill(STYLE_BUILDER
-							.colorExpression(Color.WHITE)), size0, halfLit) },
-			new org.geotools.styling.Symbol[0], FeatureUtil.FILTER_FACTORY2
-					.literal(1), size0, zeroLit);
-
 	static final Graphic SELECTION_GRAPHIC2 = STYLE_FACTORY.createGraphic(
 			new ExternalGraphic[0], new Mark[] { STYLE_FACTORY.createMark(
 					FeatureUtil.FILTER_FACTORY2.literal("circle"), null,
@@ -215,7 +222,6 @@
 							.colorExpression(Color.BLACK)), size2, zeroLit) },
 			new org.geotools.styling.Symbol[0], FeatureUtil.FILTER_FACTORY2
 					.literal(1), size2, zeroLit);
-
 	static final Graphic SELECTION_GRAPHIC3 = STYLE_FACTORY.createGraphic(
 			new ExternalGraphic[0], new Mark[] { STYLE_FACTORY.createMark(
 					FeatureUtil.FILTER_FACTORY2.literal("circle"), null,
@@ -224,231 +230,40 @@
 					zeroLit) }, new org.geotools.styling.Symbol[0],
 			FeatureUtil.FILTER_FACTORY2.literal(1), size3, zeroLit);
 
+	static final Graphic BLINK_GRAPHIC1 = STYLE_FACTORY.createGraphic(
+			new ExternalGraphic[0], new Mark[] { STYLE_FACTORY.createMark(
+					FeatureUtil.FILTER_FACTORY2.literal("circle"), null,
+					STYLE_FACTORY.createFill(STYLE_BUILDER
+							.colorExpression(Color.WHITE)), size0, halfLit) },
+			new org.geotools.styling.Symbol[0], FeatureUtil.FILTER_FACTORY2
+					.literal(1), size0, zeroLit);
+	private static final FilterFactory FILTER_FACTORY = FeatureUtil.FILTER_FACTORY;
+
 	/**
 	 * THis string is set as the Name of the Rules that describe selected
 	 * features
 	 **/
 	public static final String SELECTION_RULE_ID = "SelectionRule";
+//
+//	/** transparent color */
+//	public static final Color TRANSPARENT_COLOR = new Color(0, 0, 0, 0);
 
 	/**
-	 * Erstellt einen Default-Style fuer die Klassen/Interfaces:
-	 * StyledFeaturesInterface, GridCoverage2D, FeatureCollection, FeatureSource
-	 * und GeometryAttributeType.
+	 * Unless {@link ColorMap} is not sorted automatically, this method calls
+	 * {@link #sortColorMap(ColorMap)} after inserting the color map entry.
 	 * 
-	 * @param object
-	 *            {@link GridCoverage2D},
-	 *            {@link org.geotools.coverage.grid.io.AbstractGridCoverage2DReader}
-	 *            oder {@link FeatureCollection}
-	 * @return {@code null} falls kein Style generiert werden kann
-	 * 
-	 * @Deprectated Use FeatureUtil.createDefaultStyle and
-	 *              FeatureUtil.getGeometryForm
-	 */
-	public static Style createDefaultStyle(Object object) {
-		Style style = STYLE_BUILDER.createStyle(); // SK.. nicer default than
-		// null !
-
-		if (object instanceof StyledFeaturesInterface)
-			style = FeatureUtil
-					.createDefaultStyle(((StyledFeaturesInterface<?>) object)
-							.getSchema().getGeometryDescriptor());
-
-		if (object instanceof GridCoverage2D
-				|| object instanceof AbstractGridCoverage2DReader
-				|| object instanceof StyledRasterInterface)
-			style = GridUtil.createDefaultStyle();
-
-		if (object instanceof FeatureCollection)
-			style = FeatureUtil
-					.createDefaultStyle((FeatureCollection<SimpleFeatureType, SimpleFeature>) object);
-
-		if (object instanceof FeatureSource)
-			style = FeatureUtil.createDefaultStyle(((FeatureSource) object)
-					.getSchema().getGeometryDescriptor());
-
-		if (object instanceof GeometryAttributeType)
-			style = FeatureUtil
-					.createDefaultStyle((GeometryAttributeType) object);
-
-		return style;
-	}
-
-	/**
-	 * Erzeugt eine {@link Category} fuer die NoData-Werte transparent
-	 * dargestellt werden.
-	 * 
-	 * @param geoValue
-	 *            Geo-Wert, der NoData repraesentiert
-	 */
-	public static Category createNoDataCategory(double geoValue) {
-		return createNoDataCategory(0, geoValue);
-	}
-
-	/**
-	 * Erzeugt eine {@link Category} fuer die NoData-Werte transparent
-	 * dargestellt werden.
-	 * 
-	 * @param value
-	 *            Sample-Wert der Category
-	 * @param geoValue
-	 *            Geo-Wert, der NoData repraesentiert
-	 */
-	public static Category createNoDataCategory(int value, double geoValue) {
-		return new Category(
-				Vocabulary.formatInternational(VocabularyKeys.NODATA),
-				new Color[] { new Color(0, 0, 0, 0) }, new NumberRange(value,
-						value), new NumberRange(geoValue, geoValue));
-	}
-
-	/**
-	 * Erzeugt eine {@link GridSampleDimension} aus einer {@link ColorMap}.
-	 * 
-	 * @param name
-	 *            Name fuer die {@link GridSampleDimension}
 	 * @param colorMap
-	 *            fuer jeden Eintrag der {@link ColorMap} wird eine
-	 *            {@link Category} erzeugt
-	 * @param noDataValues
-	 *            Werte fuer die zusaetzliche {@link Category Categorys}
-	 *            erstellt werden, welche die transparent dargestellt werden
-	 *            (wenn {@code null} wird keine zusaetzliche {@link Category}
-	 *            erstellt)
-	 * @param unit
-	 *            Einheit der Werte in der {@link GridSampleDimension} (kann
-	 *            {@code null} sein)
+	 *            the color map to extend
+	 * @param colorMapEntry
+	 *            the new entry
 	 */
-	public static GridSampleDimension createDiscreteGridSampleDimension(
-			String name, ColorMap colorMap, double[] noDataValues, Unit<?> unit) {
-		if (colorMap.getColorMapEntries().length == 0)
-			return null;
-
-		SortedMap<Integer, Category> categories = new TreeMap<Integer, Category>();
-		if (noDataValues == null)
-			noDataValues = new double[0];
-
-		// Create a (discrete) Category for each ColorMapEntry
-		int colorMapMin = Integer.MAX_VALUE;
-		int colorMapMax = Integer.MIN_VALUE;
-		for (ColorMapEntry cme : colorMap.getColorMapEntries()) {
-			String label = cme.getLabel();
-			Color color = getColorFromColorMapEntry(cme);
-			double value = getQuantityFromColorMapEntry(cme);
-			int intValue = (int) Math.round(value);
-			colorMapMin = Math.min(colorMapMin, intValue);
-			colorMapMax = Math.max(colorMapMax, intValue);
-			// if ( label == null || label.trim().equals("") )
-			// label = String.valueOf(intValue);
-			if (label == null)
-				label = "";
-			categories.put(intValue, new Category(label, new Color[] { color },
-					new NumberRange(intValue, intValue), new NumberRange(
-							intValue, intValue)));
-		}
-
-		// If NoData-Value is set, create an additional Category
-		for (double noDataValue : noDataValues) {
-			int value = categories.lastKey() + 10; // value not already used
-			categories.put(value, createNoDataCategory(value, noDataValue));
-			colorMapMin = Math.min(colorMapMin, (int) noDataValue);
-			colorMapMax = Math.max(colorMapMax, (int) noDataValue);
-		}
-
-		// Declare "all" values smaller/greater the color map values
-		// automatically as NoData
-		// int colorMapRange = colorMapMax - colorMapMin;
-		// double lowerStart = colorMapMin - 10000*colorMapRange;
-		// double higherEnd = colorMapMax + 10000*colorMapRange;
-		final int lowerStart = Integer.MIN_VALUE;
-		final int higherEnd = Integer.MAX_VALUE;
-		categories.put(colorMapMax + 10, new Category("_autoNoData1_",
-				new Color[] { new Color(0, 0, 0, 0) }, new NumberRange(
-						colorMapMax + 1, colorMapMax + 2), new NumberRange(
-						colorMapMax + 1, higherEnd)));
-		if (colorMapMin < colorMapMax)
-			categories.put(colorMapMin - 10, new Category("_autoNoData2_",
-					new Color[] { new Color(0, 0, 0, 0) },
-					// new NumberRange(colorMapMin-2, colorMapMin-1), //
-					// logischer, aber klappt nicht!?
-					NumberRange.create(colorMapMax + 3, colorMapMax + 4),
-					// new NumberRange(colorMapMax + 3, colorMapMax + 4),
-					NumberRange.create(lowerStart, colorMapMin - 1)
-			// new NumberRange(lowerStart, colorMapMin - 1)
-					));
-
-		// Create the GridSampleDimension
-		GridSampleDimension gsd = new GridSampleDimension(name, categories
-				.values().toArray(new Category[0]), unit).geophysics(true);
-
-		for (Category c : (List<Category>) gsd.getCategories())
-			LOGGER.debug(c.toString());
-
-		return gsd;
+	public static ColorMap addColorMapEntryAndSort(ColorMap colorMap,
+			ColorMapEntry colorMapEntry) {
+		colorMap.addColorMapEntry(colorMapEntry);
+		return sortColorMap(colorMap);
 	}
 
 	/**
-	 * Liefert die Farbpalette zu einem Style, wenn der Style aus einem
-	 * {@link RasterSymbolizer} erzeugt wurde.
-	 * 
-	 * @param style
-	 *            Style Wenn <code>null</code>, dann wird style auf
-	 *            {@link GridUtil}.createDefaultStyle() gesetzt
-	 * @return <code>null</code> wenn der Style nicht auf einem
-	 *         {@link RasterSymbolizer} basiert.
-	 */
-	public static ColorMap getColorMapFromStyle(final Style style) {
-		final List<ColorMap> colorMapsFromStyle = getColorMapsFromStyle(style);
-		if (colorMapsFromStyle.size() > 0)
-			return colorMapsFromStyle.get(0);
-		else
-			return null;
-
-	}
-
-	/**
-	 * Liefert alle Farbpaletten aus einem Style, wenn irgendo
-	 * {@link RasterSymbolizer} enthalten sind.
-	 * 
-	 * @param style
-	 *            Style Wenn <code>null</code>, dann wird style auf
-	 *            {@link GridUtil}.createDefaultStyle() gesetzt
-	 * @return Leere Liste wenn keine RasterSymbolizer enthalten ist.
-	 */
-	public static List<ColorMap> getColorMapsFromStyle(Style style) {
-
-		if (style == null)
-			style = GridUtil.createDefaultStyle();
-
-		final List<RasterSymbolizer> rasterSymbolizers = getRasterSymbolizers(style);
-
-		final List<ColorMap> colorMaps = new ArrayList<ColorMap>();
-
-		for (final RasterSymbolizer rs : rasterSymbolizers) {
-			if (rs.getColorMap() != null) {
-				colorMaps.add(rs.getColorMap());
-			}
-		}
-
-		return colorMaps;
-	}
-
-	/**
-	 * Ermittelt fuer einen Wert den {@link ColorMapEntry} aus einer
-	 * {@link ColorMap}.
-	 * 
-	 * @param value
-	 *            Wert
-	 * @return {@code null}, wenn in der {@link ColorMap} kein expliziter
-	 *         Eintrag fuer den Wert hinterlegt ist
-	 */
-	public static ColorMapEntry findColorMapEntry(ColorMap colorMap,
-			double value) {
-		for (ColorMapEntry entry : colorMap.getColorMapEntries())
-			if (value == getQuantityFromColorMapEntry(entry))
-				return entry;
-		return null;
-	}
-
-	/**
 	 * Applies general properties (color map type and extended colors) to a
 	 * {@link ColorMap}.
 	 * 
@@ -466,121 +281,53 @@
 	}
 
 	/**
-	 * Unless {@link ColorMap} has no methods to remove an entry this method
-	 * creates a new {@link ColorMap} with the identical entries except the one
-	 * to remove.
+	 * Removes all label information from the {@link ColorMapEntry}s of the
+	 * given {@link ColorMap}
 	 * 
-	 * @param colorMap
-	 *            the color map to remove entries from
-	 * @param idx
-	 *            the entry index to remove
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
 	 */
-	public static ColorMap removeColorMapEntry(ColorMap colorMap, int idx) {
-		ColorMap newColorMap = new ColorMapImpl();
-		applyColorMapProperties(colorMap, newColorMap);
-
-		ColorMapEntry[] entry = colorMap.getColorMapEntries();
-		for (int i = 0; i < entry.length; i++)
-			if (i != idx)
-				newColorMap.addColorMapEntry(entry[i]);
-
-		return newColorMap;
+	public static ColorMap clearColorMapLabels(ColorMap colorMap) {
+		for (ColorMapEntry cme : colorMap.getColorMapEntries()) {
+			cme.setLabel(null);
+		}
+		return colorMap;
 	}
 
 	/**
-	 * Unless {@link ColorMap} has no methods to remove an entry this method
-	 * creates a new {@link ColorMap} with the identical entries except the one
-	 * to remove.
+	 * Clons a {@link Graphic} element
 	 * 
-	 * @param colorMap
-	 *            the color map to remove entries from
-	 * @param colorMapEntry
-	 *            the entry to remove
+	 * @param graphicFill
+	 * @return
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
 	 */
-	public static ColorMap removeColorMapEntry(ColorMap colorMap,
-			ColorMapEntry colorMapEntry) {
-		ColorMap newColorMap = new ColorMapImpl();
-		applyColorMapProperties(colorMap, newColorMap);
-
-		ColorMapEntry[] entry = colorMap.getColorMapEntries();
-		for (int i = 0; i < entry.length; i++)
-			if (entry[i] != colorMapEntry)
-				newColorMap.addColorMapEntry(entry[i]);
-
-		return newColorMap;
+	public static Graphic clone(Graphic graphic) {
+		DuplicatingStyleVisitor duplicatingStyleVisitor = new DuplicatingStyleVisitor();
+		graphic.accept(duplicatingStyleVisitor);
+		return (Graphic) duplicatingStyleVisitor.getCopy();
 	}
 
 	/**
-	 * Unless {@link ColorMap} is not sorted automatically, this method calls
-	 * {@link #sortColorMap(ColorMap)} after inserting the color map entry.
+	 * Clones a Style by converting it to XML and reading it back in.
 	 * 
-	 * @param colorMap
-	 *            the color map to extend
-	 * @param colorMapEntry
-	 *            the new entry
+	 * @param style
+	 *            the {@link Style} to be copied.
 	 */
-	public static ColorMap addColorMapEntryAndSort(ColorMap colorMap,
-			ColorMapEntry colorMapEntry) {
-		colorMap.addColorMapEntry(colorMapEntry);
-		return sortColorMap(colorMap);
+	public static Style clone(Style style) {
+		DuplicatingStyleVisitor duplicatingStyleVisitor = new DuplicatingStyleVisitor();
+		style.accept(duplicatingStyleVisitor);
+		return (Style) duplicatingStyleVisitor.getCopy();
 	}
 
 	/**
-	 * Sorts a {@link ColorMap} according to the value of its entries.
-	 * 
-	 * @param colorMap
-	 *            the color map to sort
+	 * Clones a {@link Symbolizer} using the {@link DuplicatingStyleVisitor}.
 	 */
-	public static ColorMap sortColorMap(ColorMap colorMap) {
-		ColorMap newColorMap = new ColorMapImpl();
-		applyColorMapProperties(colorMap, newColorMap);
-
-		// Put all color map entries in a sorted map (with
-		// collision lists!)
-		SortedMap<Double, Vector<ColorMapEntry>> sortedEntries = new TreeMap<Double, Vector<ColorMapEntry>>();
-		for (ColorMapEntry entry : colorMap.getColorMapEntries()) {
-			double quantity = getQuantityFromColorMapEntry(entry);
-			Vector<ColorMapEntry> collisionList = sortedEntries.get(quantity);
-			if (collisionList == null) {
-				collisionList = new Vector<ColorMapEntry>();
-				sortedEntries.put(quantity, collisionList);
-			}
-			collisionList.add(entry);
-		}
-
-		// According to the order of the sorted map, put all
-		// color map entries to the new ColorMap
-		for (Vector<ColorMapEntry> collisionList : sortedEntries.values())
-			for (ColorMapEntry entry : collisionList)
-				newColorMap.addColorMapEntry(entry);
-
-		return newColorMap;
+	public static Symbolizer clone(Symbolizer sym) {
+		DuplicatingStyleVisitor duplicatingStyleVisitor = new DuplicatingStyleVisitor();
+		sym.accept(duplicatingStyleVisitor);
+		return (Symbolizer) duplicatingStyleVisitor.getCopy();
 	}
 
 	/**
-	 * Returns the color map type specified by a given string.
-	 * 
-	 * @param typeStr
-	 *            a string
-	 * @see ColorMap#getType()
-	 */
-	public static int getColorMapType(String typeStr) {
-		if (typeStr == null)
-			throw new IllegalArgumentException("Unknown color map type: "
-					+ typeStr);
-
-		typeStr = typeStr.trim().toLowerCase();
-		if (typeStr.equals("ramp") || typeStr.equals("type_ramp"))
-			return ColorMap.TYPE_RAMP;
-		if (typeStr.equals("intervals") || typeStr.equals("type_intervals"))
-			return ColorMap.TYPE_INTERVALS;
-		if (typeStr.equals("values") || typeStr.equals("type_values"))
-			return ColorMap.TYPE_VALUES;
-
-		throw new IllegalArgumentException("Unknown color map type: " + typeStr);
-	}
-
-	/**
 	 * Kopiert eine {@link ColorMap}.
 	 * 
 	 * @return <code>null</code> wenn die uebergebene ColorMap <code>null</code>
@@ -600,7 +347,8 @@
 		if (colorMap == null)
 			return null;
 		ColorMapEntry[] entry = colorMap.getColorMapEntries();
-		ColorMap newColorMap = new ColorMapImpl();
+//		ColorMap newColorMap = new ColorMapImpl();
+		ColorMap newColorMap = STYLE_FACTORY.createColorMap();
 		newColorMap.setType(colorMap.getType());
 		for (int i = 0; i < entry.length; i++)
 			newColorMap.addColorMapEntry(cloneColorMapEntry(entry[i]));
@@ -624,33 +372,6 @@
 	}
 
 	/**
-	 * Prueft, ob zwei {@link ColorMap}-Instanzen gleich sind.
-	 * 
-	 * @param cm1
-	 *            eine Farbpalette
-	 * @param cm2
-	 *            eine andere Farbpalette
-	 */
-	public static boolean colorMapsEqual(ColorMap cm1, ColorMap cm2) {
-		if (cm1 == null ^ cm2 == null)
-			return false;
-		if (cm1 == cm2)
-			return true;
-
-		ColorMapEntry[] cme1 = cm1.getColorMapEntries();
-		ColorMapEntry[] cme2 = cm2.getColorMapEntries();
-		if (cme1.length != cme2.length)
-			return false;
-
-		// Farbpaletten-Eintraege muessen gleich sein und in gleicher
-		// Reihenfolge vorliegen!
-		for (int i = 0; i < cme1.length; i++)
-			if (!colorMapEntriesEqual(cme1[i], cme2[i]))
-				return false;
-		return true;
-	}
-
-	/**
 	 * Prueft, ob zwei {@link ColorMapEntry}-Instanzen gleich sind. Dies ist der
 	 * Fall, wenn ihnen der gleiche Wert, die gleiche Farbe, die gleiche
 	 * Transparenz und das gleiche Label zugeordnet ist.
@@ -692,31 +413,6 @@
 	}
 
 	/**
-	 * Erzeugt einen {@link ColorMapEntry}.
-	 * 
-	 * @param label
-	 *            Label fuer den Farbpaletten-Eintrag
-	 * @param quantity
-	 *            Wert fuer den Farbpaletten-Eintrag
-	 * @param color
-	 *            Farbe fuer den Farbpaletten-Eintrag
-	 * @param opacity
-	 *            Transparenz fuer die Farbe des Farbpaletten-Eintrag
-	 */
-	public static ColorMapEntry createColorMapEntry(String label,
-			Double quantity, Color color, double opacity) {
-		ColorMapEntry newEntry = new ColorMapEntryImpl();
-		try {
-			newEntry.setLabel(label);
-			newEntry.setColor(STYLE_BUILDER.colorExpression(color));
-			newEntry.setOpacity(STYLE_BUILDER.literalExpression(opacity));
-			newEntry.setQuantity(STYLE_BUILDER.literalExpression(quantity));
-		} catch (Exception err) {
-		}
-		return newEntry;
-	}
-
-	/**
 	 * Kopiert einen {@link ColorMapEntry}.
 	 * 
 	 * @return <code>null</code> wenn der uebergebene ColorMapEntry
@@ -737,957 +433,565 @@
 	}
 
 	/**
-	 * Liefert den Wert eines Farbpaletten-Eintrag.
+	 * Prueft, ob zwei {@link ColorMap}-Instanzen gleich sind.
 	 * 
-	 * @param expression
-	 *            Expression, die einen String oder einen Double liefert
-	 * @return {@code null}, wenn <code>null</code> uebergeben wird
+	 * @param cm1
+	 *            eine Farbpalette
+	 * @param cm2
+	 *            eine andere Farbpalette
 	 */
-	public static Double getQuantityFromExpression(Expression expression) {
-		// gt2-2.3.4:
-		// if ( expression == null || expression.getValue(null) == null )
-		// return null
-		// Object exprValue = evaluate.getValue(null);
-		// gt2-2.3.4:
-		if (expression == null || expression.evaluate(null) == null)
-			return null;
-		Object exprValue = expression.evaluate(null);
+	public static boolean colorMapsEqual(ColorMap cm1, ColorMap cm2) {
+		if (cm1 == null ^ cm2 == null)
+			return false;
+		if (cm1 == cm2)
+			return true;
 
-		return (exprValue instanceof String) ? Double
-				.valueOf((String) exprValue) : ((Number) exprValue)
-				.doubleValue();
-	}
+		ColorMapEntry[] cme1 = cm1.getColorMapEntries();
+		ColorMapEntry[] cme2 = cm2.getColorMapEntries();
+		if (cme1.length != cme2.length)
+			return false;
 
-	/**
-	 * Liefert den Wert eines Farbpaletten-Eintrag.
-	 * 
-	 * @param entry
-	 *            Farbpaletten-Eintrag
-	 * @return {@code null}, wenn <code>null</code> uebergeben wird
-	 */
-	public static Double getQuantityFromColorMapEntry(ColorMapEntry entry) {
-		if (entry == null)
-			return null;
-		return getQuantityFromExpression(entry.getQuantity());
+		// Farbpaletten-Eintraege muessen gleich sein und in gleicher
+		// Reihenfolge vorliegen!
+		for (int i = 0; i < cme1.length; i++)
+			if (!colorMapEntriesEqual(cme1[i], cme2[i]))
+				return false;
+		return true;
 	}
 
-	/**
-	 * Setzt den Wert eines Farbpaletten-Eintrag.
+	/***************************************************************************
+	 * Copies all Values from one {@link TextSymbolizer} to another
+	 * {@link TextSymbolizer}
 	 * 
-	 * @param entry
-	 *            Farbpaletten-Eintrag
-	 * @param quantity
-	 *            neuer Wert
-	 */
-	public static void setQuantityForColorMapEntry(ColorMapEntry entry,
-			double quantity) {
-		if (entry != null)
-			entry.setQuantity(STYLE_BUILDER.literalExpression(quantity));
-	}
-
-	/**
-	 * Liefert die Transparenz eines Farbpaletten-Eintrag.
+	 * @param from
+	 *            {@link TextSymbolizer} source
+	 * @param to
+	 *            {@link TextSymbolizer} target. May not be <code>null</code>.
 	 * 
-	 * @param expression
-	 *            Expression, die einen String oder einen Double liefert
-	 * @return 1.0, wenn <code>null</code> uebergeben wird
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
 	 */
-	public static Double getOpacityFromExpression(Expression expression) {
-		// gt2-2.3.4:
-		// if ( expression == null || expression.getValue(null) == null )
-		// return 1.0
-		// Object exprValue = evaluate.getValue(null);
-		// gt2-2.3.4:
-		if (expression == null || expression.evaluate(null) == null)
-			return 1.0;
-		Object exprValue = expression.evaluate(null);
+	public static void copyAllValues(final TextSymbolizer from,
+			final TextSymbolizer to) {
+		to.setLabel(from.getLabel());
+		to.setPriority(from.getPriority());
 
-		return (exprValue instanceof String) ? Double
-				.valueOf((String) exprValue) : ((Number) exprValue)
-				.doubleValue();
-	}
+		// TODO Does not copy all that has to be copied!
 
-	/**
-	 * Liefert die Transparenz eines Farbpaletten-Eintrag.
-	 * 
-	 * @param entry
-	 *            Farbpaletten-Eintrag
-	 * @return 1.0, wenn <code>null</code> uebergeben wird
-	 */
-	public static Double getOpacityFromColorMapEntry(ColorMapEntry entry) {
-		if (entry == null)
-			return 1.0;
-		return getOpacityFromExpression(entry.getOpacity());
+		final FilterFactory2 ff2 = FeatureUtil.FILTER_FACTORY2;
+
+		to.getFonts()[0].setFontFamily(ff2.literal(from.getFonts()[0]
+				.getFontFamily().toString()));
+		to.getFonts()[0].setFontSize(ff2.literal(from.getFonts()[0]
+				.getFontSize().toString()));
+		to.getFonts()[0].setFontWeight(ff2.literal(from.getFonts()[0]
+				.getFontWeight().toString()));
+		to.getFonts()[0].setFontStyle(ff2.literal(from.getFonts()[0]
+				.getFontStyle().toString()));
 	}
 
 	/**
-	 * Setzt die Transparenz eines Farbpaletten-Eintrag.
+	 * Since GT2.6, the AttributeNames are case sensitive. Also the raster
+	 * Styles need GeometryProperty set to "geom" to work. This method checks
+	 * all referenced AttributeNames.
 	 * 
-	 * @param entry
-	 *            Farbpaletten-Eintrag
-	 * @param opacity
-	 *            Transparenzwert
+	 * @param Schema
+	 *            may be <code>null</code>, e.g. for raster layers
+	 * 
+	 *            TODO Rename to correctStye
 	 */
-	public static void setOpacityForColorMapEntry(ColorMapEntry entry,
-			double opacity) {
-		if (entry != null)
-			entry.setOpacity(STYLE_BUILDER.literalExpression(opacity));
+	public static Style correctPropertyNames(Style style) {
+		return correctPropertyNames(style, null);
 	}
 
 	/**
-	 * Liefert die Farbe eines Farbpaletten-Eintrag.
+	 * Since GT2.6, the AttributeNames are case sensitive. Also the raster
+	 * Styles need GeometryProperty set to "geom" to work. This method checks
+	 * all referenced AttributeNames and checks them against the schema.
 	 * 
-	 * @param expression
-	 *            Expression, die einen String liefert
+	 * @param Schema
+	 *            may be <code>null</code>, e.g. for raster layers
+	 * 
+	 *            TODO Rename to correctStye
 	 */
-	public static Color getColorFromExpression(Expression expression) {
-		if (expression == null)
-			return null;
+	public static Style correctPropertyNames(Style style,
+			final SimpleFeatureType schema) {
 
-		if (expression instanceof ConstantExpression) {
-			ConstantExpression a = (ConstantExpression) expression;
-			Object obj = a.getValue();
-			if (obj instanceof Color) {
-				return (Color) obj;
-			}
-		}
+		DuplicatingStyleVisitor dsv = new DuplicatingStyleVisitor() {
+			@Override
+			public Expression copy(Expression expression) {
+				if (expression instanceof FilterFunction_strConcat) {
+					FilterFunction_strConcat strConcat = (FilterFunction_strConcat) expression;
 
-		return Color.decode(expression.toString());
+					List<Expression> children = strConcat.getParameters();
+					List<Expression> correctedChildren = new ArrayList<Expression>();
+					for (Expression o : children) {
+						correctedChildren.add(copy(o));
+					}
+					strConcat.setParameters(correctedChildren);
 
-		// Old way Martin did it:
-		// return Color.decode((String) expression.evaluate(null));
+				} else if (expression instanceof DivideImpl) {
+					DivideImpl divFilter = (DivideImpl) expression;
+					divFilter.setExpression1(copy(divFilter.getExpression1()));
+					divFilter.setExpression2(copy(divFilter.getExpression2()));
+				} else if (expression instanceof PropertyName) {
+					PropertyName pName = (PropertyName) expression;
 
-	}
+					Name correctedName = FeatureUtil
+							.findBestMatchingAttributeFallBackFirst(schema,
+									pName.getPropertyName());
 
-	/**
-	 * Liefert die Farbe eines Farbpaletten-Eintrag.
-	 * 
-	 * @param entry
-	 *            Farbpaletten-Eintrag
-	 */
-	public static Color getColorFromColorMapEntry(ColorMapEntry entry) {
-		// if ( entry == null || entry.getColor() == null ||
-		// entry.getColor().getValue(null) == null ) // gt2-2.3.4
-		if (entry == null || entry.getColor() == null
-				|| entry.getColor().evaluate(null) == null) // gt2-2-4-2
-			return null;
+					return ff.property(correctedName);
+				}
+				return super.copy(expression);
+			};
 
-		// // Transparenz
-		// Double opacity = getOpacityFromColorMapEntry(entry);
+			@Override
+			protected Filter copy(Filter filter) {
+				if (filter instanceof DivideImpl) {
+					DivideImpl divFilter = (DivideImpl) filter;
+					divFilter.setExpression1(copy(divFilter.getExpression1()));
+					divFilter.setExpression2(copy(divFilter.getExpression2()));
+				} else if (filter instanceof IsNullImpl) {
+					IsNullImpl isNullFilter = (IsNullImpl) filter;
+					isNullFilter.setExpression1(copy(isNullFilter
+							.getExpression1()));
+				} else if (filter instanceof NotImpl) {
+					NotImpl notFilter = (NotImpl) filter;
+					List<Filter> children = notFilter.getChildren();
+					List<Filter> correctedChildren = new ArrayList<Filter>();
+					for (Filter ex : children) {
+						correctedChildren.add(copy(ex));
+					}
+					notFilter.setChildren(correctedChildren);
+				} else if (filter instanceof OrImpl) {
+					OrImpl notFilter = (OrImpl) filter;
+					List<Filter> children = notFilter.getChildren();
+					List<Filter> correctedChildren = new ArrayList<Filter>();
+					for (Filter ex : children) {
+						correctedChildren.add(copy(ex));
+					}
+					notFilter.setChildren(correctedChildren);
+				} else if (filter instanceof AndImpl) {
+					AndImpl andFilter = (AndImpl) filter;
+					List<Filter> children = andFilter.getChildren();
+					List<Filter> correctedChildren = new ArrayList<Filter>();
+					for (Filter ex : children) {
+						correctedChildren.add(copy(ex));
+					}
+					andFilter.setChildren(correctedChildren);
+				} else if (filter instanceof BinaryComparisonAbstract) {
+					BinaryComparisonAbstract binFilter = (BinaryComparisonAbstract) filter;
+					binFilter.setExpression1(copy(binFilter.getExpression1()));
+					binFilter.setExpression2(copy(binFilter.getExpression2()));
 
-		return getColorFromExpression(entry.getColor());
-	}
+					// TODO noch viel mehr faelle!!
+					if (filter instanceof IsBetweenImpl) {
+						IsBetweenImpl isbetween = (IsBetweenImpl) filter;
+						isbetween
+								.setExpression(copy(isbetween.getExpression()));
+					}
 
-	/**
-	 * Setzt die Farbe eines Farbpaletten-Eintrag.
-	 * 
-	 * @param entry
-	 *            Farbpaletten-Eintrag
-	 * @param color
-	 *            eine Farbe
-	 */
-	public static void setColorForColorMapEntry(ColorMapEntry entry, Color color) {
-		if (entry != null)
-			entry.setColor(STYLE_BUILDER.colorExpression(color));
-	}
+				}
+				return (Filter) super.copy(filter);
+			};
 
-	/**
-	 * Erzeugt einen {@link Style} aus einem {@linkplain Element JDOM-Element},
-	 * des eine SLD-Definition enthaelt
-	 * 
-	 * @param element
-	 *            Element mit SLD-Definition
-	 */
-	public static Style createStyleFromSLD(Element element) {
-		String xmlDefinition = new XMLOutputter().outputString(element);
-		// TODO: Workaround, because gt2-2.6.x has problems when the
-		// ColorMapEntries are not in the ascending order according to
-		// their values
-		// --> maybe we can bring the XML-Elements to an ascending order
-		// prior to interprete the XML
+			@Override
+			public void visit(ColorMap cm) {
+				super.visit(sortColorMap(cm));
+			}
 
-		ByteArrayInputStream inputStream = null;
-		try {
-			inputStream = new ByteArrayInputStream(xmlDefinition.getBytes());
-			Style[] style = loadSLD(inputStream);
-			return style == null || style.length == 0 ? null : style[0];
-		} finally {
-			IOUtils.closeQuietly(inputStream);
-		}
-	}
+			@Override
+			public void visit(LineSymbolizer sym) {
+				sym.setGeometryPropertyName(FeatureUtil
+						.findBestMatchingAttributeFallBackFirst(schema,
+								sym.getGeometryPropertyName()).getLocalPart());
+				super.visit(sym);
+			}
 
-	/**
-	 * Creates a {@link Style} for a {@link Grid} layer from a {@link ColorMap}
-	 * 
-	 * @param colorMap
-	 *            If null, then defaultStyle for Grid will be used
-	 * @param name
-	 *            The name to give to the Style. null will result in name=
-	 *            {@link GridUtil#UNNAMED_RASTER_STYLE_NAME} or
-	 *            GridUtil#DEFAULT_RASTER_STYLE_NAME} (if no colorMap is given).
-	 * 
-	 * @param title
-	 *            The Title to give to the Style. null will result in title=
-	 *            {@link GridUtil#UNTITLED_RASTER_STYLE_TITLE} or
-	 *            {@link GridUtil#DEFAULT_RASTER_STYLE_TITLE} (if no colorMap is
-	 *            given)
-	 * 
-	 * @return Always a {@link Style} that you can be applyed to a
-	 *         {@link GridCoverage}.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 */
-	public static Style createStyleFromColorMap(ColorMap colorMap, String name,
-			String title) {
-		if (colorMap == null)
-			return GridUtil.createDefaultStyle();
+			@Override
+			public void visit(PointSymbolizer sym) {
+				sym.setGeometryPropertyName(FeatureUtil
+						.findBestMatchingAttributeFallBackFirst(schema,
+								sym.getGeometryPropertyName()).getLocalPart());
+				super.visit(sym);
+			}
 
-		if (name == null)
-			// A colorMap was provided, but no name.
-			name = GridUtil.UNNAMED_RASTER_STYLE_NAME;
+			@Override
+			public void visit(PolygonSymbolizer sym) {
+				sym.setGeometryPropertyName(FeatureUtil
+						.findBestMatchingAttributeFallBackFirst(schema,
+								sym.getGeometryPropertyName()).getLocalPart());
+				super.visit(sym);
+			}
 
-		if (title == null)
-			// A colorMap was provided, but no title.
-			title = GridUtil.UNTITLED_RASTER_STYLE_TITLE;
+			public void visit(RasterSymbolizer sym) {
+				sym.setGeometryPropertyName("geom");
+				super.visit(sym);
+			}
 
-		RasterSymbolizerImpl rasterSymbolizerImpl = new RasterSymbolizerImpl();
+			@Override
+			public void visit(TextSymbolizer sym) {
+				sym.setGeometryPropertyName(FeatureUtil
+						.findBestMatchingAttributeFallBackFirst(schema,
+								sym.getGeometryPropertyName()).getLocalPart());
+				if (sym.getLabel() != null)
+					sym.setLabel(copy(sym.getLabel()));
 
-		// MS: In GT-2.6.1 the attribute for the raster style is "grid",
-		// not "raster". Setting the geometry to NULL causes that
-		// the grid attribute is determined dynamically during rendering
-		rasterSymbolizerImpl.setGeometry(null);// new
-												// AttributeExpressionImpl("grid"));
+				if (sym.getPriority() != null)
+					sym.setPriority(copy(sym.getPriority()));
 
-		// Entferne alle label informationen
-		clearColorMapLabels(colorMap);
-
-		rasterSymbolizerImpl.setColorMap(colorMap);
-		Symbolizer[] symbolizers = { rasterSymbolizerImpl };
-		RuleImpl ruleImpl = new RuleImpl(symbolizers) {
+				super.visit(sym);
+			}
 		};
-		Rule[] rules = { ruleImpl };
-		FeatureTypeStyleImpl featureTypeStyleImpl = new FeatureTypeStyleImpl(
-				rules) {
-		};
 
-		Style style = STYLE_FACTORY.createStyle();
-		style.setName(name);
-		style.getDescription().setTitle(title);
-		style.featureTypeStyles().add(featureTypeStyleImpl);
-		return style;
-	}
+		dsv.visit(style);
 
-	/**
-	 * Removes all label information from the {@link ColorMapEntry}s of the
-	 * given {@link ColorMap}
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 */
-	public static ColorMap clearColorMapLabels(ColorMap colorMap) {
-		for (ColorMapEntry cme : colorMap.getColorMapEntries()) {
-			cme.setLabel(null);
-		}
-		return colorMap;
+		Style copiedCleanStyle = (Style) dsv.getCopy();
+		return copiedCleanStyle;
 	}
 
 	/**
-	 * Creates a {@link Style} for a {@link Grid} layer from a {@link ColorMap}
-	 * Title will be set to {@link GridUtil#UNTITLED_RASTER_STYLE_TITLE}
-	 * 
-	 * @param colorMap
-	 *            If null, then defaultStyle for Grid will be used
-	 * @param name
-	 *            The name to give to the Style. null will result in name
-	 *            {@link GridUtil#UNTITLED_RASTER_STYLE_TITLE}
-	 * 
-	 * @return Always a Style that you can apply to a {@link GridCoverage}.
-	 *         Style has name {@link GridUtil#DEFAULT_RASTER_STYLE_NAME} if no
-	 *         colormap was provided.
-	 * 
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * @return A {@link FeatureTypeStyle} that can be used style the given
+	 *         geoObject during a blink or highlight process.
 	 */
-	public static Style createStyleFromColorMap(ColorMap colorMap, String name) {
-		return createStyleFromColorMap(colorMap, name, null);
-	}
-
-	/**
-	 * Loads {@link Style}s from a SLD {@link InputStream}
-	 * 
-	 * @param url
-	 *            {@link URL} to read the SLD from
-	 * 
-	 * @return An {@link Array} of {@link Style}s, can be length==0 if no
-	 *         UserStyles in SLD file. null if file not exists
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 */
-	public static Style[] loadSLD(URL url) {
-		InputStream openStream = null;
-		try {
-			openStream = url.openStream();
-			return loadSLD(openStream);
-		} catch (IOException e) {
-			return null;
-		} finally {
-			IOUtils.closeQuietly(openStream);
+	public static FeatureTypeStyle createBlinkFeatureTypeStyle(Object geoObject) {
+		if (geoObject instanceof GridCoverage2D
+				|| geoObject instanceof org.geotools.coverage.grid.io.AbstractGridCoverage2DReader) {
+			// Wenn irgendwann mal selection für raster möglich ist, dann hier
+			// einen schöneren style erstellen.
+			return GridUtil.createDefaultStyle().featureTypeStyles().get(0);
 		}
-	}
 
-	/**
-	 * Loads {@link Style}s from a SLD {@link InputStream}
-	 * 
-	 * @param inputStream
-	 *            {@link InputStream} to read the SLD from
-	 * 
-	 * @return An {@link Array} of {@link Style}s, can be length==0. null if
-	 *         file not exists
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 */
-	public static Style[] loadSLD(InputStream inputStream) {
-
-		Style[] styles = null;
-		try {
-			SLDParser stylereader = new SLDParser(StylingUtil.STYLE_FACTORY,
-					inputStream);
-			styles = stylereader.readXML();
-			return styles;
-		} catch (Exception e) {
-			LOGGER.warn(
-					" ... no styles recognized. Return 'new Style[] { null }' ",
-					e);
-			return new Style[] { null };
+		// We have vector-data. Now let's determine the type...
+		GeometryForm geometryForm = null;
+		if (geoObject instanceof FeatureCollection) {
+			geometryForm = FeatureUtil
+					.getGeometryForm((FeatureCollection<SimpleFeatureType, SimpleFeature>) geoObject);
+		} else if (geoObject instanceof GeometryAttributeType) {
+			geometryForm = FeatureUtil
+					.getGeometryForm((GeometryAttributeType) geoObject);
+		} else if (geoObject instanceof FeatureSource) {
+			geometryForm = FeatureUtil
+					.getGeometryForm((FeatureSource<SimpleFeatureType, SimpleFeature>) geoObject);
 		}
 
-	}
+		Symbolizer[] symbolizers = new Symbolizer[0];
 
-	/**
-	 * Loads {@link Style}s from a SLD {@link File}
-	 * 
-	 * @param sldFile
-	 *            {@link File} to read the SLD from
-	 * 
-	 * @return An {@link Array} of {@link Style}s, can be length==0
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 */
-	public static Style[] loadSLD(File sldFile) throws FileNotFoundException {
+		Graphic bg2;
+		switch (geometryForm) {
 
-		FileInputStream inputStream = null;
-		try {
-			inputStream = new FileInputStream(sldFile);
-			final Style[] loadedSLD = loadSLD(inputStream);
-			return loadedSLD;
-		} finally {
-			IOUtils.closeQuietly(inputStream);
-		}
-	}
+		case POINT:
 
-	/**
-	 * Saves the {@link Style} to OGC SLD. Overwrites any existing file. If a
-	 * FeatureTypeStyle for selection is used, it is automatically removed. This
-	 * method also checks, whether the style is actually differing from any
-	 * existing style in the {@link File}. If there is no difference, the file
-	 * is not saved again (that is more svn friendly).
-	 * 
-	 * @param origStyle
-	 *            {@link Style} to save. Any selectino related FeatureTypeStyle
-	 *            will be removed.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 * 
-	 * @return <code>true</code> if the file was really written.
-	 *         <code>false</code> means, that the existing file already was
-	 *         equals.
-	 * @throws IOException
-	 * @throws TransformerException
-	 */
-	public static final boolean saveStyleToSLD(Style origStyle, File exportFile)
-			throws TransformerException, IOException {
+			Literal size0 = FeatureUtil.FILTER_FACTORY2.literal(26);
+			Literal size1 = FeatureUtil.FILTER_FACTORY2.literal(28);
 
-		// Wenn Datei nicht mit .sld endet, die Dateierweiterung
-		// anhängen
-		exportFile = IOUtil.appendFileExt(exportFile, ".sld");
+			Graphic bg1 = STYLE_FACTORY.createGraphic(new ExternalGraphic[0],
+					new Mark[] { STYLE_FACTORY.createMark(
+							FeatureUtil.FILTER_FACTORY2.literal("circle"),
+							STYLE_BUILDER.createStroke(Color.red, 2.), null,
+							size1, halfLit) },
+					new org.geotools.styling.Symbol[0],
+					FeatureUtil.FILTER_FACTORY2.literal(1), size1, zeroLit);
 
-		SLDTRANSFORMER.setIndentation(2);
+			PointSymbolizer ps1 = STYLE_FACTORY.createPointSymbolizer();
+			ps1.setGraphic(bg1);
+			symbolizers = LangUtil.extendArray(symbolizers, ps1);
 
-		Style exportStyle = removeSelectionFeatureTypeStyle(origStyle);
+			bg2 = STYLE_FACTORY.createGraphic(new ExternalGraphic[0],
+					new Mark[] { STYLE_FACTORY.createMark(
+							FeatureUtil.FILTER_FACTORY2.literal("circle"),
+							STYLE_BUILDER.createStroke(Color.black, 2.),
+							STYLE_BUILDER.createFill(Color.WHITE, 0.3), size0,
+							halfLit) }, new org.geotools.styling.Symbol[0],
+					FeatureUtil.FILTER_FACTORY2.literal(1), size0, zeroLit);
 
-		// Nur in Datei speichern, wenn
-		if (!isStyleDifferent(exportStyle, exportFile)) {
-			return false;
-		}
+			PointSymbolizer ps2 = STYLE_FACTORY.createPointSymbolizer();
+			ps2.setGraphic(bg2);
 
-		SLDTRANSFORMER.transform(exportStyle, new FileWriter(exportFile));
-		return true;
-	}
+			symbolizers = LangUtil.extendArray(symbolizers, ps2);
+			break;
+		case POLYGON:
 
-	/**
-	 * Exports the {@link Style} to OGC SLD. If a FeatureTypeStyle for selection
-	 * is used, it is automatically removed.
-	 * 
-	 * @param style
-	 *            {@link Style} to save. Any selectino related FeatureTypeStyle
-	 *            will be removed.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 * @throws TransformerException
-	 */
-	public static final void saveStyleToSLD(Style style,
-			OutputStream exportStream) throws TransformerException {
-		SLDTRANSFORMER.setIndentation(2);
-		SLDTRANSFORMER.transform(style, exportStream);
-	}
+			PolygonSymbolizer pol1 = STYLE_BUILDER.createPolygonSymbolizer(
+					STYLE_BUILDER.createStroke(Color.red, 4), null);
+			symbolizers = LangUtil.extendArray(symbolizers, pol1);
 
-	/**
-	 * Creates a copy of the given {@link Style}, removing any
-	 * {@link FeatureTypeStyle}s that are only SELECTION related.
-	 * 
-	 * @see {@link FeatureMapLayerSelectionSynchronizer#SELECTION_STYLING_FTS_NAME}
-	 */
-	public static Style removeSelectionFeatureTypeStyle(final Style style) {
+			PolygonSymbolizer pol2 = STYLE_BUILDER.createPolygonSymbolizer(
+					STYLE_BUILDER.createStroke(Color.black, 2),
+					STYLE_BUILDER.createFill(Color.WHITE, .5));
+			symbolizers = LangUtil.extendArray(symbolizers, pol2);
 
-		// Create a copy of the style
-		DuplicatingStyleVisitor duplVisitor = new DuplicatingStyleVisitor();
-		duplVisitor.visit(style);
-		Style cleanStyle = (Style) duplVisitor.getCopy();
+			break;
 
-		// Remove any selection-FeatureTypeStyle from the new Style
-		for (int ii = 0; ii < style.featureTypeStyles().size(); ii++) {
+		case LINE:
 
-			FeatureTypeStyle fts = style.featureTypeStyles().get(ii);
+			LineSymbolizer ls = STYLE_BUILDER.createLineSymbolizer(Color.red,
+					6.);
+			symbolizers = LangUtil.extendArray(symbolizers, ls);
 
-			if (fts.getName() != null
-					&& fts.getName()
-							.equals(FeatureMapLayerSelectionSynchronizer.SELECTION_STYLING_FTS_NAME)) {
-				cleanStyle.featureTypeStyles().remove(ii);
-				break;
-			}
-		}
+			LineSymbolizer ls2 = STYLE_BUILDER.createLineSymbolizer(
+					Color.black, 4.);
+			symbolizers = LangUtil.extendArray(symbolizers, ls2);
 
-		return cleanStyle;
-	}
+			LineSymbolizer ls3 = STYLE_BUILDER.createLineSymbolizer(
+					Color.white, 2.);
+			symbolizers = LangUtil.extendArray(symbolizers, ls3);
+			break;
 
-	/**
-	 * Returns <code>null</code> or any {@link FeatureTypeStyle} contained in
-	 * the given {@link Style} that is SELECTION related.
-	 * 
-	 * @see {@link FeatureMapLayerSelectionSynchronizer#SELECTION_STYLING_FTS_NAME}
-	 */
-	public static FeatureTypeStyle getSelectionFeatureTypeStyle(
-			final Style style) {
-
-		if (style == null)
-			return null;
-
-		// Remove any selection-FeatureTypeStyle from the new Style
-		for (int ii = 0; ii < style.featureTypeStyles().size(); ii++) {
-
-			FeatureTypeStyle fts = style.featureTypeStyles().get(ii);
-
-			if (fts.getName() != null
-					&& fts.getName()
-							.equals(FeatureMapLayerSelectionSynchronizer.SELECTION_STYLING_FTS_NAME)) {
-				return style.featureTypeStyles().get(ii);
-			}
+		default:
+			throw new IllegalArgumentException("Provide a suitable object.");
 		}
 
-		return null;
+		return STYLE_BUILDER.createFeatureTypeStyle(symbolizers, Double.NaN,
+				Double.NaN);
 	}
 
 	/**
-	 * Compares a given Style and a {@link File} containg a {@link Style}.
+	 * Creates a new {@link BrewerPalette} with only one scheme (which includes
+	 * all colors). The suitablity of the palette is set to "unknown" for all
+	 * viewer types.
 	 * 
-	 * @param style1
-	 *            The first {@link Style}
-	 * @param style2file
-	 *            A {@link File} pointing to the second {@link Style}
-	 * @return <code>true</code> is they are different, ignoring any XML
-	 *         fomatting.
+	 * @param name
+	 *            name for the palette (also the description is set to this
+	 *            value)
+	 * @param colors
+	 *            colors for the palette
 	 */
-	public static boolean isStyleDifferent(Style style1, File style2file) {
-		SLDTRANSFORMER.setIndentation(2);
+	public static BrewerPalette createBrewerPalette(String name, Color[] colors) {
+		BrewerPalette palette = new BrewerPalette();
+		palette.setColors(colors);
+		palette.setName(name);
+		palette.setDescription(name);
 
+		// set suitability to UNKNOWN for all viewers
+		PaletteSuitability suitability = new PaletteSuitability();
 		try {
+			suitability.setSuitability(colors.length, new String[] { "?", "?",
+					"?", "?", "?", "?" });
+			palette.setPaletteSuitability(suitability);
+		} catch (IOException e) {
+			LOGGER.error(
+					"Unabel to PaletteSuitability.setSuitablility for colors.length="
+							+ colors, e);
+		}
 
-			if (!style2file.exists())
-				return true;
+		// Create the trivial scheme for the palette (requested colors equals
+		// number of colors)
+		int[] schema = new int[colors.length];
+		for (int j = 0; j < colors.length; j++)
+			schema[j] = j;
+		SampleScheme sampleScheme = new SampleScheme();
 
-			Style style2 = loadSLD(style2file)[0];
+		// set the trivial scheme for all schemas
+		for (int j = 2; j < schema.length; j++) {
+			sampleScheme.setSampleScheme(j, schema);
+			// sampleScheme.setSampleScheme(schema.length, schema);
+		}
 
-			return isStyleDifferent(style1, style2);
+		palette.setColorScheme(sampleScheme);
 
-		} catch (Exception e) {
-			LOGGER.debug("Comparing styles " + style1 + " and " + style2file
-					+ " failed. So we assume they are different.", e);
-			return true;
-		}
+		return palette;
 	}
 
 	/**
-	 * Compares a given Style and a {@link File} containg a {@link Style}.
+	 * Erzeugt einen {@link ColorMapEntry}.
 	 * 
-	 * @param style1
-	 *            The first {@link Style}
-	 * @param style2
-	 *            The second {@link Style} to compare to
-	 * @return <code>true</code> is they are different, ignoring any XML
-	 *         fomatting.
+	 * @param label
+	 *            Label fuer den Farbpaletten-Eintrag
+	 * @param quantity
+	 *            Wert fuer den Farbpaletten-Eintrag
+	 * @param color
+	 *            Farbe fuer den Farbpaletten-Eintrag
+	 * @param opacity
+	 *            Transparenz fuer die Farbe des Farbpaletten-Eintrag
 	 */
-	public static boolean isStyleDifferent(Style style1, Style style2) {
+	public static ColorMapEntry createColorMapEntry(String label,
+			Double quantity, Color color, double opacity) {
+		ColorMapEntry newEntry = STYLE_FACTORY.createColorMapEntry();
 		try {
-			// SLDTRANSFORMER.setEncoding(Charset.forName("UTF-8"));
-			// Transforming style2 to an XML String
-			String style1string = SLDTRANSFORMER.transform(style1);
-			String style2string = SLDTRANSFORMER.transform(style2);
-
-			return !style1string.equals(style2string);
-
-		} catch (Exception e) {
-			LOGGER.debug("Compating styles " + style1 + " and " + style2
-					+ " failed. So we assume they are different.", e);
-			return true;
+			newEntry.setLabel(label);
+			newEntry.setColor(STYLE_BUILDER.colorExpression(color));
+			newEntry.setOpacity(STYLE_BUILDER.literalExpression(opacity));
+			newEntry.setQuantity(STYLE_BUILDER.literalExpression(quantity));
+		} catch (Exception err) {
 		}
 
+		return newEntry;
 	}
 
 	/**
-	 * SLD Rules können die Paramter MinScaleDenominator und MaxScaleDenominator
-	 * enthalten. Dadurch können Elemente für manche Zoom-Stufen deaktiviert
-	 * werden.
+	 * Erstellt einen Default-Style fuer die Klassen/Interfaces:
+	 * StyledFeaturesInterface, GridCoverage2D, FeatureCollection, FeatureSource
+	 * und GeometryAttributeType.
 	 * 
-	 * Kommentar: "Sichtbarkeit" bezieht es nicht darauf, ob die Elemente auf
-	 * dem Kartenausschnitt sichtbar sind, sondern um die SLD Regeln, welche das
-	 * SimpleFeature evt. nur Scalenabhängig zeichnen.<br/>
-	 * SK 19.6.2009:Bei einem {@link PolygonSymbolizer} zählt nicht der Rand,
-	 * sondern nur ob eine Füllung vorhanden ist! Man kann dann zwar leider
-	 * nicht auf ein Rand eines Polygons ohne Fill klicken, aber dafür kann man
-	 * durch die ungefüllte Fläche klicken.
+	 * @param object
+	 *            {@link GridCoverage2D},
+	 *            {@link org.geotools.coverage.grid.io.AbstractGridCoverage2DReader}
+	 *            oder {@link FeatureCollection}
+	 * @return {@code null} falls kein Style generiert werden kann
 	 * 
-	 * @param fc
-	 *            Die zu filternde FeatureCollection. Diese wird nicht
-	 *            verändert.
-	 * @param style
-	 *            Der Style, mit dem die Features gerendert werden (z.b.
-	 *            layer.getStyle() )
-	 * 
-	 * @param scaleDenominator
-	 *            Der aktuelle ScaleDenomitor für den die Sichtbarkeit ermittelt
-	 *            wird.
-	 * 
-	 * @see RendererUtilities.calculateOGCScale
-	 * 
-	 * @return Eine FeatureCollection in welcher nur die Features enthalten
-	 *         sind, welche bei aktuellen Scale mit dem übergebenen Style
-	 *         gerendert werden.
-	 * 
-	 *         TODO Was ist mit raster?!
-	 * 
-	 *         TODO Das sollte man besser machen: Zuerst die FIlter der
-	 *         sichtbaren regeln raussuchen, und dann direkt am anfang damitmit
-	 *         mitfiltern...
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * @Deprectated Use FeatureUtil.createDefaultStyle and
+	 *              FeatureUtil.getGeometryForm
 	 */
-	public static MemoryFeatureCollection filterSLDVisibleOnly(
-			final FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
-			final Style style, final Double scaleDenominator) {
+	public static Style createDefaultStyle(Object object) {
+		Style style = STYLE_BUILDER.createStyle(); // SK.. nicer default than
+		// null !
 
-		// Eine im Speicher gehaltene FeatureCollection der sichtbaren
-		final MemoryFeatureCollection fcVisible = new MemoryFeatureCollection(
-				fc.getSchema());
+		if (object instanceof StyledFeaturesInterface)
+			style = FeatureUtil
+					.createDefaultStyle(((StyledFeaturesInterface<?>) object)
+							.getSchema().getGeometryDescriptor());
 
-		// Prüfen aller Features in der Collection
-		final Iterator<SimpleFeature> fcIt = fc.iterator();
+		if (object instanceof GridCoverage2D
+				|| object instanceof AbstractGridCoverage2DReader
+				|| object instanceof StyledRasterInterface)
+			style = GridUtil.createDefaultStyle();
 
-		try {
+		if (object instanceof FeatureCollection)
+			style = FeatureUtil
+					.createDefaultStyle((FeatureCollection<SimpleFeatureType, SimpleFeature>) object);
 
-			while (fcIt.hasNext()) {
-				final SimpleFeature feature = fcIt.next();
+		if (object instanceof FeatureSource)
+			style = FeatureUtil.createDefaultStyle(((FeatureSource) object)
+					.getSchema().getGeometryDescriptor());
 
-				for (final FeatureTypeStyle fts : style.featureTypeStyles()) {
+		if (object instanceof GeometryAttributeType)
+			style = FeatureUtil
+					.createDefaultStyle((GeometryAttributeType) object);
 
-					// Leave out FTSs that are selection related
-					if (fts.getName() != null
-							&& fts.getName()
-									.equals(FeatureMapLayerSelectionSynchronizer.SELECTION_STYLING_FTS_NAME))
-						continue;
-
-					final List<Rule> rules = fts.rules();
-
-					for (final Rule rule : rules) {
-						final double maxScaleDenominator = rule
-								.getMaxScaleDenominator();
-						final double minScaleDenominator = rule
-								.getMinScaleDenominator();
-
-						// 1. Check: Trifft die Rule auf den aktuellen Scale der
-						// JMapPane?
-						if ((minScaleDenominator > scaleDenominator)
-								|| (scaleDenominator > maxScaleDenominator)) {
-							continue;
-						}
-
-						// 2. Check: Eine Rule ist gülrig, aber trifft der
-						// Filter für dieses SimpleFeature?
-						final Filter rFilter = rule.getFilter();
-						if ((rFilter != null) && (!rFilter.evaluate(feature)))
-							continue;
-
-						// 3. Check: Passt einer der Symbolizer dieser Rule zu
-						// dem
-						// SimpleFeature? Dieser Check wird in
-						// "real world" meistens klappen, es sei denn, ein
-						// Hansel
-						// gibt einen LineSymbolizer für ein PointLayer an.
-						boolean passt = false;
-						for (final Symbolizer symb : rule.getSymbolizers()) {
-
-							final Geometry geom = (Geometry) feature
-									.getDefaultGeometry();
-
-							if ((geom instanceof MultiPoint)
-									|| (geom instanceof com.vividsolutions.jts.geom.Point)) {
-								if (symb instanceof PointSymbolizer) {
-									if (((PointSymbolizer) symb).getGraphic() != null)
-										passt = true;
-									break;
-								}
-							} else if ((geom instanceof MultiLineString)
-									|| (geom instanceof LineString)) {
-								if (symb instanceof LineSymbolizer) {
-									if (((LineSymbolizer) symb).getStroke() != null)
-										passt = true;
-									break;
-								}
-							} else if ((geom instanceof MultiPolygon)
-									|| (geom instanceof Polygon)) {
-
-								if (symb instanceof PolygonSymbolizer) {
-									if (((PolygonSymbolizer) symb).getFill() != null)
-										passt = true;
-									break;
-								}
-
-								if (symb instanceof PointSymbolizer) {
-									// This is a special case and not handles
-									// 100% correct yet. Polygons visualized
-									// with Pointsymbolizers should also have
-									// different Filters when they are selected
-									if (((PointSymbolizer) symb).getGraphic() != null)
-										passt = true;
-									break;
-								}
-							} else {
-								LOGGER.warn("Unbekannter geom Typ! Gehe von sichbar aus!");
-								passt = true;
-							}
-						}
-						if (!passt)
-							continue;
-
-						// Nun sollte das feature wiklich sichtbar sein
-						fcVisible.add(feature);
-					}
-				}
-			}
-		} catch (final java.lang.IllegalStateException e) {
-			LOGGER.error("Iterating over the features", e);
-			/**
-			 * SK: 14.Apri 2009. It happened a few time to that fcIt.hasNext
-			 * suddenly threw an exception for the "africa countries.shp":
-			 * Exception in thread "AWT-EventQueue-0"
-			 * java.lang.IllegalStateException: ShapeType changed illegally from
-			 * Polygon to Undefined at org.geotools.
-			 * data.shapefile.shp.ShapefileReader.nextRecord(ShapefileReader
-			 * .java:452) at org.geotools.data.shapefile.indexed.
-			 * IndexedShapefileDataStore$Reader
-			 * .next(IndexedShapefileDataStore.java:1272) at
-			 * org.geotools.data.FIDFeatureReader.next(FIDFeatureReader.java:92)
-			 * at org .geotools.data.FilteringFeatureReader.hasNext(
-			 * FilteringFeatureReader .java:125) at
-			 * org.geotools.data.store.FeatureReaderIterator.hasNext(
-			 * FeatureReaderIterator.java:44) at
-			 * schmitzm.geotools.feature.FeatureUtil
-			 * .filterSLDVisibleOnly(FeatureUtil.java:216) *
-			 * 
-			 */
-		}
-
-		// LOGGER.info("filterSLDVisibleOnly removed "+ (fc.size() -
-		// fcVisible.size()) + " features.");
-
-		return fcVisible;
+		return style;
 	}
 
 	/**
-	 * @param style
-	 *            A {@link Style} to search for the first {@link TextSymbolizer}
-	 *            that will be used for the given {@link SimpleFeature}.
+	 * Erzeugt eine {@link GridSampleDimension} aus einer {@link ColorMap}.
 	 * 
-	 * @author Stefan A. Tzeggai
-	 * 
-	 * @return <code>null</code> or the first {@link TextSymbolizer} found in
-	 *         the style that applies to the {@link SimpleFeature}.
+	 * @param name
+	 *            Name fuer die {@link GridSampleDimension}
+	 * @param colorMap
+	 *            fuer jeden Eintrag der {@link ColorMap} wird eine
+	 *            {@link Category} erzeugt
+	 * @param noDataValues
+	 *            Werte fuer die zusaetzliche {@link Category Categorys}
+	 *            erstellt werden, welche die transparent dargestellt werden
+	 *            (wenn {@code null} wird keine zusaetzliche {@link Category}
+	 *            erstellt)
+	 * @param unit
+	 *            Einheit der Werte in der {@link GridSampleDimension} (kann
+	 *            {@code null} sein)
 	 */
-	public static TextSymbolizer getTextSymbolizer(final Style style,
-			final SimpleFeature f) {
-		if (f == null)
+	public static GridSampleDimension createDiscreteGridSampleDimension(
+			String name, ColorMap colorMap, double[] noDataValues, Unit<?> unit) {
+		if (colorMap.getColorMapEntries().length == 0)
 			return null;
-		try {
-			if (style != null) {
 
-				for (final FeatureTypeStyle fts : style.featureTypeStyles()) {
-					for (final Rule r : fts.rules()) {
+		SortedMap<Integer, Category> categories = new TreeMap<Integer, Category>();
+		if (noDataValues == null)
+			noDataValues = new double[0];
 
-						final Filter filter = r.getFilter();
-
-						if (filter != null && (!filter.evaluate(f))) {
-							continue;
-						}
-
-						for (final Symbolizer symb : r.getSymbolizers()) {
-							if (symb instanceof TextSymbolizer) {
-								return (TextSymbolizer) symb;
-							}
-						}
-
-					}
-				}
-
-			}
-
-		} catch (final Exception e) {
-			LOGGER.error("error - filter API stuff?", e);
-			return null;
+		// Create a (discrete) Category for each ColorMapEntry
+		int colorMapMin = Integer.MAX_VALUE;
+		int colorMapMax = Integer.MIN_VALUE;
+		for (ColorMapEntry cme : colorMap.getColorMapEntries()) {
+			String label = cme.getLabel();
+			Color color = getColorFromColorMapEntry(cme);
+			double value = getQuantityFromColorMapEntry(cme);
+			int intValue = (int) Math.round(value);
+			colorMapMin = Math.min(colorMapMin, intValue);
+			colorMapMax = Math.max(colorMapMax, intValue);
+			// if ( label == null || label.trim().equals("") )
+			// label = String.valueOf(intValue);
+			if (label == null)
+				label = "";
+			categories.put(intValue, new Category(label, new Color[] { color },
+					new NumberRange(intValue, intValue), new NumberRange(
+							intValue, intValue)));
 		}
-		return null;
-	}
 
-	/**
-	 * @param style
-	 *            A {@link Style} to search for all {@link TextSymbolizer}s . No
-	 *            guarantee, that any one of them will ever be used for any
-	 *            feature (think about filters).
-	 * 
-	 * @author Stefan A. Tzeggai
-	 * 
-	 * @return {@link List} or all {@link TextSymbolizer}s found in the
-	 *         {@link Style}.
-	 */
-	public static List<TextSymbolizer> getVisibleTextSymbolizers(
-			final Style style) {
-		List<TextSymbolizer> results = new ArrayList<TextSymbolizer>();
-		try {
-			if (style != null) {
-
-				for (final FeatureTypeStyle fts : style.featureTypeStyles()) {
-					for (final Rule r : fts.rules()) {
-
-						if (r.getFilter() != null) {
-
-							/*
-							 * We are comparing it to AsUtil.alwaysfalsefilter
-							 * 
-							 * public static final PropertyIsEqualTo
-							 * allwaysFalseFilter = ff2.equals(ff2
-							 * .literal("1"), ff2.literal("2"));
-							 */
-							try {
-
-								Filter f = r.getFilter();
-								if (f instanceof And) {
-									And and = (And) f;
-									if (and.getChildren() != null) {
-										Filter candidateF = and.getChildren()
-												.get(0);
-										if (candidateF instanceof PropertyIsEqualTo) {
-											final PropertyIsEqualTo compare = (PropertyIsEqualTo) candidateF;
-											if (compare.getExpression1() instanceof Literal
-													&& compare.getExpression2() instanceof Literal) {
-												Literal test1 = (Literal) compare
-														.getExpression1();
-												Literal test2 = (Literal) compare
-														.getExpression2();
-												if (test1.toString()
-														.equals("1")
-														&& test2.toString()
-																.equals("2")) {
-													// This TextSymbolizer is
-													// disabled using
-													// ASUtil.allwaysFalseFilter
-													// LOGGER.debug("Ignoring Rule "+
-													// r
-													// +" because the filter is "+f);
-													continue;
-												}
-											}
-										}
-									}
-								}
-							} catch (Exception e) {
-								LOGGER.debug(
-										"Checking for textSymbolizer allwaysFalseFilter",
-										e);
-							}
-						}
-
-						results.addAll(getTextSymbolizers(r.getSymbolizers()));
-					}
-				}
-
-			}
-
-		} catch (final Exception e) {
-			LOGGER.error("error - filter API stuff?", e);
-			return results;
+		// If NoData-Value is set, create an additional Category
+		for (double noDataValue : noDataValues) {
+			int value = categories.lastKey() + 10; // value not already used
+			categories.put(value, createNoDataCategory(value, noDataValue));
+			colorMapMin = Math.min(colorMapMin, (int) noDataValue);
+			colorMapMax = Math.max(colorMapMax, (int) noDataValue);
 		}
-		return results;
-	}
 
-	/**
-	 * @param style
-	 *            A {@link Style} to search for all {@link TextSymbolizer}s . No
-	 *            guarantee, that any one of them will ever be used for any
-	 *            feature (think about filters).
-	 * 
-	 * @author Stefan A. Tzeggai
-	 * 
-	 * @return {@link List} or all {@link TextSymbolizer}s found in the
-	 *         {@link Style}.
-	 */
-	public static List<TextSymbolizer> getTextSymbolizers(final Style style) {
-		List<TextSymbolizer> results = new ArrayList<TextSymbolizer>();
-		try {
-			if (style != null) {
+		// Declare "all" values smaller/greater the color map values
+		// automatically as NoData
+		// int colorMapRange = colorMapMax - colorMapMin;
+		// double lowerStart = colorMapMin - 10000*colorMapRange;
+		// double higherEnd = colorMapMax + 10000*colorMapRange;
+		final int lowerStart = Integer.MIN_VALUE;
+		final int higherEnd = Integer.MAX_VALUE;
+		categories.put(colorMapMax + 10, new Category("_autoNoData1_",
+				new Color[] { new Color(0, 0, 0, 0) }, new NumberRange(
+						colorMapMax + 1, colorMapMax + 2), new NumberRange(
+						colorMapMax + 1, higherEnd)));
+		if (colorMapMin < colorMapMax)
+			categories.put(colorMapMin - 10, new Category("_autoNoData2_",
+					new Color[] { new Color(0, 0, 0, 0) },
+					// new NumberRange(colorMapMin-2, colorMapMin-1), //
+					// logischer, aber klappt nicht!?
+					NumberRange.create(colorMapMax + 3, colorMapMax + 4),
+					// new NumberRange(colorMapMax + 3, colorMapMax + 4),
+					NumberRange.create(lowerStart, colorMapMin - 1)
+			// new NumberRange(lowerStart, colorMapMin - 1)
+					));
 
-				for (final FeatureTypeStyle fts : style.featureTypeStyles()) {
-					for (final Rule r : fts.rules()) {
-						results.addAll(getTextSymbolizers(r.getSymbolizers()));
-					}
-				}
+		// Create the GridSampleDimension
+		GridSampleDimension gsd = new GridSampleDimension(name, categories
+				.values().toArray(new Category[0]), unit).geophysics(true);
 
-			}
+		for (Category c : (List<Category>) gsd.getCategories())
+			LOGGER.debug(c.toString());
 
-		} catch (final Exception e) {
-			LOGGER.error("error - filter API stuff?", e);
-			return results;
-		}
-		return results;
+		return gsd;
 	}
 
 	/**
-	 * @param symbolizers
-	 *            List of Symbolizers to search for all {@link TextSymbolizer}s
-	 *            . No guarantee, that any one of them will ever be used for any
-	 *            feature (think about filters).
+	 * Erzeugt eine {@link Category} fuer die NoData-Werte transparent
+	 * dargestellt werden.
 	 * 
-	 * @author Stefan A. Tzeggai
-	 * 
-	 * @return {@link List} or all {@link TextSymbolizer}s found in the given
-	 *         symbolizers.
+	 * @param geoValue
+	 *            Geo-Wert, der NoData repraesentiert
 	 */
-	public static List<TextSymbolizer> getTextSymbolizers(
-			Symbolizer[] symbolizers) {
-		List<TextSymbolizer> results = new ArrayList<TextSymbolizer>();
-		try {
-			if (symbolizers != null) {
-
-				for (final Symbolizer symb : symbolizers) {
-					if (symb instanceof TextSymbolizer) {
-						results.add((TextSymbolizer) symb);
-					}
-				}
-
-			}
-
-		} catch (final Exception e) {
-			LOGGER.error("error - filter API stuff?", e);
-			return results;
-		}
-		return results;
+	public static Category createNoDataCategory(double geoValue) {
+		return createNoDataCategory(0, geoValue);
 	}
 
 	/**
-	 * Clones a Style by converting it to XML and reading it back in.
+	 * Erzeugt eine {@link Category} fuer die NoData-Werte transparent
+	 * dargestellt werden.
 	 * 
-	 * @param style
-	 *            the {@link Style} to be copied.
+	 * @param value
+	 *            Sample-Wert der Category
+	 * @param geoValue
+	 *            Geo-Wert, der NoData repraesentiert
 	 */
-	public static Style clone(Style style) {
-		DuplicatingStyleVisitor duplicatingStyleVisitor = new DuplicatingStyleVisitor();
-		style.accept(duplicatingStyleVisitor);
-		return (Style) duplicatingStyleVisitor.getCopy();
+	public static Category createNoDataCategory(int value, double geoValue) {
+		return new Category(
+				Vocabulary.formatInternational(VocabularyKeys.NODATA),
+				new Color[] { new Color(0, 0, 0, 0) }, new NumberRange(value,
+						value), new NumberRange(geoValue, geoValue));
 	}
 
 	/**
-	 * Clones a {@link Symbolizer} using the {@link DuplicatingStyleVisitor}.
-	 */
-	public static Symbolizer clone(Symbolizer sym) {
-		DuplicatingStyleVisitor duplicatingStyleVisitor = new DuplicatingStyleVisitor();
-		sym.accept(duplicatingStyleVisitor);
-		return (Symbolizer) duplicatingStyleVisitor.getCopy();
-	}
-
-	/**
-	 * Clons a {@link Graphic} element
+	 * @param geoObject
+	 *            the {@link GeometryForm} the selection style shall be created
+	 *            for.
+	 * @param type
+	 *            define the look of the selection style by choosing a constant
+	 *            from {@link SelectionStylesTypes}
 	 * 
-	 * @param graphicFill
-	 * @return
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * @return a {@link Style} that is suitable to identify features of the
+	 *         given type as selected items.
 	 */
-	public static Graphic clone(Graphic graphic) {
-		DuplicatingStyleVisitor duplicatingStyleVisitor = new DuplicatingStyleVisitor();
-		graphic.accept(duplicatingStyleVisitor);
-		return (Graphic) duplicatingStyleVisitor.getCopy();
-	}
+	public static FeatureTypeStyle createSelectionFTStyle(
+			GeometryForm geometryForm, SelectionStylesTypes type) {
+		Symbolizer[] symbolizers = createSelectionSymbolizers(geometryForm,
+				type);
 
-	/**
-	 * Creates a new {@link BrewerPalette} with only one scheme (which includes
-	 * all colors). The suitablity of the palette is set to "unknown" for all
-	 * viewer types.
-	 * 
-	 * @param name
-	 *            name for the palette (also the description is set to this
-	 *            value)
-	 * @param colors
-	 *            colors for the palette
-	 */
-	public static BrewerPalette createBrewerPalette(String name, Color[] colors) {
-		BrewerPalette palette = new BrewerPalette();
-		palette.setColors(colors);
-		palette.setName(name);
-		palette.setDescription(name);
-
-		// set suitability to UNKNOWN for all viewers
-		PaletteSuitability suitability = new PaletteSuitability();
-		try {
-			suitability.setSuitability(colors.length, new String[] { "?", "?",
-					"?", "?", "?", "?" });
-			palette.setPaletteSuitability(suitability);
-		} catch (IOException e) {
-			LOGGER.error(
-					"Unabel to PaletteSuitability.setSuitablility for colors.length="
-							+ colors, e);
-		}
-
-		// Create the trivial scheme for the palette (requested colors equals
-		// number of colors)
-		int[] schema = new int[colors.length];
-		for (int j = 0; j < colors.length; j++)
-			schema[j] = j;
-		SampleScheme sampleScheme = new SampleScheme();
-
-		// set the trivial scheme for all schemas
-		for (int j = 2; j < schema.length; j++) {
-			sampleScheme.setSampleScheme(j, schema);
-			// sampleScheme.setSampleScheme(schema.length, schema);
-		}
-
-		palette.setColorScheme(sampleScheme);
-
-		return palette;
+		return STYLE_BUILDER.createFeatureTypeStyle(symbolizers, 0.0,
+				Double.POSITIVE_INFINITY);
 	}
 
 	/**
@@ -1737,41 +1041,7 @@
 
 	}
 
-	public static Style createSelectionStyle(Object geoObject,
-			SelectionStylesTypes type) {
-		FeatureTypeStyle fts = createSelectionFTStyle(geoObject, type);
-		Style style = STYLE_FACTORY.createStyle();
-		style.featureTypeStyles().clear();
-		style.featureTypeStyles().add(fts);
-		return style;
-
-	}
-
 	/**
-	 * @param geoObject
-	 *            the {@link GeometryForm} the selection style shall be created
-	 *            for.
-	 * @param type
-	 *            define the look of the selection style by choosing a constant
-	 *            from {@link SelectionStylesTypes}
-	 * 
-	 * @return a {@link Style} that is suitable to identify features of the
-	 *         given type as selected items.
-	 */
-	public static FeatureTypeStyle createSelectionFTStyle(
-			GeometryForm geometryForm, SelectionStylesTypes type) {
-		Symbolizer[] symbolizers = createSelectionSymbolizers(geometryForm,
-				type);
-
-		return STYLE_BUILDER.createFeatureTypeStyle(symbolizers, 0.0,
-				Double.POSITIVE_INFINITY);
-	}
-
-	public enum SelectionStylesTypes {
-		LeftTop2RightBottom_lines, RightTop2LeftBottom_lines, Outline_only, LeftTop2RightBottom_lines_biggaps, RightTop2LeftBottom_lines_biggaps, RightTop2LeftBottom_lines_smallgaps, LeftTop2RightBottom_lines_smallgaps
-	}
-
-	/**
 	 * Creates a rule which paints features as selected.
 	 * 
 	 * @param geometryForm
@@ -1818,15 +1088,19 @@
 		return rule;
 	}
 
+	public static Style createSelectionStyle(Object geoObject,
+			SelectionStylesTypes type) {
+		FeatureTypeStyle fts = createSelectionFTStyle(geoObject, type);
+		Style style = STYLE_FACTORY.createStyle();
+		style.featureTypeStyles().clear();
+		style.featureTypeStyles().add(fts);
+		return style;
+
+	}
+
 	public static Symbolizer[] createSelectionSymbolizers(
 			GeometryForm geometryForm, SelectionStylesTypes type) {
 		Symbolizer[] symbolizers = new Symbolizer[0];
-		//
-		// // TODO Not a good idea to put the 500 here as constant!
-		// final Function offsetFunction = FilterUtil.FILTER_FAC2.function(
-		// "offset", FilterUtil.FILTER_FAC2.property("the_geom"),
-		// FilterUtil.FILTER_FAC2.literal(-500), FilterUtil.FILTER_FAC2
-		// .literal(500));
 
 		double size = 15.;
 		if (type == SelectionStylesTypes.RightTop2LeftBottom_lines_smallgaps
@@ -1933,6 +1207,113 @@
 		return symbolizers;
 	}
 
+	/**
+	 * Creates a {@link Style} for a {@link Grid} layer from a {@link ColorMap}
+	 * Title will be set to {@link GridUtil#UNTITLED_RASTER_STYLE_TITLE}
+	 * 
+	 * @param colorMap
+	 *            If null, then defaultStyle for Grid will be used
+	 * @param name
+	 *            The name to give to the Style. null will result in name
+	 *            {@link GridUtil#UNTITLED_RASTER_STYLE_TITLE}
+	 * 
+	 * @return Always a Style that you can apply to a {@link GridCoverage}.
+	 *         Style has name {@link GridUtil#DEFAULT_RASTER_STYLE_NAME} if no
+	 *         colormap was provided.
+	 * 
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 */
+	public static Style createStyleFromColorMap(ColorMap colorMap, String name) {
+		return createStyleFromColorMap(colorMap, name, null);
+	}
+
+	/**
+	 * Creates a {@link Style} for a {@link Grid} layer from a {@link ColorMap}
+	 * 
+	 * @param colorMap
+	 *            If null, then defaultStyle for Grid will be used
+	 * @param name
+	 *            The name to give to the Style. null will result in name=
+	 *            {@link GridUtil#UNNAMED_RASTER_STYLE_NAME} or
+	 *            GridUtil#DEFAULT_RASTER_STYLE_NAME} (if no colorMap is given).
+	 * 
+	 * @param title
+	 *            The Title to give to the Style. null will result in title=
+	 *            {@link GridUtil#UNTITLED_RASTER_STYLE_TITLE} or
+	 *            {@link GridUtil#DEFAULT_RASTER_STYLE_TITLE} (if no colorMap is
+	 *            given)
+	 * 
+	 * @return Always a {@link Style} that you can be applyed to a
+	 *         {@link GridCoverage}.
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 */
+	public static Style createStyleFromColorMap(ColorMap colorMap, String name,
+			String title) {
+		if (colorMap == null)
+			return GridUtil.createDefaultStyle();
+
+		if (name == null)
+			// A colorMap was provided, but no name.
+			name = GridUtil.UNNAMED_RASTER_STYLE_NAME;
+
+		if (title == null)
+			// A colorMap was provided, but no title.
+			title = GridUtil.UNTITLED_RASTER_STYLE_TITLE;
+
+		RasterSymbolizerImpl rasterSymbolizerImpl = new RasterSymbolizerImpl();
+
+		// MS: In GT-2.6.1 the attribute for the raster style is "grid",
+		// not "raster". Setting the geometry to NULL causes that
+		// the grid attribute is determined dynamically during rendering
+		rasterSymbolizerImpl.setGeometry(null);// new
+												// AttributeExpressionImpl("grid"));
+
+		// Entferne alle label informationen
+		clearColorMapLabels(colorMap);
+
+		rasterSymbolizerImpl.setColorMap(colorMap);
+		Symbolizer[] symbolizers = { rasterSymbolizerImpl };
+		RuleImpl ruleImpl = new RuleImpl(symbolizers) {
+		};
+		Rule[] rules = { ruleImpl };
+		FeatureTypeStyleImpl featureTypeStyleImpl = new FeatureTypeStyleImpl(
+				rules) {
+		};
+
+		Style style = STYLE_FACTORY.createStyle();
+		style.setName(name);
+		style.getDescription().setTitle(title);
+		style.featureTypeStyles().add(featureTypeStyleImpl);
+		return style;
+	}
+
+	/**
+	 * Erzeugt einen {@link Style} aus einem {@linkplain Element JDOM-Element},
+	 * des eine SLD-Definition enthaelt
+	 * 
+	 * @param element
+	 *            Element mit SLD-Definition
+	 */
+	public static Style createStyleFromSLD(Element element) {
+		String xmlDefinition = new XMLOutputter().outputString(element);
+		// TODO: Workaround, because gt2-2.6.x has problems when the
+		// ColorMapEntries are not in the ascending order according to
+		// their values
+		// --> maybe we can bring the XML-Elements to an ascending order
+		// prior to interprete the XML
+
+		ByteArrayInputStream inputStream = null;
+		try {
+			inputStream = new ByteArrayInputStream(xmlDefinition.getBytes());
+			Style[] style = loadSLD(inputStream);
+			return style == null || style.length == 0 ? null : style[0];
+		} finally {
+			IOUtils.closeQuietly(inputStream);
+		}
+	}
+
 	public static Style createStyleSimple(Object geoObject, Color color,
 			Color color2) {
 		if (geoObject instanceof GridCoverage2D
@@ -2006,238 +1387,337 @@
 		return style;
 	}
 
-	//
-	// /**
-	// * Doubles the number of palettes by adding the reverse palette to every
-	// * palette. The name of the reverse palette is the name of the original
-	// * palette plus the letter R.
-	// *
-	// * @author SK
-	// * @param palettes The original list of {@link BrewerPalette
-	// BrewerPalettes}
-	// */
-	// public static BrewerPalette[] addReversePalettes(BrewerPalette[]
-	// palettes) {
-	// BrewerPalette[] newPalettes = new BrewerPalette[palettes.length * 2];
-	//
-	// int pos = 0;
-	// for (BrewerPalette bp : palettes) {
-	// newPalettes[pos] = bp;
-	// pos++;
-	// Color[] newColors = new Color[bp.getMaxColors()];
-	//
-	// List<Color> colorList =
-	// java.util.Arrays.asList(bp.getColors(bp.getMaxColors()));
-	// Collections.reverse(colorList);
-	// colorList.toArray(newColors);
-	//
-	// try {
-	// newPalettes[pos] = StylingUtil.createBrewerPalette(bp.getName()
-	// + "R", newColors);
-	// newPalettes[pos].setPaletteSuitability(bp
-	// .getPaletteSuitability());
-	// newPalettes[pos].setDescription(bp.getDescription()+" reversed");
-	// newPalettes[pos].setType(bp.getType());
-	// newPalettes[pos].setColorScheme(bp.getColorScheme());
-	// } catch (IOException e) {
-	// LOGGER.error("",e);
-	// newPalettes[pos] = bp;
-	// }
-	//
-	// pos++;
-	// }
-	//
-	// return newPalettes;
-	// }
-
 	/**
-	 * Replaces the "main" color in a given {@link Symbolizer} element
+	 * SLD Rules können die Paramter MinScaleDenominator und MaxScaleDenominator
+	 * enthalten. Dadurch können Elemente für manche Zoom-Stufen deaktiviert
+	 * werden.
 	 * 
+	 * Kommentar: "Sichtbarkeit" bezieht es nicht darauf, ob die Elemente auf
+	 * dem Kartenausschnitt sichtbar sind, sondern um die SLD Regeln, welche das
+	 * SimpleFeature evt. nur Scalenabhängig zeichnen.<br/>
+	 * SK 19.6.2009:Bei einem {@link PolygonSymbolizer} zählt nicht der Rand,
+	 * sondern nur ob eine Füllung vorhanden ist! Man kann dann zwar leider
+	 * nicht auf ein Rand eines Polygons ohne Fill klicken, aber dafür kann man
+	 * durch die ungefüllte Fläche klicken.
+	 * 
+	 * @param fc
+	 *            Die zu filternde FeatureCollection. Diese wird nicht
+	 *            verändert.
+	 * @param style
+	 *            Der Style, mit dem die Features gerendert werden (z.b.
+	 *            layer.getStyle() )
+	 * 
+	 * @param scaleDenominator
+	 *            Der aktuelle ScaleDenomitor für den die Sichtbarkeit ermittelt
+	 *            wird.
+	 * 
+	 * @see RendererUtilities.calculateOGCScale
+	 * 
+	 * @return Eine FeatureCollection in welcher nur die Features enthalten
+	 *         sind, welche bei aktuellen Scale mit dem übergebenen Style
+	 *         gerendert werden.
+	 * 
+	 *         TODO Was ist mit raster?!
+	 * 
+	 *         TODO Das sollte man besser machen: Zuerst die FIlter der
+	 *         sichtbaren regeln raussuchen, und dann direkt am anfang damitmit
+	 *         mitfiltern...
+	 * 
 	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
 	 */
-	public static void replaceSymbolizerColor(Symbolizer symb, Color oldColor,
-			Color newColor) {
-		if (symb == null)
-			return;
+	public static MemoryFeatureCollection filterSLDVisibleOnly(
+			final FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
+			final Style style, final Double scaleDenominator) {
 
-		if (symb instanceof PointSymbolizer) {
-			PointSymbolizer ps = (PointSymbolizer) symb;
-			replacePointSymbolizerColor(ps, oldColor, newColor);
-		}
+		// Eine im Speicher gehaltene FeatureCollection der sichtbaren
+		final MemoryFeatureCollection fcVisible = new MemoryFeatureCollection(
+				fc.getSchema());
 
-		if (symb instanceof PolygonSymbolizer) {
-			PolygonSymbolizer ps = (PolygonSymbolizer) symb;
-			replacePolygonSymbolizerColor(ps, oldColor, newColor);
-		}
+		// Prüfen aller Features in der Collection
+		final Iterator<SimpleFeature> fcIt = fc.iterator();
 
-		if (symb instanceof LineSymbolizer) {
-			LineSymbolizer ps = (LineSymbolizer) symb;
-			replaceLineSymbolizerColor(ps, oldColor, newColor);
+		try {
+
+			while (fcIt.hasNext()) {
+				final SimpleFeature feature = fcIt.next();
+
+				for (final FeatureTypeStyle fts : style.featureTypeStyles()) {
+
+					// Leave out FTSs that are selection related
+					if (fts.getName() != null
+							&& fts.getName()
+									.equals(FeatureMapLayerSelectionSynchronizer.SELECTION_STYLING_FTS_NAME))
+						continue;
+
+					final List<Rule> rules = fts.rules();
+
+					for (final Rule rule : rules) {
+						final double maxScaleDenominator = rule
+								.getMaxScaleDenominator();
+						final double minScaleDenominator = rule
+								.getMinScaleDenominator();
+
+						// 1. Check: Trifft die Rule auf den aktuellen Scale der
+						// JMapPane?
+						if ((minScaleDenominator > scaleDenominator)
+								|| (scaleDenominator > maxScaleDenominator)) {
+							continue;
+						}
+
+						// 2. Check: Eine Rule ist gülrig, aber trifft der
+						// Filter für dieses SimpleFeature?
+						final Filter rFilter = rule.getFilter();
+						if ((rFilter != null) && (!rFilter.evaluate(feature)))
+							continue;
+
+						// 3. Check: Passt einer der Symbolizer dieser Rule zu
+						// dem
+						// SimpleFeature? Dieser Check wird in
+						// "real world" meistens klappen, es sei denn, ein
+						// Hansel
+						// gibt einen LineSymbolizer für ein PointLayer an.
+						boolean passt = false;
+						for (final Symbolizer symb : rule.getSymbolizers()) {
+
+							final Geometry geom = (Geometry) feature
+									.getDefaultGeometry();
+
+							if ((geom instanceof MultiPoint)
+									|| (geom instanceof com.vividsolutions.jts.geom.Point)) {
+								if (symb instanceof PointSymbolizer) {
+									if (((PointSymbolizer) symb).getGraphic() != null)
+										passt = true;
+									break;
+								}
+							} else if ((geom instanceof MultiLineString)
+									|| (geom instanceof LineString)) {
+								if (symb instanceof LineSymbolizer) {
+									if (((LineSymbolizer) symb).getStroke() != null)
+										passt = true;
+									break;
+								}
+							} else if ((geom instanceof MultiPolygon)
+									|| (geom instanceof Polygon)) {
+
+								if (symb instanceof PolygonSymbolizer) {
+									if (((PolygonSymbolizer) symb).getFill() != null)
+										passt = true;
+									break;
+								}
+
+								if (symb instanceof PointSymbolizer) {
+									// This is a special case and not handles
+									// 100% correct yet. Polygons visualized
+									// with Pointsymbolizers should also have
+									// different Filters when they are selected
+									if (((PointSymbolizer) symb).getGraphic() != null)
+										passt = true;
+									break;
+								}
+							} else {
+								LOGGER.warn("Unbekannter geom Typ! Gehe von sichbar aus!");
+								passt = true;
+							}
+						}
+						if (!passt)
+							continue;
+
+						// Nun sollte das feature wiklich sichtbar sein
+						fcVisible.add(feature);
+					}
+				}
+			}
+		} catch (final java.lang.IllegalStateException e) {
+			LOGGER.error("Iterating over the features", e);
+			/**
+			 * SK: 14.Apri 2009. It happened a few time to that fcIt.hasNext
+			 * suddenly threw an exception for the "africa countries.shp":
+			 * Exception in thread "AWT-EventQueue-0"
+			 * java.lang.IllegalStateException: ShapeType changed illegally from
+			 * Polygon to Undefined at org.geotools.
+			 * data.shapefile.shp.ShapefileReader.nextRecord(ShapefileReader
+			 * .java:452) at org.geotools.data.shapefile.indexed.
+			 * IndexedShapefileDataStore$Reader
+			 * .next(IndexedShapefileDataStore.java:1272) at
+			 * org.geotools.data.FIDFeatureReader.next(FIDFeatureReader.java:92)
+			 * at org .geotools.data.FilteringFeatureReader.hasNext(
+			 * FilteringFeatureReader .java:125) at
+			 * org.geotools.data.store.FeatureReaderIterator.hasNext(
+			 * FeatureReaderIterator.java:44) at
+			 * schmitzm.geotools.feature.FeatureUtil
+			 * .filterSLDVisibleOnly(FeatureUtil.java:216) *
+			 * 
+			 */
 		}
 
+		// LOGGER.info("filterSLDVisibleOnly removed "+ (fc.size() -
+		// fcVisible.size()) + " features.");
+
+		return fcVisible;
 	}
 
 	/**
-	 * Replaces the "main" color in a given {@link LineSymbolizer} element
+	 * SLD Rules können die Paramter MinScaleDenominator und MaxScaleDenominator
+	 * enthalten. Dadurch können Elemente für manche Zoom-Stufen deaktiviert
+	 * werden.
 	 * 
+	 * @param fc
+	 *            Die zu filternde FeatureCollection. Diese wird nicht
+	 *            verändert.
+	 * @param style
+	 *            Der Style, mit dem die Features gerendert werden (z.b.
+	 *            layer.getStyle() )
+	 * 
+	 * @return Eine FeatureCollection in welcher nur die Features enthalten
+	 *         sind, welche bei aktuellen Scale mit dem übergebenen Style
+	 *         gerendert werden.
+	 * 
 	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
 	 */
-	public static void replaceLineSymbolizerColor(LineSymbolizer ps,
-			Color oldColor, Color newColor) {
-		if (ps == null)
-			return;
+	public static FeatureCollection<SimpleFeatureType, SimpleFeature> filterSLDVisibleOnly(
+			final FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
+			final Style style, XMapPane xMapPane) {
 
-		replaceStrokeColor(ps.getStroke(), oldColor, newColor);
-	}
+		if (xMapPane == null || style == null)
+			return new EmptyFeatureCollection(fc.getSchema());
 
-	/**
-	 * Replaces the "main" color in a given {@link PointSymbolizer} element
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 */
-	public static void replacePointSymbolizerColor(PointSymbolizer ps,
-			Color oldColor, Color newColor) {
-		if (ps == null)
-			return;
+		// Der "scaleDenominator" der aktuellen JMapPane
+		Double scaleDenominator = RendererUtilities.calculateOGCScale(
+				new ReferencedEnvelope(xMapPane.getMapArea(), xMapPane
+						.getMapContext().getCoordinateReferenceSystem()),
+				xMapPane.getBounds().width, null);
 
-		replaceGraphicColor(ps.getGraphic(), oldColor, newColor);
+		return filterSLDVisibleOnly(fc, style, scaleDenominator);
 	}
 
 	/**
-	 * Replaces the "main" color in a given {@link PolygonSymbolizer} element
+	 * Ermittelt fuer einen Wert den {@link ColorMapEntry} aus einer
+	 * {@link ColorMap}.
 	 * 
-	 * @param oldColor
-	 * @param newColor
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 * @param ps
+	 * @param value
+	 *            Wert
+	 * @return {@code null}, wenn in der {@link ColorMap} kein expliziter
+	 *         Eintrag fuer den Wert hinterlegt ist
 	 */
-	public static void replacePolygonSymbolizerColor(PolygonSymbolizer ps,
-			Color oldColor, Color newColor) {
-		replaceFillColor(ps.getFill(), oldColor, newColor);
-		replaceStrokeColor(ps.getStroke(), oldColor, newColor);
+	public static ColorMapEntry findColorMapEntry(ColorMap colorMap,
+			double value) {
+		for (ColorMapEntry entry : colorMap.getColorMapEntries())
+			if (value == getQuantityFromColorMapEntry(entry))
+				return entry;
+		return null;
 	}
 
 	/**
-	 * Replaces the "main" color in a given {@link Stroke} element
+	 * Liefert die Farbe eines Farbpaletten-Eintrag.
 	 * 
-	 * @param stroke
-	 * @param oldColor
-	 * @param newColor
+	 * @param entry
+	 *            Farbpaletten-Eintrag
 	 */
-	public static void replaceStrokeColor(Stroke stroke, Color oldColor,
-			Color newColor) {
-		if (stroke == null)
-			return;
+	public static Color getColorFromColorMapEntry(ColorMapEntry entry) {
+		// if ( entry == null || entry.getColor() == null ||
+		// entry.getColor().getValue(null) == null ) // gt2-2.3.4
+		if (entry == null || entry.getColor() == null
+				|| entry.getColor().evaluate(null) == null) // gt2-2-4-2
+			return null;
 
-		if ((stroke.getColor() != null)
-				&& (StylingUtil.getColorFromExpression(stroke.getColor())
-						.equals(oldColor)))
-			stroke.setColor(StylingUtil.STYLE_BUILDER.colorExpression(newColor));
+		// // Transparenz
+		// Double opacity = getOpacityFromColorMapEntry(entry);
 
-		replaceGraphicColor(stroke.getGraphicFill(), oldColor, newColor);
-
-		replaceGraphicColor(stroke.getGraphicStroke(), oldColor, newColor);
-
+		return getColorFromExpression(entry.getColor());
 	}
 
 	/**
-	 * Replaces the "main" color in a given {@link Fill} element
+	 * Liefert die Farbe eines Farbpaletten-Eintrag.
 	 * 
-	 * @param fill
-	 * @param oldColor
-	 * @param newColor
+	 * @param expression
+	 *            Expression, die einen String liefert
 	 */
-	public static void replaceFillColor(Fill fill, Color oldColor,
-			Color newColor) {
-		if (fill == null)
-			return;
+	public static Color getColorFromExpression(Expression expression) {
+		if (expression == null)
+			return null;
 
-		if ((fill.getColor() != null)
-				&& (getColorFromExpression(fill.getColor()).equals(oldColor)))
-			fill.setColor(STYLE_BUILDER.colorExpression(newColor));
+		if (expression instanceof ConstantExpression) {
+			ConstantExpression a = (ConstantExpression) expression;
+			Object obj = a.getValue();
+			if (obj instanceof Color) {
+				return (Color) obj;
+			}
+		}
 
-		replaceGraphicColor(fill.getGraphicFill(), oldColor, newColor);
-		//
-		// if ((fill.getBackgroundColor() != null)
-		// && (getColorFromExpression(fill.getBackgroundColor())
-		// .equals(oldColor)))
-		// fill.setBackgroundColor(STYLE_BUILDER.colorExpression(newColor));
+		return Color.decode(expression.toString());
+
+		// Old way Martin did it:
+		// return Color.decode((String) expression.evaluate(null));
+
 	}
 
 	/**
-	 * Replaces the "main" color in a given {@link Graphic} element
+	 * Liefert die Farbpalette zu einem Style, wenn der Style aus einem
+	 * {@link RasterSymbolizer} erzeugt wurde.
 	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * @param style
+	 *            Style Wenn <code>null</code>, dann wird style auf
+	 *            {@link GridUtil}.createDefaultStyle() gesetzt
+	 * @return <code>null</code> wenn der Style nicht auf einem
+	 *         {@link RasterSymbolizer} basiert.
 	 */
-	public static void replaceGraphicColor(Graphic graphic, Color oldColor,
-			Color newColor) {
-		if (graphic == null)
-			return;
+	public static ColorMap getColorMapFromStyle(final Style style) {
+		final List<ColorMap> colorMapsFromStyle = getColorMapsFromStyle(style);
+		if (colorMapsFromStyle.size() > 0)
+			return colorMapsFromStyle.get(0);
+		else
+			return null;
 
-		if ((graphic.getMarks() != null) && (graphic.getMarks().length > 0)) {
-
-			// Checking for Colors in Marks...
-			for (Mark m : graphic.getMarks()) {
-
-				replaceFillColor(m.getFill(), oldColor, newColor);
-
-				replaceStrokeColor(m.getStroke(), oldColor, newColor);
-
-			}
-		}
 	}
 
 	/**
-	 * @return the {@link Color} used in the {@link Graphic} or null, if an
-	 *         {@link ExternalGraphic} is used.
+	 * Liefert alle Farbpaletten aus einem Style, wenn irgendo
+	 * {@link RasterSymbolizer} enthalten sind.
 	 * 
-	 * @param graphic
-	 *            If <code>null</code> returns <code>null</code>
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * @param style
+	 *            Style Wenn <code>null</code>, dann wird style auf
+	 *            {@link GridUtil}.createDefaultStyle() gesetzt
+	 * @return Leere Liste wenn keine RasterSymbolizer enthalten ist.
 	 */
-	public static Color getGraphicColor(Graphic graphic) {
-		if (graphic == null)
-			return null;
+	public static List<ColorMap> getColorMapsFromStyle(Style style) {
 
-		Color foundColor = null;
+		if (style == null)
+			style = GridUtil.createDefaultStyle();
 
-		if ((graphic.getMarks() != null) && (graphic.getMarks().length > 0)) {
+		final List<RasterSymbolizer> rasterSymbolizers = getRasterSymbolizers(style);
 
-			// Checking for Colors in Marks...
-			for (Mark m : graphic.getMarks()) {
+		final List<ColorMap> colorMaps = new ArrayList<ColorMap>();
 
-				if (foundColor == null)
-					foundColor = getFillColor(m.getFill());
-
-				if (foundColor == null)
-					foundColor = getStrokeColor(m.getStroke());
+		for (final RasterSymbolizer rs : rasterSymbolizers) {
+			if (rs.getColorMap() != null) {
+				colorMaps.add(rs.getColorMap());
 			}
-
 		}
 
-		return foundColor;
+		return colorMaps;
 	}
 
 	/**
-	 * @return the first {@link Color} used in a {@link Stroke}.
+	 * Returns the color map type specified by a given string.
 	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * @param typeStr
+	 *            a string
+	 * @see ColorMap#getType()
 	 */
-	public static Color getStrokeColor(Stroke stroke) {
-		if (stroke == null)
-			return null;
+	public static int getColorMapType(String typeStr) {
+		if (typeStr == null)
+			throw new IllegalArgumentException("Unknown color map type: "
+					+ typeStr);
 
-		if (stroke.getColor() != null)
-			return StylingUtil.getColorFromExpression(stroke.getColor());
+		typeStr = typeStr.trim().toLowerCase();
+		if (typeStr.equals("ramp") || typeStr.equals("type_ramp"))
+			return ColorMap.TYPE_RAMP;
+		if (typeStr.equals("intervals") || typeStr.equals("type_intervals"))
+			return ColorMap.TYPE_INTERVALS;
+		if (typeStr.equals("values") || typeStr.equals("type_values"))
+			return ColorMap.TYPE_VALUES;
 
-		if (getGraphicColor(stroke.getGraphicStroke()) != null)
-			return getGraphicColor(stroke.getGraphicStroke());
-
-		if (getGraphicColor(stroke.getGraphicFill()) != null)
-			return getGraphicColor(stroke.getGraphicFill());
-
-		return null;
+		throw new IllegalArgumentException("Unknown color map type: " + typeStr);
 	}
 
 	/**
@@ -2261,139 +1741,119 @@
 	}
 
 	/**
-	 * @return the first {@link Color} used in a {@link Symbolizer}.
+	 * Geopublisher allows to use one or two attributes for labelling, like
 	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * <code>
+	 
+	    <sld:Label>
+          <ogc:PropertyName>ORTSRATSBE</ogc:PropertyName>: <ogc:PropertyName>ORB_SCHLUE</ogc:PropertyName>
+        </sld:Label>
+
+        </code>
+	 * 
+	 * Returns the first attribute found in the label expression of the given
+	 * {@link TextSymbolizer}. If non is found for some reason, the method tries
+	 * to return the first attribute from the schema. We expect the layer to
+	 * have some attributes, because otherwise AS shouldn't even create the
+	 * LabellingTab.
 	 */
-	public static Color getSymbolizerColor(Symbolizer symb) {
-		if (symb == null)
-			return null;
+	public static PropertyName getFirstPropertyName(final SimpleFeatureType ft,
+			final TextSymbolizer textSymbolizer) {
+		final Expression labelExpression = textSymbolizer.getLabel();
+		try {
+			if (labelExpression instanceof PropertyName) {
+				// There is no second property
+				return (PropertyName) labelExpression;
+			} else if (labelExpression instanceof Function) {
+				final Function filterExpression = (Function) labelExpression;
+				final FilterAttributeExtractor attExVid = new FilterAttributeExtractor(
+						ft);
 
-		if (symb instanceof PointSymbolizer) {
-			PointSymbolizer ps = (PointSymbolizer) symb;
-			return getPointSymbolizerColor(ps);
-		}
+				attExVid.visit(filterExpression, null);
 
-		if (symb instanceof PolygonSymbolizer) {
-			PolygonSymbolizer ps = (PolygonSymbolizer) symb;
-			return getPolygonSymbolizerColor(ps);
-		}
+				final String[] attributeNames = attExVid.getAttributeNames();
 
-		if (symb instanceof LineSymbolizer) {
-			LineSymbolizer ps = (LineSymbolizer) symb;
-			return getLineSymbolizerColor(ps);
+				if (attributeNames.length == 0)
+					return null;
+
+				String prop1 = null;
+				if (attributeNames.length == 1) {
+					// Easy
+					prop1 = attributeNames[0];
+				} else {
+
+					if (filterExpression.toString().indexOf(attributeNames[0]) < filterExpression
+							.toString().indexOf(attributeNames[1])) {
+						prop1 = attributeNames[0];
+						// prop2 = attributeNames[1];
+					} else {
+						prop1 = attributeNames[1];
+						// prop2 = attributeNames[0];
+					}
+
+				}
+				return FilterUtil.FILTER_FAC2.property(prop1);
+			}
+		} catch (final Exception e) {
+			LOGGER.error("Reading the second property for labelling failed", e);
+			return null;
 		}
 
-		return null;
+		// TODO this is not rockhard.. could NPE
+		return FilterUtil.FILTER_FAC2.property(ft.getAttributeDescriptors()
+				.get(1).getLocalName());
 	}
 
 	/**
-	 * @return the first {@link Color} used in a {@link LineSymbolizer}.
+	 * @return the {@link Color} used in the {@link Graphic} or null, if an
+	 *         {@link ExternalGraphic} is used.
 	 * 
+	 * @param graphic
+	 *            If <code>null</code> returns <code>null</code>
+	 * 
 	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
 	 */
-	public static Color getLineSymbolizerColor(LineSymbolizer ps) {
-		if (ps == null)
+	public static Color getGraphicColor(Graphic graphic) {
+		if (graphic == null)
 			return null;
 
 		Color foundColor = null;
 
-		if (foundColor == null)
-			foundColor = getStrokeColor(ps.getStroke());
+		if ((graphic.getMarks() != null) && (graphic.getMarks().length > 0)) {
 
+			// Checking for Colors in Marks...
+			for (Mark m : graphic.getMarks()) {
+
+				if (foundColor == null)
+					foundColor = getFillColor(m.getFill());
+
+				if (foundColor == null)
+					foundColor = getStrokeColor(m.getStroke());
+			}
+
+		}
+
 		return foundColor;
 	}
 
 	/**
-	 * @return the first {@link Color} used in a {@link PolygonSymbolizer}.
+	 * @return the first {@link Color} used in a {@link LineSymbolizer}.
 	 * 
 	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
 	 */
-	public static Color getPolygonSymbolizerColor(PolygonSymbolizer ps) {
+	public static Color getLineSymbolizerColor(LineSymbolizer ps) {
 		if (ps == null)
 			return null;
 
 		Color foundColor = null;
 
 		if (foundColor == null)
-			foundColor = getFillColor(ps.getFill());
-
-		if (foundColor == null)
 			foundColor = getStrokeColor(ps.getStroke());
 
 		return foundColor;
 	}
 
 	/**
-	 * @return the first {@link Color} used in a {@link PointSymbolizer}.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 */
-	public static Color getPointSymbolizerColor(PointSymbolizer ps) {
-		if (ps == null)
-			return null;
-
-		return getGraphicColor(ps.getGraphic());
-	}
-
-	/***************************************************************************
-	 * Copies all Values from one {@link TextSymbolizer} to another
-	 * {@link TextSymbolizer}
-	 * 
-	 * @param from
-	 *            {@link TextSymbolizer} source
-	 * @param to
-	 *            {@link TextSymbolizer} target. May not be <code>null</code>.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
-	 */
-	public static void copyAllValues(final TextSymbolizer from,
-			final TextSymbolizer to) {
-		to.setLabel(from.getLabel());
-		to.setPriority(from.getPriority());
-
-		// TODO Does not copy all that has to be copied!
-
-		final FilterFactory2 ff2 = FeatureUtil.FILTER_FACTORY2;
-
-		to.getFonts()[0].setFontFamily(ff2.literal(from.getFonts()[0]
-				.getFontFamily().toString()));
-		to.getFonts()[0].setFontSize(ff2.literal(from.getFonts()[0]
-				.getFontSize().toString()));
-		to.getFonts()[0].setFontWeight(ff2.literal(from.getFonts()[0]
-				.getFontWeight().toString()));
-		to.getFonts()[0].setFontStyle(ff2.literal(from.getFonts()[0]
-				.getFontStyle().toString()));
-	}
-
-	/**
-	 * Returns all {@link RasterSymbolizer} that are contained in a
-	 * {@link Style}. {@link RasterSymbolizer} from {@link FeatureTypeStyle}s
-	 * that are selection related are ignored.
-	 */
-	public static List<RasterSymbolizer> getRasterSymbolizers(Style style) {
-		final List<RasterSymbolizer> rsList = new ArrayList<RasterSymbolizer>();
-		for (FeatureTypeStyle fts : style.featureTypeStyles()) {
-
-			// Leave out FTSs that are selection related
-			if (fts.getName() != null
-					&& fts.getName()
-							.equals(FeatureMapLayerSelectionSynchronizer.SELECTION_STYLING_FTS_NAME))
-				continue;
-
-			for (Rule r : fts.rules()) {
-				for (Symbolizer symb : r.getSymbolizers()) {
-					if (symb instanceof RasterSymbolizer) {
-						rsList.add((RasterSymbolizer) symb);
-					}
-				}
-			}
-		}
-
-		return rsList;
-	}
-
-	/**
 	 * Super smart metod ;-) Needs to be extended to look at the graphic width
 	 * and Geometry type.
 	 * 
@@ -2451,198 +1911,132 @@
 	}
 
 	/**
-	 * SLD Rules können die Paramter MinScaleDenominator und MaxScaleDenominator
-	 * enthalten. Dadurch können Elemente für manche Zoom-Stufen deaktiviert
-	 * werden.
+	 * Liefert die Transparenz eines Farbpaletten-Eintrag.
 	 * 
-	 * @param fc
-	 *            Die zu filternde FeatureCollection. Diese wird nicht
-	 *            verändert.
-	 * @param style
-	 *            Der Style, mit dem die Features gerendert werden (z.b.
-	 *            layer.getStyle() )
+	 * @param entry
+	 *            Farbpaletten-Eintrag
+	 * @return 1.0, wenn <code>null</code> uebergeben wird
+	 */
+	public static Double getOpacityFromColorMapEntry(ColorMapEntry entry) {
+		if (entry == null)
+			return 1.0;
+		return getOpacityFromExpression(entry.getOpacity());
+	}
+
+	/**
+	 * Liefert die Transparenz eines Farbpaletten-Eintrag.
 	 * 
-	 * @return Eine FeatureCollection in welcher nur die Features enthalten
-	 *         sind, welche bei aktuellen Scale mit dem übergebenen Style
-	 *         gerendert werden.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * @param expression
+	 *            Expression, die einen String oder einen Double liefert
+	 * @return 1.0, wenn <code>null</code> uebergeben wird
 	 */
-	public static FeatureCollection<SimpleFeatureType, SimpleFeature> filterSLDVisibleOnly(
-			final FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
-			final Style style, XMapPane xMapPane) {
+	public static Double getOpacityFromExpression(Expression expression) {
+		// gt2-2.3.4:
+		// if ( expression == null || expression.getValue(null) == null )
+		// return 1.0
+		// Object exprValue = evaluate.getValue(null);
+		// gt2-2.3.4:
+		if (expression == null || expression.evaluate(null) == null)
+			return 1.0;
+		Object exprValue = expression.evaluate(null);
 
-		if (xMapPane == null || style == null)
-			return new EmptyFeatureCollection(fc.getSchema());
-
-		// Der "scaleDenominator" der aktuellen JMapPane
-		Double scaleDenominator = RendererUtilities.calculateOGCScale(
-				new ReferencedEnvelope(xMapPane.getMapArea(), xMapPane
-						.getMapContext().getCoordinateReferenceSystem()),
-				xMapPane.getBounds().width, null);
-
-		return filterSLDVisibleOnly(fc, style, scaleDenominator);
+		return (exprValue instanceof String) ? Double
+				.valueOf((String) exprValue) : ((Number) exprValue)
+				.doubleValue();
 	}
 
 	/**
-	 * Since GT2.6, the AttributeNames are case sensitive. Also the raster
-	 * Styles need GeometryProperty set to "geom" to work. This method checks
-	 * all referenced AttributeNames.
+	 * @return the first {@link Color} used in a {@link PointSymbolizer}.
 	 * 
-	 * @param Schema
-	 *            may be <code>null</code>, e.g. for raster layers
-	 * 
-	 *            TODO Rename to correctStye
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
 	 */
-	public static Style correctPropertyNames(Style style) {
-		return correctPropertyNames(style, null);
+	public static Color getPointSymbolizerColor(PointSymbolizer ps) {
+		if (ps == null)
+			return null;
+
+		return getGraphicColor(ps.getGraphic());
 	}
 
 	/**
-	 * Since GT2.6, the AttributeNames are case sensitive. Also the raster
-	 * Styles need GeometryProperty set to "geom" to work. This method checks
-	 * all referenced AttributeNames and checks them against the schema.
+	 * @return the first {@link Color} used in a {@link PolygonSymbolizer}.
 	 * 
-	 * @param Schema
-	 *            may be <code>null</code>, e.g. for raster layers
-	 * 
-	 *            TODO Rename to correctStye
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
 	 */
-	public static Style correctPropertyNames(Style style,
-			final SimpleFeatureType schema) {
+	public static Color getPolygonSymbolizerColor(PolygonSymbolizer ps) {
+		if (ps == null)
+			return null;
 
-		DuplicatingStyleVisitor dsv = new DuplicatingStyleVisitor() {
-			public void visit(RasterSymbolizer sym) {
-				sym.setGeometryPropertyName("geom");
-				super.visit(sym);
-			};
+		Color foundColor = null;
 
-			@Override
-			public void visit(ColorMap cm) {
-				super.visit(sortColorMap(cm));
-			};
+		if (foundColor == null)
+			foundColor = getFillColor(ps.getFill());
 
-			@Override
-			public void visit(LineSymbolizer sym) {
-				sym.setGeometryPropertyName(FeatureUtil
-						.findBestMatchingAttributeFallBackFirst(schema,
-								sym.getGeometryPropertyName()).getLocalPart());
-				super.visit(sym);
-			}
+		if (foundColor == null)
+			foundColor = getStrokeColor(ps.getStroke());
 
-			@Override
-			public void visit(PolygonSymbolizer sym) {
-				sym.setGeometryPropertyName(FeatureUtil
-						.findBestMatchingAttributeFallBackFirst(schema,
-								sym.getGeometryPropertyName()).getLocalPart());
-				super.visit(sym);
-			}
+		return foundColor;
+	}
 
-			@Override
-			public void visit(PointSymbolizer sym) {
-				sym.setGeometryPropertyName(FeatureUtil
-						.findBestMatchingAttributeFallBackFirst(schema,
-								sym.getGeometryPropertyName()).getLocalPart());
-				super.visit(sym);
-			}
+	/**
+	 * Liefert den Wert eines Farbpaletten-Eintrag.
+	 * 
+	 * @param entry
+	 *            Farbpaletten-Eintrag
+	 * @return {@code null}, wenn <code>null</code> uebergeben wird
+	 */
+	public static Double getQuantityFromColorMapEntry(ColorMapEntry entry) {
+		if (entry == null)
+			return null;
+		return getQuantityFromExpression(entry.getQuantity());
+	}
 
-			@Override
-			public void visit(TextSymbolizer sym) {
-				sym.setGeometryPropertyName(FeatureUtil
-						.findBestMatchingAttributeFallBackFirst(schema,
-								sym.getGeometryPropertyName()).getLocalPart());
-				if (sym.getLabel() != null)
-					sym.setLabel(copy(sym.getLabel()));
+	/**
+	 * Liefert den Wert eines Farbpaletten-Eintrag.
+	 * 
+	 * @param expression
+	 *            Expression, die einen String oder einen Double liefert
+	 * @return {@code null}, wenn <code>null</code> uebergeben wird
+	 */
+	public static Double getQuantityFromExpression(Expression expression) {
+		// gt2-2.3.4:
+		// if ( expression == null || expression.getValue(null) == null )
+		// return null
+		// Object exprValue = evaluate.getValue(null);
+		// gt2-2.3.4:
+		if (expression == null || expression.evaluate(null) == null)
+			return null;
+		Object exprValue = expression.evaluate(null);
 
-				if (sym.getPriority() != null)
-					sym.setPriority(copy(sym.getPriority()));
+		return (exprValue instanceof String) ? Double
+				.valueOf((String) exprValue) : ((Number) exprValue)
+				.doubleValue();
+	}
 
-				super.visit(sym);
-			}
+	/**
+	 * Returns all {@link RasterSymbolizer} that are contained in a
+	 * {@link Style}. {@link RasterSymbolizer} from {@link FeatureTypeStyle}s
+	 * that are selection related are ignored.
+	 */
+	public static List<RasterSymbolizer> getRasterSymbolizers(Style style) {
+		final List<RasterSymbolizer> rsList = new ArrayList<RasterSymbolizer>();
+		for (FeatureTypeStyle fts : style.featureTypeStyles()) {
 
-			@Override
-			public Expression copy(Expression expression) {
-				if (expression instanceof FilterFunction_strConcat) {
-					FilterFunction_strConcat strConcat = (FilterFunction_strConcat) expression;
+			// Leave out FTSs that are selection related
+			if (fts.getName() != null
+					&& fts.getName()
+							.equals(FeatureMapLayerSelectionSynchronizer.SELECTION_STYLING_FTS_NAME))
+				continue;
 
-					List<Expression> children = strConcat.getParameters();
-					List<Expression> correctedChildren = new ArrayList<Expression>();
-					for (Expression o : children) {
-						correctedChildren.add(copy(o));
+			for (Rule r : fts.rules()) {
+				for (Symbolizer symb : r.getSymbolizers()) {
+					if (symb instanceof RasterSymbolizer) {
+						rsList.add((RasterSymbolizer) symb);
 					}
-					strConcat.setParameters(correctedChildren);
-
-				} else if (expression instanceof DivideImpl) {
-					DivideImpl divFilter = (DivideImpl) expression;
-					divFilter.setExpression1(copy(divFilter.getExpression1()));
-					divFilter.setExpression2(copy(divFilter.getExpression2()));
-				} else if (expression instanceof PropertyName) {
-					PropertyName pName = (PropertyName) expression;
-
-					Name correctedName = FeatureUtil
-							.findBestMatchingAttributeFallBackFirst(schema,
-									pName.getPropertyName());
-
-					return ff.property(correctedName);
 				}
-				return super.copy(expression);
 			}
+		}
 
-			@Override
-			protected Filter copy(Filter filter) {
-				if (filter instanceof DivideImpl) {
-					DivideImpl divFilter = (DivideImpl) filter;
-					divFilter.setExpression1(copy(divFilter.getExpression1()));
-					divFilter.setExpression2(copy(divFilter.getExpression2()));
-				} else if (filter instanceof IsNullImpl) {
-					IsNullImpl isNullFilter = (IsNullImpl) filter;
-					isNullFilter.setExpression1(copy(isNullFilter
-							.getExpression1()));
-				} else if (filter instanceof NotImpl) {
-					NotImpl notFilter = (NotImpl) filter;
-					List<Filter> children = notFilter.getChildren();
-					List<Filter> correctedChildren = new ArrayList<Filter>();
-					for (Filter ex : children) {
-						correctedChildren.add(copy(ex));
-					}
-					notFilter.setChildren(correctedChildren);
-				} else if (filter instanceof OrImpl) {
-					OrImpl notFilter = (OrImpl) filter;
-					List<Filter> children = notFilter.getChildren();
-					List<Filter> correctedChildren = new ArrayList<Filter>();
-					for (Filter ex : children) {
-						correctedChildren.add(copy(ex));
-					}
-					notFilter.setChildren(correctedChildren);
-				} else if (filter instanceof AndImpl) {
-					AndImpl andFilter = (AndImpl) filter;
-					List<Filter> children = andFilter.getChildren();
-					List<Filter> correctedChildren = new ArrayList<Filter>();
-					for (Filter ex : children) {
-						correctedChildren.add(copy(ex));
-					}
-					andFilter.setChildren(correctedChildren);
-				} else if (filter instanceof BinaryComparisonAbstract) {
-					BinaryComparisonAbstract binFilter = (BinaryComparisonAbstract) filter;
-					binFilter.setExpression1(copy(binFilter.getExpression1()));
-					binFilter.setExpression2(copy(binFilter.getExpression2()));
-
-					// TODO noch viel mehr faelle!!
-					if (filter instanceof IsBetweenImpl) {
-						IsBetweenImpl isbetween = (IsBetweenImpl) filter;
-						isbetween
-								.setExpression(copy(isbetween.getExpression()));
-					}
-
-				}
-				return (Filter) super.copy(filter);
-			}
-		};
-
-		dsv.visit(style);
-
-		Style copiedCleanStyle = (Style) dsv.getCopy();
-		return copiedCleanStyle;
+		return rsList;
 	}
 
 	/**
@@ -2691,199 +2085,447 @@
 	}
 
 	/**
-	 * Geopublisher allows to use one or two attributes for labelling, like
+	 * Returns <code>null</code> or any {@link FeatureTypeStyle} contained in
+	 * the given {@link Style} that is SELECTION related.
 	 * 
-	 * <code>
-	 
-	    <sld:Label>
-          <ogc:PropertyName>ORTSRATSBE</ogc:PropertyName>: <ogc:PropertyName>ORB_SCHLUE</ogc:PropertyName>
-        </sld:Label>
+	 * @see {@link FeatureMapLayerSelectionSynchronizer#SELECTION_STYLING_FTS_NAME}
+	 */
+	public static FeatureTypeStyle getSelectionFeatureTypeStyle(
+			final Style style) {
 
-        </code>
+		if (style == null)
+			return null;
+
+		// Remove any selection-FeatureTypeStyle from the new Style
+		for (int ii = 0; ii < style.featureTypeStyles().size(); ii++) {
+
+			FeatureTypeStyle fts = style.featureTypeStyles().get(ii);
+
+			if (fts.getName() != null
+					&& fts.getName()
+							.equals(FeatureMapLayerSelectionSynchronizer.SELECTION_STYLING_FTS_NAME)) {
+				return style.featureTypeStyles().get(ii);
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * @return the first {@link Color} used in a {@link Stroke}.
 	 * 
-	 * Returns the first attribute found in the label expression of the given
-	 * {@link TextSymbolizer}. If non is found for some reason, the method tries
-	 * to return the first attribute from the schema. We expect the layer to
-	 * have some attributes, because otherwise AS shouldn't even create the
-	 * LabellingTab.
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
 	 */
-	public static PropertyName getFirstPropertyName(final SimpleFeatureType ft,
-			final TextSymbolizer textSymbolizer) {
-		final Expression labelExpression = textSymbolizer.getLabel();
+	public static Color getStrokeColor(Stroke stroke) {
+		if (stroke == null)
+			return null;
+
+		if (stroke.getColor() != null)
+			return StylingUtil.getColorFromExpression(stroke.getColor());
+
+		if (getGraphicColor(stroke.getGraphicStroke()) != null)
+			return getGraphicColor(stroke.getGraphicStroke());
+
+		if (getGraphicColor(stroke.getGraphicFill()) != null)
+			return getGraphicColor(stroke.getGraphicFill());
+
+		return null;
+	}
+
+	//
+	// /**
+	// * Doubles the number of palettes by adding the reverse palette to every
+	// * palette. The name of the reverse palette is the name of the original
+	// * palette plus the letter R.
+	// *
+	// * @author SK
+	// * @param palettes The original list of {@link BrewerPalette
+	// BrewerPalettes}
+	// */
+	// public static BrewerPalette[] addReversePalettes(BrewerPalette[]
+	// palettes) {
+	// BrewerPalette[] newPalettes = new BrewerPalette[palettes.length * 2];
+	//
+	// int pos = 0;
+	// for (BrewerPalette bp : palettes) {
+	// newPalettes[pos] = bp;
+	// pos++;
+	// Color[] newColors = new Color[bp.getMaxColors()];
+	//
+	// List<Color> colorList =
+	// java.util.Arrays.asList(bp.getColors(bp.getMaxColors()));
+	// Collections.reverse(colorList);
+	// colorList.toArray(newColors);
+	//
+	// try {
+	// newPalettes[pos] = StylingUtil.createBrewerPalette(bp.getName()
+	// + "R", newColors);
+	// newPalettes[pos].setPaletteSuitability(bp
+	// .getPaletteSuitability());
+	// newPalettes[pos].setDescription(bp.getDescription()+" reversed");
+	// newPalettes[pos].setType(bp.getType());
+	// newPalettes[pos].setColorScheme(bp.getColorScheme());
+	// } catch (IOException e) {
+	// LOGGER.error("",e);
+	// newPalettes[pos] = bp;
+	// }
+	//
+	// pos++;
+	// }
+	//
+	// return newPalettes;
+	// }
+
+	/**
+	 * @return the first {@link Color} used in a {@link Symbolizer}.
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 */
+	public static Color getSymbolizerColor(Symbolizer symb) {
+		if (symb == null)
+			return null;
+
+		if (symb instanceof PointSymbolizer) {
+			PointSymbolizer ps = (PointSymbolizer) symb;
+			return getPointSymbolizerColor(ps);
+		}
+
+		if (symb instanceof PolygonSymbolizer) {
+			PolygonSymbolizer ps = (PolygonSymbolizer) symb;
+			return getPolygonSymbolizerColor(ps);
+		}
+
+		if (symb instanceof LineSymbolizer) {
+			LineSymbolizer ps = (LineSymbolizer) symb;
+			return getLineSymbolizerColor(ps);
+		}
+
+		return null;
+	}
+
+	/**
+	 * @param style
+	 *            A {@link Style} to search for the first {@link TextSymbolizer}
+	 *            that will be used for the given {@link SimpleFeature}.
+	 * 
+	 * @author Stefan A. Tzeggai
+	 * 
+	 * @return <code>null</code> or the first {@link TextSymbolizer} found in
+	 *         the style that applies to the {@link SimpleFeature}.
+	 */
+	public static TextSymbolizer getTextSymbolizer(final Style style,
+			final SimpleFeature f) {
+		if (f == null)
+			return null;
 		try {
-			if (labelExpression instanceof PropertyName) {
-				// There is no second property
-				return (PropertyName) labelExpression;
-			} else if (labelExpression instanceof Function) {
-				final Function filterExpression = (Function) labelExpression;
-				final FilterAttributeExtractor attExVid = new FilterAttributeExtractor(
-						ft);
+			if (style != null) {
 
-				attExVid.visit(filterExpression, null);
+				for (final FeatureTypeStyle fts : style.featureTypeStyles()) {
+					for (final Rule r : fts.rules()) {
 
-				final String[] attributeNames = attExVid.getAttributeNames();
+						final Filter filter = r.getFilter();
 
-				if (attributeNames.length == 0)
-					return null;
+						if (filter != null && (!filter.evaluate(f))) {
+							continue;
+						}
 
-				String prop1 = null;
-				if (attributeNames.length == 1) {
-					// Easy
-					prop1 = attributeNames[0];
-				} else {
+						for (final Symbolizer symb : r.getSymbolizers()) {
+							if (symb instanceof TextSymbolizer) {
+								return (TextSymbolizer) symb;
+							}
+						}
 
-					if (filterExpression.toString().indexOf(attributeNames[0]) < filterExpression
-							.toString().indexOf(attributeNames[1])) {
-						prop1 = attributeNames[0];
-						// prop2 = attributeNames[1];
-					} else {
-						prop1 = attributeNames[1];
-						// prop2 = attributeNames[0];
 					}
+				}
 
-				}
-				return FilterUtil.FILTER_FAC2.property(prop1);
 			}
+
 		} catch (final Exception e) {
-			LOGGER.error("Reading the second property for labelling failed", e);
+			LOGGER.error("error - filter API stuff?", e);
 			return null;
 		}
-
-		// TODO this is not rockhard.. could NPE
-		return FilterUtil.FILTER_FAC2.property(ft.getAttributeDescriptors()
-				.get(1).getLocalName());
+		return null;
 	}
 
 	/**
-	 * AtlasStyler has a fixed system that allows to use one or two label
-	 * attributes. If two are used, the are seperated by ": ". This mehtod stes
-	 * one or two ProperybaName fields.
+	 * @param style
+	 *            A {@link Style} to search for all {@link TextSymbolizer}s . No
+	 *            guarantee, that any one of them will ever be used for any
+	 *            feature (think about filters).
 	 * 
-	 * @param symbolizer
-	 *            the {@link TextSymbolizer} to call setLabel(Expression) on.
-	 * @param literalLabelField1
-	 *            may not be null!
-	 * @param literalLabelField2
-	 *            may be <code>null</code>
+	 * @author Stefan A. Tzeggai
+	 * 
+	 * @return {@link List} or all {@link TextSymbolizer}s found in the
+	 *         {@link Style}.
 	 */
-	public static void setDoublePropertyName(final TextSymbolizer symbolizer,
-			final PropertyName literalLabelField1,
-			final PropertyName literalLabelField2) {
-		if (literalLabelField2 != null
-				&& !literalLabelField2.toString().equalsIgnoreCase("-")) {
-			final Literal trenner = FilterUtil.FILTER_FAC2.literal(": ");
-			final Function f3 = FilterUtil.FILTER_FAC2.function("strConcat",
-					trenner, literalLabelField2);
-			final Function bothExpression = FilterUtil.FILTER_FAC2.function(
-					"strConcat", literalLabelField1, f3);
-			LOGGER.debug("Extended label expression is now: " + bothExpression);
-			symbolizer.setLabel(bothExpression);
-		} else {
-			symbolizer.setLabel(literalLabelField1);
+	public static List<TextSymbolizer> getTextSymbolizers(final Style style) {
+		List<TextSymbolizer> results = new ArrayList<TextSymbolizer>();
+		try {
+			if (style != null) {
+
+				for (final FeatureTypeStyle fts : style.featureTypeStyles()) {
+					for (final Rule r : fts.rules()) {
+						results.addAll(getTextSymbolizers(r.getSymbolizers()));
+					}
+				}
+
+			}
+
+		} catch (final Exception e) {
+			LOGGER.error("error - filter API stuff?", e);
+			return results;
 		}
+		return results;
 	}
 
 	/**
-	 * @return A {@link FeatureTypeStyle} that can be used style the given
-	 *         geoObject during a blink or highlight process.
+	 * @param symbolizers
+	 *            List of Symbolizers to search for all {@link TextSymbolizer}s
+	 *            . No guarantee, that any one of them will ever be used for any
+	 *            feature (think about filters).
+	 * 
+	 * @author Stefan A. Tzeggai
+	 * 
+	 * @return {@link List} or all {@link TextSymbolizer}s found in the given
+	 *         symbolizers.
 	 */
-	public static FeatureTypeStyle createBlinkFeatureTypeStyle(Object geoObject) {
-		if (geoObject instanceof GridCoverage2D
-				|| geoObject instanceof org.geotools.coverage.grid.io.AbstractGridCoverage2DReader) {
-			// Wenn irgendwann mal selection für raster möglich ist, dann hier
-			// einen schöneren style erstellen.
-			return GridUtil.createDefaultStyle().featureTypeStyles().get(0);
-		}
+	public static List<TextSymbolizer> getTextSymbolizers(
+			Symbolizer[] symbolizers) {
+		List<TextSymbolizer> results = new ArrayList<TextSymbolizer>();
+		try {
+			if (symbolizers != null) {
 
-		// We have vector-data. Now let's determine the type...
-		GeometryForm geometryForm = null;
-		if (geoObject instanceof FeatureCollection) {
-			geometryForm = FeatureUtil
-					.getGeometryForm((FeatureCollection<SimpleFeatureType, SimpleFeature>) geoObject);
-		} else if (geoObject instanceof GeometryAttributeType) {
-			geometryForm = FeatureUtil
-					.getGeometryForm((GeometryAttributeType) geoObject);
-		} else if (geoObject instanceof FeatureSource) {
-			geometryForm = FeatureUtil
-					.getGeometryForm((FeatureSource<SimpleFeatureType, SimpleFeature>) geoObject);
+				for (final Symbolizer symb : symbolizers) {
+					if (symb instanceof TextSymbolizer) {
+						results.add((TextSymbolizer) symb);
+					}
+				}
+
+			}
+
+		} catch (final Exception e) {
+			LOGGER.error("error - filter API stuff?", e);
+			return results;
 		}
+		return results;
+	}
 
-		Symbolizer[] symbolizers = new Symbolizer[0];
+	/**
+	 * @param style
+	 *            A {@link Style} to search for all {@link TextSymbolizer}s . No
+	 *            guarantee, that any one of them will ever be used for any
+	 *            feature (think about filters).
+	 * 
+	 * @author Stefan A. Tzeggai
+	 * 
+	 * @return {@link List} or all {@link TextSymbolizer}s found in the
+	 *         {@link Style}.
+	 */
+	public static List<TextSymbolizer> getVisibleTextSymbolizers(
+			final Style style) {
+		List<TextSymbolizer> results = new ArrayList<TextSymbolizer>();
+		try {
+			if (style != null) {
 
-		Graphic bg2;
-		switch (geometryForm) {
+				for (final FeatureTypeStyle fts : style.featureTypeStyles()) {
+					for (final Rule r : fts.rules()) {
 
-		case POINT:
+						if (r.getFilter() != null) {
 
-			Literal size0 = FeatureUtil.FILTER_FACTORY2.literal(26);
-			Literal size1 = FeatureUtil.FILTER_FACTORY2.literal(28);
+							/*
+							 * We are comparing it to AsUtil.alwaysfalsefilter
+							 * 
+							 * public static final PropertyIsEqualTo
+							 * allwaysFalseFilter = ff2.equals(ff2
+							 * .literal("1"), ff2.literal("2"));
+							 */
+							try {
 
-			Graphic bg1 = STYLE_FACTORY.createGraphic(new ExternalGraphic[0],
-					new Mark[] { STYLE_FACTORY.createMark(
-							FeatureUtil.FILTER_FACTORY2.literal("circle"),
-							STYLE_BUILDER.createStroke(Color.red, 2.), null,
-							size1, halfLit) },
-					new org.geotools.styling.Symbol[0],
-					FeatureUtil.FILTER_FACTORY2.literal(1), size1, zeroLit);
+								Filter f = r.getFilter();
+								if (f instanceof And) {
+									And and = (And) f;
+									if (and.getChildren() != null) {
+										Filter candidateF = and.getChildren()
+												.get(0);
+										if (candidateF instanceof PropertyIsEqualTo) {
+											final PropertyIsEqualTo compare = (PropertyIsEqualTo) candidateF;
+											if (compare.getExpression1() instanceof Literal
+													&& compare.getExpression2() instanceof Literal) {
+												Literal test1 = (Literal) compare
+														.getExpression1();
+												Literal test2 = (Literal) compare
+														.getExpression2();
+												if (test1.toString()
+														.equals("1")
+														&& test2.toString()
+																.equals("2")) {
+													// This TextSymbolizer is
+													// disabled using
+													// ASUtil.allwaysFalseFilter
+													// LOGGER.debug("Ignoring Rule "+
+													// r
+													// +" because the filter is "+f);
+													continue;
+												}
+											}
+										}
+									}
+								}
+							} catch (Exception e) {
+								LOGGER.debug(
+										"Checking for textSymbolizer allwaysFalseFilter",
+										e);
+							}
+						}
 
-			PointSymbolizer ps1 = STYLE_FACTORY.createPointSymbolizer();
-			ps1.setGraphic(bg1);
-			symbolizers = LangUtil.extendArray(symbolizers, ps1);
+						results.addAll(getTextSymbolizers(r.getSymbolizers()));
+					}
+				}
 
-			bg2 = STYLE_FACTORY.createGraphic(new ExternalGraphic[0],
-					new Mark[] { STYLE_FACTORY.createMark(
-							FeatureUtil.FILTER_FACTORY2.literal("circle"),
-							STYLE_BUILDER.createStroke(Color.black, 2.),
-							STYLE_BUILDER.createFill(Color.WHITE, 0.3), size0,
-							halfLit) }, new org.geotools.styling.Symbol[0],
-					FeatureUtil.FILTER_FACTORY2.literal(1), size0, zeroLit);
+			}
 
-			PointSymbolizer ps2 = STYLE_FACTORY.createPointSymbolizer();
-			ps2.setGraphic(bg2);
+		} catch (final Exception e) {
+			LOGGER.error("error - filter API stuff?", e);
+			return results;
+		}
+		return results;
+	}
 
-			symbolizers = LangUtil.extendArray(symbolizers, ps2);
-			break;
-		case POLYGON:
+	/**
+	 * Compares a given Style and a {@link File} containg a {@link Style}.
+	 * 
+	 * @param style1
+	 *            The first {@link Style}
+	 * @param style2file
+	 *            A {@link File} pointing to the second {@link Style}
+	 * @return <code>true</code> is they are different, ignoring any XML
+	 *         fomatting.
+	 */
+	public static boolean isStyleDifferent(Style style1, File style2file) {
+		SLDTRANSFORMER.setIndentation(2);
 
-			PolygonSymbolizer pol1 = STYLE_BUILDER.createPolygonSymbolizer(
-					STYLE_BUILDER.createStroke(Color.red, 4), null);
-			symbolizers = LangUtil.extendArray(symbolizers, pol1);
+		try {
 
-			PolygonSymbolizer pol2 = STYLE_BUILDER.createPolygonSymbolizer(
-					STYLE_BUILDER.createStroke(Color.black, 2),
-					STYLE_BUILDER.createFill(Color.WHITE, .5));
-			symbolizers = LangUtil.extendArray(symbolizers, pol2);
+			if (!style2file.exists())
+				return true;
 
-			break;
+			Style style2 = loadSLD(style2file)[0];
 
-		case LINE:
+			return isStyleDifferent(style1, style2);
 
-			LineSymbolizer ls = STYLE_BUILDER.createLineSymbolizer(Color.red,
-					6.);
-			symbolizers = LangUtil.extendArray(symbolizers, ls);
+		} catch (Exception e) {
+			LOGGER.debug("Comparing styles " + style1 + " and " + style2file
+					+ " failed. So we assume they are different.", e);
+			return true;
+		}
+	}
 
-			LineSymbolizer ls2 = STYLE_BUILDER.createLineSymbolizer(
-					Color.black, 4.);
-			symbolizers = LangUtil.extendArray(symbolizers, ls2);
+	/**
+	 * Compares a given Style and a {@link File} containg a {@link Style}.
+	 * 
+	 * @param style1
+	 *            The first {@link Style}
+	 * @param style2
+	 *            The second {@link Style} to compare to
+	 * @return <code>true</code> is they are different, ignoring any XML
+	 *         fomatting.
+	 */
+	public static boolean isStyleDifferent(Style style1, Style style2) {
+		try {
+			// SLDTRANSFORMER.setEncoding(Charset.forName("UTF-8"));
+			// Transforming style2 to an XML String
+			String style1string = SLDTRANSFORMER.transform(style1);
+			String style2string = SLDTRANSFORMER.transform(style2);
 
-			LineSymbolizer ls3 = STYLE_BUILDER.createLineSymbolizer(
-					Color.white, 2.);
-			symbolizers = LangUtil.extendArray(symbolizers, ls3);
-			break;
+			return !style1string.equals(style2string);
 
-		default:
-			throw new IllegalArgumentException("Provide a suitable object.");
+		} catch (Exception e) {
+			LOGGER.debug("Compating styles " + style1 + " and " + style2
+					+ " failed. So we assume they are different.", e);
+			return true;
 		}
 
-		return STYLE_BUILDER.createFeatureTypeStyle(symbolizers, Double.NaN,
-				Double.NaN);
 	}
 
-	public static StyledLayerDescriptor loadStyledLayerDescriptor(Reader reader) {
+	/**
+	 * Loads {@link Style}s from a SLD {@link File}
+	 * 
+	 * @param sldFile
+	 *            {@link File} to read the SLD from
+	 * 
+	 * @return An {@link Array} of {@link Style}s, can be length==0
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 */
+	public static Style[] loadSLD(File sldFile) throws FileNotFoundException {
+
+		FileInputStream inputStream = null;
+		try {
+			inputStream = new FileInputStream(sldFile);
+			final Style[] loadedSLD = loadSLD(inputStream);
+			return loadedSLD;
+		} finally {
+			IOUtils.closeQuietly(inputStream);
+		}
+	}
+
+	/**
+	 * Loads {@link Style}s from a SLD {@link InputStream}
+	 * 
+	 * @param inputStream
+	 *            {@link InputStream} to read the SLD from
+	 * 
+	 * @return An {@link Array} of {@link Style}s, can be length==0. null if
+	 *         file not exists
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 */
+	public static Style[] loadSLD(InputStream inputStream) {
+
+		Style[] styles = null;
+		try {
+			SLDParser stylereader = new SLDParser(StylingUtil.STYLE_FACTORY,
+					inputStream);
+			styles = stylereader.readXML();
+			return styles;
+		} catch (Exception e) {
+			LOGGER.warn(
+					" ... no styles recognized. Return 'new Style[] { null }' ",
+					e);
+			return new Style[] { null };
+		}
+
+	}
+
+	/**
+	 * Loads {@link Style}s from a SLD {@link InputStream}
+	 * 
+	 * @param url
+	 *            {@link URL} to read the SLD from
+	 * 
+	 * @return An {@link Array} of {@link Style}s, can be length==0 if no
+	 *         UserStyles in SLD file. null if file not exists
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 */
+	public static Style[] loadSLD(URL url) {
+		InputStream openStream = null;
+		try {
+			openStream = url.openStream();
+			return loadSLD(openStream);
+		} catch (IOException e) {
+			return null;
+		} finally {
+			IOUtils.closeQuietly(openStream);
+		}
+	}
+
+	public static StyledLayerDescriptor loadStyledLayerDescriptor(
+			InputStream inputStream) {
 		StyledLayerDescriptor sld = null;
 		try {
 			SLDParser stylereader = new SLDParser(StylingUtil.STYLE_FACTORY,
-					reader);
+					inputStream);
 			sld = stylereader.parseSLD();
 			return sld;
 		} catch (Exception e) {
@@ -2894,12 +2536,11 @@
 		}
 	}
 
-	public static StyledLayerDescriptor loadStyledLayerDescriptor(
-			InputStream inputStream) {
+	public static StyledLayerDescriptor loadStyledLayerDescriptor(Reader reader) {
 		StyledLayerDescriptor sld = null;
 		try {
 			SLDParser stylereader = new SLDParser(StylingUtil.STYLE_FACTORY,
-					inputStream);
+					reader);
 			sld = stylereader.parseSLD();
 			return sld;
 		} catch (Exception e) {
@@ -2910,47 +2551,80 @@
 		}
 	}
 
+	static public ColorMap parseColormapToSld(File colormapFile)
+			throws IOException {
+		return parseColormapToSld(DataUtilities.fileToURL(colormapFile));
+	}
+
 	/**
-	 * Converts a {@link StyledLayerDescriptor} or any of it's subcomponents to
-	 * XML
+	 * Creates a Geotools Colormap containing all the Color Palette definitions
+	 * defined in the File. The File may have different formats. Supported
+	 * formats are<br/>
+	 * <ul>
+	 * <li>gdalinfo output</li>
+	 * </ul>
 	 * 
-	 * @throws TransformerException
+	 * <br/>
+	 * The returned {@link ColorMap} is of type {@link ColorMap#TYPE_VALUES}.
+	 * 
+	 * TODO Stefan Tzeggai Support gdal xml.aux format!
+	 * 
+	 * @see http 
+	 *      ://osgeo-org.1803224.n2.nabble.com/gdal-dev-Color-palette-file-for
+	 *      -use-in-rgb2pct-td4493744.html
 	 */
-	public static String toXMLString(Object sld) throws TransformerException {
-		SLDTRANSFORMER.setIndentation(1);
-		return SLDTRANSFORMER.transform(sld);
-	}
-
-	static public ColorMap parseColormapToSld(URL colormapUrl)
-			throws IOException {
-		return parseColormapToSld(DataUtilities.urlToFile(colormapUrl));
-	}
-
-	static Pattern GDALCOLORMAP_4 = Pattern
-			.compile("(\\d+): (\\d+),(\\d+),(\\d+),(\\d+).*$");
-
-	static public ColorMap parseColormapToSld(File file) throws IOException {
+	static public ColorMap parseColormapToSld(URL url) throws IOException {
 		String[] labels = new String[0];
 		double[] quantities = new double[0];
 		Color[] colors = new Color[0];
 
-		String readFileAsString = IOUtil.readFileAsString(file);
+		String readFileAsString = IOUtil.readURLasString(url);
 		for (String line : readFileAsString.split("\\n")) {
-			Matcher matcher = GDALCOLORMAP_4.matcher(line);
-			if (matcher.find()) {
-				String q = matcher.group(1);
-				String r = matcher.group(2);
-				String g = matcher.group(3);
-				String b = matcher.group(4);
-				String o = matcher.group(5);
-				
-				Color color = new Color(Integer.valueOf(r), Integer.valueOf(g),Integer.valueOf(b), Integer.valueOf(o));
-				
-				// Arrays verlängern
-				labels = LangUtil.extendArray(labels, "");
-				colors = LangUtil.extendArray(colors, color);
-				quantities = LangUtil.extendArray(quantities, Double.valueOf(q));
+
+			try {
+
+				Matcher matcher = GDALINFO_COLORMAP_RGBA.matcher(line);
+				if (matcher.find()) {
+					Color color = new Color(Integer.valueOf(matcher.group(2)),
+							Integer.valueOf(matcher.group(3)),
+							Integer.valueOf(matcher.group(4)),
+							Integer.valueOf(matcher.group(5)));
+
+					// Arrays verlängern
+					labels = LangUtil.extendArray(labels, "");
+					colors = LangUtil.extendArray(colors, color);
+					quantities = LangUtil.extendArray(quantities,
+							Double.valueOf(matcher.group(1)));
+
+					// Zur nächsten Zeile springen
+					continue;
+				}
+			} catch (Exception e) {
+				Log.warn("Error parsing a line to ColorMapEntry. Line = '"
+						+ line + "'. Skipped.", e);
 			}
+
+			try {
+				Matcher matcher = GDALINFO_COLORMAP_RGB.matcher(line);
+				if (matcher.find()) {
+					Color color = new Color(Integer.valueOf(matcher.group(2)),
+							Integer.valueOf(matcher.group(3)),
+							Integer.valueOf(matcher.group(4)));
+
+					// Arrays verlängern
+					labels = LangUtil.extendArray(labels, "");
+					colors = LangUtil.extendArray(colors, color);
+					quantities = LangUtil.extendArray(quantities,
+							Double.valueOf(matcher.group(1)));
+
+					// Zur nächsten Zeile springen
+					continue;
+
+				}
+			} catch (Exception e) {
+				Log.warn("Error parsing a line to ColorMapEntry. Line = '"
+						+ line + "'. Skipped.", e);
+			}
 		}
 
 		int type = ColorMap.TYPE_VALUES;
@@ -2959,4 +2633,383 @@
 		return createColorMap;
 	}
 
+	/**
+	 * Unless {@link ColorMap} has no methods to remove an entry this method
+	 * creates a new {@link ColorMap} with the identical entries except the one
+	 * to remove.
+	 * 
+	 * @param colorMap
+	 *            the color map to remove entries from
+	 * @param colorMapEntry
+	 *            the entry to remove
+	 */
+	public static ColorMap removeColorMapEntry(ColorMap colorMap,
+			ColorMapEntry colorMapEntry) {
+		ColorMap newColorMap = new ColorMapImpl();
+		applyColorMapProperties(colorMap, newColorMap);
+
+		ColorMapEntry[] entry = colorMap.getColorMapEntries();
+		for (int i = 0; i < entry.length; i++)
+			if (entry[i] != colorMapEntry)
+				newColorMap.addColorMapEntry(entry[i]);
+
+		return newColorMap;
+	}
+
+	/**
+	 * Unless {@link ColorMap} has no methods to remove an entry this method
+	 * creates a new {@link ColorMap} with the identical entries except the one
+	 * to remove.
+	 * 
+	 * @param colorMap
+	 *            the color map to remove entries from
+	 * @param idx
+	 *            the entry index to remove
+	 */
+	public static ColorMap removeColorMapEntry(ColorMap colorMap, int idx) {
+		ColorMap newColorMap = new ColorMapImpl();
+		applyColorMapProperties(colorMap, newColorMap);
+
+		ColorMapEntry[] entry = colorMap.getColorMapEntries();
+		for (int i = 0; i < entry.length; i++)
+			if (i != idx)
+				newColorMap.addColorMapEntry(entry[i]);
+
+		return newColorMap;
+	}
+
+	/**
+	 * Creates a copy of the given {@link Style}, removing any
+	 * {@link FeatureTypeStyle}s that are only SELECTION related.
+	 * 
+	 * @see {@link FeatureMapLayerSelectionSynchronizer#SELECTION_STYLING_FTS_NAME}
+	 */
+	public static Style removeSelectionFeatureTypeStyle(final Style style) {
+
+		// Create a copy of the style
+		DuplicatingStyleVisitor duplVisitor = new DuplicatingStyleVisitor();
+		duplVisitor.visit(style);
+		Style cleanStyle = (Style) duplVisitor.getCopy();
+
+		// Remove any selection-FeatureTypeStyle from the new Style
+		for (int ii = 0; ii < style.featureTypeStyles().size(); ii++) {
+
+			FeatureTypeStyle fts = style.featureTypeStyles().get(ii);
+
+			if (fts.getName() != null
+					&& fts.getName()
+							.equals(FeatureMapLayerSelectionSynchronizer.SELECTION_STYLING_FTS_NAME)) {
+				cleanStyle.featureTypeStyles().remove(ii);
+				break;
+			}
+		}
+
+		return cleanStyle;
+	}
+
+	/**
+	 * Replaces the "main" color in a given {@link Fill} element
+	 * 
+	 * @param fill
+	 * @param oldColor
+	 * @param newColor
+	 */
+	public static void replaceFillColor(Fill fill, Color oldColor,
+			Color newColor) {
+		if (fill == null)
+			return;
+
+		if ((fill.getColor() != null)
+				&& (getColorFromExpression(fill.getColor()).equals(oldColor)))
+			fill.setColor(STYLE_BUILDER.colorExpression(newColor));
+
+		replaceGraphicColor(fill.getGraphicFill(), oldColor, newColor);
+		//
+		// if ((fill.getBackgroundColor() != null)
+		// && (getColorFromExpression(fill.getBackgroundColor())
+		// .equals(oldColor)))
+		// fill.setBackgroundColor(STYLE_BUILDER.colorExpression(newColor));
+	}
+
+	/**
+	 * Replaces the "main" color in a given {@link Graphic} element
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 */
+	public static void replaceGraphicColor(Graphic graphic, Color oldColor,
+			Color newColor) {
+		if (graphic == null)
+			return;
+
+		if ((graphic.getMarks() != null) && (graphic.getMarks().length > 0)) {
+
+			// Checking for Colors in Marks...
+			for (Mark m : graphic.getMarks()) {
+
+				replaceFillColor(m.getFill(), oldColor, newColor);
+
+				replaceStrokeColor(m.getStroke(), oldColor, newColor);
+
+			}
+		}
+	}
+
+	/**
+	 * Replaces the "main" color in a given {@link LineSymbolizer} element
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 */
+	public static void replaceLineSymbolizerColor(LineSymbolizer ps,
+			Color oldColor, Color newColor) {
+		if (ps == null)
+			return;
+
+		replaceStrokeColor(ps.getStroke(), oldColor, newColor);
+	}
+
+	/**
+	 * Replaces the "main" color in a given {@link PointSymbolizer} element
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 */
+	public static void replacePointSymbolizerColor(PointSymbolizer ps,
+			Color oldColor, Color newColor) {
+		if (ps == null)
+			return;
+
+		replaceGraphicColor(ps.getGraphic(), oldColor, newColor);
+	}
+
+	/**
+	 * Replaces the "main" color in a given {@link PolygonSymbolizer} element
+	 * 
+	 * @param oldColor
+	 * @param newColor
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * @param ps
+	 */
+	public static void replacePolygonSymbolizerColor(PolygonSymbolizer ps,
+			Color oldColor, Color newColor) {
+		replaceFillColor(ps.getFill(), oldColor, newColor);
+		replaceStrokeColor(ps.getStroke(), oldColor, newColor);
+	}
+
+	/**
+	 * Replaces the "main" color in a given {@link Stroke} element
+	 * 
+	 * @param stroke
+	 * @param oldColor
+	 * @param newColor
+	 */
+	public static void replaceStrokeColor(Stroke stroke, Color oldColor,
+			Color newColor) {
+		if (stroke == null)
+			return;
+
+		if ((stroke.getColor() != null)
+				&& (StylingUtil.getColorFromExpression(stroke.getColor())
+						.equals(oldColor)))
+			stroke.setColor(StylingUtil.STYLE_BUILDER.colorExpression(newColor));
+
+		replaceGraphicColor(stroke.getGraphicFill(), oldColor, newColor);
+
+		replaceGraphicColor(stroke.getGraphicStroke(), oldColor, newColor);
+
+	}
+
+	/**
+	 * Replaces the "main" color in a given {@link Symbolizer} element
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 */
+	public static void replaceSymbolizerColor(Symbolizer symb, Color oldColor,
+			Color newColor) {
+		if (symb == null)
+			return;
+
+		if (symb instanceof PointSymbolizer) {
+			PointSymbolizer ps = (PointSymbolizer) symb;
+			replacePointSymbolizerColor(ps, oldColor, newColor);
+		}
+
+		if (symb instanceof PolygonSymbolizer) {
+			PolygonSymbolizer ps = (PolygonSymbolizer) symb;
+			replacePolygonSymbolizerColor(ps, oldColor, newColor);
+		}
+
+		if (symb instanceof LineSymbolizer) {
+			LineSymbolizer ps = (LineSymbolizer) symb;
+			replaceLineSymbolizerColor(ps, oldColor, newColor);
+		}
+
+	}
+
+	/**
+	 * Saves the {@link Style} to OGC SLD. Overwrites any existing file. If a
+	 * FeatureTypeStyle for selection is used, it is automatically removed. This
+	 * method also checks, whether the style is actually differing from any
+	 * existing style in the {@link File}. If there is no difference, the file
+	 * is not saved again (that is more svn friendly).
+	 * 
+	 * @param origStyle
+	 *            {@link Style} to save. Any selectino related FeatureTypeStyle
+	 *            will be removed.
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * 
+	 * @return <code>true</code> if the file was really written.
+	 *         <code>false</code> means, that the existing file already was
+	 *         equals.
+	 * @throws IOException
+	 * @throws TransformerException
+	 */
+	public static final boolean saveStyleToSLD(Style origStyle, File exportFile)
+			throws TransformerException, IOException {
+
+		// Wenn Datei nicht mit .sld endet, die Dateierweiterung
+		// anhängen
+		exportFile = IOUtil.appendFileExt(exportFile, ".sld");
+
+		SLDTRANSFORMER.setIndentation(2);
+
+		Style exportStyle = removeSelectionFeatureTypeStyle(origStyle);
+
+		// Nur in Datei speichern, wenn
+		if (!isStyleDifferent(exportStyle, exportFile)) {
+			return false;
+		}
+
+		SLDTRANSFORMER.transform(exportStyle, new FileWriter(exportFile));
+		return true;
+	}
+
+	/**
+	 * Exports the {@link Style} to OGC SLD. If a FeatureTypeStyle for selection
+	 * is used, it is automatically removed.
+	 * 
+	 * @param style
+	 *            {@link Style} to save. Any selectino related FeatureTypeStyle
+	 *            will be removed.
+	 * 
+	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+	 * @throws TransformerException
+	 */
+	public static final void saveStyleToSLD(Style style,
+			OutputStream exportStream) throws TransformerException {
+		SLDTRANSFORMER.setIndentation(2);
+		SLDTRANSFORMER.transform(style, exportStream);
+	}
+
+	/**
+	 * Setzt die Farbe eines Farbpaletten-Eintrag.
+	 * 
+	 * @param entry
+	 *            Farbpaletten-Eintrag
+	 * @param color
+	 *            eine Farbe
+	 */
+	public static void setColorForColorMapEntry(ColorMapEntry entry, Color color) {
+		if (entry != null)
+			entry.setColor(STYLE_BUILDER.colorExpression(color));
+	}
+
+	/**
+	 * AtlasStyler has a fixed system that allows to use one or two label
+	 * attributes. If two are used, the are seperated by ": ". This mehtod stes
+	 * one or two ProperybaName fields.
+	 * 
+	 * @param symbolizer
+	 *            the {@link TextSymbolizer} to call setLabel(Expression) on.
+	 * @param literalLabelField1
+	 *            may not be null!
+	 * @param literalLabelField2
+	 *            may be <code>null</code>
+	 */
+	public static void setDoublePropertyName(final TextSymbolizer symbolizer,
+			final PropertyName literalLabelField1,
+			final PropertyName literalLabelField2) {
+		if (literalLabelField2 != null
+				&& !literalLabelField2.toString().equalsIgnoreCase("-")) {
+			final Literal trenner = FilterUtil.FILTER_FAC2.literal(": ");
+			final Function f3 = FilterUtil.FILTER_FAC2.function("strConcat",
+					trenner, literalLabelField2);
+			final Function bothExpression = FilterUtil.FILTER_FAC2.function(
+					"strConcat", literalLabelField1, f3);
+			LOGGER.debug("Extended label expression is now: " + bothExpression);
+			symbolizer.setLabel(bothExpression);
+		} else {
+			symbolizer.setLabel(literalLabelField1);
+		}
+	}
+
+	/**
+	 * Setzt die Transparenz eines Farbpaletten-Eintrag.
+	 * 
+	 * @param entry
+	 *            Farbpaletten-Eintrag
+	 * @param opacity
+	 *            Transparenzwert
+	 */
+	public static void setOpacityForColorMapEntry(ColorMapEntry entry,
+			double opacity) {
+		if (entry != null)
+			entry.setOpacity(STYLE_BUILDER.literalExpression(opacity));
+	}
+
+	/**
+	 * Setzt den Wert eines Farbpaletten-Eintrag.
+	 * 
+	 * @param entry
+	 *            Farbpaletten-Eintrag
+	 * @param quantity
+	 *            neuer Wert
+	 */
+	public static void setQuantityForColorMapEntry(ColorMapEntry entry,
+			double quantity) {
+		if (entry != null)
+			entry.setQuantity(STYLE_BUILDER.literalExpression(quantity));
+	}
+
+	/**
+	 * Sorts a {@link ColorMap} according to the value of its entries.
+	 * 
+	 * @param colorMap
+	 *            the color map to sort
+	 */
+	public static ColorMap sortColorMap(ColorMap colorMap) {
+		ColorMap newColorMap = new ColorMapImpl();
+		applyColorMapProperties(colorMap, newColorMap);
+
+		// Put all color map entries in a sorted map (with
+		// collision lists!)
+		SortedMap<Double, Vector<ColorMapEntry>> sortedEntries = new TreeMap<Double, Vector<ColorMapEntry>>();
+		for (ColorMapEntry entry : colorMap.getColorMapEntries()) {
+			double quantity = getQuantityFromColorMapEntry(entry);
+			Vector<ColorMapEntry> collisionList = sortedEntries.get(quantity);
+			if (collisionList == null) {
+				collisionList = new Vector<ColorMapEntry>();
+				sortedEntries.put(quantity, collisionList);
+			}
+			collisionList.add(entry);
+		}
+
+		// According to the order of the sorted map, put all
+		// color map entries to the new ColorMap
+		for (Vector<ColorMapEntry> collisionList : sortedEntries.values())
+			for (ColorMapEntry entry : collisionList)
+				newColorMap.addColorMapEntry(entry);
+
+		return newColorMap;
+	}
+
+	/**
+	 * Converts a {@link StyledLayerDescriptor} or any of it's subcomponents to
+	 * XML
+	 * 
+	 * @throws TransformerException
+	 */
+	public static String toXMLString(Object sld) throws TransformerException {
+		SLDTRANSFORMER.setIndentation(1);
+		return SLDTRANSFORMER.transform(sld);
+	}
 }

Modified: trunk/src_junit/schmitzm/lang/ResourceProviderTest.java
===================================================================
--- trunk/src_junit/schmitzm/lang/ResourceProviderTest.java	2010-10-26 10:00:10 UTC (rev 1173)
+++ trunk/src_junit/schmitzm/lang/ResourceProviderTest.java	2010-10-26 10:00:34 UTC (rev 1174)
@@ -54,6 +54,10 @@
 
 	@Test
 	public void testCreatePropertyFile() {
+		
+		// TODO Martin Schmitzm MS + Stefan Tzeggai
+		
+		// TODO Test schreiben, dass das etwas sinnvolles exportiert.
 		String before = "A\nB\nC";
 		String after = before.replaceAll("\\n", "\\\\n");
 		assertFalse(before.equals(after));



More information about the Schmitzm-commits mailing list