comparison org.eclipse.jface/src/org/eclipse/jface/dialogs/DialogSettings.d @ 12:bc29606a740c

Added dwt-addons in original directory structure of eclipse.org
author Frank Benoit <benoit@tionex.de>
date Sat, 14 Mar 2009 18:23:29 +0100
parents
children 52184e4b815c
comparison
equal deleted inserted replaced
11:43904fec5dca 12:bc29606a740c
1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.jface.dialogs.DialogSettings;
14
15 import org.eclipse.jface.dialogs.IDialogSettings;
16
17
18 static import tango.text.xml.Document;
19 static import tango.text.xml.SaxParser;
20 static import tango.text.xml.PullParser;
21
22 import java.lang.all;
23 import java.util.Enumeration;
24 import java.util.Collections;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.Map;
28 import java.util.HashMap;
29 import java.util.Set;
30 static import java.io.OutputStream;
31 static import tango.text.convert.Integer;
32 static import tango.text.convert.Float;
33 static import tango.text.Text;
34 static import tango.io.stream.Format;
35 static import tango.io.model.IConduit;
36 import tango.io.device.File;
37 import tango.core.Exception;
38 import java.nonstandard.XmlTranscode;
39
40 /**
41 * Concrete implementation of a dialog settings (<code>IDialogSettings</code>)
42 * using a hash table and XML. The dialog store can be read
43 * from and saved to a stream. All keys and values must be strings or array of
44 * strings. Primitive types are converted to strings.
45 * <p>
46 * This class was not designed to be subclassed.
47 *
48 * Here is an example of using a DialogSettings:
49 * </p>
50 * <pre>
51 * <code>
52 * DialogSettings settings = new DialogSettings("root");
53 * settings.put("Boolean1",true);
54 * settings.put("Long1",100);
55 * settings.put("Array1",new String[]{"aaaa1","bbbb1","cccc1"});
56 * DialogSettings section = new DialogSettings("sectionName");
57 * settings.addSection(section);
58 * section.put("Int2",200);
59 * section.put("Float2",1.1);
60 * section.put("Array2",new String[]{"aaaa2","bbbb2","cccc2"});
61 * settings.save("c:\\temp\\test\\dialog.xml");
62 * </code>
63 * </pre>
64 * @noextend This class is not intended to be subclassed by clients.
65 */
66
67 public class DialogSettings : IDialogSettings {
68 alias tango.text.xml.Document.Document!(char) Document;
69 alias tango.text.xml.Document.Document!(char).Node Element;
70 // The name of the DialogSettings.
71 private String name;
72
73 /* A Map of DialogSettings representing each sections in a DialogSettings.
74 It maps the DialogSettings' name to the DialogSettings */
75 private Map sections;
76
77 /* A Map with all the keys and values of this sections.
78 Either the keys an values are restricted to strings. */
79 private Map items;
80
81 // A Map with all the keys mapped to array of strings.
82 private Map arrayItems;
83
84 private static const String TAG_SECTION = "section";//$NON-NLS-1$
85
86 private static const String TAG_NAME = "name";//$NON-NLS-1$
87
88 private static const String TAG_KEY = "key";//$NON-NLS-1$
89
90 private static const String TAG_VALUE = "value";//$NON-NLS-1$
91
92 private static const String TAG_LIST = "list";//$NON-NLS-1$
93
94 private static const String TAG_ITEM = "item";//$NON-NLS-1$
95
96 /**
97 * Create an empty dialog settings which loads and saves its
98 * content to a file.
99 * Use the methods <code>load(String)</code> and <code>store(String)</code>
100 * to load and store this dialog settings.
101 *
102 * @param sectionName the name of the section in the settings.
103 */
104 public this(String sectionName) {
105 name = sectionName;
106 items = new HashMap();
107 arrayItems = new HashMap();
108 sections = new HashMap();
109 }
110
111 /* (non-Javadoc)
112 * Method declared on IDialogSettings.
113 */
114 public IDialogSettings addNewSection(String sectionName) {
115 DialogSettings section = new DialogSettings(sectionName);
116 addSection(section);
117 return section;
118 }
119
120 /* (non-Javadoc)
121 * Method declared on IDialogSettings.
122 */
123 public void addSection(IDialogSettings section) {
124 sections.put(stringcast(section.getName()), cast(Object)section);
125 }
126
127 /* (non-Javadoc)
128 * Method declared on IDialogSettings.
129 */
130 public String get(String key) {
131 return stringcast(items.get(stringcast(key)));
132 }
133
134 /* (non-Javadoc)
135 * Method declared on IDialogSettings.
136 */
137 public String[] getArray(String key) {
138 return stringArrayFromObject(arrayItems.get(stringcast(key)));
139 }
140
141 /* (non-Javadoc)
142 * Method declared on IDialogSettings.
143 */
144 public bool getBoolean(String key) {
145 return stringcast(items.get(stringcast(key))) == "true";
146 }
147
148 /* (non-Javadoc)
149 * Method declared on IDialogSettings.
150 */
151 public double getDouble(String key) {
152 String setting = stringcast(items.get(stringcast(key)));
153 if (setting is null) {
154 throw new NumberFormatException(
155 "There is no setting associated with the key \"" ~ key ~ "\"");//$NON-NLS-1$ //$NON-NLS-2$
156 }
157
158 return tango.text.convert.Float.toFloat(setting);
159 }
160
161 /* (non-Javadoc)
162 * Method declared on IDialogSettings.
163 */
164 public float getFloat(String key) {
165 String setting = stringcast(items.get(stringcast(key)));
166 if (setting is null) {
167 throw new NumberFormatException(
168 "There is no setting associated with the key \"" ~ key ~ "\"");//$NON-NLS-1$ //$NON-NLS-2$
169 }
170
171 return tango.text.convert.Float.toFloat(setting);
172 }
173
174 /* (non-Javadoc)
175 * Method declared on IDialogSettings.
176 */
177 public int getInt(String key) {
178 String setting = stringcast(items.get(stringcast(key)));
179 if (setting is null) {
180 //new Integer(null) will throw a NumberFormatException and meet our spec, but this message
181 //is clearer.
182 throw new NumberFormatException(
183 "There is no setting associated with the key \"" ~ key ~ "\"");//$NON-NLS-1$ //$NON-NLS-2$
184 }
185
186 return tango.text.convert.Integer.toInt(setting);
187 }
188
189 /* (non-Javadoc)
190 * Method declared on IDialogSettings.
191 */
192 public long getLong(String key) {
193 String setting = stringcast(items.get(stringcast(key)));
194 if (setting is null) {
195 //new Long(null) will throw a NumberFormatException and meet our spec, but this message
196 //is clearer.
197 throw new NumberFormatException(
198 "There is no setting associated with the key \"" ~ key ~ "\"");//$NON-NLS-1$ //$NON-NLS-2$
199 }
200
201 return tango.text.convert.Integer.toLong(setting);
202 }
203
204 /* (non-Javadoc)
205 * Method declared on IDialogSettings.
206 */
207 public String getName() {
208 return name;
209 }
210
211 /* (non-Javadoc)
212 * Method declared on IDialogSettings.
213 */
214 public IDialogSettings getSection(String sectionName) {
215 return cast(IDialogSettings) sections.get(stringcast(sectionName));
216 }
217
218 /* (non-Javadoc)
219 * Method declared on IDialogSettings.
220 */
221 public IDialogSettings[] getSections() {
222 Collection values = sections.values();
223 IDialogSettings[] result = arraycast!(IDialogSettings)( values.toArray() );
224 return result;
225 }
226
227 /* (non-Javadoc)
228 * Method declared on IDialogSettings.
229 */
230 public void load( tango.io.model.IConduit.InputStream input) {
231 Document document = new Document();
232 try {
233 char[] content;
234 char[1024] readbuf;
235 int chunksize = 0;
236 while( (chunksize=input.read(readbuf)) !is tango.io.model.IConduit.InputStream.Eof ){
237 content ~= readbuf[ 0 .. chunksize ];
238 }
239 document.parse( content );
240
241 //Strip out any comments first
242 foreach( n; document.query[].filter( delegate bool(Element n) {
243 return n.type is tango.text.xml.PullParser.XmlNodeType.Comment ;
244 })){
245 //TODO: remove() was added after tango 0.99.5
246 //n.remove();
247 }
248 load(document, document.tree.child );
249 } catch (IOException e) {
250 // ignore
251 } catch (TextException e) {
252 // ignore
253 }
254 }
255
256 /* (non-Javadoc)
257 * Method declared on IDialogSettings.
258 */
259 //TODO: solve overload load(char[])
260 public void load(String fileName) {
261 scope file = new File( fileName );
262 load( file.input );
263 file.close;
264 }
265
266 /* (non-Javadoc)
267 * Load the setting from the <code>document</code>
268 */
269 private void load(Document document, Element root) {
270
271 name = root.attributes.name(null,TAG_NAME).value();
272
273 foreach( n; root.query[TAG_ITEM] ){
274 if( root is n.parent() ){
275 String key = n.attributes.name(null,TAG_KEY).value().dup;
276 String value = n.attributes.name(null,TAG_VALUE).value().dup;
277 items.put(stringcast(key), stringcast(value));
278 }
279 }
280 foreach( n; root.query[TAG_LIST].dup ){
281 if( root is n.parent() ){
282 auto child = n;
283 String key = child.attributes.name(null,TAG_KEY).value().dup;
284 char[][] valueList;
285 foreach( node; root.query[TAG_ITEM].dup ){
286 if (child is node.parent()) {
287 valueList ~= node.attributes.name(null,TAG_VALUE).value().dup;
288 }
289 }
290 arrayItems.put(stringcast(key), new ArrayWrapperString2(valueList) );
291 }
292 }
293 foreach( n; root.query[TAG_SECTION].dup ){
294 if( root is n.parent() ){
295 DialogSettings s = new DialogSettings("NoName");//$NON-NLS-1$
296 s.load(document, n);
297 addSection(s);
298 }
299 }
300 }
301
302 /* (non-Javadoc)
303 * Method declared on IDialogSettings.
304 */
305 public void put(String key, String[] value) {
306 arrayItems.put(stringcast(key), new ArrayWrapperString2(value));
307 }
308
309 /* (non-Javadoc)
310 * Method declared on IDialogSettings.
311 */
312 public void put(String key, double value) {
313 put(key, tango.text.convert.Float.toString(value));
314 }
315
316 /* (non-Javadoc)
317 * Method declared on IDialogSettings.
318 */
319 public void put(String key, float value) {
320 put(key, tango.text.convert.Float.toString(value));
321 }
322
323 /* (non-Javadoc)
324 * Method declared on IDialogSettings.
325 */
326 public void put(String key, int value) {
327 put(key, tango.text.convert.Integer.toString(value));
328 }
329
330 /* (non-Javadoc)
331 * Method declared on IDialogSettings.
332 */
333 public void put(String key, long value) {
334 put(key, tango.text.convert.Integer.toString(value));
335 }
336
337 /* (non-Javadoc)
338 * Method declared on IDialogSettings.
339 */
340 public void put(String key, String value) {
341 items.put(stringcast(key), stringcast(value));
342 }
343
344 /* (non-Javadoc)
345 * Method declared on IDialogSettings.
346 */
347 public void put(String key, bool value) {
348 put(key, value ? "true" : "false" );
349 }
350
351 /* (non-Javadoc)
352 * Method declared on IDialogSettings.
353 */
354 public void save(tango.io.model.IConduit.OutputStream writer) {
355 save(new XMLWriter(writer));
356 }
357
358
359 /* (non-Javadoc)
360 * Method declared on IDialogSettings.
361 */
362 public void save(String fileName) {
363 auto stream = new tango.io.device.File.File(
364 fileName,
365 tango.io.device.File.File.WriteCreate);
366 XMLWriter writer = new XMLWriter(stream.output);
367 save(writer);
368 writer.close();
369 }
370
371 /* (non-Javadoc)
372 * Save the settings in the <code>document</code>.
373 */
374 private void save(XMLWriter out_) {
375 HashMap attributes = new HashMap(2);
376 attributes.put(stringcast(TAG_NAME), stringcast(name is null ? "" : name)); //$NON-NLS-1$
377 out_.startTag(TAG_SECTION, attributes);
378 attributes.clear();
379
380 Object EMPTY_STR = new ArrayWrapperString("");
381 foreach( key,value; items ){
382 attributes.put(stringcast(TAG_KEY), key is null ? EMPTY_STR : key); //$NON-NLS-1$
383 String string = stringcast(value);//cast(String) items.get(stringcast(key));
384 attributes.put(stringcast(TAG_VALUE), stringcast(string is null ? "" : string)); //$NON-NLS-1$
385 out_.printTag(TAG_ITEM, attributes, true);
386 }
387
388 attributes.clear();
389 foreach( key,value; arrayItems ){
390 attributes.put(stringcast(TAG_KEY), key is null ? EMPTY_STR : key); //$NON-NLS-1$
391 out_.startTag(TAG_LIST, attributes);
392 attributes.clear();
393 String[] strValues = stringArrayFromObject(value);
394 if (value !is null) {
395 for (int index = 0; index < strValues.length; index++) {
396 String string = strValues[index];
397 attributes.put(stringcast(TAG_VALUE), stringcast(string is null ? "" : string)); //$NON-NLS-1$
398 out_.printTag(TAG_ITEM, attributes, true);
399 }
400 }
401 out_.endTag(TAG_LIST);
402 attributes.clear();
403 }
404 for (Iterator i = sections.values().iterator(); i.hasNext();) {
405 (cast(DialogSettings) i.next()).save(out_);
406 }
407 out_.endTag(TAG_SECTION);
408 }
409
410
411 /**
412 * A simple XML writer. Using this instead of the javax.xml.transform classes allows
413 * compilation against JCL Foundation (bug 80059).
414 */
415 private static class XMLWriter : tango.io.stream.Format.FormatOutput!(char) {
416 /** current number of tabs to use for ident */
417 protected int tab;
418
419 /** the xml header */
420 protected static const String XML_VERSION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; //$NON-NLS-1$
421
422 /**
423 * Create a new XMLWriter
424 * @param output the write to used when writing to
425 */
426 public this(tango.io.model.IConduit.OutputStream output) {
427 super( tango.text.convert.Format.Format, output);
428 tab = 0;
429 print(XML_VERSION);
430 newline;
431 }
432
433 /**
434 * write the intended end tag
435 * @param name the name of the tag to end
436 */
437 public void endTag(String name) {
438 tab--;
439 printTag("/" ~ name, null, false); //$NON-NLS-1$
440 }
441
442 private void printTabulation() {
443 for (int i = 0; i < tab; i++) {
444 super.print('\t');
445 }
446 }
447
448 /**
449 * write the tag to the stream and format it by itending it and add new line after the tag
450 * @param name the name of the tag
451 * @param parameters map of parameters
452 * @param close should the tag be ended automatically (=> empty tag)
453 */
454 public void printTag(String name, HashMap parameters, bool close) {
455 printTag(name, parameters, true, true, close);
456 }
457
458 private void printTag(String name, HashMap parameters, bool shouldTab, bool newLine, bool close) {
459 StringBuffer sb = new StringBuffer();
460 sb.append('<');
461 sb.append(name);
462 if (parameters !is null) {
463 for (Enumeration e = Collections.enumeration(parameters.keySet()); e.hasMoreElements();) {
464 sb.append(" "); //$NON-NLS-1$
465 String key = stringcast( e.nextElement());
466 sb.append(key);
467 sb.append("=\""); //$NON-NLS-1$
468 //sb.append(getEscaped(String.valueOf(parameters.get(key))));
469 sb.append(xmlEscape(stringcast(parameters.get(stringcast(key)))));
470 sb.append("\""); //$NON-NLS-1$
471 }
472 }
473 if (close) {
474 sb.append('/');
475 }
476 sb.append('>');
477 if (shouldTab) {
478 printTabulation();
479 }
480 if (newLine) {
481 print(sb.toString());
482 newline;
483 } else {
484 print(sb.toString());
485 }
486 }
487
488 /**
489 * start the tag
490 * @param name the name of the tag
491 * @param parameters map of parameters
492 */
493 public void startTag(String name, HashMap parameters) {
494 startTag(name, parameters, true);
495 tab++;
496 }
497
498 private void startTag(String name, HashMap parameters, bool newLine) {
499 printTag(name, parameters, true, newLine, false);
500 }
501 }
502
503 }