xref: /titanic_41/usr/src/cmd/krb5/kadmin/gui/visualrt/sunsoft/jws/visual/rt/type/Converter.java (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * ident	"%Z%%M%	%I%	%E% SMI"
24  *
25  * Copyright (c) 2000 by Sun Microsystems, Inc.
26  * All rights reserved.
27  */
28 
29 /*
30  *        Copyright (C) 1996  Active Software, Inc.
31  *                  All rights reserved.
32  *
33  * @(#) Converter.java 1.65 - last change made 08/20/97
34  */
35 
36 package sunsoft.jws.visual.rt.type;
37 
38 import sunsoft.jws.visual.rt.base.Global;
39 
40 import sunsoft.jws.visual.rt.base.*;
41 
42 import java.util.*;
43 
44 /**
45 * Base class for all converters.  Converts a type of
46 * object to a string
47 * and back again.
48 *
49 * @version 1.65, 08/20/97
50 */
51 
52 public abstract class Converter {
53     /**
54      * Table of names for each registered converter.
55      */
56     private static Hashtable converterNameTable = new Hashtable();
57 
58     /**
59      * Table of instances for each converter that has
60      * been instantiated.
61     */
62     private static Hashtable converterInstanceTable = new Hashtable();
63 
64     /**
65      * Adds a new type converter to the global table of converters.  A
66      * converter must be listed for this table in order for the search
67      * for a converter for that particular type to be successful.
68      *
69      * @param typeName the name of the type (what is returned by a
70      * call to getClass().getType() for an instance of that type)
71      * @param converterClassName the full name of the converter class
72      */
addConverter(String typeName, String converterClassName)73     public static void addConverter(String typeName,
74 				    String converterClassName) {
75         converterNameTable.put(typeName, converterClassName);
76     }
77 
78     /**
79      * Initialize the type converters for the types we know about.
80      */
81     static {
82         addConverter(/* NOI18N */"[I", /* NOI18N */
83 		     "sunsoft.jws.visual.rt.type.IntArrayConverter");
84         addConverter(/* NOI18N */"[D", /* NOI18N */
85 		     "sunsoft.jws.visual.rt.type.DoubleArrayConverter");
86         addConverter(/* NOI18N */"java.lang.String",
87 		     /* NOI18N */"sunsoft.jws.visual.rt.type.StringConverter");
88         addConverter(/* NOI18N */"[Ljava.lang.String;",
89 	     /* NOI18N */"sunsoft.jws.visual.rt.type.StringArrayConverter");
90         addConverter(/* NOI18N */"java.lang.Boolean",
91 	     /* NOI18N */"sunsoft.jws.visual.rt.type.BooleanConverter");
92         addConverter(/* NOI18N */"java.lang.Character",
93 	     /* NOI18N */"sunsoft.jws.visual.rt.type.CharacterConverter");
94         addConverter(/* NOI18N */"java.lang.Integer",
95 	     /* NOI18N */"sunsoft.jws.visual.rt.type.IntegerConverter");
96         addConverter(/* NOI18N */"java.awt.Color",
97 		     /* NOI18N */"sunsoft.jws.visual.rt.type.ColorConverter");
98         addConverter(/* NOI18N */"java.awt.SystemColor",
99 		     /* NOI18N */"sunsoft.jws.visual.rt.type.ColorConverter");
100         addConverter(/* NOI18N */"java.awt.Font",
101 		     /* NOI18N */"sunsoft.jws.visual.rt.type.FontConverter");
102         addConverter(/* NOI18N */"java.awt.Point",
103 		     /* NOI18N */"sunsoft.jws.visual.rt.type.PointConverter");
104         addConverter(/* NOI18N */"java.awt.Dimension",
105 	     /* NOI18N */"sunsoft.jws.visual.rt.type.DimensionConverter");
106         addConverter(/* NOI18N */"java.awt.Insets",
107 		     /* NOI18N */"sunsoft.jws.visual.rt.type.InsetsConverter");
108         addConverter(/* NOI18N */
109 		     "sunsoft.jws.visual.rt.awt.GBConstraints",
110 	     /* NOI18N */"sunsoft.jws.visual.rt.type.GBConstraintsConverter");
111         addConverter(/* NOI18N */
112 		     "sunsoft.jws.visual.rt.base.AttributeManager",
113 		     /* NOI18N */"sunsoft.jws.visual.rt.type.AMConverter");
114         addConverter(/* NOI18N */"sunsoft.jws.visual.rt.type.AMRef",
115 		     /* NOI18N */"sunsoft.jws.visual.rt.type.AMRefConverter");
116         addConverter(/* NOI18N */
117 		     "sunsoft.jws.visual.rt.base.Attribute",
118 	     /* NOI18N */"sunsoft.jws.visual.rt.type.AttributeConverter");
119         addConverter(/* NOI18N */
120 		     "sunsoft.jws.visual.rt.base.AttributeList",
121 	     /* NOI18N */"sunsoft.jws.visual.rt.type.AttributeListConverter");
122         addConverter(/* NOI18N */"sunsoft.jws.visual.rt.type.ImageRef",
123 	     /* NOI18N */"sunsoft.jws.visual.rt.type.ImageRefConverter");
124         addConverter(/* NOI18N */
125 		     "sunsoft.jws.visual.rt.type.AlignmentEnum",
126 	     /* NOI18N */"sunsoft.jws.visual.rt.type.BaseEnumConverter");
127         addConverter(/* NOI18N */
128 		     "sunsoft.jws.visual.rt.type.AnchorEnum",
129 	     /* NOI18N */"sunsoft.jws.visual.rt.type.BaseEnumConverter");
130         addConverter(/* NOI18N */
131 		     "sunsoft.jws.visual.rt.type.OrientationEnum",
132 	     /* NOI18N */"sunsoft.jws.visual.rt.type.BaseEnumConverter");
133         addConverter(/* NOI18N */
134 		     "sunsoft.jws.visual.rt.type.ReliefEnum",
135 	     /* NOI18N */"sunsoft.jws.visual.rt.type.BaseEnumConverter");
136         addConverter(/* NOI18N */"sunsoft.jws.visual.rt.type.ModeEnum",
137 	     /* NOI18N */"sunsoft.jws.visual.rt.type.BaseEnumConverter");
138         addConverter(/* NOI18N */"unknown", /* NOI18N */
139 		     "sunsoft.jws.visual.rt.type.UnknownTypeConverter");
140     }
141 
142     /**
143      * Returns an existing converter for the given type.  Creates a new
144      * converter only if necessary (typically the first
145      * time one is asked for.)
146     */
getConverter(String typeName)147     public static Converter getConverter(String typeName) {
148         Converter converter;
149 
150         converter = (Converter)converterInstanceTable.get(typeName);
151         if (converter != null)
152             return converter;
153 
154         String converterType = (String) converterNameTable.get
155 	    (typeName);
156         if (converterType == null) {
157             /* JSTYLED */
158 	    // Load the class for the type and try again. Some types have
159             // static initializers that register their converters.
160             loadType(typeName);
161             converterType = (String) converterNameTable.get(typeName);
162         }
163 
164         if (converterType == null) {
165             converterType = (String) converterNameTable.get
166 		(/* NOI18N */"unknown");
167             if (converterType == null)
168                 /* JSTYLED */
169 		throw new Error(Global.getMsg("sunsoft.jws.visual.rt.type.Converter.No__converter__defined.20"));
170         }
171         try {
172             Class c = Class.forName(converterType);
173             converter = (Converter) c.newInstance();
174             converter.setConverterType(typeName);
175             converterInstanceTable.put(typeName, converter);
176             return converter;
177         }
178         catch (Exception e) {
179             throw new Error(e.getMessage());
180         }
181     }
182 
loadType(String typeName)183     private static void loadType(String typeName) {
184         // For arrays, use the array type
185         if (typeName.charAt(0) == /* NOI18N */ '[') {
186             int i;
187             int len = typeName.length();
188             for (i = 0; i < len; i++) {
189                 if (typeName.charAt(i) != /* NOI18N */ '[')
190                     break;
191             }
192             i++;
193             if (i < len)
194                 typeName = typeName.substring(i, len-1);
195         }
196 
197         try {
198             Class.forName(typeName);
199         }
200         catch (ClassNotFoundException ex) {
201             /* JSTYLED */
202 	    System.out.println(Global.getMsg("sunsoft.jws.visual.rt.type.Converter.Class__not__found__for__.21") + typeName + /* NOI18N */"\".");
203         }
204     }
205 
206     /**
207      * Returns true if there is a converter for the given type.
208      */
hasConverter(String typeName)209     public static boolean hasConverter(String typeName) {
210         return (converterNameTable.containsKey(typeName));
211     }
212 
213     /**
214      * The type editors (for more complex types.)
215      */
216     private static Hashtable typeEditorNameTable = new Hashtable();
217 
218     /**
219      * Registers a type editor for a type.  At run-time (in generated
220      * applications) there will typically be no editors, but they are
221      * needed for the attribute editor in the designer.  The designer
222      * will set up all the standard ones.
223      *
224      * @see TypeEditor
225      */
addTypeEditor(String typeName, String editorClassName)226     public static void addTypeEditor(String typeName,
227 				     String editorClassName) {
228         typeEditorNameTable.put(typeName, editorClassName);
229     }
230 
231     /**
232      * Returns true if there is an editor for the given type.
233      *
234      * @see TypeEditor
235      */
hasTypeEditor(String typeName)236     public static boolean hasTypeEditor(String typeName) {
237         return (typeEditorNameTable.containsKey(typeName));
238     }
239 
240     /* BEGIN JSTYLED */
241     /**
242      * Returns a new instance of a type editor.
243      * The caller (typically the
244      * Designer) gets a new one of these every time, one for each
245      * attribute being edited, even if they are the same type.  Caching
246      * instances of these type editors is up to the caller.
247      */
248     /* END JSTYLED */
249 
newTypeEditor(String typeName)250     public static TypeEditor newTypeEditor(String typeName) {
251         String editorType = (String) typeEditorNameTable.get(typeName);
252 
253         if (editorType != null) {
254             try {
255                 // instances of type editors are NOT cached
256                 Class c = Class.forName(editorType);
257                 return ((TypeEditor) c.newInstance());
258             }
259             catch (Exception ex) {
260                 /* JSTYLED */
261 		throw new VJException(Global.newline() + /* NOI18N */"    " + ex.toString());
262             }
263         }
264 
265         return null;
266     }
267 
268     /**
269      * Returns whether a converter instance has an
270      * associated type editor.
271      *
272      * @see TypeEditor
273      */
hasTypeEditor()274     public boolean hasTypeEditor() {
275         return (hasTypeEditor(getConverterType()));
276     }
277 
278     /**
279      * Returns a new instance of the type editor associated with this
280      * converter.
281      */
newTypeEditor()282     public TypeEditor newTypeEditor() {
283         return (newTypeEditor(getConverterType()));
284     }
285     /* JSTYLED */
286     // ------ Interfaces for Sub-Classers -----------------------------------
287 
288     /**
289      * The name of the type being edited.
290      */
291     protected String converterType;
292 
293     /**
294      * An interface that can be overridden in sub-classes
295      * to whom the type
296      * converted is important.
297      *
298      * @see BaseEnumConverter
299      */
setConverterType(String type)300     protected void setConverterType(String type) {
301         converterType = type;
302     }
303 
304     /**
305      * Returns the type of object converted by this converter.
306      */
getConverterType()307     public String getConverterType() {
308         return (converterType);
309     }
310 
311     /* BEGIN JSTYLED */
312     /**
313      * Returns the string representation for an instance of
314      * the type this
315      * converter converts.  Must be declared in subclasses
316      * to convert an
317      * object of the type specific to that subclass of Converter.
318      * <p>
319      * One of the two "convertToString" methods must be overridden in
320      * the converter sub-class.  The overridden "convertToString"
321      * method
322      * should NOT call "super.convertToString".  It is preferrable to
323      * override the StringBuffer version (the other one) because this
324      * will result in better performance.
325      */
326     /* END JSTYLED */
convertToString(Object obj)327     public String convertToString(Object obj) {
328         enterConvert(TOSTRING, false);
329         StringBuffer buf = new StringBuffer();
330         convertToString(obj, buf);
331         exitConvert(TOSTRING, false);
332 
333         return buf.toString();
334     }
335 
336     /**
337      * Places a string representation of an instance of the type this
338      * converter converts into a string buffer.
339      */
convertToString(Object obj, StringBuffer buf)340     public void convertToString(Object obj, StringBuffer buf) {
341         enterConvert(TOSTRING, true);
342         buf.append(convertToString(obj));
343         exitConvert(TOSTRING, true);
344     }
345 
346     /**
347      * Returns a new instance of the type this converter converts, as
348      * specified by the string given.  Must be declared
349      * in subclasses of
350      * Converter to convert a string representation into an object of
351      * the type converted by the subclass.
352      */
convertFromString(String s)353     public abstract Object convertFromString(String s);
354 
355     /**
356      * Converts an instance of the type into a block of code.
357      */
convertToCodeBlock(String amName, Attribute a, int indent, StringBuffer buf)358     public void convertToCodeBlock(String amName,
359 				   Attribute a, int indent, StringBuffer buf) {
360 
361         Converter c = getConverter(a.getType());
362         String attr_name;
363 
364         indent(buf, indent);
365         buf.append(amName);
366         buf.append(/* NOI18N */".set(\"");
367         attr_name = a.getName();
368         buf.append(attr_name);
369         buf.append(/* NOI18N */"\", ");
370         buf.append(c.convertToCode(a.getValue()));
371         buf.append(/* NOI18N */");");
372         newline(buf);
373     }
374 
375     /**
376      * Converts an instance of the type converted into a line of code.
377      * This method provides a default way for any type to get a
378      * convertToCode method into it.  It generates code that will feed
379      * the string representation of the object into the
380      * appropriate type
381      * converter.  The performance isn't as good as customized
382      * convertToCode functions in subclasses since more classes have to
383      * be loaded at runtime.
384      */
convertToCode(Object obj)385     public String convertToCode(Object obj) {
386         if (obj != null)
387             return (/* NOI18N */"convert(\"" +
388 		    obj.getClass().getName() + /* NOI18N */"\", \""
389 		    + convertToString(obj) + /* NOI18N */"\")");
390         else
391             return (/* NOI18N */"null");
392     }
393 
394     /**
395      * Returns the string that should be displayed in the attribute
396      * editor.  Subclassers that want something displayed other than
397      * what is returned from convertToString should override this
398      * method to return that.
399      */
displayString(Object obj)400     public String displayString(Object obj) {
401         return (convertToString(obj));
402     }
403 
404     /**
405      * Returns true if this type should be displayed in an editor.
406      *
407      * For the attribute editor, a return value of false means that the
408      * the textfield will be hidden.
409      *
410      * @return true
411      */
viewableAsString()412     public boolean viewableAsString() {
413         return true;
414     }
415 
416     /**
417      * Returns true if this type is simple enough to be
418      * edited as a string
419      * in an editor.
420      *
421      * Sub-classers that represent type too complex for
422      * this should override
423      * this function to return false.  For the attribute editor,
424      * this means
425      * that the textfield will be read-only.
426      *
427      * @see #viewableAsString
428      * @return same as viewableAsString
429      */
editableAsString()430     public boolean editableAsString() {
431         return viewableAsString();
432     }
433 
434     /**
435      * These weird looking enter/exit methods ensure that the converter
436      * sub-class is overriding at least one of the "convertToString"
437      * methods, and at least one of the "convertToCode" methods.
438      * An error will be thrown at runtime if this in not the case.
439      * If this check wasn't done here , then the failure to
440      * override one
441      * of the methods would result in an infinite loop.
442      */
443     private static final int TOSTRING = 0;
444     private static final int TOCODE = 1;
445 
446     private boolean converting[] = {false, false};
447     private boolean isBuffered[] = {false, false};
448     private int convertRecurse[] = {0, 0};
449 
enterConvert(int c, boolean isBuffered)450     private void enterConvert(int c, boolean isBuffered) {
451         if (converting[c] && this.isBuffered[c] != isBuffered)
452             throw new Error(Global.getMsg(
453 	  "sunsoft.jws.visual.rt.type.Converter.Sub-classes__of__Conve.22"));
454 
455         this.isBuffered[c] = isBuffered;
456         converting[c] = true;
457         convertRecurse[c]++;
458     }
459 
exitConvert(int c, boolean isBuffered)460     private void exitConvert(int c, boolean isBuffered) {
461         if (!converting[c])
462 	    /* BEGIN JSTYLED */
463 	    throw new Error(Global.getMsg("sunsoft.jws.visual.rt.type.Converter.Convert__exit__without.25"));
464 
465 	if (this.isBuffered[c] != isBuffered)
466 	    throw new Error(Global.getMsg("sunsoft.jws.visual.rt.type.Converter.isBuffered__mismatch__.26"));
467 
468 	/* END JSTYLED */
469 	convertRecurse[c]--;
470         if (convertRecurse[c] == 0)
471             converting[c] = false;
472     }
473     /* BEGIN JSTYLED */
474     // ------ Utility Functions ----------------------------------------------
475 
476     /**
477      * Returns a string that can be used as a newline.
478      * This string includes
479      * a carriage return if we are running on Windows.
480      */
481     /* END JSTYLED */
newline()482     public static String newline() {
483         return Global.newline();
484     }
485 
486     /**
487      * Appends a newline to buf.  This also appends a carriage return
488      * if we are running on Windows.
489      */
newline(StringBuffer buf)490     public static void newline(StringBuffer buf) {
491         Global.newline(buf);
492     }
493 
494     private static final String indentString = /* NOI18N */"  ";
495     private static int indentLevel = 0;
496 
497     /**
498      * Appends spaces to "buf" based on the current indent level.
499      */
indent(StringBuffer buf)500     protected static void indent(StringBuffer buf) {
501         for (int i = 0; i < indentLevel; i++)
502             buf.append(indentString);
503     }
504 
505     /**
506      * Appends spaces to "buf" based on the given indent level.
507      */
indent(StringBuffer buf, int indentLevel)508     protected static void indent(StringBuffer buf, int indentLevel) {
509         for (int i = 0; i < indentLevel; i++)
510             buf.append(/* NOI18N */ ' ');
511     }
512 
513     /**
514      * Increments the indent level.
515      */
incrIndent()516     protected static void incrIndent() {
517         indentLevel++;
518     }
519 
520     /**
521      * Decrements the indent level.
522      */
decrIndent()523     protected static void decrIndent() {
524         indentLevel--;
525     }
526 
527     /**
528      * Returns the current indent level.
529      */
indentLevel()530     protected static int indentLevel() {
531         return indentLevel;
532     }
533 
534     /**
535      * Returns the last token in a class name.  i.e. the name that you
536      * can use for a class when you've imported the class already.
537      */
shortClassName(String className)538     public static String shortClassName(String className) {
539         int index = className.lastIndexOf(/* NOI18N */ '.');
540         if (index == -1)
541             return (className);
542         else
543             return (className.substring(index + 1));
544     }
545 
546 }
547