xref: /aoo4110/main/ridljar/com/sun/star/uno/Type.java (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package com.sun.star.uno;
25 
26 import java.util.HashMap;
27 
28 /**
29  * Represents the UNO built-in type <code>TYPE</code>.
30  *
31  * <p>The UNO type is not directly mapped to <code>java.lang.Class</code> for at
32  * least two reasons.  For one, some UNO types (like <code>UNSIGNED
33  * SHORT</code>) do not have a matching Java class.  For another, it can be
34  * necessary to describe a type which is unknown to the Java runtime system
35  * (for example, for delaying the need of a class, so that it is possible to
36  * generate it on the fly.)
37  *
38  * <p>A <code>Type</code> is uniquely determined by its type class (a
39  * <code>TypeClass</code>) and its type name (a <code>String</code>); these two
40  * will never be <code>null</code>.  A <code>Type</code> may have an additional
41  * "z class" (a <code>java.lang.Class</code>), giving a Java class type that
42  * corresponds to the UNO type.  Also, a <code>Type</code> can cache a type
43  * description (a <code>com.sun.star.uno.ITypeDescription</code>), which can be
44  * computed and set by <code>TypeDescription.getTypeDescription</code>.
45  */
46 public class Type {
47     // The following private static members and static initializer must come
48     // first in the class definition, so that the class can be initialized
49     // sucessfully:
50 
51     private static final String TYPE_NAME_VOID = "void";
52     private static final String TYPE_NAME_BOOLEAN = "boolean";
53     private static final String TYPE_NAME_BYTE = "byte";
54     private static final String TYPE_NAME_SHORT = "short";
55     private static final String TYPE_NAME_UNSIGNED_SHORT = "unsigned short";
56     private static final String TYPE_NAME_LONG = "long";
57     private static final String TYPE_NAME_UNSIGNED_LONG = "unsigned long";
58     private static final String TYPE_NAME_HYPER = "hyper";
59     private static final String TYPE_NAME_UNSIGNED_HYPER = "unsigned hyper";
60     private static final String TYPE_NAME_FLOAT = "float";
61     private static final String TYPE_NAME_DOUBLE = "double";
62     private static final String TYPE_NAME_CHAR = "char";
63     private static final String TYPE_NAME_STRING = "string";
64     private static final String TYPE_NAME_TYPE = "type";
65     private static final String TYPE_NAME_ANY = "any";
66 
67     // must be sorted same as TypeClass:
68     private static final String[] __typeClassToTypeName = new String[] {
69         TYPE_NAME_VOID,
70         TYPE_NAME_CHAR,
71         TYPE_NAME_BOOLEAN,
72         TYPE_NAME_BYTE,
73         TYPE_NAME_SHORT,
74         TYPE_NAME_UNSIGNED_SHORT,
75         TYPE_NAME_LONG,
76         TYPE_NAME_UNSIGNED_LONG,
77         TYPE_NAME_HYPER,
78         TYPE_NAME_UNSIGNED_HYPER,
79         TYPE_NAME_FLOAT,
80         TYPE_NAME_DOUBLE,
81         TYPE_NAME_STRING,
82         TYPE_NAME_TYPE,
83         TYPE_NAME_ANY
84     };
85 
86     private static final HashMap __javaClassToTypeClass = new HashMap();
87     static {
__javaClassToTypeClass.put( void.class, new TypeClass[] { TypeClass.VOID, TypeClass.VOID })88         __javaClassToTypeClass.put(
89             void.class, new TypeClass[] { TypeClass.VOID, TypeClass.VOID });
__javaClassToTypeClass.put( Void.class, new TypeClass[] { TypeClass.VOID, TypeClass.VOID })90         __javaClassToTypeClass.put(
91             Void.class, new TypeClass[] { TypeClass.VOID, TypeClass.VOID });
__javaClassToTypeClass.put( boolean.class, new TypeClass[] { TypeClass.BOOLEAN, TypeClass.BOOLEAN })92         __javaClassToTypeClass.put(
93             boolean.class,
94             new TypeClass[] { TypeClass.BOOLEAN, TypeClass.BOOLEAN });
__javaClassToTypeClass.put( Boolean.class, new TypeClass[] { TypeClass.BOOLEAN, TypeClass.BOOLEAN })95         __javaClassToTypeClass.put(
96             Boolean.class,
97             new TypeClass[] { TypeClass.BOOLEAN, TypeClass.BOOLEAN });
__javaClassToTypeClass.put( byte.class, new TypeClass[] { TypeClass.BYTE, TypeClass.BYTE })98         __javaClassToTypeClass.put(
99             byte.class, new TypeClass[] { TypeClass.BYTE, TypeClass.BYTE });
__javaClassToTypeClass.put( Byte.class, new TypeClass[] { TypeClass.BYTE, TypeClass.BYTE })100         __javaClassToTypeClass.put(
101             Byte.class, new TypeClass[] { TypeClass.BYTE, TypeClass.BYTE });
__javaClassToTypeClass.put( short.class, new TypeClass[] { TypeClass.SHORT, TypeClass.UNSIGNED_SHORT })102         __javaClassToTypeClass.put(
103             short.class,
104             new TypeClass[] { TypeClass.SHORT, TypeClass.UNSIGNED_SHORT });
__javaClassToTypeClass.put( Short.class, new TypeClass[] { TypeClass.SHORT, TypeClass.UNSIGNED_SHORT })105         __javaClassToTypeClass.put(
106             Short.class,
107             new TypeClass[] { TypeClass.SHORT, TypeClass.UNSIGNED_SHORT });
__javaClassToTypeClass.put( int.class, new TypeClass[] { TypeClass.LONG, TypeClass.UNSIGNED_LONG })108         __javaClassToTypeClass.put(
109             int.class,
110             new TypeClass[] { TypeClass.LONG, TypeClass.UNSIGNED_LONG });
__javaClassToTypeClass.put( Integer.class, new TypeClass[] { TypeClass.LONG, TypeClass.UNSIGNED_LONG })111         __javaClassToTypeClass.put(
112             Integer.class,
113             new TypeClass[] { TypeClass.LONG, TypeClass.UNSIGNED_LONG });
__javaClassToTypeClass.put( long.class, new TypeClass[] { TypeClass.HYPER, TypeClass.UNSIGNED_HYPER })114         __javaClassToTypeClass.put(
115             long.class,
116             new TypeClass[] { TypeClass.HYPER, TypeClass.UNSIGNED_HYPER });
__javaClassToTypeClass.put( Long.class, new TypeClass[] { TypeClass.HYPER, TypeClass.UNSIGNED_HYPER })117         __javaClassToTypeClass.put(
118             Long.class,
119             new TypeClass[] { TypeClass.HYPER, TypeClass.UNSIGNED_HYPER });
__javaClassToTypeClass.put( float.class, new TypeClass[] { TypeClass.FLOAT, TypeClass.FLOAT })120         __javaClassToTypeClass.put(
121             float.class, new TypeClass[] { TypeClass.FLOAT, TypeClass.FLOAT });
__javaClassToTypeClass.put( Float.class, new TypeClass[] { TypeClass.FLOAT, TypeClass.FLOAT })122         __javaClassToTypeClass.put(
123             Float.class, new TypeClass[] { TypeClass.FLOAT, TypeClass.FLOAT });
__javaClassToTypeClass.put( double.class, new TypeClass[] { TypeClass.DOUBLE, TypeClass.DOUBLE })124         __javaClassToTypeClass.put(
125             double.class,
126             new TypeClass[] { TypeClass.DOUBLE, TypeClass.DOUBLE });
__javaClassToTypeClass.put( Double.class, new TypeClass[] { TypeClass.DOUBLE, TypeClass.DOUBLE })127         __javaClassToTypeClass.put(
128             Double.class,
129             new TypeClass[] { TypeClass.DOUBLE, TypeClass.DOUBLE });
__javaClassToTypeClass.put( char.class, new TypeClass[] { TypeClass.CHAR, TypeClass.CHAR })130         __javaClassToTypeClass.put(
131             char.class, new TypeClass[] { TypeClass.CHAR, TypeClass.CHAR });
__javaClassToTypeClass.put( Character.class, new TypeClass[] { TypeClass.CHAR, TypeClass.CHAR })132         __javaClassToTypeClass.put(
133             Character.class,
134             new TypeClass[] { TypeClass.CHAR, TypeClass.CHAR });
__javaClassToTypeClass.put( String.class, new TypeClass[] { TypeClass.STRING, TypeClass.STRING })135         __javaClassToTypeClass.put(
136             String.class,
137             new TypeClass[] { TypeClass.STRING, TypeClass.STRING });
__javaClassToTypeClass.put( Type.class, new TypeClass[] { TypeClass.TYPE, TypeClass.TYPE })138         __javaClassToTypeClass.put(
139             Type.class, new TypeClass[] { TypeClass.TYPE, TypeClass.TYPE });
__javaClassToTypeClass.put( Any.class, new TypeClass[] { TypeClass.ANY, TypeClass.ANY })140         __javaClassToTypeClass.put(
141             Any.class, new TypeClass[] { TypeClass.ANY, TypeClass.ANY });
__javaClassToTypeClass.put( Object.class, new TypeClass[] { TypeClass.ANY, TypeClass.INTERFACE })142         __javaClassToTypeClass.put(
143             Object.class,
144             new TypeClass[] { TypeClass.ANY, TypeClass.INTERFACE });
145     }
146 
147     public static final Type VOID = new Type(void.class);
148     public static final Type CHAR = new Type(char.class);
149     public static final Type BOOLEAN = new Type(boolean.class);
150     public static final Type BYTE = new Type(byte.class);
151     public static final Type SHORT = new Type(short.class);
152     public static final Type UNSIGNED_SHORT = new Type(
153         TYPE_NAME_UNSIGNED_SHORT, TypeClass.UNSIGNED_SHORT);
154     public static final Type LONG = new Type(int.class);
155     public static final Type UNSIGNED_LONG = new Type(
156         TYPE_NAME_UNSIGNED_LONG, TypeClass.UNSIGNED_LONG);
157     public static final Type HYPER = new Type(long.class);
158     public static final Type UNSIGNED_HYPER = new Type(
159         TYPE_NAME_UNSIGNED_HYPER, TypeClass.UNSIGNED_HYPER);
160     public static final Type FLOAT = new Type(float.class);
161     public static final Type DOUBLE = new Type(double.class);
162     public static final Type STRING = new Type(String.class);
163     public static final Type TYPE = new Type(Type.class);
164     public static final Type ANY = new Type(Any.class);
165 
166     /**
167      * Constructs a new <code>Type</code> which defaults to <code>VOID</code>.
168      */
Type()169     public Type() {
170         init(null, void.class, false, false);
171     }
172 
173     /**
174      * Constructs a new <code>Type</code> with the given type class and type
175      * name.
176      *
177      * @param typeName the type name.  Must not be <code>null</code>.
178      * @param typeClass the type class.  Must not be <code>null</code>, and must
179      *     match the <code>typeName</code> (for example, it is illegal to
180      *     combine a <code>typeName</code> of <code>"void"</code> with a
181      *     <code>typeClass</code> of <code>BOOLEAN</code>).
182      */
Type(String typeName, TypeClass typeClass)183     public Type(String typeName, TypeClass typeClass) {
184         _typeClass = typeClass;
185         _typeName = typeName;
186     }
187 
188     /**
189      * Constructs a new <code>Type</code> from the given
190      * <code>java.lang.Class</code>.
191      *
192      * <p>This is equivalent to <code>Type(zClass, false)</code>.</p>
193      *
194      * @param zClass the Java class of this type.  Must not be
195      *     <code>null</code>.
196      */
Type(Class zClass)197     public Type(Class zClass) {
198         init(null, zClass, false, false);
199     }
200 
201     /**
202      * Constructs a new <code>Type</code> from the given
203      * <code>java.lang.Class</code>, handling ambiguous cases.
204      *
205      * <p>In certain cases, one Java class corresponds to two UNO types (e.g.,
206      * the Java class <code>short[].class</code> corresponds to both a sequence
207      * of <code>SHORT</code> and a sequence of <code>UNSIGNED SHORT</code> in
208      * UNO).  In such ambiguous cases, the parameter <code>alternative</code>
209      * controls which UNO type is chosen:</p>
210      * <ul>
211      *   <li>If the Java type is (an array type with element type)
212      *   <code>short</code> or <code>java.lang.Short</code>:  If
213      *   <code>alternative</code> is <code>false</code>, the chosen UNO type is
214      *   (a sequence type with element type) <code>SHORT</code>.  If
215      *   <code>alternative</code> is <code>true</code>, the chosen UNO type is
216      *   (a sequence type with element type) <code>UNSIGNED SHORT</code>.</li>
217      *
218      *   <li>If the Java type is (an array type with element type)
219      *   <code>int</code> or <code>java.lang.Integer</code>:  If
220      *   <code>alternative</code> is <code>false</code>, the chosen UNO type is
221      *   (a sequence type with element type) <code>LONG</code>.  If
222      *   <code>alternative</code> is <code>true</code>, the chosen UNO type is
223      *   (a sequence type with element type) <code>UNSIGNED LONG</code>.</li>
224      *
225      *   <li>If the Java type is (an array type with element type)
226      *   <code>long</code> or <code>java.lang.Long</code>:  If
227      *   <code>alternative</code> is <code>false</code>, the chosen UNO type is
228      *   (a sequence type with element type) <code>HYPER</code>.  If
229      *   <code>alternative</code> is <code>true</code>, the chosen UNO type is
230      *   (a sequence type with element type) <code>UNSIGNED HYPER</code>.</li>
231      *
232      *   <li>If the Java type is (an array type with element type)
233      *   <code>java.lang.Object</code>:  If <code>alternative</code> is
234      *   <code>false</code>, the chosen UNO type is (a sequence type with
235      *   element type) <code>ANY</code>.  If <code>alternative</code> is
236      *   <code>true</code>, the chosen UNO type is (a sequence type with element
237      *   type) <code>com.sun.star.uno.XInterface</code>.</li>
238      * </ul>
239      * <p>In all other cases, the value of <code>alternative</code> is
240      * ignored.</p>
241      *
242      * <p>This constructor cannot be used to create <code>Type</code> instances
243      * that represent (sequences of) instantiated polymorphic struct types.</p>
244      *
245      * @param zClass the Java class of this type; must not be <code>null</code>
246      * @param alternative controls which UNO type to choose in case of
247      *     ambiguities
248      *
249      * @since UDK 3.2.0
250      */
Type(Class zClass, boolean alternative)251     public Type(Class zClass, boolean alternative) {
252         init(null, zClass, alternative, false);
253     }
254 
255     /**
256      * Constructs a new <code>Type</code> from the given type description.
257      *
258      * @param typeDescription a type description.  Must not be
259      *     <code>null</code>.
260      */
Type(ITypeDescription typeDescription)261     public Type(ITypeDescription typeDescription) {
262         _typeName         = typeDescription.getTypeName();
263         _typeClass        = typeDescription.getTypeClass();
264         _iTypeDescription = typeDescription;
265     }
266 
267     /**
268      * Constructs a new <code>Type</code> with the given type name.
269      *
270      * @param typeName the name of this type; must not be <code>null</code>.
271      */
Type(String typeName)272     public Type(String typeName) {
273         if (typeName.startsWith("[]")) {
274             _typeName = typeName;
275             _typeClass = TypeClass.SEQUENCE;
276             return;
277         }
278         for (int i = 0; i < __typeClassToTypeName.length; ++i) {
279             if (__typeClassToTypeName[i].equals(typeName)) {
280                 _typeName = typeName;
281                 _typeClass = TypeClass.fromInt(i);
282                 return;
283             }
284         }
285         int i = typeName.indexOf('<');
286         try {
287             init(
288                 typeName,
289                 Class.forName(i < 0 ? typeName : typeName.substring(0, i)),
290                 false, i >= 0);
291         } catch (ClassNotFoundException e) {
292             throw new RuntimeException(e.toString());
293         }
294     }
295 
296     /**
297      * Constructs a new <code>Type</code> with the given type class.
298      *
299      * @param typeClass the type class of this type; must not be
300      *     <code>null</code>.  Only type classes for simple types are allowed
301      *     here.
302      *
303      * @throws IllegalArgumentException if the given <code>typeClass</code> is
304      *     not simple (for example, a struct or an interface type).  This
305      *     constructor could not find out the type name in such a case.
306      */
Type(TypeClass typeClass)307     public Type(TypeClass typeClass) {
308         if(__isTypeClassPrimitive(typeClass)) {
309             _typeClass = typeClass;
310             _typeName = __typeClassToTypeName[typeClass.getValue()];
311         }
312         else
313             throw new IllegalArgumentException(typeClass + " is not primitive");
314     }
315 
316     /**
317      * Gets the type class.
318      *
319      * @return the type class.  Will never be <code>null</code>, but might be
320      *     <code>UNKNOWN</code>.
321      */
getTypeClass()322     public TypeClass getTypeClass() {
323         return _typeClass;
324     }
325 
326     /**
327      * Gets the type name.
328      *
329      * @return the type name; will never be <code>null</code>
330      */
getTypeName()331     public String getTypeName() {
332         return _typeName;
333     }
334 
335     /**
336      * Gets the Java class.
337      *
338      * @return the type name; may be <code>null</code> in extreme situations
339      *     (inconsistent <code>TypeClass</code>, error loading a class)
340      */
getZClass()341     public Class getZClass() {
342         synchronized (this) {
343             if (_class == null) {
344                 _class = determineClass();
345             }
346         }
347         return _class;
348     }
349 
350     /**
351      * Gives the type description of this type.
352      *
353      * @return the type description; may be <code>null</code>
354      */
getTypeDescription()355     public ITypeDescription getTypeDescription() {
356         return _iTypeDescription;
357     }
358 
359     /**
360      * Sets the type description for this type.
361      *
362      * @param typeDescription the type description
363      */
setTypeDescription(ITypeDescription typeDescription)364     public void setTypeDescription(ITypeDescription typeDescription) {
365         _iTypeDescription = typeDescription;
366     }
367 
368     /**
369      * Determines whether this UNO type is a supertype of another UNO type.
370      *
371      * UNO only defines the following supertype relations:
372      * (1)  A struct type t1 is a supertype of a struct type t2, if either t1
373      * and t2 are the same, or t1 is a direct or indirect parent of t2.
374      * (2)  An exception type t1 is a supertype of an exception type t2, if
375      * either t1 and t2 are the same, or t1 is a direct or indirect parent
376      * of t2.
377      * (3)  An interface type t1 is a supertype of an interface type t2, if
378      * either t1 and t2 are the same, or t1 is a direct or indirect parent
379      * of t2.
380      *
381      * Following the conventions of the Java UNO language binding,
382      * com.sun.star.uno.Exception is not considered a supertype of
383      * com.sun.star.uno.RuntimeException or any exception type derived from
384      * com.sun.star.uno.RuntimeException.
385      *
386      * @param type some Type
387      * @return true if this type is a supertype of the given type
388      *
389      * @since UDK 3.2.0
390      */
isSupertypeOf(Type type)391     public boolean isSupertypeOf(Type type) {
392         if (_typeClass != type._typeClass) {
393             return false;
394         }
395         switch (_typeClass.getValue()) {
396         case TypeClass.SEQUENCE_value:
397         case TypeClass.ENUM_value:
398             return _typeName.equals(type._typeName);
399 
400         case TypeClass.STRUCT_value:
401             // This check exploits the fact that an instantiated polymorphic
402             // struct type may not be the direct base of a struct type:
403             if (_typeName.indexOf('<') >= 0 || type._typeName.indexOf('<') >= 0)
404             {
405                 return _typeName.equals(type._typeName);
406             }
407         case TypeClass.EXCEPTION_value:
408         case TypeClass.INTERFACE_value:
409             Class c1 = getZClass();
410             Class c2 = type.getZClass();
411             return c1 != null && c2 != null && c1.isAssignableFrom(c2);
412 
413         default:
414             return true;
415         }
416     }
417 
418     // @see java.lang.Object#equals
equals(Object obj)419     public boolean equals(Object obj) {
420         return obj instanceof Type
421             && _typeClass == ((Type) obj)._typeClass
422             && _typeName.equals(((Type) obj)._typeName);
423     }
424 
425     // @see java.lang.Object#hashCode
hashCode()426     public int hashCode() {
427         return _typeName.hashCode();
428     }
429 
430     // @see java.lang.Object#toString
toString()431     public String toString() {
432         return "Type[" + _typeName + "]";
433     }
434 
init( String name, Class zClass, boolean alternative, boolean arguments)435     private void init(
436         String name, Class zClass, boolean alternative, boolean arguments)
437     {
438         TypeClass[] tc = (TypeClass[]) __javaClassToTypeClass.get(zClass);
439         if (tc != null) {
440             // tc only contains primitive type classes, except for
441             // TypeClass.INTERFACE, which stands for XInterface (the alternative
442             // interpretation of java.lang.Object):
443             _typeClass = tc[alternative ? 1 : 0];
444             _typeName = _typeClass == TypeClass.INTERFACE
445                 ? XInterface.class.getName()
446                 : __typeClassToTypeName[_typeClass.getValue()];
447             // do not assign _class from zClass, as _class should always be
448             // normalized (e.g., boolean.class instead of
449             // java.lang.Boolean.class); getZClass will later calculate the
450             // correct class when needed
451         } else if (zClass.isArray()) {
452             Type t = new Type(zClass.getComponentType(), alternative);
453             _typeClass = t.getTypeClass() != TypeClass.UNKNOWN
454                 ? TypeClass.SEQUENCE : TypeClass.UNKNOWN;
455             _typeName = "[]" + t.getTypeName();
456             // do not assign _class from zClass, as _class should always be
457             // normalized (e.g., boolean[].class instead of
458             // java.lang.Boolean[].class); getZClass will later calculate the
459             // correct class when needed
460         } else if (Enum.class.isAssignableFrom(zClass)) {
461             _typeClass = zClass != Enum.class
462                 ? TypeClass.ENUM : TypeClass.UNKNOWN;
463             _typeName = zClass.getName();
464             _class = zClass;
465         } else if (Throwable.class.isAssignableFrom(zClass)) {
466             _typeClass
467                 = com.sun.star.uno.Exception.class.isAssignableFrom(zClass)
468                 || com.sun.star.uno.RuntimeException.class.isAssignableFrom(
469                     zClass)
470                 ? TypeClass.EXCEPTION : TypeClass.UNKNOWN;
471             _typeName = zClass.getName();
472             _class = zClass;
473         } else if (zClass.isInterface()) {
474             _typeClass = XInterface.class.isAssignableFrom(zClass)
475                 ? TypeClass.INTERFACE : TypeClass.UNKNOWN;
476             _typeName = zClass.getName();
477             _class = zClass;
478         } else if (XInterface.class.isAssignableFrom(zClass)) {
479             // This case is needed by code that uses this constructor to
480             // calculate the UNO type corresponding to a Java object:
481             _typeClass = TypeClass.INTERFACE;
482             _typeName = XInterface.class.getName();
483             _class = XInterface.class;
484         } else {
485             // assert zClass != Object.class && !zClass.isPrimitive();
486             _typeClass = TypeClass.STRUCT;
487             _typeName = name == null ? zClass.getName() : name;
488             _class = zClass;
489         }
490         if (arguments && _typeClass != TypeClass.STRUCT) {
491             throw new IllegalArgumentException(
492                 zClass + " cannot have type arguments");
493         }
494     }
495 
determineClass()496     private Class determineClass() {
497         switch (_typeClass.getValue()) {
498         case TypeClass.VOID_value:
499             return _typeName.equals(TYPE_NAME_VOID) ? void.class : null;
500 
501         case TypeClass.BOOLEAN_value:
502             return _typeName.equals(TYPE_NAME_BOOLEAN) ? boolean.class : null;
503 
504         case TypeClass.BYTE_value:
505             return _typeName.equals(TYPE_NAME_BYTE) ? byte.class : null;
506 
507         case TypeClass.SHORT_value:
508             return _typeName.equals(TYPE_NAME_SHORT) ? short.class : null;
509 
510         case TypeClass.UNSIGNED_SHORT_value:
511             return _typeName.equals(TYPE_NAME_UNSIGNED_SHORT)
512                 ? short.class : null;
513 
514         case TypeClass.LONG_value:
515             return _typeName.equals(TYPE_NAME_LONG) ? int.class : null;
516 
517         case TypeClass.UNSIGNED_LONG_value:
518             return _typeName.equals(TYPE_NAME_UNSIGNED_LONG) ? int.class : null;
519 
520         case TypeClass.HYPER_value:
521             return _typeName.equals(TYPE_NAME_HYPER) ? long.class : null;
522 
523         case TypeClass.UNSIGNED_HYPER_value:
524             return _typeName.equals(TYPE_NAME_UNSIGNED_HYPER)
525                 ? long.class : null;
526 
527         case TypeClass.FLOAT_value:
528             return _typeName.equals(TYPE_NAME_FLOAT) ? float.class : null;
529 
530         case TypeClass.DOUBLE_value:
531             return _typeName.equals(TYPE_NAME_DOUBLE) ? double.class : null;
532 
533         case TypeClass.CHAR_value:
534             return _typeName.equals(TYPE_NAME_CHAR) ? char.class : null;
535 
536         case TypeClass.STRING_value:
537             return _typeName.equals(TYPE_NAME_STRING) ? String.class : null;
538 
539         case TypeClass.TYPE_value:
540             return _typeName.equals(TYPE_NAME_TYPE) ? Type.class : null;
541 
542         case TypeClass.ANY_value:
543             return _typeName.equals(TYPE_NAME_ANY) ? Object.class : null;
544 
545         case TypeClass.SEQUENCE_value:
546             StringBuffer buf = new StringBuffer();
547             int offset = 0;
548             for (; _typeName.startsWith("[]", offset); offset += "[]".length())
549             {
550                 buf.append('[');
551             }
552             if (buf.length() == 0) {
553                 return null;
554             }
555             String base = _typeName.substring(offset);
556             if (base.equals(TYPE_NAME_VOID)) {
557                 buf.append('V');
558             } else if (base.equals(TYPE_NAME_BOOLEAN)) {
559                 buf.append('Z');
560             } else if (base.equals(TYPE_NAME_BYTE)) {
561                 buf.append('B');
562             } else if (base.equals(TYPE_NAME_SHORT)
563                        || base.equals(TYPE_NAME_UNSIGNED_SHORT)) {
564                 buf.append('S');
565             } else if (base.equals(TYPE_NAME_LONG)
566                        || base.equals(TYPE_NAME_UNSIGNED_LONG)) {
567                 buf.append('I');
568             } else if (base.equals(TYPE_NAME_HYPER)
569                        || base.equals(TYPE_NAME_UNSIGNED_HYPER)) {
570                 buf.append('J');
571             } else if (base.equals(TYPE_NAME_FLOAT)) {
572                 buf.append('F');
573             } else if (base.equals(TYPE_NAME_DOUBLE)) {
574                 buf.append('D');
575             } else if (base.equals(TYPE_NAME_CHAR)) {
576                 buf.append('C');
577             } else if (base.equals(TYPE_NAME_STRING)) {
578                 buf.append("Ljava.lang.String;");
579             } else if (base.equals(TYPE_NAME_TYPE)) {
580                 buf.append("Lcom.sun.star.uno.Type;");
581             } else if (base.equals(TYPE_NAME_ANY)) {
582                 buf.append("Ljava.lang.Object;");
583             } else {
584                 int args = base.indexOf('<');
585                 if (args >= 0) {
586                     base = base.substring(0, args);
587                 }
588                 Class c;
589                 try {
590                     c = Class.forName(base);
591                 } catch (ClassNotFoundException e) {
592                     return null;
593                 }
594                 if (args < 0 && new Type(c).getTypeClass() == TypeClass.UNKNOWN)
595                 {
596                     return null;
597                 }
598                 buf.append('L');
599                 buf.append(base);
600                 buf.append(';');
601             }
602             try {
603                 return Class.forName(buf.toString());
604             } catch (ClassNotFoundException e) {
605                 return null;
606             }
607 
608         case TypeClass.ENUM_value:
609         case TypeClass.EXCEPTION_value:
610         case TypeClass.INTERFACE_value:
611             {
612                 Class c;
613                 try {
614                     c = Class.forName(_typeName);
615                 } catch (ClassNotFoundException e) {
616                     return null;
617                 }
618                 return new Type(c).equals(this) ? c : null;
619             }
620 
621         case TypeClass.STRUCT_value:
622             {
623                 int args = _typeName.indexOf('<');
624                 Class c;
625                 try {
626                     c = Class.forName(
627                         args < 0 ? _typeName : _typeName.substring(0, args));
628                 } catch (ClassNotFoundException e) {
629                     return null;
630                 }
631                 return args >= 0 || new Type(c).equals(this) ? c : null;
632             }
633 
634         default:
635             return null;
636         }
637     }
638 
__isTypeClassPrimitive(TypeClass typeClass)639     private static boolean __isTypeClassPrimitive(TypeClass typeClass) {
640         return typeClass.getValue() < __typeClassToTypeName.length;
641     }
642 
643     protected TypeClass _typeClass; // TODO should be final
644     protected String _typeName; // TODO should be final
645 
646     protected Class _class;
647     protected ITypeDescription _iTypeDescription;
648 }
649