/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.axis.utils; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; public class ArrayUtil { private static class ArrayInfo { public Class componentType; public Class arrayType; public int dimension; } public static class NonConvertable { public NonConvertable() { } } /** An object indicating that the conversion is not possible */ public static final NonConvertable NON_CONVERTABLE = new NonConvertable(); /** * Convert ArrayOfT to T[]. * @param obj the object of type ArrayOfT to convert * @param arrayType the destination array type * @return returns the converted array object. * If not convertable the original obj argument is returned. * If the obj is not type of ArrayOfT or the value is null, null is returned. */ public static Object convertObjectToArray(Object obj, Class arrayType) { try { ArrayInfo arri = new ArrayInfo(); boolean rc = internalIsConvertable(obj.getClass(), arri, arrayType); if (rc == false) { return obj; } BeanPropertyDescriptor pd = null; pd = getArrayComponentPD(obj.getClass()); if (pd == null) { return NON_CONVERTABLE; } Object comp = pd.get(obj); if (comp == null) { return null; } int arraylen = 0; if (comp.getClass().isArray()) { arraylen = Array.getLength(comp); } else { return comp; } int[] dims = new int[arri.dimension]; dims[0] = arraylen; Object targetArray = Array.newInstance(arri.componentType, dims); for (int i = 0; i < arraylen; i++) { Object subarray = Array.get(comp, i); Class subarrayClass = arrayType.getComponentType(); Array.set(targetArray, i, convertObjectToArray(subarray, subarrayClass)); } return targetArray; } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; } /** * Check if the clazz(perhaps ArrayOfT class) can be converted to T[]. * @param clazz a class of ArrayOfT * @param arrayType an array class (T[]) * @return true if converable, false if not */ public static boolean isConvertable(Class clazz, Class arrayType) { ArrayInfo arrInfo = new ArrayInfo(); return internalIsConvertable(clazz, arrInfo, arrayType); } /** * Check if the clazz(perhaps ArrayOfT class) can be converted to T[]. * @param clazz a class of ArrayOfT * @param arri convert result information * @param arrayType an array class (T[]) * @return true if converable, false if not */ private static boolean internalIsConvertable(Class clazz, ArrayInfo arri, Class arrayType) { BeanPropertyDescriptor pd = null, oldPd = null; if (!arrayType.isArray()) return false; Class destArrCompType = arrayType.getComponentType(); Class src = clazz; int depth = 0; while (true) { pd = getArrayComponentPD(src); if (pd == null) break; depth++; src = pd.getType(); oldPd = pd; if (destArrCompType.isAssignableFrom(src)) break; } if (depth == 0 || oldPd.getType() == null) { return false; } arri.componentType = oldPd.getType(); arri.dimension = depth; Class componentType = oldPd.getType(); int[] dims = new int[depth]; Object array = Array.newInstance(componentType, dims); arri.arrayType = array.getClass(); if (arrayType.isAssignableFrom(arri.arrayType)) return true; else return false; } /** * Gets the BeanPropertyDescriptor of ArrayOfT class's array member. * @param clazz a class of perhaps ArrayOfT type. * @return the BeanPropertyDescriptor. If the clazz is not type of ArrayOfT, null is returned. */ private static BeanPropertyDescriptor getArrayComponentPD(Class clazz) { BeanPropertyDescriptor bpd = null; int count = 0; Class cls = clazz; while (cls != null && cls.getName() != null && !cls.getName().equals("java.lang.Object")) { BeanPropertyDescriptor bpds[] = BeanUtils.getPd(clazz); for (int i = 0; i < bpds.length; i++) { BeanPropertyDescriptor pd = bpds[i]; if (pd.isReadable() && pd.isWriteable() && pd.isIndexed()) { count++; if (count >= 2) return null; else bpd = pd; } } cls = cls.getSuperclass(); } if (count == 1) { return bpd; } else return null; } /** * Gets the dimension of arrayType * @param arrayType an array class * @return the dimension */ public static int getArrayDimension(Class arrayType) { if (!arrayType.isArray()) return 0; int dim = 0; Class compType = arrayType; do { dim++; arrayType = compType; compType = arrayType.getComponentType(); } while (compType.isArray()); return dim; } private static Object createNewInstance(Class cls) throws InstantiationException, IllegalAccessException { Object obj = null; if (!cls.isPrimitive()) obj = cls.newInstance(); else { if (boolean.class.isAssignableFrom(cls)) obj = new Boolean(false); else if (byte.class.isAssignableFrom(cls)) obj = new Byte((byte)0); else if (char.class.isAssignableFrom(cls)) obj = new Character('\u0000'); else if (short.class.isAssignableFrom(cls)) obj = new Short((short)0); else if (int.class.isAssignableFrom(cls)) obj = new Integer(0); else if (long.class.isAssignableFrom(cls)) obj = new Long(0L); else if (float.class.isAssignableFrom(cls)) obj = new Float(0.0F); else if (double.class.isAssignableFrom(cls)) obj = new Double(0.0D); } return obj; } /** * Convert an array object of which type is T[] to ArrayOfT class. * @param array the array object * @param destClass the destination class * @return the object of type destClass if convertable, null if not. */ public static Object convertArrayToObject(Object array, Class destClass) { int dim = getArrayDimension(array.getClass()); if (dim == 0) { return null; } Object dest = null; try { // create the destArray int arraylen = Array.getLength(array); Object destArray = null; Class destComp = null; if (!destClass.isArray()) { dest = destClass.newInstance(); BeanPropertyDescriptor pd = getArrayComponentPD(destClass); if (pd == null) return null; destComp = pd.getType(); destArray = Array.newInstance(destComp, arraylen); pd.set(dest, destArray); } else { destComp = destClass.getComponentType(); dest = Array.newInstance(destComp, arraylen); destArray = dest; } // iniialize the destArray for (int i = 0; i < arraylen; i++) { Array.set(destArray, i, createNewInstance(destComp)); } // set the destArray for (int i = 0; i < arraylen; i++) { Object comp = Array.get(array, i); if(comp == null) continue; if (comp.getClass().isArray()) { Class cls = Array.get(destArray, i).getClass(); Array.set(destArray, i, convertArrayToObject(comp, cls)); } else { Array.set(destArray, i, comp); } } } catch (IllegalAccessException ignore) { return null; } catch (InvocationTargetException ignore) { return null; } catch (InstantiationException ignore) { return null; } return dest; } }