/******************************************************************************* * Copyright 2013 Naver Business Platform Corp. * * 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 com.handmark.pulltorefresh.library; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import android.content.Context; import android.content.res.TypedArray; import android.util.Log; import android.view.View; import com.handmark.pulltorefresh.configuration.xml.PullToRefreshXmlConfiguration; import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; import com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation; import com.handmark.pulltorefresh.library.internal.RotateLoadingLayout; import com.handmark.pulltorefresh.library.internal.LoadingLayout; /** * Factory which creates loading layouts * <br />Loading layouts must be listed in pulltorefresh.xml as "PullToRefresh/LoadingLayouts/layout" nodes * @author Wonjun Kim */ class LoadingLayoutFactory { private static final String LOG_TAG = LoadingLayoutFactory.class .getSimpleName(); /** * Create the class token matched by <b>{@code layoutCode}</b> * @param layoutCode Loading layout code, which must be defined in pulltorefresh.xml * @return Class token which is matched by {@code layoutCode}, or the class token of {@code RotateLoadingLayout} instance if not */ public static Class<? extends LoadingLayout> createLoadingLayoutClazzByLayoutCode(String layoutCode) { String clazzName = PullToRefreshXmlConfiguration.getInstance().getLoadingLayoutClazzName(layoutCode); return createLoadingLayoutClazz(clazzName); } /** * Create a {@code LoadingLayout} instance matched by <b>{@code clazz} token</b> * @param layoutCode Loading layout code, which must be defined in pulltorefresh.xml * @param context * @param mode * @return {@code LoadingLayout} instance if the class matched by {@code layoutCode} exists, or {@code RotateLoadingLayout} instance if not */ @SuppressWarnings("unchecked") public static Class<? extends LoadingLayout> createLoadingLayoutClazz( String clazzName) { Class<? extends LoadingLayout> loadingLayoutClazz = null; if ( clazzName == null ) { loadingLayoutClazz = DefaultLoadingLayoutFactory.createLoadingLayoutClazz(clazzName); return loadingLayoutClazz; } try { loadingLayoutClazz = (Class<LoadingLayout>) Class.forName(clazzName); } catch (ClassNotFoundException e) { Log.e(LOG_TAG,"The loading layout you have chosen class has not been found.", e); loadingLayoutClazz = DefaultLoadingLayoutFactory.createLoadingLayoutClazz(clazzName); } return loadingLayoutClazz; } /** * Create a {@code LoadingLayout} instance matched by <b>{@code layoutCode}</b> * @param layoutCode Loading layout code, which must be defined in pulltorefresh.xml * @param context * @param mode * @return {@code LoadingLayout} instance if the class matched by {@code layoutCode} exists, or {@code RotateLoadingLayout} instance if not */ public static LoadingLayout createLoadingLayout(String layoutCode, Context context, Mode mode, Orientation orientation, TypedArray attrs) { Class<? extends LoadingLayout> clazz = createLoadingLayoutClazz(layoutCode); return createLoadingLayout(clazz, context, mode, orientation, attrs); } /** * Create a {@code LoadingLayout} instance matched by <b>{@code clazz} token</b> * @param layoutCode Loading layout code, which must be defined in pulltorefresh.xml * @param context * @param mode * @return {@code LoadingLayout} instance if the class matched by {@code layoutCode} exists, or {@code RotateLoadingLayout} instance if not */ public static LoadingLayout createLoadingLayout( Class<? extends LoadingLayout> clazz, Context context, Mode mode, Orientation orientation, TypedArray attrs) { LoadingLayout layout = null; // Prevent NullPointerException if ( clazz == null ) { Log.i(LOG_TAG, "The Class token of the Loading Layout is missing. Default Loading Layout will be used."); clazz = DefaultLoadingLayoutFactory.createLoadingLayoutClazz(""); } layout = tryNewInstance(clazz, context, mode, orientation, attrs); // If trying to create new instance has failed, if (layout == null) { layout = DefaultLoadingLayoutFactory.createLoadingLayout(clazz, context, mode, orientation, attrs); } layout.setVisibility(View.INVISIBLE); return layout; } private static LoadingLayout tryNewInstance( Class<? extends LoadingLayout> clazz, Context context, Mode mode, Orientation orientation, TypedArray attrs) { LoadingLayout layout = null; try { Constructor<? extends LoadingLayout> constructor = clazz .getConstructor(Context.class, Mode.class, Orientation.class, TypedArray.class); layout = (LoadingLayout) constructor.newInstance(context, mode, orientation, attrs); } catch (IllegalArgumentException e) { Log.e(LOG_TAG, "The loading layout has failed to be created. ", e); } catch (InvocationTargetException e) { Log.e(LOG_TAG, "The loading layout has failed to be created. ", e); } catch (SecurityException e) { Log.e(LOG_TAG, "The loading layout has failed to be created. ", e); } catch (NoSuchMethodException e) { Log.e(LOG_TAG, "The loading layout has failed to be created. ", e); } catch (InstantiationException e) { Log.e(LOG_TAG, "The loading layout has failed to be created. ", e); } catch (IllegalAccessException e) { Log.e(LOG_TAG, "The loading layout has failed to be created. ", e); } catch (NullPointerException e) { Log.e(LOG_TAG, "The loading layout has failed to be created. ", e); } return layout; } /** * Factory which creates a default loading layout instance. This is used when {@code LoadingLayoutFactory} fails to create a instance * @author Wonjun Kim * */ private static class DefaultLoadingLayoutFactory { /** * @param clazzName This class name is being ignored * @return Class token of {@code RotateLoadingLayout} */ public static Class<? extends LoadingLayout> createLoadingLayoutClazz( String clazzName) { return RotateLoadingLayout.class; } /** * @param clazz Class token is being ignored. * @param context * @param mode * @return {@code RotateLoadingLayout} instance */ public static LoadingLayout createLoadingLayout( Class<? extends LoadingLayout> clazz, Context context, Mode mode, Orientation orientation, TypedArray attrs) { return new RotateLoadingLayout(context, mode, orientation, attrs); } } }