001/*
002  Licensed to the Apache Software Foundation (ASF) under one or more
003  contributor license agreements.  See the NOTICE file distributed with
004  this work for additional information regarding copyright ownership.
005  The ASF licenses this file to You under the Apache License, Version 2.0
006  (the "License"); you may not use this file except in compliance with
007  the License.  You may obtain a copy of the License at
008
009      http://www.apache.org/licenses/LICENSE-2.0
010
011  Unless required by applicable law or agreed to in writing, software
012  distributed under the License is distributed on an "AS IS" BASIS,
013  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  See the License for the specific language governing permissions and
015  limitations under the License.
016 */
017
018package org.apache.commons.cli;
019
020import java.io.File;
021import java.io.FileInputStream;
022import java.io.FileNotFoundException;
023import java.net.MalformedURLException;
024import java.net.URL;
025import java.util.Date;
026
027/**
028 * This is a temporary implementation. TypeHandler will handle the pluggableness of OptionTypes and it will direct all
029 * of these types of conversion functionalities to ConvertUtils component in Commons already. BeanUtils I think.
030 */
031public class TypeHandler {
032    /**
033     * Returns the class whose name is {@code classname}.
034     *
035     * @param classname the class name
036     * @return The class if it is found
037     * @throws ParseException if the class could not be found
038     */
039    public static Class<?> createClass(final String classname) throws ParseException {
040        try {
041            return Class.forName(classname);
042        } catch (final ClassNotFoundException e) {
043            throw new ParseException("Unable to find the class: " + classname);
044        }
045    }
046
047    /**
048     * Returns the date represented by {@code str}.
049     * <p>
050     * This method is not yet implemented and always throws an {@link UnsupportedOperationException}.
051     *
052     * @param str the date string
053     * @return The date if {@code str} is a valid date string, otherwise return null.
054     * @throws UnsupportedOperationException always
055     */
056    public static Date createDate(final String str) {
057        throw new UnsupportedOperationException("Not yet implemented");
058    }
059
060    /**
061     * Returns the File represented by {@code str}.
062     *
063     * @param str the File location
064     * @return The file represented by {@code str}.
065     */
066    public static File createFile(final String str) {
067        return new File(str);
068    }
069
070    /**
071     * Returns the File[] represented by {@code str}.
072     * <p>
073     * This method is not yet implemented and always throws an {@link UnsupportedOperationException}.
074     *
075     * @param str the paths to the files
076     * @return The File[] represented by {@code str}.
077     * @throws UnsupportedOperationException always
078     */
079    public static File[] createFiles(final String str) {
080        // to implement/port:
081        // return FileW.findFiles(str);
082        throw new UnsupportedOperationException("Not yet implemented");
083    }
084
085    /**
086     * Create a number from a String. If a . is present, it creates a Double, otherwise a Long.
087     *
088     * @param str the value
089     * @return the number represented by {@code str}
090     * @throws ParseException if {@code str} is not a number
091     */
092    public static Number createNumber(final String str) throws ParseException {
093        try {
094            if (str.indexOf('.') != -1) {
095                return Double.valueOf(str);
096            }
097            return Long.valueOf(str);
098        } catch (final NumberFormatException e) {
099            throw new ParseException(e.getMessage());
100        }
101    }
102
103    /**
104     * Create an Object from the classname and empty constructor.
105     *
106     * @param classname the argument value
107     * @return the initialized object
108     * @throws ParseException if the class could not be found or the object could not be created
109     */
110    public static Object createObject(final String classname) throws ParseException {
111        final Class<?> cl;
112
113        try {
114            cl = Class.forName(classname);
115        } catch (final ClassNotFoundException cnfe) {
116            throw new ParseException("Unable to find the class: " + classname);
117        }
118
119        try {
120            return cl.newInstance();
121        } catch (final Exception e) {
122            throw new ParseException(e.getClass().getName() + "; Unable to create an instance of: " + classname);
123        }
124    }
125
126    /**
127     * Returns the URL represented by {@code str}.
128     *
129     * @param str the URL string
130     * @return The URL in {@code str} is well-formed
131     * @throws ParseException if the URL in {@code str} is not well-formed
132     */
133    public static URL createURL(final String str) throws ParseException {
134        try {
135            return new URL(str);
136        } catch (final MalformedURLException e) {
137            throw new ParseException("Unable to parse the URL: " + str);
138        }
139    }
140
141    /**
142     * Returns the {@code Object} of type {@code clazz} with the value of {@code str}.
143     *
144     * @param str the command line value
145     * @param clazz the class representing the type of argument
146     * @param <T> type of argument
147     * @return The instance of {@code clazz} initialized with the value of {@code str}.
148     * @throws ParseException if the value creation for the given class failed
149     */
150    @SuppressWarnings("unchecked") // returned value will have type T because it is fixed by clazz
151    public static <T> T createValue(final String str, final Class<T> clazz) throws ParseException {
152        if (PatternOptionBuilder.STRING_VALUE == clazz) {
153            return (T) str;
154        }
155        if (PatternOptionBuilder.OBJECT_VALUE == clazz) {
156            return (T) createObject(str);
157        }
158        if (PatternOptionBuilder.NUMBER_VALUE == clazz) {
159            return (T) createNumber(str);
160        }
161        if (PatternOptionBuilder.DATE_VALUE == clazz) {
162            return (T) createDate(str);
163        }
164        if (PatternOptionBuilder.CLASS_VALUE == clazz) {
165            return (T) createClass(str);
166        }
167        if (PatternOptionBuilder.FILE_VALUE == clazz) {
168            return (T) createFile(str);
169        }
170        if (PatternOptionBuilder.EXISTING_FILE_VALUE == clazz) {
171            return (T) openFile(str);
172        }
173        if (PatternOptionBuilder.FILES_VALUE == clazz) {
174            return (T) createFiles(str);
175        }
176        if (PatternOptionBuilder.URL_VALUE == clazz) {
177            return (T) createURL(str);
178        }
179        throw new ParseException("Unable to handle the class: " + clazz);
180    }
181
182    /**
183     * Returns the {@code Object} of type {@code obj} with the value of {@code str}.
184     *
185     * @param str the command line value
186     * @param obj the type of argument
187     * @return The instance of {@code obj} initialized with the value of {@code str}.
188     * @throws ParseException if the value creation for the given object type failed
189     */
190    public static Object createValue(final String str, final Object obj) throws ParseException {
191        return createValue(str, (Class<?>) obj);
192    }
193
194    /**
195     * Returns the opened FileInputStream represented by {@code str}.
196     *
197     * @param str the file location
198     * @return The file input stream represented by {@code str}.
199     * @throws ParseException if the file is not exist or not readable
200     */
201    public static FileInputStream openFile(final String str) throws ParseException {
202        try {
203            return new FileInputStream(str);
204        } catch (final FileNotFoundException e) {
205            throw new ParseException("Unable to find file: " + str);
206        }
207    }
208}