alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * Copyright 1999-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.commons.jxpath.util;

import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.jxpath.JXPathException;
import org.apache.commons.jxpath.NodeSet;
import org.apache.commons.jxpath.Pointer;

/**
 * The default implementation of TypeConverter.
 *
 * @author Dmitri Plotnikov
 * @version $Revision: 1.15 $ $Date: 2004/07/25 13:16:04 $
 */
public class BasicTypeConverter implements TypeConverter {

    /**
     * Returns true if it can convert the supplied
     * object to the specified class.
     */
    public boolean canConvert(Object object, Class toType) {
        if (object == null) {
            return true;
        }

        if (toType == Object.class) {
            return true;
        }

        Class fromType = object.getClass();
        if (fromType.equals(toType)) {
            return true;
        }

        if (toType.isAssignableFrom(fromType)) {
            return true;
        }

        if (toType == String.class) {
            return true;
        }

        if (object instanceof Boolean) {
            if (toType == boolean.class
                || Number.class.isAssignableFrom(toType)) {
                return true;
            }
        }
        else if (object instanceof Number) {
            if (toType.isPrimitive()
                || Number.class.isAssignableFrom(toType)) {
                return true;
            }
        }
        else if (object instanceof Character) {
            if (toType == char.class) {
                return true;
            }
        }
        else if (object instanceof String) {
            if (toType.isPrimitive()) {
                return true;
            }
            if (toType == Boolean.class
                || toType == Character.class
                || toType == Byte.class
                || toType == Short.class
                || toType == Integer.class
                || toType == Long.class
                || toType == Float.class
                || toType == Double.class) {
                return true;
            }
        }
        else if (fromType.isArray()) {
            // Collection -> array
            if (toType.isArray()) {
                Class cType = toType.getComponentType();
                int length = Array.getLength(object);
                for (int i = 0; i < length; i++) {
                    Object value = Array.get(object, i);
                    if (!canConvert(value, cType)) {
                        return false;
                    }
                }
                return true;
            }
            else if (Collection.class.isAssignableFrom(toType)) {
                return canCreateCollection(toType);
            }
            else {
                if (Array.getLength(object) > 0) {
                    Object value = Array.get(object, 0);
                    return canConvert(value, toType);
                }
                else {
                    return canConvert("", toType);
                }
            }
        }
        else if (object instanceof Collection) {
            // Collection -> array
            if (toType.isArray()) {
                Class cType = toType.getComponentType();
                Iterator it = ((Collection) object).iterator();
                while (it.hasNext()) {
                    Object value = it.next();
                    if (!canConvert(value, cType)) {
                        return false;
                    }
                }
                return true;
            }
            else if (Collection.class.isAssignableFrom(toType)) {
                return canCreateCollection(toType);
            }
            else {
                if (((Collection) object).size() > 0) {
                    Object value;
                    if (object instanceof List) {
                        value = ((List) object).get(0);
                    }
                    else {
                        Iterator it = ((Collection) object).iterator();
                        value = it.next();
                    }
                    return canConvert(value, toType);
                }
                else {
                    return canConvert("", toType);
                }
            }
        }
        else if (object instanceof NodeSet) {
            return canConvert(((NodeSet) object).getValues(), toType);
        }
        else if (object instanceof Pointer) {
            return canConvert(((Pointer) object).getValue(), toType);
        }
        return ConvertUtils.lookup(toType) != null;
    }

