Revision 41397 trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.mapcontext/org.gvsig.fmap.mapcontext.api/src/main/java/org/gvsig/fmap/mapcontext/rendering/symbols/impl/DefaultSymbolManager.java

View differences:

DefaultSymbolManager.java
3 3
 *
4 4
 * Copyright (C) 2007-2013 gvSIG Association.
5 5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10 10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15 15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 19
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
23 22
 */
24 23
/*
25 24
 * AUTHORS (In addition to CIT):
......
41 40
import java.io.FileInputStream;
42 41
import java.io.FileOutputStream;
43 42
import java.io.IOException;
43
import java.util.ArrayList;
44 44
import java.util.Arrays;
45
import java.util.Collection;
45 46
import java.util.Collections;
46 47
import java.util.Comparator;
47 48
import java.util.HashMap;
49
import java.util.List;
48 50
import java.util.Map;
49 51
import java.util.Random;
50

  
52
import org.apache.commons.io.FileUtils;
53
import org.apache.commons.io.FilenameUtils;
54
import org.apache.commons.io.filefilter.FileFilterUtils;
55
import org.apache.commons.lang3.StringUtils;
51 56
import org.gvsig.fmap.mapcontext.MapContextRuntimeException;
52 57
import org.gvsig.fmap.mapcontext.impl.InvalidRegisteredClassException;
53 58
import org.gvsig.fmap.mapcontext.impl.RegisteredClassInstantiationException;
54 59
import org.gvsig.fmap.mapcontext.rendering.symbols.IMultiLayerSymbol;
55 60
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
61
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol_v2;
56 62
import org.gvsig.fmap.mapcontext.rendering.symbols.IWarningSymbol;
57 63
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolException;
58 64
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbolManager;
......
73 79

  
74 80
/**
75 81
 * Default {@link SymbolManager} implementation.
76
 * 
82
 *
77 83
 * @author gvSIG team
78 84
 */
