001package org.andromda.core.common;
002
003import org.apache.commons.lang.StringUtils;
004
005/**
006 * Contains Exception handling utilities.
007 *
008 * @author Chad Brandon
009 */
010public class ExceptionUtils
011{
012    /**
013     * Checks if the argument is null, and if so, throws an IllegalArgumentException, does nothing if not.
014     *
015     * @param methodExecuteName the name of the method we are currently executing
016     * @param argumentName the name of the argument we are checking for null
017     * @param argument the argument we are checking
018     * @deprecated used {@link #checkNull(String, Object)} instead since we can detect the method name.
019     */
020    @Deprecated
021    public static void checkNull(
022        final String methodExecuteName,
023        final String argumentName,
024        final Object argument)
025    {
026        checkNull(
027            argumentName,
028            argument,
029            3);
030    }
031
032    /**
033     * Checks if the argument is null, and if so, throws an IllegalArgumentException, does nothing if not.
034     *
035     * @param argumentName the name of the argument we are checking for null
036     * @param argument the argument we are checking
037     */
038    public static void checkNull(
039        final String argumentName,
040        final Object argument)
041    {
042        checkNull(
043            argumentName,
044            argument,
045            3);
046    }
047
048    /**
049     * Checks if the argument is null, and if so, throws an IllegalArgumentException, does nothing if not.
050     *
051     * @param argumentName the name of the argument we are checking for null
052     * @param argument the argument we are checking
053     * @param stackDepth the depth of the stack from which to retrieve the methodInformation.
054     */
055    private static void checkNull(
056        final String argumentName,
057        final Object argument,
058        final int stackDepth)
059    {
060        if (StringUtils.isEmpty(argumentName))
061        {
062            throw new IllegalArgumentException("'argumentName' can not be null or an empty String");
063        }
064
065        if (argument == null)
066        {
067            throw new IllegalArgumentException(getMethodName(stackDepth) + " - '" + argumentName + "' can not be null");
068        }
069    }
070
071    /**
072     * Checks if the argument is null or an empty String throws an IllegalArgumentException if it is, does nothing if
073     * not.
074     *
075     * @param methodExecuteName the name of the method we are currently executing
076     * @param argumentName the name of the argument we are checking for null
077     * @param argument the argument we are checking
078     * @deprecated use {@link #checkEmpty(String, String)} instead since we can detect the method name.
079     */
080    @Deprecated
081    public static void checkEmpty(
082        final String methodExecuteName,
083        final String argumentName,
084        final String argument)
085    {
086        checkEmpty(
087            argumentName,
088            argument,
089            3);
090    }
091
092    /**
093     * Checks if the argument is null or an empty String throws an IllegalArgumentException if it is, does nothing if
094     * not.
095     *
096     * @param argumentName the name of the argument we are checking for null
097     * @param argument the argument we are checking
098     */
099    public static void checkEmpty(
100        final String argumentName,
101        final String argument)
102    {
103        checkEmpty(
104            argumentName,
105            argument,
106            3);
107    }
108
109    /**
110     * Checks if the argument is null or an empty String throws an IllegalArgumentException if it is, does nothing if
111     * not.
112     *
113     * @param argumentName the name of the argument we are checking for null
114     * @param argument the argument we are checking
115     * @param stackDepth the depth of the stack from which to retrieve the methodInformation.
116     */
117    private static void checkEmpty(
118        final String argumentName,
119        final String argument,
120        final int stackDepth)
121    {
122        if (StringUtils.isEmpty(argumentName))
123        {
124            throw new IllegalArgumentException("'argumentName' can not be null or an empty String");
125        }
126        if (StringUtils.isEmpty(argument))
127        {
128            throw new IllegalArgumentException(getMethodName(stackDepth) + " - '" + argumentName +
129                "' can not be null or an empty String");
130        }
131    }
132
133    /**
134     * Checks if the argumentClass is assignable to assignableToClass, and if not throws an IllegalArgumentException,
135     * otherwise does nothing.
136     *
137     * @param methodExecuteName the method name of the method, this method is being executed within
138     * @param assignableToClass the Class that argumentClass must be assignable to
139     * @param argumentClass the argumentClass we are checking
140     * @param argumentName the name of the argument we are checking
141     * @deprecated use {@link #checkAssignable(Class, String, Class)} since we can detect the method name.
142     */
143    @Deprecated
144    public static void checkAssignable(
145        final String methodExecuteName,
146        final Class assignableToClass,
147        final String argumentName,
148        final Class argumentClass)
149    {
150        checkAssignable(
151            assignableToClass,
152            argumentName,
153            argumentClass,
154            3);
155    }
156
157    /**
158     * Checks if the argumentClass is assignable to assignableToClass, and if not throws an IllegalArgumentException,
159     * otherwise does nothing.
160     *
161     * @param assignableToClass the Class that argumentClass must be assignable to
162     * @param argumentClass the argumentClass we are checking
163     * @param argumentName the name of the argument we are checking
164     */
165    public static void checkAssignable(
166        final Class assignableToClass,
167        final String argumentName,
168        final Class argumentClass)
169    {
170        checkAssignable(
171            assignableToClass,
172            argumentName,
173            argumentClass,
174            3);
175    }
176
177    /**
178     * Checks if the argumentClass is assignable to assignableToClass, and if not throws an IllegalArgumentException,
179     * otherwise does nothing.
180     *
181     * @param assignableToClass the Class that argumentClass must be assignable to
182     * @param argumentClass the argumentClass we are checking
183     * @param argumentName the name of the argument we are checking
184     * @param stackDepth the depth of the stack from which to retrieve the method information.
185     */
186    private static void checkAssignable(
187        final Class assignableToClass,
188        final String argumentName,
189        final Class argumentClass,
190        final int stackDepth)
191    {
192        if (assignableToClass == null)
193        {
194            throw new IllegalArgumentException("'assignableToClass' can not be null");
195        }
196        if (argumentClass == null)
197        {
198            throw new IllegalArgumentException("'argumentClass' can not be null");
199        }
200        if (StringUtils.isEmpty(argumentName))
201        {
202            throw new IllegalArgumentException("'argumentName can not be null or an empty String");
203        }
204
205        // this is what the method is for
206        if (!assignableToClass.isAssignableFrom(argumentClass))
207        {
208            throw new IllegalArgumentException(getMethodName(stackDepth) + " - '" + argumentName + "' class --> '" +
209                argumentClass + "' must be assignable to class --> '" + assignableToClass + '\'');
210        }
211    }
212
213    /**
214     * Attempts to retrieve the root cause of the exception, if it can not be
215     * found, the <code>throwable</code> itself is returned.
216     *
217     * @param throwable the exception from which to retrieve the root cause.
218     * @return the root cause of the exception
219     */
220    public static Throwable getRootCause(Throwable throwable)
221    {
222        final Throwable root = org.apache.commons.lang.exception.ExceptionUtils.getRootCause(throwable);
223        if (root != null)
224        {
225            throwable = root;
226        }
227        return throwable;
228    }
229
230    /**
231     * Gets the appropriate method name for the method being checked.
232     *
233     * @return the name of the method.
234     */
235    private static String getMethodName(int stackDepth)
236    {
237        String methodName = null;
238        final Throwable throwable = new Throwable();
239        final StackTraceElement[] stack = throwable.getStackTrace();
240        if (stack.length >= stackDepth)
241        {
242            final StackTraceElement element = stack[stackDepth];
243            methodName = element.getClassName() + '.' + element.getMethodName();
244        }
245        return methodName;
246    }
247}