    /**
     * Converts the supplied object to the specified
     * type. Throws a runtime exception if the conversion is
     * not possible.
     */
    public Object convert(Object object, Class toType) {
        if (object == null) {
            if (toType.isPrimitive()) {
                return convertNullToPrimitive(toType);
            }
            return null;
        }

        if (toType == Object.class) {
            if (object instanceof NodeSet) {
                return convert(((NodeSet) object).getValues(), toType);
            }
            else if (object instanceof Pointer) {
                return convert(((Pointer) object).getValue(), toType);
            }
            return object;
        }

        Class fromType = object.getClass();
        if (fromType.equals(toType) || toType.isAssignableFrom(fromType)) {
            return object;
        }

        if (fromType.isArray()) {
            int length = Array.getLength(object);
            if (toType.isArray()) {
                Class cType = toType.getComponentType();

                Object array = Array.newInstance(cType, length);
                for (int i = 0; i < length; i++) {
                    Object value = Array.get(object, i);
                    Array.set(array, i, convert(value, cType));
                }
                return array;
            }
            else if (Collection.class.isAssignableFrom(toType)) {
                Collection collection = allocateCollection(toType);
                for (int i = 0; i < length; i++) {
                    collection.add(Array.get(object, i));
                }
                return unmodifiableCollection(collection);
            }
            else {
                if (length > 0) { 
                    Object value = Array.get(object, 0);
                    return convert(value, toType);
                }
                else {
                    return convert("", toType);
                }
            }
        }
        else if (object instanceof Collection) {
            int length = ((Collection) object).size();
            if (toType.isArray()) {
                Class cType = toType.getComponentType();
                Object array = Array.newInstance(cType, length);
                Iterator it = ((Collection) object).iterator();
                for (int i = 0; i < length; i++) {
                    Object value = it.next();
                    Array.set(array, i, convert(value, cType));
                }
                return array;
            }
            else if (Collection.class.isAssignableFrom(toType)) {
                Collection collection = allocateCollection(toType);
                collection.addAll((Collection) object);
                return unmodifiableCollection(collection);
            }
            else {
                if (length > 0) {
                    Object value;
                    if (object instanceof List) {
                        value = ((List) object).get(0);
                    }
                    else {
                        Iterator it = ((Collection) object).iterator();
                        value = it.next();
                    }
                    return convert(value, toType);
                }
                else {
                    return convert("", toType);
                }
            }
        }
        else if (object instanceof NodeSet) {
            return convert(((NodeSet) object).getValues(), toType);
        }
        else if (object instanceof Pointer) {
            return convert(((Pointer) object).getValue(), toType);
        }
        else if (toType == String.class) {
            return object.toString();
        }
        else if (object instanceof Boolean) {
            if (toType == boolean.class) {
                return object;
            }
            boolean value = ((Boolean) object).booleanValue();
            return allocateNumber(toType, value ? 1 : 0);
        }
        else if (object instanceof Number) {
            double value = ((Number) object).doubleValue();
            if (toType == boolean.class || toType == Boolean.class) {
                return value == 0.0 ? Boolean.FALSE : Boolean.TRUE;
            }
            if (toType.isPrimitive()
                || Number.class.isAssignableFrom(toType)) {
                return allocateNumber(toType, value);
            }
        }
        else if (object instanceof Character) {
            if (toType == char.class) {
                return object;
            }
        }
        else if (object instanceof String) {
            Object value = convertStringToPrimitive(object, toType);
            if (value != null) {
                return value;
            }
        }
        
        Converter converter = ConvertUtils.lookup(toType);
        if (converter != null) {
            return converter.convert(toType, object);
        }

        throw new RuntimeException(
            "Cannot convert " + object.getClass() + " to " + toType);
    }

    protected Object convertNullToPrimitive(Class toType) {
        if (toType == boolean.class) {
            return Boolean.FALSE;
        }
        if (toType == char.class) {
            return new Character('\0');
        }
        if (toType == byte.class) {
            return new Byte((byte) 0);
        }
        if (toType == short.class) {
            return new Short((short) 0);
        }
        if (toType == int.class) {
            return new Integer(0);
        }
        if (toType == long.class) {
            return new Long(0L);
        }
        if (toType == float.class) {
            return new Float(0.0f);
        }
        if (toType == double.class) {
            return new Double(0.0);
        }
        return null;
    }