79 85
public class DefaultSymbolManager implements SymbolManager {
80 86

  
81
	private static final Logger logger = LoggerFactory.getLogger(DefaultSymbolManager.class);
82
	
83
	private SymbolPreferences symbolPreferences =
84
			new DefaultSymbolPreferences();
87
    private static final Logger logger = LoggerFactory.getLogger(DefaultSymbolManager.class);
85 88

  
86
	private Map symbolsByName = Collections.synchronizedMap(new HashMap());
89
    private SymbolPreferences symbolPreferences
90
            = new DefaultSymbolPreferences();
87 91

  
88
	private Map symbolsByShapeType = Collections.synchronizedMap(new HashMap());
92
    private Map symbolsByName = Collections.synchronizedMap(new HashMap());
89 93

  
90
	private Map multiLineSymbolsByName =
91
			Collections.synchronizedMap(new HashMap());
94
    private Map symbolsByShapeType = Collections.synchronizedMap(new HashMap());
92 95

  
93
	private Map multiLineSymbolsByShapeType =
94
			Collections.synchronizedMap(new HashMap());
96
    private Map multiLineSymbolsByName
97
            = Collections.synchronizedMap(new HashMap());
95 98

  
96
	private IWarningSymbol warningSymbol;
99
    private Map multiLineSymbolsByShapeType
100
            = Collections.synchronizedMap(new HashMap());
97 101

  
98
	private Object warningSymbolLock = new Object();
102
    private IWarningSymbol warningSymbol;
99 103

  
100
	public ISymbol[] loadSymbols(File folder) throws SymbolException {
101
		return loadSymbols(folder, null);
102
	}
104
    private Object warningSymbolLock = new Object();
103 105

  
104
	public ISymbol[] loadSymbols(File folder, FileFilter fileFilter)
105
			throws SymbolException {
106
		// TODO: add symbol caching
106
    public ISymbol[] loadSymbols(File folder) throws SymbolException {
107
        return loadSymbols(folder, null);
108
    }
107 109

  
108
		if (folder.exists()) {
110
    public ISymbol[] loadSymbols(File folder, FileFilter fileFilter)
111
            throws SymbolException {
112
        // TODO: add symbol caching
109 113

  
110
			File[] symbolFiles = null;
111
			if (fileFilter == null) {
112
				symbolFiles = folder.listFiles();
113
			} else {
114
				symbolFiles = folder.listFiles(fileFilter);
115
			}
114
        if (folder.exists()) {
116 115

  
117
			if (symbolFiles != null) {
118
			    TaskStatusManager tm = ToolsLocator.getTaskStatusManager();
119
			    SimpleTaskStatus status = tm.createDefaultSimpleTaskStatus("Load symbols");
120
			    status.setRangeOfValues(0, symbolFiles.length);
121
			    status.setAutoremove(true);
122
			    status.add();
123
			    
124
			    /*
125
			     * Sorting by file name before loading.
126
			     * The problem here is that some
127
			     * descriptions can be empty, so sorting using description
128
			     * can have strange behavior. Sorting by file name is not
129
			     * very elegant, though.
130
			     */
116
            File[] symbolFiles = null;
117
            if (fileFilter == null) {
118
                symbolFiles = folder.listFiles();
119
            } else {
120
                symbolFiles = folder.listFiles(fileFilter);
121
            }
122

  
123
            if (symbolFiles != null) {
124
                TaskStatusManager tm = ToolsLocator.getTaskStatusManager();
125
                SimpleTaskStatus status = tm.createDefaultSimpleTaskStatus("Load symbols");
126
                status.setRangeOfValues(0, symbolFiles.length);
127
                status.setAutoremove(true);
128
                status.add();
129

  
130
                /*
131
                 * Sorting by file name before loading.
132
                 * The problem here is that some
133
                 * descriptions can be empty, so sorting using description
134
                 * can have strange behavior. Sorting by file name is not
135
                 * very elegant, though.
136
                 */
131 137
                status.message("sorting symbols");
132
				Arrays.sort(symbolFiles, new Comparator() {
133
					public int compare( Object o1, Object o2) {
134
						File f1 = (File) o1;
135
						File f2 = (File) o2;
136
						return f1.getName().compareTo(f2.getName());
137
					}
138
				});
138
                Arrays.sort(symbolFiles, new Comparator() {
139
                    public int compare(Object o1, Object o2) {
140
                        File f1 = (File) o1;
141
                        File f2 = (File) o2;
142
                        return f1.getName().compareTo(f2.getName());
143
                    }
144
                });
139 145

  
140
			    ISymbol[] symbols = null;
141
			    try {
142
	                symbols = new ISymbol[symbolFiles.length];
143
	                for (int i = 0; i < symbolFiles.length; i++) {
144
	                    status.setCurValue(i);
145
	                    symbols[i] = loadSymbol(symbolFiles[i]);
146
	                    
147
	                }
146
                ISymbol[] symbols = null;
147
                try {
148
                    symbols = new ISymbol[symbolFiles.length];
149
                    for (int i = 0; i < symbolFiles.length; i++) {
150
                        status.setCurValue(i);
151
                        symbols[i] = loadSymbol(symbolFiles[i]);
148 152

  
149
			    } finally {
150
			        status.terminate();
151
			    }
152
				return symbols;
153
			}
154
		}
153
                    }
155 154

  
156
		return null;
157
	}
155
                } finally {
156
                    status.terminate();
157
                }
158
                return symbols;
159
            }
160
        }
158 161

  
159
	public class SymbolsLoaderTask extends AbstractMonitorableTask {
160
	
161
		private File folder;
162
		private FileFilter filter;
163
		private Visitor visitor;
162
        return null;
163
    }
164 164

  
165
		public SymbolsLoaderTask(File folder, FileFilter filter, Visitor visitor) {
166
			super("Load symbols", true);
167
			this.folder = folder; 
168
			this.filter = filter;
169
			this.visitor = visitor;
170
			if( folder == null ) {
171
				throw new IllegalArgumentException("folder is null");
172
			}
173
			if( visitor == null ) {
174
				throw new IllegalArgumentException("visitor is null");
175
			}
176
		}
177
		
178
		private File[] getFiles() {
179
			if (filter == null) {
180
				return folder.listFiles();
181
			} else {
182
				return folder.listFiles(filter);
183
			}
184
		}
165
    public class SymbolsLoaderTask extends AbstractMonitorableTask {
185 166

  
186
		private String getVisitorName() {
187
			String s = visitor.toString() + "/" + visitor.getClass().getName();
188
			return s;
189
		}
190
		
191
		private void visit(final File file, final ISymbol symbol) throws VisitCanceledException {
192
			try {
193
				visitor.visit(symbol);
194
			} catch (BaseException e) {
195
				logger.warn("Can't call visit '"+getVisitorName()+"' to offer the symbol '"+file.getAbsolutePath()+"'.",e);
196
			}
197
		}
198
		
199
		public void run() {
200
			// TODO: add symbol caching
201
			try {
202
				logger.info("[SymbolsLoaderTask"+this.getId()+"] process initited.");
203
				if (folder.exists()) {
204
					taskStatus.setAutoremove(true);
205
					taskStatus.message("preparing");
206
					File[] symbolFiles = getFiles();
167
        private File folder;
168
        private FileFilter filter;
169
        private Visitor visitor;
207 170

  
208
					if (symbolFiles != null) {
209
						taskStatus.setRangeOfValues(0, symbolFiles.length);
171
        public SymbolsLoaderTask(File folder, FileFilter filter, Visitor visitor) {
172
            super("Load symbols", true);
173
            this.folder = folder;
174
            this.filter = filter;
175
            this.visitor = visitor;
176
            if (folder == null) {
177
                throw new IllegalArgumentException("folder is null");
178
            }
179
            if (visitor == null) {
180
                throw new IllegalArgumentException("visitor is null");
181
            }
182
        }
210 183

  
211
						/*
212
						 * Sorting by file name before loading. The problem here
213
						 * is that some descriptions can be empty, so sorting
214
						 * using description can have strange behavior. Sorting
215
						 * by file name is not very elegant, though.
216
						 */
217
						taskStatus.message("sorting");
218
						Arrays.sort(symbolFiles, new Comparator() {
219
							public int compare(Object o1, Object o2) {
220
								File f1 = (File) o1;
221
								File f2 = (File) o2;
222
								return f1.getName().compareTo(f2.getName());
223
							}
224
						});
184
        private File[] getFiles() {
185
            if (filter == null) {
186
                return folder.listFiles();
187
            } else {
188
                return folder.listFiles(filter);
189
            }
190
        }
225 191

  
226
						taskStatus.message("loading");
227
						for (int i = 0; i < symbolFiles.length; i++) {
228
							taskStatus.setCurValue(i);
229
							if( taskStatus.isCancellationRequested() ) {
230
								logger.info("[SymbolsLoaderTask"+this.getId()+"] process canceled.");
231
								break;
232
							}
233
							ISymbol symbol = null;
234
							try {
235
								symbol = loadSymbol(symbolFiles[i]);
236
								visit(symbolFiles[i], symbol);
237
							} catch (VisitCanceledException e) {
238
								break;
239
							} catch (SymbolException e) {
240
								logger.warn("Can't load symbol '"
241
										+ symbolFiles[i].getAbsolutePath()
242
										+ "'.", e);
243
							}
244
						}
245
						taskStatus.message("");
192
        private String getVisitorName() {
193
            String s = visitor.toString() + "/" + visitor.getClass().getName();
194
            return s;
195
        }
246 196

  
247
					}
248
				}
197
        private void visit(final File file, final ISymbol symbol) throws VisitCanceledException {
198
            try {
199
                visitor.visit(symbol);
200
            } catch (BaseException e) {
201
                logger.warn("Can't call visit '" + getVisitorName() + "' to offer the symbol '" + file.getAbsolutePath() + "'.", e);
202
            }
203
        }
249 204

  
250
			} finally {
251
				taskStatus.terminate();
252
			}
253
			logger.info("[SymbolsLoaderTask"+this.getId()+"] process terminated.");
205
        public void run() {
206
            // TODO: add symbol caching
207
            try {
208
                logger.info("[SymbolsLoaderTask" + this.getId() + "] process initited.");
209
                if (folder.exists()) {
210
                    taskStatus.setAutoremove(true);
211
                    taskStatus.message("preparing");
212
                    File[] symbolFiles = getFiles();
254 213

  
255
		}
256
	}
257
	
258
	public CancellableTask loadSymbols(File folder, FileFilter filter, Visitor visitor) {
259
		SymbolsLoaderTask task = new SymbolsLoaderTask(folder, filter, visitor);
260
		task.start();
261
		return task;
262
	}
214
                    if (symbolFiles != null) {
215
                        taskStatus.setRangeOfValues(0, symbolFiles.length);
263 216

  
264
	public void saveSymbol(ISymbol symbol, String fileName, File folder)
265
			throws SymbolException {
266
		saveSymbol(symbol, fileName, folder, false);
267
	}
217
                        /*
218
                         * Sorting by file name before loading. The problem here
219
                         * is that some descriptions can be empty, so sorting
220
                         * using description can have strange behavior. Sorting
221
                         * by file name is not very elegant, though.
222
                         */
223
                        taskStatus.message("sorting");
224
                        Arrays.sort(symbolFiles, new Comparator() {
225
                            public int compare(Object o1, Object o2) {
226
                                File f1 = (File) o1;
227
                                File f2 = (File) o2;
228
                                return f1.getName().compareTo(f2.getName());
229
                            }
230
                        });
268 231

  
269
	public void saveSymbol(ISymbol symbol, String fileName, File folder,
270
			boolean overwrite) throws SymbolException {
271
		// TODO: add symbol caching
232
                        taskStatus.message("loading");
233
                        for (int i = 0; i < symbolFiles.length; i++) {
234
                            taskStatus.setCurValue(i);
235
                            if (taskStatus.isCancellationRequested()) {
236
                                logger.info("[SymbolsLoaderTask" + this.getId() + "] process canceled.");
237
                                break;
238
                            }
239
                            ISymbol symbol = null;
240
                            try {
241
                                symbol = loadSymbol(symbolFiles[i]);
242
                                visit(symbolFiles[i], symbol);
243
                            } catch (VisitCanceledException e) {
244
                                break;
245
                            } catch (SymbolException e) {
246
                                logger.warn("Can't load symbol '"
247
                                        + symbolFiles[i].getAbsolutePath()
248
                                        + "'.", e);
249
                            }
250
                        }
251
                        taskStatus.message("");
272 252

  
273
		PersistenceManager persistenceManager = ToolsLocator
274
				.getPersistenceManager();
253
                    }
254
                }
275 255

  
276
		File symbolFile = new File(folder, fileName);
277
		if (!overwrite && symbolFile.exists()) {
278
			throw new SymbolFileAlreadyExistsException(symbolFile);
279
		}
256
            } finally {
257
                taskStatus.terminate();
258
            }
259
            logger.info("[SymbolsLoaderTask" + this.getId() + "] process terminated.");
280 260

  
281
		try {
282
			FileOutputStream fos = new FileOutputStream(symbolFile);
261
        }
262
    }
283 263

  
284
			persistenceManager.saveState(persistenceManager.getState(symbol),
285
					fos);
264
    public CancellableTask loadSymbols(File folder, FileFilter filter, Visitor visitor) {
265
        SymbolsLoaderTask task = new SymbolsLoaderTask(folder, filter, visitor);
266
        task.start();
267
        return task;
268
    }
286 269

  
287
			fos.flush();
288
			fos.close();
289
		} catch (PersistenceException e) {
290
			throw new SaveSymbolException(e);
291
		} catch (IOException e) {
292
			throw new SaveSymbolException(e);
293
		}
294
	}
270
    public void saveSymbol(ISymbol symbol, String fileName, File folder)
271
            throws SymbolException {
272
        saveSymbol(symbol, fileName, folder, false);
295 273

  
296
	/**
297
	 * Loads a persisted symbol from the given file.
298
	 */
299
	private ISymbol loadSymbol(File file) throws SymbolException {
300
		if (file.exists()) {
301
			try {
302
				FileInputStream fis = new FileInputStream(file);
274
    }
303 275

  
304
				PersistenceManager persistenceManager = ToolsLocator
305
						.getPersistenceManager();
276
    public void saveSymbol(ISymbol symbol, String fileName, File folder,
277
            boolean overwrite) throws SymbolException {
278
        // TODO: add symbol caching
306 279

  
307
				PersistentState state = persistenceManager.loadState(fis);
308
				ISymbol symbol = (ISymbol) persistenceManager.create(state);
280
        PersistenceManager persistenceManager = ToolsLocator
281
                .getPersistenceManager();
309 282

  
310
				fis.close();
311
				return symbol;
312
			} catch (PersistenceException e) {
313
				throw new LoadSymbolException(e);
314
			} catch (IOException e) {
315
				throw new LoadSymbolException(e);
316
			}
317
		}
283
        File symbolFile = new File(folder, fileName);
284
        if (!overwrite && symbolFile.exists()) {
285
            throw new SymbolFileAlreadyExistsException(symbolFile);
286
        }
318 287

  
319
		return null;
320
	}
288
        try {
289
            FileOutputStream fos = new FileOutputStream(symbolFile);
321 290

  
322
	public SymbolPreferences getSymbolPreferences() {
323
		return symbolPreferences;
324
	}
291
            persistenceManager.saveState(persistenceManager.getState(symbol),
292
                    fos);
325 293

  
326
	public ISymbol createSymbol(String symbolName)
327
			throws MapContextRuntimeException {
328
		return createSymbol(symbolName, (Class) symbolsByName.get(symbolName),
329
				ISymbol.class);
330
	}
294
            fos.flush();
295
            fos.close();
296
        } catch (PersistenceException e) {
297
            throw new SaveSymbolException(e);
298
        } catch (IOException e) {
299
            throw new SaveSymbolException(e);
300
        }
301
        if (symbol instanceof ISymbol_v2) {
302
            ISymbol_v2 symbolv2 = (ISymbol_v2) symbol;
303
            if (StringUtils.isBlank(symbolv2.getID())) {
304
                symbolv2.setID(FilenameUtils.getBaseName(fileName));
305
            }
306
        }
307
    }
331 308

  
332
	public ISymbol createSymbol(int shapeType)
333
			throws MapContextRuntimeException {
334
		String symbolName =
335
				(String) symbolsByShapeType.get(new Integer(shapeType));
309
    /**
310
     * Loads a persisted symbol from the given file.
311
     */
312
    private ISymbol loadSymbol(File file) throws SymbolException {
313
        if (file.exists()) {
314
            try {
315
                FileInputStream fis = new FileInputStream(file);
336 316

  
337
		return symbolName == null ? null : createSymbol(symbolName);
338
	}
317
                PersistenceManager persistenceManager = ToolsLocator
318
                        .getPersistenceManager();
339 319

  
340
	public ISymbol createSymbol(String symbolName, Color color)
341
			throws MapContextRuntimeException {
342
		ISymbol symbol = createSymbol(symbolName);
320
                PersistentState state = persistenceManager.loadState(fis);
321
                ISymbol symbol = (ISymbol) persistenceManager.create(state);
343 322

  
344
		if (symbol != null) {
345
			symbol.setColor(color);
346
		}
323
                fis.close();
324
                if (symbol instanceof ISymbol_v2) {
325
                    ISymbol_v2 symbolv2 = (ISymbol_v2) symbol;
326
                    symbolv2.setID(FilenameUtils.getBaseName(file.getName()));
327
                }
328
                return symbol;
329
            } catch (PersistenceException e) {
330
                throw new LoadSymbolException(e);
331
            } catch (IOException e) {
332
                throw new LoadSymbolException(e);
333
            }
334
        }
347 335

  
348
		return symbol;
349
	}
336
        return null;
337
    }
350 338

  
351
	public ISymbol createSymbol(int shapeType, Color color)
352
			throws MapContextRuntimeException {
353
		String symbolName =
354
				(String) symbolsByShapeType.get(new Integer(shapeType));
339
    public SymbolPreferences getSymbolPreferences() {
340
        return symbolPreferences;
341
    }
355 342

  
356
		return symbolName == null ? null : createSymbol(symbolName, color);
357
	}
343
    public ISymbol createSymbol(String symbolName)
344
            throws MapContextRuntimeException {
345
        return createSymbol(symbolName, (Class) symbolsByName.get(symbolName),
346
                ISymbol.class);
347
    }
358 348

  
359
	public IMultiLayerSymbol createMultiLayerSymbol(String symbolName)
360
			throws MapContextRuntimeException {
361
		return (IMultiLayerSymbol) createSymbol(symbolName,
362
				(Class) multiLineSymbolsByName.get(symbolName),
363
				IMultiLayerSymbol.class);
364
	}
349
    public ISymbol createSymbol(int shapeType)
350
            throws MapContextRuntimeException {
351
        String symbolName
352
                = (String) symbolsByShapeType.get(new Integer(shapeType));
365 353

  
366
	public IMultiLayerSymbol createMultiLayerSymbol(int shapeType)
367
			throws MapContextRuntimeException {
368
		String symbolName =
369
				(String) multiLineSymbolsByShapeType.get(new Integer(shapeType));
354
        return symbolName == null ? null : createSymbol(symbolName);
355
    }
370 356

  
371
		return symbolName == null ? null : createMultiLayerSymbol(symbolName);
372
	}
357
    public ISymbol createSymbol(String symbolName, Color color)
358
            throws MapContextRuntimeException {
359
        ISymbol symbol = createSymbol(symbolName);
373 360

  
374
	public void registerSymbol(String symbolName, Class symbolClass)
375
			throws MapContextRuntimeException {
376
		if (symbolClass == null || !ISymbol.class.isAssignableFrom(symbolClass)) {
377
			throw new InvalidRegisteredClassException(ISymbol.class,
378
					symbolClass, symbolName);
379
		}
380
		symbolsByName.put(symbolName, symbolClass);
381
	}
361
        if (symbol != null) {
362
            symbol.setColor(color);
363
        }
382 364

  
383
	public void registerSymbol(String symbolName, int[] shapeTypes,
384
			Class symbolClass) throws MapContextRuntimeException {
385
		registerSymbol(symbolName, symbolClass);
386
		if (shapeTypes != null) {
387
			for (int i = 0; i < shapeTypes.length; i++) {
388
				symbolsByShapeType.put(new Integer(shapeTypes[i]), symbolName);
389
			}
390
		}
391
	}
365
        return symbol;
366
    }
392 367

  
393
	public void registerMultiLayerSymbol(String symbolName, Class symbolClass)
394
			throws MapContextRuntimeException {
395
		if (symbolClass == null
396
				|| !IMultiLayerSymbol.class.isAssignableFrom(symbolClass)) {
397
			throw new InvalidRegisteredClassException(IMultiLayerSymbol.class,
398
					symbolClass, symbolName);
399
		}
368
    public ISymbol createSymbol(int shapeType, Color color)
369
            throws MapContextRuntimeException {
370
        String symbolName
371
                = (String) symbolsByShapeType.get(new Integer(shapeType));
400 372

  
401
		multiLineSymbolsByName.put(symbolName, symbolClass);
402
	}
373
        return symbolName == null ? null : createSymbol(symbolName, color);
374
    }
403 375

  
404
	public void registerMultiLayerSymbol(String symbolName, int[] shapeTypes,
405
			Class symbolClass) throws MapContextRuntimeException {
406
		registerMultiLayerSymbol(symbolName, symbolClass);
407
		if (shapeTypes != null) {
408
			for (int i = 0; i < shapeTypes.length; i++) {
409
				multiLineSymbolsByShapeType.put(new Integer(shapeTypes[i]),
410
						symbolName);
411
			}
412
		}
413
	}
376
    public IMultiLayerSymbol createMultiLayerSymbol(String symbolName)
377
            throws MapContextRuntimeException {
378
        return (IMultiLayerSymbol) createSymbol(symbolName,
379
                (Class) multiLineSymbolsByName.get(symbolName),
380
                IMultiLayerSymbol.class);
381
    }
414 382

  
415
	public IWarningSymbol getWarningSymbol(String message, String symbolDesc,
416
			int symbolDrawExceptionType) throws MapContextRuntimeException {
417
		synchronized (warningSymbolLock) {
418
			if (warningSymbol == null) {
419
				warningSymbol = (IWarningSymbol) createSymbol("warning");
420
			}
421
		}
383
    public IMultiLayerSymbol createMultiLayerSymbol(int shapeType)
384
            throws MapContextRuntimeException {
385
        String symbolName
386
                = (String) multiLineSymbolsByShapeType.get(new Integer(shapeType));
422 387

  
423
		// TODO: set those values as parameter values in the draw method.
424
		warningSymbol.setDescription(symbolDesc);
425
		warningSymbol.setMessage(message);
426
		warningSymbol.setDrawExceptionType(symbolDrawExceptionType);
388
        return symbolName == null ? null : createMultiLayerSymbol(symbolName);
389
    }
427 390

  
428
		return warningSymbol;
429
	}
391
    public void registerSymbol(String symbolName, Class symbolClass)
392
            throws MapContextRuntimeException {
393
        if (symbolClass == null || !ISymbol.class.isAssignableFrom(symbolClass)) {
394
            throw new InvalidRegisteredClassException(ISymbol.class,
395
                    symbolClass, symbolName);
396
        }
397
        symbolsByName.put(symbolName, symbolClass);
398
    }
430 399

  
431
	private ISymbol createSymbol(String symbolName, Class symbolClass,
432
			Class expectedType) throws MapContextRuntimeException {
433
		ISymbol symbol;
434
		try {
435
			symbol =
436
					(ISymbol) (symbolClass == null ? null
437
							: symbolClass.newInstance());
438
		} catch (InstantiationException e) {
439
			throw new RegisteredClassInstantiationException(expectedType,
440
					symbolClass, symbolName, e);
441
		} catch (IllegalAccessException e) {
442
			throw new RegisteredClassInstantiationException(expectedType,
443
					symbolClass, symbolName, e);
444
		}
400
    public void registerSymbol(String symbolName, int[] shapeTypes,
401
            Class symbolClass) throws MapContextRuntimeException {
402
        registerSymbol(symbolName, symbolClass);
403
        if (shapeTypes != null) {
404
            for (int i = 0; i < shapeTypes.length; i++) {
405
                symbolsByShapeType.put(new Integer(shapeTypes[i]), symbolName);
406
            }
407
        }
408
    }
445 409

  
446
		Color the_color = null;
447
		
410
    public void registerMultiLayerSymbol(String symbolName, Class symbolClass)
411
            throws MapContextRuntimeException {
412
        if (symbolClass == null
413
                || !IMultiLayerSymbol.class.isAssignableFrom(symbolClass)) {
414
            throw new InvalidRegisteredClassException(IMultiLayerSymbol.class,
415
                    symbolClass, symbolName);
416
        }
417

  
418
        multiLineSymbolsByName.put(symbolName, symbolClass);
419
    }
420

  
421
    public void registerMultiLayerSymbol(String symbolName, int[] shapeTypes,
422
            Class symbolClass) throws MapContextRuntimeException {
423
        registerMultiLayerSymbol(symbolName, symbolClass);
424
        if (shapeTypes != null) {
425
            for (int i = 0; i < shapeTypes.length; i++) {
426
                multiLineSymbolsByShapeType.put(new Integer(shapeTypes[i]),
427
                        symbolName);
428
            }
429
        }
430
    }
431

  
432
    public IWarningSymbol getWarningSymbol(String message, String symbolDesc,
433
            int symbolDrawExceptionType) throws MapContextRuntimeException {
434
        synchronized (warningSymbolLock) {
435
            if (warningSymbol == null) {
436
                warningSymbol = (IWarningSymbol) createSymbol("warning");
437
            }
438
        }
439

  
440
        // TODO: set those values as parameter values in the draw method.
441
        warningSymbol.setDescription(symbolDesc);
442
        warningSymbol.setMessage(message);
443
        warningSymbol.setDrawExceptionType(symbolDrawExceptionType);
444

  
445
        return warningSymbol;
446
    }
447

  
448
    private ISymbol createSymbol(String symbolName, Class symbolClass,
449
            Class expectedType) throws MapContextRuntimeException {
450
        ISymbol symbol;
451
        try {
452
            symbol
453
                    = (ISymbol) (symbolClass == null ? null
454
                    : symbolClass.newInstance());
455
        } catch (InstantiationException e) {
456
            throw new RegisteredClassInstantiationException(expectedType,
457
                    symbolClass, symbolName, e);
458
        } catch (IllegalAccessException e) {
459
            throw new RegisteredClassInstantiationException(expectedType,
460
                    symbolClass, symbolName, e);
461
        }
462

  
463
        Color the_color = null;
464

  
448 465
        if (getSymbolPreferences().isDefaultSymbolFillColorAleatory()) {
449
            
466

  
450 467
            the_color = getRandomBrewerBasedColor();
451
            
468

  
452 469
        } else {
453 470
            // not random
454 471
            the_color = getSymbolPreferences().getDefaultSymbolFillColor();
455 472
        }
456 473
        symbol.setColor(the_color);
457
		// Perform this initialization into the Symbol implementation
458
		// if (symbol instanceof CartographicSupport) {
459
		// CartographicSupport cs = (CartographicSupport) symbol;
460
		// cs.setUnit(getDefaultCartographicSupportMeasureUnit());
461
		// cs
462
		// .setReferenceSystem(getDefaultCartographicSupportReferenceSystem();
463
		// }
474
        // Perform this initialization into the Symbol implementation
475
        // if (symbol instanceof CartographicSupport) {
476
        // CartographicSupport cs = (CartographicSupport) symbol;
477
        // cs.setUnit(getDefaultCartographicSupportMeasureUnit());
478
        // cs
479
        // .setReferenceSystem(getDefaultCartographicSupportReferenceSystem();
480
        // }
464 481

  
465
		return symbol;
466
	}
467
	
468
	public void setSymbolPreferences(SymbolPreferences symbolPreferences) {
469
		this.symbolPreferences = symbolPreferences;
470
	}
471
	
472
	/**
473
	 * 
474
	 * @param col
475
	 * @return color 1/3 closer to black
476
	 */
477
	public static Color darker(Color col) {
478
	    return new Color(
479
	        (2 * col.getRed()) / 3,
480
	        (2 * col.getGreen()) / 3,
481
	        (2 * col.getBlue()) / 3,
482
	        col.getAlpha());
483
	}
482
        return symbol;
483
    }
484 484

  
485
	/**
486
	 * 
487
	 * @param col
488
	 * @return color 1/3 closer to white
489
	 */
490
	public static Color lighter(Color col) {
491
	    Color resp = invert(col);
492
	    resp = darker(resp);
493
	    return invert(resp);
494
	}
495
	
496
	/**
497
	 * 
498
	 * @param col
499
	 * @return inverted color (inverts each band, same alpha)
500
	 */
501
	public static Color invert(Color col) {
485
    public void setSymbolPreferences(SymbolPreferences symbolPreferences) {
486
        this.symbolPreferences = symbolPreferences;
487
    }
488

  
489
    public List getSymbolLibraryNames() {
490
        File rootfolder = new File(this.getSymbolPreferences().getSymbolLibraryPath());
491
        Collection libraries = FileUtils.listFiles(rootfolder, FileFilterUtils.directoryFileFilter(), null);
492
        List l = new ArrayList();
493
        l.addAll(libraries);
494
        return l;
495
    }
496

  
497
    public ISymbol getSymbol(String libraryName, String symbolID) throws SymbolException {
498
        File rootfolder = new File(this.getSymbolPreferences().getSymbolLibraryPath());
499
        Collection symbols = FileUtils.listFiles(rootfolder,
500
                FileFilterUtils.nameFileFilter(symbolID + getSymbolPreferences().getSymbolFileExtension()),
501
                FileFilterUtils.trueFileFilter()
502
        );
503
        if (symbols == null) {
504
            return null;
505
        }
506
        if (symbols.isEmpty()) {
507
            return null;
508
        }
509

  
510
        File f = (File) symbols.iterator().next();
511
        ISymbol symbol = loadSymbol(f);
512
        return symbol;
513
    }
514

  
515
    /**
516
     *
517
     * @param col
518
     * @return color 1/3 closer to black
519
     */
520
    public static Color darker(Color col) {
502 521
        return new Color(
503
            255 - col.getRed(),
504
            255 - col.getGreen(),
505
            255 - col.getBlue(),
506
            col.getAlpha());
507
	}
508
	
509
	private static Color getRandomBrewerBasedColor() {
510
	    
511
	    int ind = rnd.nextInt(BREWER_COLOR.length);
512
	    Color resp = BREWER_COLOR[ind]; 
513
	    ind = rnd.nextInt(100);
514
	    if (ind > 66) {
515
	        resp = darker(resp);
516
	    } else {
517
	        if (ind > 33) {
518
	            resp = lighter(resp);
519
	        }
520
	        // ...else resp remains the same
521
	    }
522
	    
523
	    // finally add some dark noise 
524
	    resp = addDarkNoise(resp);
525
	    return resp;
526
	}
527
	
522
                (2 * col.getRed()) / 3,
523
                (2 * col.getGreen()) / 3,
524
                (2 * col.getBlue()) / 3,
525
                col.getAlpha());
526
    }
