1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 package com.sun.star.uno; 21 22 /** 23 * This class provides static methods which aim at exploring the contents of an 24 * Any and extracting its value. 25 * 26 * <p>All public methods take an Object argument that either is the immediate object, 27 * such as Boolean, Type, interface implementation, or an Any that contains an 28 * object.</p> 29 * 30 * <p>The methods which extract the value do a widening conversion. See the 31 * method comments for the respective conversions.</p> 32 */ 33 public class AnyConverter 34 { 35 /** 36 * Determines the type of an Any object. 37 * 38 * @param object any object. 39 * @return type object. 40 */ getType( Object object )41 public static Type getType( Object object ) 42 { 43 Type t; 44 if (null == object) 45 { 46 t = m_XInterface_type; 47 } 48 else if (object instanceof Any) 49 { 50 t = ((Any)object).getType(); 51 // nested any 52 if (TypeClass.ANY_value == t.getTypeClass().getValue()) 53 return getType( ((Any)object).getObject() ); 54 } 55 else 56 { 57 t = new Type( object.getClass() ); 58 } 59 return t; 60 } 61 62 /** 63 * Checks if the any contains the idl type <code>void</code>. 64 * 65 * @param object the object to check. 66 * @return true when the any is void, false otherwise. 67 */ isVoid(Object object)68 public static boolean isVoid(Object object){ 69 return containsType(TypeClass.VOID, object); 70 } 71 72 /** 73 * Checks if the any contains a value of the idl type <code>char</code>. 74 * 75 * @param object the object to check. 76 * @return true when the any contains a char, false otherwise. 77 */ isChar(Object object)78 public static boolean isChar(Object object){ 79 return containsType(TypeClass.CHAR, object); 80 } 81 82 /** 83 * Checks if the any contains a value of the idl type <code>boolean</code>. 84 * 85 * @param object the object to check. 86 * @return true when the any contains a boolean, false otherwise. 87 */ isBoolean(Object object)88 public static boolean isBoolean(Object object){ 89 return containsType(TypeClass.BOOLEAN, object); 90 } 91 92 /** 93 * Checks if the any contains a value of the idl type <code>byte</code>. 94 * 95 * @param object the object to check. 96 * @return true when the any contains a byte, false otherwise. 97 */ isByte(Object object)98 public static boolean isByte(Object object){ 99 return containsType(TypeClass.BYTE, object); 100 } 101 102 /** 103 * Checks if the any contains a value of the idl type <code>short</code>. 104 * 105 * @param object the object to check. 106 * @return true when the any contains a short, false otherwise. 107 */ isShort(Object object)108 public static boolean isShort(Object object){ 109 return containsType(TypeClass.SHORT, object); 110 } 111 112 /** 113 * Checks if the any contains a value of the idl type <code>long</code> 114 * (which maps to a java-int). 115 * 116 * @param object the object to check. 117 * @return true when the any contains a int, false otherwise. 118 */ isInt(Object object)119 public static boolean isInt(Object object){ 120 return containsType(TypeClass.LONG, object); 121 } 122 123 /** 124 * Checks if the any contains a value of the idl type <code>hyper</code> 125 * (which maps to a java-long). 126 * 127 * @param object the object to check. 128 * @return true when the any contains a long, false otherwise. 129 */ isLong(Object object)130 public static boolean isLong(Object object){ 131 return containsType(TypeClass.HYPER, object); 132 } 133 134 /** 135 * Checks if the any contains a value of the idl type <code>float</code>. 136 * 137 * @param object the object to check. 138 * @return true when the any contains a float, false otherwise. 139 */ isFloat(Object object)140 public static boolean isFloat(Object object){ 141 return containsType(TypeClass.FLOAT, object); 142 } 143 144 /** 145 * Checks if the any contains a value of the idl type <code>double</code>. 146 * 147 * @param object the object to check. 148 * @return true when the any contains a double, false otherwise. 149 */ isDouble(Object object)150 public static boolean isDouble(Object object){ 151 return containsType(TypeClass.DOUBLE, object); 152 } 153 154 /** 155 * Checks if the any contains a value of the idl type <code>string</code>. 156 * 157 * @param object the object to check. 158 * @return true when the any contains a string, false otherwise. 159 */ isString(Object object)160 public static boolean isString(Object object){ 161 return containsType(TypeClass.STRING, object); 162 } 163 164 /** 165 * Checks if the any contains a value of the idl type <code>enum</code>. 166 * 167 * @param object the object to check. 168 * @return true if the any contains an enum, false otherwise. 169 */ isEnum(Object object)170 public static boolean isEnum(Object object) 171 { 172 return containsType(TypeClass.ENUM, object); 173 } 174 175 /** 176 * Checks if the any contains a value of the idl type <code>type</code>. 177 * 178 * @param object the object to check. 179 * @return true when the any contains a type, false otherwise. 180 */ isType(Object object)181 public static boolean isType(Object object){ 182 return containsType(TypeClass.TYPE, object); 183 } 184 185 /** 186 * Checks if the any contains an interface, struct, exception, sequence or enum. 187 * 188 * <p>If <em>object</em> is an any with an interface type, then true is also 189 * returned if the any contains a null reference. This is because interfaces 190 * are allowed to have a null value contrary to other UNO types.</p> 191 * 192 * @param object the object to check. 193 * @return true if the any contains an object. 194 */ isObject(Object object)195 public static boolean isObject(Object object) 196 { 197 int tc = getType(object).getTypeClass().getValue(); 198 return (TypeClass.INTERFACE_value == tc || 199 TypeClass.STRUCT_value == tc || 200 TypeClass.EXCEPTION_value == tc || 201 TypeClass.SEQUENCE_value == tc || 202 TypeClass.ENUM_value == tc); 203 } 204 205 /** 206 * Checks if the any contains UNO idl sequence value (meaning a java array 207 * containing elements which are values of UNO idl types). 208 * 209 * @param object the object to check. 210 * @return true when the any contains an object which implements interfaces, 211 * false otherwise. 212 */ isArray(Object object)213 public static boolean isArray(Object object){ 214 return containsType(TypeClass.SEQUENCE, object); 215 } 216 217 /** 218 * Converts a Char object or an Any object containing a Char object into a 219 * simple char. 220 * 221 * @param object the object to convert. 222 * @return the char contained within the object. 223 * @throws com.sun.star.lang.IllegalArgumentException in case no char is 224 * contained within object. 225 * 226 * @see #isChar 227 */ toChar(Object object)228 public static char toChar(Object object) throws com.sun.star.lang.IllegalArgumentException{ 229 Character ret= (Character)convertSimple(TypeClass.CHAR, null, object); 230 return ret.charValue(); 231 } 232 233 /** 234 * Converts a Boolean object or an Any object containing a Boolean object 235 * into a simple boolean. 236 * 237 * @param object the object to convert. 238 * @return the boolean contained within the object 239 * @throws com.sun.star.lang.IllegalArgumentException in case no boolean is 240 * contained within object 241 * 242 * @see #isBoolean 243 */ toBoolean(Object object)244 public static boolean toBoolean(Object object) throws com.sun.star.lang.IllegalArgumentException{ 245 Boolean ret= (Boolean)convertSimple(TypeClass.BOOLEAN, null, object); 246 return ret.booleanValue(); 247 } 248 249 /** 250 * Converts a Byte object or an Any object containing a Byte object into a 251 * simple byte. 252 * 253 * @param object the object to convert. 254 * @return the boolean contained within the object. 255 * @throws com.sun.star.lang.IllegalArgumentException in case no byte is 256 * contained within object. 257 * 258 * @see #isBoolean 259 */ toByte(Object object)260 public static byte toByte(Object object) throws com.sun.star.lang.IllegalArgumentException{ 261 Byte ret= (Byte)convertSimple(TypeClass.BYTE, null, object); 262 return ret.byteValue(); 263 } 264 265 /** 266 * Converts a number object into a simple short and allows widening conversions. 267 * 268 * <p>Allowed argument types are Byte, Short or Any containing these types.</p> 269 * 270 * @param object the object to convert. 271 * @throws com.sun.star.lang.IllegalArgumentException in case no short or 272 * byte is contained within object. 273 * 274 * @return the short contained within the object. 275 */ toShort(Object object)276 public static short toShort(Object object) throws com.sun.star.lang.IllegalArgumentException{ 277 Short ret= (Short)convertSimple(TypeClass.SHORT, null, object); 278 return ret.shortValue(); 279 } 280 /** 281 * Converts a number object into an idl unsigned short and allows widening 282 * conversions. 283 * 284 * <p>Allowed argument types are Anies containing idl unsigned short values.</p> 285 * 286 * @param object the object to convert. 287 * @throws com.sun.star.lang.IllegalArgumentException in case no idl unsigned 288 * short is contained within Any. 289 * 290 * @return an (unsigned) short. 291 */ toUnsignedShort(Object object)292 public static short toUnsignedShort(Object object) 293 throws com.sun.star.lang.IllegalArgumentException 294 { 295 Short ret= (Short)convertSimple(TypeClass.UNSIGNED_SHORT, null, object); 296 return ret.shortValue(); 297 } 298 299 /** 300 * Converts a number object into a simple int and allows widening conversions. 301 * 302 * <p>Allowed argument types are Byte, Short, Integer or Any containing these 303 * types.</p> 304 * 305 * @param object the object to convert. 306 * @throws com.sun.star.lang.IllegalArgumentException in case no short, byte 307 * or int is contained within object. 308 * 309 * @return the int contained within the object. 310 */ toInt(Object object)311 public static int toInt(Object object) throws com.sun.star.lang.IllegalArgumentException{ 312 Integer ret= (Integer) convertSimple( TypeClass.LONG, null, object); 313 return ret.intValue(); 314 } 315 /** 316 * Converts a number object into an idl unsigned long and allows widening 317 * conversions. 318 * 319 * <p>Allowed argument types are Anies containing idl unsigned short or 320 * unsigned long values.</p> 321 * 322 * @param object the object to convert. 323 * @throws com.sun.star.lang.IllegalArgumentException in case no idl unsigned 324 * short nor unsigned long is contained within Any. 325 * 326 * @return an (unsigned) int. 327 */ toUnsignedInt(Object object)328 public static int toUnsignedInt(Object object) 329 throws com.sun.star.lang.IllegalArgumentException 330 { 331 Integer ret = (Integer)convertSimple(TypeClass.UNSIGNED_LONG, null, object); 332 return ret.intValue(); 333 } 334 335 /** 336 * Converts a number object into a simple long and allows widening conversions. 337 * 338 * <p>Allowed argument types are Byte, Short, Integer, Long or Any containing 339 * these types.</p> 340 * 341 * @param object the object to convert. 342 * @throws com.sun.star.lang.IllegalArgumentException in case no short, byte, 343 * int or long is contained within object. 344 * 345 * @return the long contained within the object. 346 */ toLong(Object object)347 public static long toLong(Object object) throws com.sun.star.lang.IllegalArgumentException{ 348 Long ret= (Long) convertSimple( TypeClass.HYPER, null, object); 349 return ret.longValue(); 350 } 351 /** 352 * Converts a number object into an idl unsigned hyper and allows widening 353 * conversions. 354 * 355 * <p>Allowed argument types are Anies containing idl unsigned short, unsigned 356 * long or unsigned hyper values.</p> 357 * 358 * @param object the object to convert. 359 * @throws com.sun.star.lang.IllegalArgumentException in case no idl unsigned 360 * short, nor unsigned long nor unsigned hyper is contained within object. 361 * 362 * @return an (unsigned) long. 363 */ toUnsignedLong(Object object)364 public static long toUnsignedLong(Object object) 365 throws com.sun.star.lang.IllegalArgumentException 366 { 367 Long ret = (Long)convertSimple(TypeClass.UNSIGNED_HYPER, null, object); 368 return ret.longValue(); 369 } 370 371 /** 372 * Converts a number object into a simple float and allows widening conversions. 373 * 374 * <p>Allowed argument types are Byte, Short, Float or Any containing these 375 * types.</p> 376 * 377 * @param object the object to convert. 378 * @throws com.sun.star.lang.IllegalArgumentException in case no byte, short 379 * or float is contained within object. 380 * 381 * @return the float contained within the object. 382 */ toFloat(Object object)383 public static float toFloat(Object object) throws com.sun.star.lang.IllegalArgumentException{ 384 Float ret= (Float) convertSimple( TypeClass.FLOAT,null, object); 385 return ret.floatValue(); 386 } 387 388 /** 389 * Converts a number object into a simple double and allows widening conversions. 390 * 391 * <p>Allowed argument types are Byte, Short, Int, Float, Double or Any 392 * containing these types.</p> 393 * 394 * @param object the object to convert. 395 * @throws com.sun.star.lang.IllegalArgumentException in case no byte, short, 396 * int, float or double is contained within object. 397 * 398 * @return the double contained within the object. 399 */ toDouble(Object object)400 public static double toDouble(Object object) throws com.sun.star.lang.IllegalArgumentException { 401 Double ret= (Double) convertSimple( TypeClass.DOUBLE, null, object); 402 return ret.doubleValue(); 403 } 404 405 /** 406 * Converts a string or an any containing a string into a string. 407 * 408 * @param object the object to convert. 409 * @throws com.sun.star.lang.IllegalArgumentException in case no string is 410 * contained within object. 411 * 412 * @return the string contained within the object. 413 */ toString(Object object)414 public static String toString(Object object) throws com.sun.star.lang.IllegalArgumentException { 415 return (String) convertSimple( TypeClass.STRING, null, object); 416 } 417 418 /** 419 * Converts a Type or an any containing a Type into a Type. 420 * 421 * @param object the object to convert. 422 * @throws com.sun.star.lang.IllegalArgumentException in case no type is 423 * contained within object. 424 * 425 * @return the type contained within the object. 426 */ toType(Object object)427 public static Type toType(Object object) throws com.sun.star.lang.IllegalArgumentException { 428 return (Type) convertSimple( TypeClass.TYPE, null, object); 429 } 430 431 /** 432 * Converts a UNO object (struct, exception, sequence, enum or interface) or 433 * an Any containing these types into a UNO object of a specified destination 434 * type. 435 * 436 * <p> For interfaces, the argument <em>object</em> is queried for the interface 437 * specified by the <em>type</em> argument.</p> 438 * 439 * <p>That query (UnoRuntime.queryInterface) might return null, if the interface 440 * is not implemented or a null-ref or a VOID any is given.</p> 441 * 442 * @param type type of the returned value. 443 * @param object the object that is to be converted. 444 * @throws com.sun.star.lang.IllegalArgumentException in case conversion is 445 * not possible. 446 * 447 * @return destination object. 448 */ toObject(Type type, Object object)449 public static Object toObject(Type type, Object object) 450 throws com.sun.star.lang.IllegalArgumentException 451 { 452 return convertSimple( type.getTypeClass(), type, object ); 453 } 454 /** 455 * Converts a UNO object (struct, exception, sequence, enum or interface) or 456 * an Any containing these types into a UNO object of a specified destination 457 * type. 458 * 459 * <p>For interfaces, the argument <em>object</em> is queried for the interface 460 * specified by the <em>type</em> argument. That query (UnoRuntime.queryInterface) 461 * might return null, if the interface is not implemented or a null-ref or a 462 * VOID any is given.</p> 463 * 464 * @param clazz class of the returned value. 465 * @param object the object that is to be converted. 466 * @throws com.sun.star.lang.IllegalArgumentException in case conversion is 467 * not possible. 468 * 469 * @return destination object. 470 */ toObject(Class<?> clazz, Object object)471 public static Object toObject(Class<?> clazz, Object object) 472 throws com.sun.star.lang.IllegalArgumentException 473 { 474 return toObject( new Type( clazz ), object ); 475 } 476 477 /** 478 * Converts an array or an any containing an array into an array. 479 * 480 * @param object the object to convert. 481 * @throws com.sun.star.lang.IllegalArgumentException in case no array is 482 * contained within object. 483 * 484 * @return the array contained within the object. 485 */ toArray( Object object)486 public static Object toArray( Object object) throws com.sun.star.lang.IllegalArgumentException { 487 return convertSimple( TypeClass.SEQUENCE, null, object); 488 } 489 490 /** 491 * Examines the argument <em>object</em> if is correspond to the type in 492 * argument <em>what</em>. 493 * 494 * <p><em>object</em> is either matched directly against the type or if it is 495 * an any then the contained object is matched against the type.</p> 496 */ containsType( TypeClass what, Object object)497 private static boolean containsType( TypeClass what, Object object){ 498 return (getType(object).getTypeClass().getValue() == what.getValue()); 499 } 500 501 private static final Type m_XInterface_type = new Type( XInterface.class ); 502 convertSimple( TypeClass destTClass, Type destType, Object object_ )503 private static Object convertSimple( TypeClass destTClass, Type destType, Object object_ ) 504 throws com.sun.star.lang.IllegalArgumentException 505 { 506 Object object; 507 Type type; 508 if (object_ instanceof Any) { 509 // unbox 510 Any a = (Any)object_; 511 object = a.getObject(); 512 type = a.getType(); 513 // nested any 514 if (TypeClass.ANY_value == type.getTypeClass().getValue()) 515 return convertSimple( destTClass, destType, object ); 516 } else { 517 object = object_; 518 type = (null == object ? m_XInterface_type : new Type( object.getClass() )); 519 } 520 521 int tc = type.getTypeClass().getValue(); 522 int dest_tc = destTClass.getValue(); 523 524 if (null == object) { 525 // special for interfaces 526 if (TypeClass.INTERFACE_value == tc && dest_tc == tc) 527 return null; 528 } else { 529 switch (dest_tc) { 530 case TypeClass.CHAR_value: 531 if (tc == TypeClass.CHAR_value) 532 return object; 533 break; 534 case TypeClass.BOOLEAN_value: 535 if (tc == TypeClass.BOOLEAN_value) 536 return object; 537 break; 538 case TypeClass.BYTE_value: 539 if (tc == TypeClass.BYTE_value) 540 return object; 541 break; 542 case TypeClass.SHORT_value: 543 switch (tc) { 544 case TypeClass.BYTE_value: 545 return Short.valueOf( ((Byte)object).byteValue() ); 546 case TypeClass.SHORT_value: 547 return object; 548 } 549 break; 550 case TypeClass.UNSIGNED_SHORT_value: 551 switch (tc) { 552 case TypeClass.UNSIGNED_SHORT_value: 553 return object; 554 } 555 break; 556 case TypeClass.LONG_value: 557 switch (tc) { 558 case TypeClass.BYTE_value: 559 return Integer.valueOf( ((Byte)object).byteValue() ); 560 case TypeClass.SHORT_value: 561 case TypeClass.UNSIGNED_SHORT_value: 562 return Integer.valueOf( ((Short)object).shortValue() ); 563 case TypeClass.LONG_value: 564 return object; 565 } 566 break; 567 case TypeClass.UNSIGNED_LONG_value: 568 switch (tc) { 569 case TypeClass.UNSIGNED_SHORT_value: 570 return Integer.valueOf( ((Short)object).shortValue() ); 571 case TypeClass.UNSIGNED_LONG_value: 572 return object; 573 } 574 break; 575 case TypeClass.HYPER_value: 576 switch (tc) { 577 case TypeClass.BYTE_value: 578 return Long.valueOf( ((Byte)object).byteValue() ); 579 case TypeClass.SHORT_value: 580 case TypeClass.UNSIGNED_SHORT_value: 581 return Long.valueOf( ((Short)object).shortValue() ); 582 case TypeClass.LONG_value: 583 case TypeClass.UNSIGNED_LONG_value: 584 return Long.valueOf( ((Integer)object).intValue() ); 585 case TypeClass.HYPER_value: 586 return object; 587 } 588 break; 589 case TypeClass.UNSIGNED_HYPER_value: 590 switch (tc) { 591 case TypeClass.UNSIGNED_SHORT_value: 592 return Long.valueOf( ((Short)object).shortValue() ); 593 case TypeClass.UNSIGNED_LONG_value: 594 return Long.valueOf( ((Integer)object).intValue() ); 595 case TypeClass.UNSIGNED_HYPER_value: 596 return object; 597 } 598 break; 599 case TypeClass.FLOAT_value: 600 switch (tc) { 601 case TypeClass.BYTE_value: 602 return new Float( ((Byte)object).byteValue() ); 603 case TypeClass.SHORT_value: 604 return new Float( ((Short)object).shortValue() ); 605 case TypeClass.FLOAT_value: 606 return object; 607 } 608 break; 609 case TypeClass.DOUBLE_value: 610 switch (tc) { 611 case TypeClass.BYTE_value: 612 return new Double( ((Byte)object).byteValue() ); 613 case TypeClass.SHORT_value: 614 return new Double( ((Short)object).shortValue() ); 615 case TypeClass.LONG_value: 616 return new Double( ((Integer)object).intValue() ); 617 case TypeClass.FLOAT_value: 618 return new Double( ((Float)object).floatValue() ); 619 case TypeClass.DOUBLE_value: 620 return object; 621 } 622 break; 623 case TypeClass.ENUM_value: 624 if (tc == TypeClass.ENUM_value && 625 (null == destType || destType.equals( type ) /* optional destType */)) 626 { 627 return object; 628 } 629 break; 630 case TypeClass.STRING_value: 631 if (tc == TypeClass.STRING_value) 632 return object; 633 break; 634 case TypeClass.TYPE_value: 635 if (tc == TypeClass.TYPE_value) 636 return object; 637 break; 638 case TypeClass.INTERFACE_value: 639 // Because object is a class, not an interface, it is 640 // controversial what kind of Type "new Type(object.class)" 641 // above should return (UNKNOWN or INTERFACE), so that we should 642 // not check here for "tc == TypeClass.INTERFACE_value". 643 // Instead, we check whether object (indirectly) derives from 644 // XInterface: 645 if (object instanceof XInterface) 646 return UnoRuntime.queryInterface( destType, object ); 647 break; 648 case TypeClass.STRUCT_value: 649 case TypeClass.EXCEPTION_value: 650 if (destType.isSupertypeOf(type)) { 651 return object; 652 } 653 break; 654 case TypeClass.SEQUENCE_value: 655 if (tc == TypeClass.SEQUENCE_value && 656 (null == destType || destType.equals( type ) /* optional destType */)) 657 { 658 return object; 659 } 660 break; 661 } 662 } 663 throw new com.sun.star.lang.IllegalArgumentException( 664 "The Argument did not hold the proper type"); 665 } 666 } 667 668 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 669