    protected Object convertStringToPrimitive(Object object, Class toType) {
        if (toType == boolean.class || toType == Boolean.class) {
            return Boolean.valueOf((String) object);
        }
        if (toType == char.class || toType == Character.class) {
            return new Character(((String) object).charAt(0));
        }
        if (toType == byte.class || toType == Byte.class) {
            return new Byte((String) object);
        }
        if (toType == short.class || toType == Short.class) {
            return new Short((String) object);
        }
        if (toType == int.class || toType == Integer.class) {
            return new Integer((String) object);
        }
        if (toType == long.class || toType == Long.class) {
            return new Long((String) object);
        }
        if (toType == float.class || toType == Float.class) {
            return new Float((String) object);
        }
        if (toType == double.class || toType == Double.class) {
            return new Double((String) object);
        }
        return null;
    }
    
    protected Number allocateNumber(Class type, double value) {
        if (type == Byte.class || type == byte.class) {
            return new Byte((byte) value);
        }
        if (type == Short.class || type == short.class) {
            return new Short((short) value);
        }
        if (type == Integer.class || type == int.class) {
            return new Integer((int) value);
        }
        if (type == Long.class || type == long.class) {
            return new Long((long) value);
        }
        if (type == Float.class || type == float.class) {
            return new Float((float) value);
        }
        if (type == Double.class || type == double.class) {
            return new Double(value);
        }
        return null;
    }

    protected boolean canCreateCollection(Class type) {
        if (!type.isInterface()
            && ((type.getModifiers() & Modifier.ABSTRACT) == 0)) {
            return true;
        }

        if (type == List.class) {
            return true;
        }

        if (type == Set.class) {
            return true;
        }
        return false;
    }

    protected Collection allocateCollection(Class type) {
        if (!type.isInterface()
            && ((type.getModifiers() & Modifier.ABSTRACT) == 0)) {
            try {
                return (Collection) type.newInstance();
            }
            catch (Exception ex) {
                throw new JXPathException(
                    "Cannot create collection of type: " + type,
                    ex);
            }
        }

        if (type == List.class) {
            return new ArrayList();
        }
        if (type == Set.class) {
            return new HashSet();
        }
        throw new RuntimeException("Cannot create collection of type: " + type);
    }
    
    protected Collection unmodifiableCollection(Collection collection) {
        if (collection instanceof List) {
            return Collections.unmodifiableList((List) collection);
        }
        else if (collection instanceof Set) {
            return Collections.unmodifiableSet((Set) collection);
        }
        // Cannot wrap it into a proper unmodifiable collection, 
        // so we just return the original collection itself
        return collection;
    }
    
    static final class ValueNodeSet implements NodeSet {
        private List values;
        private List pointers;

        public ValueNodeSet(List values) {
           this.values = values;
        }
        
        public List getValues() {
            return Collections.unmodifiableList(values);
        }
        
        public List getNodes() {
            return Collections.unmodifiableList(values);
        }
        
        public List getPointers() {
            if (pointers == null) {
                pointers = new ArrayList();
                for (int i = 0; i < values.size(); i++) {
                    pointers.add(new ValuePointer(values.get(i)));
                }
                pointers = Collections.unmodifiableList(pointers);
            }
            return pointers;
        }
    }
    
    static final class ValuePointer implements Pointer {
        private Object bean;

        public ValuePointer(Object object) {
            this.bean = object;
        }
        
        public Object getValue() {
            return bean;
        }
        
        public Object getNode() {
            return bean;
        }
        
        public Object getRootNode() {
            return bean;
        }        
        
        public void setValue(Object value) {
            throw new UnsupportedOperationException();
        }
        
        public Object clone() {
            return this;
        }
        
        public int compareTo(Object object) {
            return 0;
        }
        
        public String asPath() {
            if (bean == null) {
                return "null()";
            }
            else if (bean instanceof Number) {
                String string = bean.toString();
                if (string.endsWith(".0")) {
                    string = string.substring(0, string.length() - 2);
                }
                return string;
            }
            else if (bean instanceof Boolean) {
                return ((Boolean) bean).booleanValue() ? "true()" : "false()";
            }
            else if (bean instanceof String) {
                return "'" + bean + "'";
            }
            return "{object of type " + bean.getClass().getName() + "}";
        }
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.