001: /*
002: * uDig - User Friendly Desktop Internet GIS client
003: * http://udig.refractions.net
004: * (C) 2004, Refractions Research Inc.
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: */
017: package net.refractions.udig.style.sld;
018:
019: import java.awt.Color;
020:
021: import net.refractions.udig.ui.graphics.SLDs;
022:
023: import org.geotools.styling.FeatureTypeStyle;
024: import org.geotools.styling.LineSymbolizer;
025: import org.geotools.styling.Rule;
026: import org.geotools.styling.Style;
027: import org.geotools.styling.StyleBuilder;
028: import org.geotools.styling.Symbolizer;
029:
030: /**
031: * A context sensitive SLD content editor.
032: * <p>
033: * This class is intended to be used by a StyleConfigurator providing
034: * SLD style content.
035: * <p>
036: * An SLD style object can contain any number of FeatureTypeStyle objects, which can in turn contain
037: * any number of Rule objects, which can in turn contain any number of Symbolizer objects.
038: * </p>
039: * <p>
040: * Concepts:
041: * <ul>
042: * <li>notion of a default FeatureTypeStyle (with a single rule)
043: * <li>notion of a default Rule
044: * </ul>
045: * This allows Configurators who simply want to add a new symbolizer
046: * to the style to forgo the creation and setup of the style hierarchy.
047: * </p>
048: *
049: * <p>
050: * This class also provides the ability to look up symbolizers by class
051: * against the "default rule".
052: * This allows configurators interested in a particular symbolizer
053: * to 'track' the instance of it as the default rule is changed.
054: * </p>
055: * <h3>Instructions for Subclassing</h3>
056: * <p>
057: * This base implementation works against the "first" rule in the Style.
058: * When providing a SLDConfigurator specific subclass (say for themeing)
059: * you may wish to connect the "defaultRule" up to the current rule.
060: * </p>
061: * <p>
062: * You may also supply context sensitive overrrides for color, simply
063: * override the methods such as color( LineSymbolizer line ) to return
064: * the correct default when a line is null.
065: * </p>
066: *
067: * @author Justin Deoliveira
068: * @since 0.9
069: */
070: public class SLDContentManager {
071:
072: /** the actual SLD style * */
073: private Style style;
074:
075: /** the style builder * */
076: private StyleBuilder styleBuilder;
077:
078: /**
079: * Creates the SLD content manager.
080: */
081: public SLDContentManager() {
082: }
083:
084: /**
085: * Creates the SLD content manager.
086: *
087: * @param styleBuilder The builder object used to create style content.
088: * @param style The SLD style itself.
089: */
090: public SLDContentManager(StyleBuilder styleBuilder, Style style) {
091: init(styleBuilder, style);
092: // styleBuilder = new StyleBuilder(StyleFactory.createStyleFactory());
093: // style = styleBuilder.createStyle();
094: }
095:
096: /**
097: * Initializes the content manager with a new style.
098: *
099: * @param styleBuilder The builder object used to create style content.
100: * @param style The SLD style itself.
101: */
102: public void init(StyleBuilder styleBuilder, Style style) {
103: this .styleBuilder = styleBuilder;
104: this .style = style;
105: }
106:
107: /**
108: * @return Returns the SLD style.
109: */
110: public Style getStyle() {
111: return style;
112: }
113:
114: /**
115: * @return Returns the styleBuilder.
116: */
117: public StyleBuilder getStyleBuilder() {
118: return styleBuilder;
119: }
120:
121: /**
122: * Returns the the first feature type style for the SLD style. The feature type style is created
123: * if it does not exist.
124: *
125: * @return The default (first) feature type style.
126: */
127: public FeatureTypeStyle getDefaultFeatureTypeStyle() {
128: FeatureTypeStyle[] styles = style.getFeatureTypeStyles();
129: if (styles == null || styles.length == 0
130: || styles[0].getRules().length == 0) {
131: // create a feature type style
132: return createFeatureTypeStyle("default"); //$NON-NLS-1$
133: }
134:
135: return styles[0];
136: }
137:
138: /**
139: * Returns a feature type style with specific name, or null if no such feature type style
140: * exists.
141: *
142: * @param name The name of the feature type style.
143: * @return the feature type style identified by name, or null.
144: */
145: public FeatureTypeStyle getFeatureTypeStyle(String name) {
146: FeatureTypeStyle[] styles = style.getFeatureTypeStyles();
147: if (styles == null)
148: return null;
149:
150: for (int i = 0; i < styles.length; i++) {
151: if (styles[i].getName().equals(name))
152: return styles[i];
153: }
154:
155: return null;
156: }
157:
158: /**
159: * @return the first rule in the default feature type style.
160: */
161: public Rule getDefaultRule() {
162: FeatureTypeStyle ftStyle = getDefaultFeatureTypeStyle();
163: if (ftStyle.getRules() == null
164: || ftStyle.getRules().length == 0) {
165: // create an empty rule
166: Rule rule = createRule(ftStyle);
167: return rule;
168: }
169:
170: return ftStyle.getRules()[0];
171: }
172:
173: /**
174: * Creates a new feature type style for the object, and adds it to the style.
175: *
176: * @param name The name of feature type style.
177: * @return The newly created feature type style.
178: */
179: public FeatureTypeStyle createFeatureTypeStyle(String name) {
180: FeatureTypeStyle ftStyle = styleBuilder.createFeatureTypeStyle(
181: name, new Rule[] {});
182: style.addFeatureTypeStyle(ftStyle);
183: return ftStyle;
184: }
185:
186: /**
187: * Creates an empty rule. This method does not associate the rule with the SLD style. The rule
188: * is created with an empty symbolizer list.
189: *
190: * @return The newly created rule.
191: */
192: public Rule createRule() {
193: return styleBuilder.createRule(new Symbolizer[] {});
194: }
195:
196: /**
197: * Creates a new rule for a specific feature type style. The rule is created with an empty
198: * symbolizer list.
199: *
200: * @param ftStyle The feature type style for the rule.
201: * @return The newly created rule.
202: */
203: public Rule createRule(FeatureTypeStyle ftStyle) {
204: Rule rule = createRule();
205: ftStyle.addRule(rule);
206:
207: return rule;
208: }
209:
210: /**
211: * Returns the first symbolizer of a particular class for a rule or none if no such symbolizer
212: * exists.
213: *
214: * @param rule The rule containing the symbolizer to be returned.
215: * @param theClass The typed class of the symbolizer.
216: * @return The symbolizer of type T, or null if none exists.
217: */
218: public <T> T getSymbolizer(Rule rule, Class<T> theClass) {
219: Symbolizer[] symbolizers = rule.getSymbolizers();
220: if (symbolizers == null || theClass == null)
221: return null;
222:
223: for (int i = 0; i < symbolizers.length; i++) {
224: if (symbolizers[i] == null)
225: continue;
226: if (theClass.isAssignableFrom(symbolizers[i].getClass()))
227: return theClass.cast(symbolizers[i]);
228: }
229:
230: return null;
231: }
232:
233: /**
234: * Returns the first symbolizer of a particular class from the default rule or none if no such
235: * symbolizer exists.
236: *
237: * @param theClass The typed class of the symbolizer.
238: * @return The symbolizer of type T, or null if none exists.
239: */
240: public <T extends Symbolizer> T getSymbolizer(Class<T> theClass) {
241: return getSymbolizer(getDefaultRule(), theClass);
242: }
243:
244: /**
245: * Adds a symbolizer to the default rule.
246: *
247: * @param symbolizer The symbolizer to add.
248: */
249: public void addSymbolizer(Symbolizer symbolizer) {
250: addSymbolizer(getDefaultRule(), symbolizer);
251: }
252:
253: /**
254: * Adds a symbolizer to a rule.
255: *
256: * @param rule The rule.
257: * @param symbolizer The symbolizer
258: */
259: public void addSymbolizer(Rule rule, Symbolizer symbolizer) {
260: Symbolizer[] syms = rule.getSymbolizers();
261: if (syms == null) {
262: syms = new Symbolizer[] { symbolizer };
263: } else {
264: Symbolizer[] newSyms = new Symbolizer[syms.length + 1];
265: System.arraycopy(syms, 0, newSyms, 0, syms.length);
266: newSyms[syms.length] = symbolizer;
267: syms = newSyms;
268: }
269:
270: rule.setSymbolizers(syms);
271: }
272:
273: /**
274: * Adds a symbolizer by class.
275: *
276: * @param theClass The class of the symbolizer.
277: */
278: public void addSymbolizer(Class<Symbolizer> theClass) {
279: addSymbolizer(SLD.createDefault(theClass));
280: // if (PointSymbolizer.class.isAssignableFrom(theClass)) {
281: // addSymbolizer(SLDContent.createPointSymbolizer());
282: // }
283: // else if (LineSymbolizer.class.isAssignableFrom(theClass)) {
284: // addSymbolizer(SLDContent.createLineSymbolizer());
285: // }
286: // else if (PolygonSymbolizer.class.isAssignableFrom(theClass)) {
287: // addSymbolizer(SLDContent.createPolygonSymbolizer());
288: // }
289: // else if (TextSymbolizer.class.isAssignableFrom(theClass)) {
290: // addSymbolizer(SLDContent.createTextSymbolizer());
291: // }
292: // else if (RasterSymbolizer.class.isAssignableFrom(theClass)) {
293: // addSymbolizer(SLDContent.createRasterSymbolizer());
294: // }
295: }
296:
297: public void removeSymbolizer(Symbolizer symbolizer) {
298: if (symbolizer == null)
299: return;
300:
301: Symbolizer[] symbolizers = getDefaultRule().getSymbolizers();
302: int i = 0;
303: for (; i < symbolizers.length; i++) {
304: if (symbolizers[i].equals(symbolizer))
305: break;
306: }
307:
308: if (i < symbolizers.length) {
309: Symbolizer[] newSymbolizers = new Symbolizer[symbolizers.length - 1];
310: System.arraycopy(symbolizers, 0, newSymbolizers, 0, i);
311: System.arraycopy(symbolizers, i + 1, newSymbolizers, i,
312: symbolizers.length - (i + 1));
313: getDefaultRule().setSymbolizers(newSymbolizers);
314: }
315: }
316:
317: /**
318: * Removes the first symbolizer of the specified class from the default rule.
319: *
320: * @param theClass The class of the symbolizer.
321: */
322: public void removeSymbolizer(Class<Symbolizer> theClass) {
323: if (theClass == null)
324: return;
325:
326: Symbolizer[] symbolizers = getDefaultRule().getSymbolizers();
327: int i = 0;
328: for (; i < symbolizers.length; i++) {
329: if (theClass.isAssignableFrom(symbolizers[i].getClass()))
330: break;
331: }
332:
333: if (i < symbolizers.length) {
334: Symbolizer[] newSymbolizers = new Symbolizer[symbolizers.length - 1];
335: System.arraycopy(symbolizers, 0, newSymbolizers, 0, i);
336: System.arraycopy(symbolizers, i + 1, newSymbolizers, i,
337: symbolizers.length - (i + 1));
338: getDefaultRule().setSymbolizers(newSymbolizers);
339: }
340: }
341:
342: //
343: // Context (ie "default" rule sensitive access)
344: //
345: public Color color(LineSymbolizer line) {
346: return SLDs.color(line);
347: }
348:
349: public double width(LineSymbolizer line) {
350: return SLDs.lineWidth(line);
351: }
352:
353: public double opacity(LineSymbolizer line) {
354: return SLDs.lineOpacity(line);
355: }
356: }
|