527

  
528
    /**
529
     *
530
     * @param col
531
     * @return color 1/3 closer to white
532
     */
533
    public static Color lighter(Color col) {
534
        Color resp = invert(col);
535
        resp = darker(resp);
536
        return invert(resp);
537
    }
538

  
539
    /**
540
     *
541
     * @param col
542
     * @return inverted color (inverts each band, same alpha)
543
     */
544
    public static Color invert(Color col) {
545
        return new Color(
546
                255 - col.getRed(),
547
                255 - col.getGreen(),
548
                255 - col.getBlue(),
549
                col.getAlpha());
550
    }
551

  
552
    private static Color getRandomBrewerBasedColor() {
553

  
554
        int ind = rnd.nextInt(BREWER_COLOR.length);
555
        Color resp = BREWER_COLOR[ind];
556
        ind = rnd.nextInt(100);
557
        if (ind > 66) {
558
            resp = darker(resp);
559
        } else {
560
            if (ind > 33) {
561
                resp = lighter(resp);
562
            }
563
            // ...else resp remains the same
564
        }
565

  
566
        // finally add some dark noise 
567
        resp = addDarkNoise(resp);
568
        return resp;
569
    }
570

  
528 571
    private static Color addDarkNoise(Color c) {
529 572
        int r = Math.max(0, c.getRed() - rnd.nextInt(30));
530 573
        int g = Math.max(0, c.getGreen() - rnd.nextInt(30));
......
534 577

  
535 578
    private static Color[] BREWER_COLOR = new Color[36];
536 579
    private static final Random rnd = new Random();
537
	
538
	static {
539
	    /**
540
	     * Colors from www.ColorBrewer.org by Cynthia A. Brewer,
541
	     * Geography, Pennsylvania State University.
542
	     *
543
	     * Using groups of 4 colors from the 9 Diverging Schemes
544
	     * 4 * 9 = 36 colors
545
	     */
546
	    BREWER_COLOR[0] = new Color(230, 97, 1);
547
	    BREWER_COLOR[1] = new Color(253, 184, 99);
548
	    BREWER_COLOR[2] = new Color(178, 171, 210);
549
	    BREWER_COLOR[3] = new Color(94, 60, 153);
550
	    BREWER_COLOR[4] = new Color(166, 97, 26);
551
	    BREWER_COLOR[5] = new Color(223, 194, 125);
552
	    BREWER_COLOR[6] = new Color(128, 205, 193);
553
	    BREWER_COLOR[7] = new Color(1, 133, 113);
554
	    BREWER_COLOR[8] = new Color(123, 50, 148);
555
	    BREWER_COLOR[9] = new Color(194, 165, 207);
556
	    BREWER_COLOR[10] = new Color(166, 219, 160);
557
	    BREWER_COLOR[11] = new Color(0, 136, 55);
558
	    BREWER_COLOR[12] = new Color(208, 28, 139);
559
	    BREWER_COLOR[13] = new Color(241, 182, 218);
560
	    BREWER_COLOR[14] = new Color(184, 225, 134);
561
	    BREWER_COLOR[15] = new Color(77, 172, 38);
562
	    BREWER_COLOR[16] = new Color(202, 0, 32);
563
	    BREWER_COLOR[17] = new Color(244, 165, 130);
564
	    BREWER_COLOR[18] = new Color(146, 197, 222);
565
	    BREWER_COLOR[19] = new Color(5, 113, 176);
566
	    BREWER_COLOR[20] = new Color(202, 0, 32);
567
	    BREWER_COLOR[21] = new Color(244, 165, 130);
568
	    BREWER_COLOR[22] = new Color(186, 186, 186);
569
	    BREWER_COLOR[23] = new Color(64, 64, 64);
570
	    BREWER_COLOR[24] = new Color(215, 25, 28);
571
	    BREWER_COLOR[25] = new Color(253, 174, 97);
572
	    BREWER_COLOR[26] = new Color(171, 217, 233);
573
	    BREWER_COLOR[27] = new Color(44, 123, 182);
574
	    BREWER_COLOR[28] = new Color(215, 25, 28);
575
	    BREWER_COLOR[29] = new Color(253, 174, 97);
576
	    BREWER_COLOR[30] = new Color(171, 221, 164);
577
	    BREWER_COLOR[31] = new Color(43, 131, 186);
578
	    BREWER_COLOR[32] = new Color(215, 25, 28);
579
	    BREWER_COLOR[33] = new Color(253, 174, 97);
580
	    BREWER_COLOR[34] = new Color(166, 217, 106);
581
	    BREWER_COLOR[35] = new Color(26, 150, 65);
582
	}
583 580

  
584
	
585
}
581
    static {
582
        /**
583
         * Colors from www.ColorBrewer.org by Cynthia A. Brewer, Geography,
584
         * Pennsylvania State University.
585
         *
586
         * Using groups of 4 colors from the 9 Diverging Schemes 4 * 9 = 36
587
         * colors
588
         */
589
        BREWER_COLOR[0] = new Color(230, 97, 1);
590
        BREWER_COLOR[1] = new Color(253, 184, 99);
591
        BREWER_COLOR[2] = new Color(178, 171, 210);
592
        BREWER_COLOR[3] = new Color(94, 60, 153);
593
        BREWER_COLOR[4] = new Color(166, 97, 26);
594
        BREWER_COLOR[5] = new Color(223, 194, 125);
595
        BREWER_COLOR[6] = new Color(128, 205, 193);
596
        BREWER_COLOR[7] = new Color(1, 133, 113);
597
        BREWER_COLOR[8] = new Color(123, 50, 148);
598
        BREWER_COLOR[9] = new Color(194, 165, 207);
599
        BREWER_COLOR[10] = new Color(166, 219, 160);
600
        BREWER_COLOR[11] = new Color(0, 136, 55);
601
        BREWER_COLOR[12] = new Color(208, 28, 139);
602
        BREWER_COLOR[13] = new Color(241, 182, 218);
603
        BREWER_COLOR[14] = new Color(184, 225, 134);
604
        BREWER_COLOR[15] = new Color(77, 172, 38);
605
        BREWER_COLOR[16] = new Color(202, 0, 32);
606
        BREWER_COLOR[17] = new Color(244, 165, 130);
607
        BREWER_COLOR[18] = new Color(146, 197, 222);
608
        BREWER_COLOR[19] = new Color(5, 113, 176);
609
        BREWER_COLOR[20] = new Color(202, 0, 32);
610
        BREWER_COLOR[21] = new Color(244, 165, 130);
611
        BREWER_COLOR[22] = new Color(186, 186, 186);
612
        BREWER_COLOR[23] = new Color(64, 64, 64);
613
        BREWER_COLOR[24] = new Color(215, 25, 28);
614
        BREWER_COLOR[25] = new Color(253, 174, 97);
615
        BREWER_COLOR[26] = new Color(171, 217, 233);
616
        BREWER_COLOR[27] = new Color(44, 123, 182);
617
        BREWER_COLOR[28] = new Color(215, 25, 28);
618
        BREWER_COLOR[29] = new Color(253, 174, 97);
619
        BREWER_COLOR[30] = new Color(171, 221, 164);
620
        BREWER_COLOR[31] = new Color(43, 131, 186);
621
        BREWER_COLOR[32] = new Color(215, 25, 28);
622
        BREWER_COLOR[33] = new Color(253, 174, 97);
623
        BREWER_COLOR[34] = new Color(166, 217, 106);
624
        BREWER_COLOR[35] = new Color(26, 150, 65);
625
    }
626

  
627
}

Also available in: Unified diff