001    /*
002     *  Copyright 2004 The Apache Software Foundation
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.apache.commons.convert.conversion;
017    
018    import org.apache.commons.convert.Conversion;
019    import org.apache.commons.convert.Converter;
020    
021    /**
022     * Abstract base class for conversion objects that provides basic features.
023     * <p>
024     * Most Conversion implementations will extend this class. It provides convenient
025     * implementations of the methods of the interface, and simplifies null-handling
026     * in the subclass.
027     * <p>
028     * To implement a conversion from a single class, simply extend this class and
029     * implement the {@link #convertValue(Object, Converter)} method. To implement a 
030     * conversion from a class and its subclasses, use {@link AbstractConversionFactory}.
031     *
032     * @author Stephen Colebourne
033     * @version $Id: AbstractConversion.java 155441 2005-02-26 13:19:22Z dirkv $
034     * @since 1.0
035     */
036    public abstract class AbstractConversion implements Conversion {
037    
038        /** Useful constant for subclass constructors */
039        protected static final Class STRING_CLASS = String.class;
040    
041        /** The type to convert from */
042        private final Class fromType;
043        /** The type to convert to */
044        private final Class toType;
045    
046        /**
047         * Constructor that stores the from and to types.
048         * 
049         * @param fromType  the type to convert from
050         * @param toType  the type to convert to
051         */
052        protected AbstractConversion(Class fromType, Class toType) {
053            super();
054            this.fromType = fromType;
055            this.toType = toType;
056        }
057    
058        //-----------------------------------------------------------------------
059        /**
060         * Converts an object from one type to another.
061         * <p>
062         * This implementation delegates to <code>convertValue</code> after handling null.
063         * If the null-safe behaviour is undesired, override this method.
064         *
065         * @param value  the input value to be converted, may be null
066         * @param converter  the converter being used, not null
067         * @return the converted value
068         * @throws Exception if conversion fails, use ConversionException if creating
069         *  a new exception, otherwise just allow exceptions to be thrown
070         */
071        public Object convert(Object value, Converter converter) throws Exception {
072            if (value == null) {
073                return null;
074            }
075            return convertValue(value, converter);
076        }
077    
078        /**
079         * Convert the specified non-null value to another type.
080         * 
081         * @param value  the input value to be converted, pre-checked to not be null
082         * @param converter  the converter being used, not null
083         * @return the converted value
084         * @throws Exception if conversion fails, use ConversionException if creating
085         *  a new exception, otherwise just allow exceptions to be thrown
086         */
087        protected Object convertValue(Object value, Converter converter) throws Exception {
088            throw new UnsupportedOperationException("Not implemented");
089        }
090    
091        //-----------------------------------------------------------------------
092        /**
093         * The type to convert from.
094         *
095         * @return the Class object representing the class to convert to
096         */
097        public Class getFromType() {
098            return fromType;
099        }
100    
101        /**
102         * The type to convert to.
103         *
104         * @return the Class object representing the class to convert from
105         */
106        public Class getToType() {
107            return toType;
108        }
109    
110        //-----------------------------------------------------------------------
111        /**
112         * Gets a suitable debugging string.
113         * 
114         * @return a debugging string
115         */
116        public String toString() {
117            String from = convertClassToName(getFromType());
118            String to = convertClassToName(getToType());
119            return "Conversion[" + from + "->" + to + "]";
120        }
121    
122        /**
123         * Converts a class to a string name for debugging.
124         * 
125         * @param cls  the class to convert
126         * @return the class name
127         */
128        private String convertClassToName(Class cls) {
129            if (cls == null) {
130                return "null";
131            }
132            String str = cls.getName();
133            int pos = str.lastIndexOf('.');
134            if (str.substring(0, pos).equals("java.lang")) {
135                str = str.substring(pos + 1);
136            }
137            if (str.substring(0, pos).equals("java.util")) {
138                str = str.substring(pos + 1);
139            }
140            return str;
141        }
142    
143    }