View Javadoc

1   package com.explosion.utilities.preferences;
2   
3   /*
4    * =============================================================================
5    * 
6    * Copyright 2004 Stephen Cowx
7    * 
8    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
9    * use this file except in compliance with the License. You may obtain a copy of
10   * the License at
11   * 
12   * http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   * 
20   * =============================================================================
21   */
22  
23  import java.awt.Color;
24  import java.awt.Font;
25  import java.io.File;
26  import java.util.ArrayList;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.StringTokenizer;
31  
32  import javax.swing.table.TableCellEditor;
33  import javax.swing.table.TableCellRenderer;
34  
35  import org.apache.log4j.LogManager;
36  import org.apache.log4j.Logger;
37  
38  import com.explosion.utilities.CryptoUtils;
39  import com.explosion.utilities.GeneralConstants;
40  import com.explosion.utilities.exception.ExceptionManagerFactory;
41  import com.explosion.utilities.preferences.groups.PreferencePersistenceException;
42  import com.explosion.utilities.preferences.persist.PreferencePersister;
43  import com.explosion.utilities.preferences.persist.PreferencePersisterFactory;
44  
45  import cryptix.util.core.Hex;
46  
47  /***
48   * This class is a wrapper class to represent a preference. Use of this class
49   * provides a generic preference interface which can be queried for display,
50   * editing and effective use. <br>
51   * <br>
52   *  
53   */
54  
55  public class Preference implements Cloneable
56  {
57  
58      private static Logger log = LogManager.getLogger(Preference.class);
59  
60      /* Preference Types */
61      public static final int PROPERTY_TYPE_TEXT = 0;
62  
63      public static final int PROPERTY_TYPE_FILE = 1;
64  
65      public static final int PROPERTY_TYPE_DIRECTORY = 2;
66  
67      public static final int PROPERTY_TYPE_INT = 3;
68  
69      public static final int PROPERTY_TYPE_FLOAT = 4;
70  
71      public static final int PROPERTY_TYPE_COLOR = 5;
72  
73      public static final int PROPERTY_TYPE_STRING_CHOICE = 6;
74  
75      public static final int PROPERTY_TYPE_INT_CHOICE = 7;
76  
77      public static final int PROPERTY_TYPE_BOOLEAN = 8;
78  
79      public static final int PROPERTY_TYPE_FONT = 9;
80  
81      public static final int PROPERTY_TYPE_ENCRYPTED = 10;
82  
83      public static final int PROPERTY_TYPE_COLLECTION = 11;
84  
85      private static final String BLUE = "B16CD1F39C7D1839";
86      
87      private static Map typeNames;
88  
89      private String uniqueIdentifier = null;
90  
91      private int collectionType = PROPERTY_TYPE_TEXT;
92  
93      private int type;
94  
95      private String longName = null;
96  
97      private String description = null;
98  
99      private List choiceValues = null;
100 
101     private List defaultValues;
102 
103     private List values;
104 
105     private Object defaultValue;
106 
107     private Object value;
108 
109     private TableCellRenderer renderer = null;
110 
111     private TableCellEditor editor = null;
112 
113     private boolean autoCommit = false;
114 
115     private List preferenceChangeListeners = new ArrayList();
116 
117     private boolean editable = true;
118 
119     private boolean visible = true;
120 
121     private boolean editorLoaded = false;
122     
123     private PreferencePersister preferencePersister;
124 
125     /***
126      * Constructor for creating Preferences of any type except collections. If
127      * you want to create a preference which is a collection then you need to
128      * use the other constructor which has an argument for specifying the
129      * collection type
130      * 
131      * @param uniqueIdentifier - the unique identified for this preference
132      * @param type - the type for this preference eg:File/Color/Boolean/String
133      *        etc
134      * @param defaultValue - the default value for this preference (may not be
135      *        null)
136      * @param referenceToStore - a reference to the backing store that will be used by the persistor to store this preference
137      *        the persistence scheme used to store this item will depend on what
138      *        type of object this is.  The factory will use the instanceof mechanism to pick a suitable persisence mechanism
139      * @throws IllegalArgumentException if the uniqueId or the defaultValue is
140      *         null
141      */
142     public Preference(String uniqueIdentifier, int type, Object defaultValue, Object referenceToStore) throws PreferenceCreateException
143     {
144         this(uniqueIdentifier, type, -1, defaultValue, referenceToStore);
145     }
146 
147     /***
148      * Constructor
149      * 
150      * @param uniqueIdentifier - the unique identified for this preference
151      * @param type - the type for this preference eg:File/Color/Boolean/String
152      *        etc
153      * @param collectionType - the type for this collection
154      * @param defaultValue - the default value for this preference (may not be
155      *        null). If this is a colelction preference then this value will be used as a default for items in the list.
156      * @param referenceToStore - a reference to the backing store that will be used by the persistor to store this preference
157      *        the persistence scheme used to store this item will depend on what
158      *        type of object this is.  The factory will use the instanceof mechanism to pick a suitable persisence mechanism
159      * @throws IllegalArgumentException if the uniqueId or the defaultValue is
160      *         null
161      */
162     public Preference(String uniqueIdentifier, int type, int collectionType, Object defaultValue, Object referenceToStore) throws PreferenceCreateException
163     {
164         try
165         {
166             setUniqueIdentifier(uniqueIdentifier);
167             setType(type);
168 
169             if (type == Preference.PROPERTY_TYPE_COLLECTION)
170             {
171                 if (collectionType == -1)
172                     throw new IllegalArgumentException("A valid collectionType argument MUST be specified for Preferences of type COLLECTION.  Valid collectionTypes are any type except COLLECTION.");
173 
174                 setCollectionType(collectionType);
175             }
176             
177             setDefaultValue(defaultValue);
178             
179             this.preferencePersister = PreferencePersisterFactory.createPreferencePersister(referenceToStore);
180             
181             preferencePersister.load(this);
182         }
183         catch (Exception e)
184         {
185             throw new PreferenceCreateException("Exception caught while loading preference.", e);
186         }
187     }
188     
189     /***
190      * Returns the unique identifier for this Preference
191      * 
192      * @return
193      */
194     public final String getUniqueIdentifier()
195     {
196         return uniqueIdentifier;
197     }
198 
199     public final void setUniqueIdentifier(String uniqueIdentifier) throws IllegalArgumentException
200     {
201         if (uniqueIdentifier == null)
202             throw new IllegalArgumentException("Argument 'uniqueIdentifier' may not be null.");
203 
204         this.uniqueIdentifier = uniqueIdentifier;
205     }
206 
207     public final boolean isEditable()
208     {
209         return editable;
210     }
211 
212     public final void setEditable(boolean editable)
213     {
214         this.editable = editable;
215     }
216 
217     /***
218      * Returns the type for this Preference
219      * 
220      * @return
221      */
222     public final int getType()
223     {
224         return type;
225     }
226 
227     public final void setType(int type)
228     {
229         this.type = type;
230     }
231 
232     /***
233      * Returns the longName for this Preference
234      * 
235      * @return
236      */
237     public final String getLongName()
238     {
239         return longName;
240     }
241 
242     public final void setLongName(String longName)
243     {
244         this.longName = longName;
245     }
246 
247     public final String getDescription()
248     {
249         return description;
250     }
251 
252     public final void setDescription(String description)
253     {
254         this.description = description;
255     }
256 
257     public final List getChoiceValues()
258     {
259         return choiceValues;
260     }
261 
262     public final void setChoiceValues(List values)
263     {
264         this.choiceValues = values;
265     }
266 
267     public final Object getDefaultValue()
268     {
269         if (defaultValue instanceof Preference)
270             return ((Preference) defaultValue).getValue();
271         else
272             return defaultValue;
273     }
274 
275     /***
276      * Sets the default valueof this preference, checks integrity of value
277      * supplied first.
278      * 
279      * @param defaultValue
280      * @throws IllegalArgumentException
281      */
282     public final void setDefaultValue(Object defaultValue) throws IllegalArgumentException
283     {
284         if (defaultValue == null)
285             throw new IllegalArgumentException("Argument 'defaultValue' may not be null.");
286 
287         if (defaultValue instanceof Preference)
288             this.defaultValue = defaultValue;
289         else
290             this.defaultValue = checkValue(defaultValue, getType());
291     }
292 
293     /***
294      * This method returns the value
295      * 
296      * @return value
297      */
298     public final Object getValue()
299     {
300         if (type == PROPERTY_TYPE_COLLECTION)
301             throw new IllegalStateException("Method getValue() should only be used when the Preference is not a collection.  Use getValues() instead.");
302 
303         if (value == null)
304             return getDefaultValue();
305 
306         return value;
307     }
308 
309     /***
310      * Sets the current value of this preference, checks integrity of value
311      * supplied first. If autoCOmmit is on, it applies thevalue to persitnt
312      * storage. It sets isDefaulted() to false; It then fires preferenceChange()
313      * to all the listeners interested. Not quite an event firing but good
314      * enough for now.
315      * 
316      * @param currentValue
317      * @throws Exception
318      */
319     public final void setValue(Object currentValue) throws Exception
320     {
321         if (type == PROPERTY_TYPE_COLLECTION)
322             throw new IllegalStateException("Method setValue() should only be used when the Preference is not a collection.  Use setValues() instead.");
323 
324         this.value = checkValue(currentValue, getType());
325 
326         if (isAutoCommit())
327             save();
328 
329         firePreferenceChangedEvent(PreferenceChangeEvent.PROPERTY_VALUE_CHANGED);
330     }
331 
332     /***
333      * This method returns the values array if it exists otherwise, it returns
334      * the defaultValues (which is an empty List if no values have been set)
335      * 
336      * @return value
337      */
338     public final List getValues()
339     {
340         if (type != PROPERTY_TYPE_COLLECTION)
341             throw new IllegalStateException("Method getValues() should only be used if the Preference is a collection.  Use getValue() instead.");
342 
343         if (values == null)
344         {
345             if (defaultValues == null)
346                 defaultValues = new ArrayList();
347 
348             return defaultValues;
349         }
350 
351         return values;
352     }
353 
354     public void addValue(Object newValue) throws Exception
355     {
356         if (type != PROPERTY_TYPE_COLLECTION)
357             throw new IllegalStateException("Method addValue() should only be used if the Preference is a collection.  This preference is not.");
358 
359         if (values == null)
360         {
361             values = new ArrayList();
362         }
363 
364         checkValue(newValue, getCollectionType());
365 
366         if (newValue == null)
367             values.add(getDefaultValue());
368         else
369             values.add(newValue);
370 
371         if (isAutoCommit())
372             save();
373 
374         firePreferenceChangedEvent(PreferenceChangeEvent.PROPERTY_COLLECTION_VALUE_CHANGED);
375     }
376 
377     public void removeValue(Object valueToRemove) throws Exception
378     {
379         if (type != PROPERTY_TYPE_COLLECTION)
380             throw new IllegalStateException("Method removeValue() should only be used if the Preference is a collection.  This preference is not.");
381 
382         if (values == null)
383         {
384             return;
385         }
386 
387         values.remove(valueToRemove);
388 
389         if (isAutoCommit())
390             save();
391 
392         firePreferenceChangedEvent(PreferenceChangeEvent.PROPERTY_COLLECTION_VALUE_CHANGED);
393     }
394 
395     /***
396      * @param newValues
397      * @throws Exception
398      */
399     public final void setValues(List newValues, int collectionType) throws Exception
400     {
401         if (type != PROPERTY_TYPE_COLLECTION)
402             throw new IllegalStateException("Method setValues() should only be used if the Preference is a collection.  Use setValue() instead.");
403 
404         this.collectionType = collectionType;
405 
406         for (int i = 0; i < newValues.size(); i++)
407         {
408             checkValue(newValues.get(i), getCollectionType());
409         }
410 
411         this.values = newValues;
412 
413         if (isAutoCommit())
414             save();
415 
416         firePreferenceChangedEvent(PreferenceChangeEvent.PROPERTY_COLLECTION_VALUE_CHANGED);
417     }
418 
419     /***
420      * @param value2
421      * @param row
422      */
423     public void setValueAt(Object value, int row) throws Exception
424     {
425         if (type != PROPERTY_TYPE_COLLECTION)
426             throw new IllegalStateException("Method setValues() should only be used if the Preference is a collection.  Use setValue() instead.");
427 
428         checkValue(value, getCollectionType());
429         
430         if (value == null)
431             values.set(row, getDefaultValue());
432         else
433             values.set(row, value);
434         
435         if (isAutoCommit())
436             save();
437 
438         firePreferenceChangedEvent(PreferenceChangeEvent.PROPERTY_COLLECTION_VALUE_CHANGED);
439     }
440 
441     public TableCellRenderer getRenderer()
442     {
443         return renderer;
444     }
445 
446     public final boolean isAutoCommit()
447     {
448         return autoCommit;
449     }
450 
451     public final void setAutoCommit(boolean autoCommit)
452     {
453         this.autoCommit = autoCommit;
454     }
455 
456     /***
457      * This method returns the value of the Preference by doing a toString on
458      * that object (for the most part anyway).
459      * 
460      * @return
461      */
462     public String toString()
463     {
464         switch (type)
465         {
466         case (PROPERTY_TYPE_FONT):
467             if (value != null)
468                 return ((Font) getValue()).getName() + ", " + ((Font) getValue()).getSize();
469             else
470                 return ((Font) getDefaultValue()).getName() + ", " + ((Font) getDefaultValue()).getSize();
471         default:
472             return (value == null ? (String) getDefaultValue().toString() : getValue().toString());
473         }
474     }
475 
476     /***
477      * This method does a little integrity checking on the choiceValues
478      * supplied, mostly it checks to see if the object is an instance of
479      * thecorrect class. Otherwise it checks valid numbers etc.
480      * 
481      * @param newValue
482      * @return convertedValue
483      * @throws IllegalArgumentException
484      */
485     protected final Object checkValue(Object newValue, int valueType) throws IllegalArgumentException
486     {
487         if (newValue == null)
488             return null;
489 
490         switch (valueType)
491         {
492         case (PROPERTY_TYPE_TEXT):
493             break;
494         case (PROPERTY_TYPE_FILE):
495             if (!(newValue instanceof File))
496                 // || (((File) newValue).exists() && !((File)
497                 // newValue).isFile()))
498                 throw new IllegalArgumentException("Error while setting property '" + getLongName() + "'.  The value of properties whose type is PROPERTY_TYPE_FILE(" + PROPERTY_TYPE_FILE
499                         + ") must be a File. " + newValue.toString());
500 
501             /* If this is a default file, use the DefaultFile class */
502             if (((File) newValue).getName().indexOf(GeneralConstants.DEFAULT_FILE) >= 0)
503                 newValue = createDefaultFile();
504 
505             break;
506         case (PROPERTY_TYPE_DIRECTORY):
507             if (!(newValue instanceof File))
508                 // || (((File) newValue).exists() && !((File)
509                 // newValue).isDirectory()))
510                 throw new IllegalArgumentException("Error while setting property '" + getLongName() + "'.  The value of properties whose type is PROPERTY_TYPE_DIRECTORY(" + PROPERTY_TYPE_DIRECTORY
511                         + ") must be a Directory. " + newValue.toString());
512 
513             /* If this is a default file, use the DefaultFile class */
514             if (((File) newValue).getName().indexOf(GeneralConstants.DEFAULT_FILE) >= 0)
515                 newValue = createDefaultFile();
516 
517             break;
518         case (PROPERTY_TYPE_COLOR):
519             if (!(newValue instanceof Color))
520                 throw new IllegalArgumentException("Error while setting property '" + getLongName() + "'.  The value of properties whose type is PROPERTY_TYPE_COLOR(" + PROPERTY_TYPE_COLOR
521                         + ") must be a Color. " + newValue.toString());
522             break;
523         case (PROPERTY_TYPE_INT):
524             if (!(newValue instanceof Integer))
525             {
526                 try
527                 {
528                     if (newValue instanceof String)
529                         newValue = new Integer((String) newValue);
530                     else
531                         throw new IllegalArgumentException("Error while setting property '" + getLongName() + "'.  The value of properties whose type is PROPERTY_TYPE_INT(" + PROPERTY_TYPE_INT
532                                 + ") must be an Integer or a String which can be made into an Integer. " + newValue.toString());
533                 }
534                 catch (NumberFormatException e)
535                 {
536                     throw new IllegalArgumentException("Error while setting property '" + getLongName() + "'.  The value of properties whose type is PROPERTY_TYPE_INT(" + PROPERTY_TYPE_INT
537                             + ") must be an Integer or a String which can be made into an Integer. " + newValue.toString());
538                 }
539             }
540             break;
541         case (PROPERTY_TYPE_FLOAT):
542             if (!(newValue instanceof Float))
543             {
544                 try
545                 {
546                     if (newValue instanceof String)
547                         newValue = new Float((String) newValue);
548                     else
549                         throw new IllegalArgumentException("Error while setting property '" + getLongName() + "'.  The value of properties whose type is PROPERTY_TYPE_FLOAT(" + PROPERTY_TYPE_FLOAT
550                                 + ") must be a Float or a String which can be made into a Float. " + newValue.toString());
551                 }
552                 catch (NumberFormatException e)
553                 {
554                     throw new IllegalArgumentException("Error while setting property '" + getLongName() + "'.  The value of properties whose type is PROPERTY_TYPE_FLOAT(" + PROPERTY_TYPE_FLOAT
555                             + ") must be a Float or a String which can be made into a Float. " + newValue.toString());
556                 }
557             }
558             break;
559         case (PROPERTY_TYPE_STRING_CHOICE):
560             break;
561         case (PROPERTY_TYPE_INT_CHOICE):
562             break;
563         case (PROPERTY_TYPE_BOOLEAN):
564             if (!(newValue instanceof Boolean))
565             {
566                 if (newValue instanceof String)
567                     newValue = new Boolean((String) newValue);
568                 else
569                     throw new IllegalArgumentException("Error while setting property '" + getLongName() + "'.  The value of properties whose type is PROPERTY_TYPE_BOOLEAN(" + PROPERTY_TYPE_BOOLEAN
570                             + ") must be a Boolean or a String which can be made into a boolean. " + newValue.toString());
571             }
572             break;
573         case (PROPERTY_TYPE_FONT):
574             if (!(newValue instanceof Font))
575                 throw new IllegalArgumentException("Error while setting property '" + getLongName() + "'.  The value of properties whose type is PROPERTY_TYPE_FONT(" + PROPERTY_TYPE_FONT
576                         + ") must be a Font. " + newValue.toString());
577             break;
578         case (PROPERTY_TYPE_ENCRYPTED):
579             break;
580         }
581         return newValue;
582     }
583 
584     /***
585      * This method saves the property to persistent storage, if the value is
586      * null, it should delete the entire key/value pair persisted if it exists
587      * or not save it if it does.
588      * 
589      * @throws Exception
590      */
591     public void save() throws PreferencePersistenceException
592     {
593         preferencePersister.save(this);
594     }
595 
596     /***
597      * This method loads the property from persistent storage if it is there, if
598      * it is not it should not populate the value.
599      * 
600      * @throws Exception
601      */
602     public void load() throws PreferencePersistenceException
603     {
604         preferencePersister.load(this);
605     }
606     
607     public void setReferenceToStore(Object referenceToStore) throws PreferencePersistenceException
608     {
609         /* Create a new persistor */
610         this.preferencePersister = PreferencePersisterFactory.createPreferencePersister(referenceToStore);
611         
612         /* Then save it in the new persister */
613         preferencePersister.save(this);
614         
615     }
616     
617     /***
618      * returns the reference to the store
619      * @return
620      */
621     public Object getReferenceToStore()
622     {
623        return this.preferencePersister.getReferenceToStore();
624         
625     }
626 
627     /***
628      * Adds a Preference Change Listener to this preference. When this
629      * Preference is updated the preferenceChanged method of the listener
630      * will get called
631      * 
632      * @param listener
633      */
634     public final void addPreferenceChangeListener(PreferenceChangeListener listener)
635     {
636         if (!preferenceChangeListeners.contains(listener))
637             preferenceChangeListeners.add(listener);
638     }    
639 
640 	/***
641 	 * Removes the specified preferenceChange Listener if it is already in the list of listeners
642 	 * @param listener
643 	 */
644 	public void removePreferenceChangeListener(PreferenceChangeListener listener) {
645 		if (!preferenceChangeListeners.contains(listener))
646             preferenceChangeListeners.remove(listener);
647 	}    
648 
649     /***
650      * Iterates through the preference Chnaged Listeners and lets them know that
651      * this preference has changed
652      */
653     public final void firePreferenceChangedEvent(int code)
654     {
655         log.debug("Preference " + this.getUniqueIdentifier() + " " + this.hashCode());
656     	PreferenceChangeEvent event = new PreferenceChangeEvent(code, this);
657     	for (int i = 0; i < preferenceChangeListeners.size(); i++)
658         {
659             ((PreferenceChangeListener) preferenceChangeListeners.get(i)).preferenceChanged(event);
660         }
661     }
662 
663     /***
664      * Derives a font from a string representation
665      * 
666      * @param fontString
667      * @return
668      */
669     public static final Font deriveFont(String fontString)
670     {
671         StringTokenizer token = new StringTokenizer(fontString, ",");
672         int style = Integer.parseInt(token.nextToken());
673         int size = Integer.parseInt(token.nextToken());
674         String name = token.nextToken();
675         return new Font(name, style, size);
676     }
677 
678     public final DefaultFile createDefaultFile()
679     {
680         return new DefaultFile(System.getProperty("user.home") + System.getProperty("file.separator") + GeneralConstants.DEFAULT_FILE);
681     }
682 
683     /***
684      * Returns an encrypted version of the given value
685      */
686     public static final String encrypt(String valueToEncrypt) throws EncryptionException
687     {
688         try
689         {
690             if (valueToEncrypt.trim().equals(""))
691                 return valueToEncrypt.trim();
692 
693             return CryptoUtils.encrypt(valueToEncrypt, Hex.fromString(BLUE));
694         }
695         catch (Exception e)
696         {
697             throw new EncryptionException("Unable to encrypt data", e);
698         }
699     }
700 
701     /***
702      * Returns a decrypted version of the given value
703      */
704     public static final String decrypt(String valueToDecrypt) throws EncryptionException
705     {
706         try
707         {
708             if (valueToDecrypt.trim().equals(""))
709                 return valueToDecrypt.trim();
710 
711             return CryptoUtils.decrypt(valueToDecrypt, Hex.fromString(BLUE));
712         }
713         catch (Exception e)
714         {
715             throw new EncryptionException("Unable to decrypt data", e);
716         }
717     }
718 
719     public boolean isVisible()
720     {
721         return visible;
722     }
723 
724     public void setVisible(boolean visible)
725     {
726         this.visible = visible;
727     }
728 
729     /***
730      * @return If a property is set to the default, this will return true. If
731      *         however, it has been set to some other value, then this property
732      *         will return false;
733      */
734     public boolean isDefaulted()
735     {
736         if (getType() == PROPERTY_TYPE_COLLECTION)
737             return values == null;
738         else
739             return value == null;
740     }
741 
742     /***
743      * @return Returns the collectionType.
744      */
745     public int getCollectionType()
746     {
747         return collectionType;
748     }
749 
750     /***
751      * @param collectionType The collectionType to set.
752      */
753     public void setCollectionType(int collectionType)
754     {
755         this.collectionType = collectionType;
756     }
757     
758     /***
759      * This method returns the name for a the type requested
760      * If the type does not exist, it returns null.
761      * @param type
762      * @return
763      */
764     public static String getNameForType(int type)
765     {
766         switch (type)
767         {
768 	        case (PROPERTY_TYPE_TEXT) : return "string";
769 	        case (PROPERTY_TYPE_FILE) : return "file";
770 	        case (PROPERTY_TYPE_DIRECTORY) : return "directory";
771 	        case (PROPERTY_TYPE_INT) : return "int";
772 	        case (PROPERTY_TYPE_FLOAT) : return "float";
773 	        case (PROPERTY_TYPE_COLOR) : return "color";
774 	        case (PROPERTY_TYPE_STRING_CHOICE) : return "choice";
775 	        case (PROPERTY_TYPE_INT_CHOICE) : return "int choice";
776 	        case (PROPERTY_TYPE_BOOLEAN) : return "boolean";
777 	        case (PROPERTY_TYPE_FONT) : return "font";
778 	        case (PROPERTY_TYPE_ENCRYPTED) : return "encrypted";
779 	        case (PROPERTY_TYPE_COLLECTION) : return "collection";
780 	        default: return null;
781         }
782     }
783     
784     /***
785      * This method returns the name for the type requested
786      * It returns -1 of it does not recognise the name.
787      * 
788      * This method is case insensitive
789      * @param type
790      * @return
791      */
792     public static int getTypeForName(String typeName)
793     {
794         if (typeNames == null)
795         {
796             typeNames = new HashMap();
797             typeNames.put("string",new Integer(0));
798             typeNames.put("file",new Integer(1));
799             typeNames.put("directory",new Integer(2));
800             typeNames.put("int",new Integer(3));
801             typeNames.put("float",new Integer(4));
802             typeNames.put("color",new Integer(5));
803             typeNames.put("choice",new Integer(6));
804             typeNames.put("int choice",new Integer(7));
805             typeNames.put("boolean",new Integer(8));
806             typeNames.put("font",new Integer(9));
807             typeNames.put("encrypted",new Integer(10));
808             typeNames.put("collection",new Integer(11));            
809         }
810         Integer typeForName = (Integer) typeNames.get(typeName.toLowerCase());
811         if (typeForName != null)
812             return typeForName.intValue();
813         else
814             return -1;
815     }
816     
817     /***
818      * Returns the Class object whch represents these preferences.
819      * @param type
820      * @return
821      */
822     public static Class getClassForType(int type)
823     {
824         switch (type)
825         {
826 	        case (PROPERTY_TYPE_TEXT) : return String.class;
827 	        case (PROPERTY_TYPE_FILE) : return File.class;
828 	        case (PROPERTY_TYPE_DIRECTORY) : return File.class;
829 	        case (PROPERTY_TYPE_INT) : return Integer.class;
830 	        case (PROPERTY_TYPE_FLOAT) : return Float.class;
831 	        case (PROPERTY_TYPE_COLOR) : return Color.class;
832 	        case (PROPERTY_TYPE_STRING_CHOICE) : return String.class;
833 	        case (PROPERTY_TYPE_INT_CHOICE) : return Integer.class;
834 	        case (PROPERTY_TYPE_BOOLEAN) : return Boolean.class;
835 	        case (PROPERTY_TYPE_FONT) : return Font.class;
836 	        case (PROPERTY_TYPE_ENCRYPTED) : return String.class;
837 	        case (PROPERTY_TYPE_COLLECTION) : return null;
838 	        default: return null;
839         }
840     }
841     
842     
843 
844     /***
845      * Creates a clone of this preference
846      * @see java.lang.Object#clone()
847      * @return
848      * @throws java.lang.CloneNotSupportedException
849      */
850     public Object clone() throws CloneNotSupportedException
851     {
852         String ui = this.uniqueIdentifier;
853         int type = this.type; 
854         int cType = this.collectionType; 
855         Object defValue = this.defaultValue; 
856         Object ref = this.preferencePersister.getReferenceToStore();
857         
858         Preference preference = null;
859         try
860         {
861             preference = new Preference(ui, type, cType, defValue, ref);
862         }
863         catch (PreferenceCreateException e)
864         {
865             ExceptionManagerFactory.getExceptionManager().manageException(e,"Exception caught while cloning Preference");
866         }
867         return preference;
868     }
869 }