/******************************************************************************* * 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.configuration.xml; import java.io.IOException; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; import android.content.res.Resources; import android.util.Log; import com.handmark.pulltorefresh.library.R; import com.handmark.pulltorefresh.library.internal.Assert; /** * {@code PullToRefreshXmlConfiguration} is an information set of PullToRefresh. It contains a list of indicator layouts and of loading layouts. An information set of PullToRefresh is converted from pulltorefresh.xml.<br /> * This Class is Singleton, and you <b>MUST</b> call {@link #init(Context)} before using this class. * @author Wonjun Kim */ public class PullToRefreshXmlConfiguration { private static final String LOG_TAG = PullToRefreshXmlConfiguration.class.getName(); /** * Singleton instance * @author Wonjun Kim */ private static class InstanceHolder { private final static PullToRefreshXmlConfiguration instance = new PullToRefreshXmlConfiguration(); private static PullToRefreshXmlConfiguration getInstance() { return instance; } } /** * Parsed information from pulltorefresh.xml */ private PullToRefreshNode node = null; /** * Default pulltorefresh path id is got from R class. */ private static final int XML_PATH_ID = R.xml.pulltorefresh; /** * flag whether it has called {@link #init(Context)} */ private boolean initialized = false; /** * Constructor <br /> * nothing to do */ private PullToRefreshXmlConfiguration() {} /** * Get singleton instance * @return {@code PullToRefreshXmlConfiguration} instance */ public static PullToRefreshXmlConfiguration getInstance() { return InstanceHolder.getInstance(); } /** * Initialize the instance before using. <br /> * Load 'res/xml/pulltorefresh.xml' in PullToRefresh library package and 'assets/pulltofresh.xml' in Android Project if it exists. <br /> * Combine information of 'res/xml/pulltorefresh.xml' and 'assets/pulltofresh.xml', and then save the information into the instance's fields.<br /> * <br /> * NOTE: This method <b>MUST</b> be called before using! * @param context Context instance and not null */ public void init(Context context) { // If an initialization was happened already, skip. if ( initialized == true ) { return; } Assert.notNull(context, "Context"); // get resources Resources resources = context.getResources(); // read the file XmlPullParser parser = resources.getXml(XML_PATH_ID); // parser the xml XmlPullParserWrapper wrapper = new XmlPullParserWrapper(parser); try { node = new PullToRefreshConfigXmlParser(wrapper).parse(); // load extended xml XmlPullParser extendedXmlParser = ExtendedConfigXmlParserFactory.createParser(context); if ( extendedXmlParser != null) { XmlPullParserWrapper extendedXmlWrapper = new XmlPullParserWrapper(extendedXmlParser); // NOTE : if some exception is thrown from PullToRefreshConfigXmlParser, Loading extended xml will be skipped. PullToRefreshNode extendedNode = new PullToRefreshConfigXmlParser(extendedXmlWrapper).parse(); node.extendProperties(extendedNode); } } catch (XmlPullParserException e) { Log.d(LOG_TAG, "It has failed to parse the xmlpullparser xml.", e); } catch (IOException e) { Log.d(LOG_TAG, "It has failed to parse the xmlpullparser xml.\n ", e); } // Intialization can be done whether reading XML has failed or not! initialized = true; } /** * @param layoutCode Layout name * @return Layout Class name ( ex: com.handmark.pulltorefresh.library.internal.FlipLoadingLayout ) */ public String getLoadingLayoutClazzName(String layoutCode) { assertInitialized(); if ( isNodeNull() ) { return null; } return node.getLoadingLayoutClazzName(layoutCode); } /** * @param layoutCode Layout name * @return Layout Class name ( ex: com.handmark.pulltorefresh.library.internal.DefaultLoadingLayout ) */ public String getIndicatorLayoutClazzName(String layoutCode) { assertInitialized(); if ( isNodeNull() ) { return null; } return node.getIndicatorLayoutClazzName(layoutCode); } /** * @param layoutCode Layout name * @return Layout Class name ( ex: com.handmark.pulltorefresh.library.internal.DefaultGoogleStyleViewLayout ) */ public String getGoogleStyleViewLayoutClazzName(String layoutCode) { assertInitialized(); if ( isNodeNull() ) { return null; } return node.getGoogleStyleViewLayoutClazzName(layoutCode); } /** * @param layoutCode Layout name * @return Layout Class name ( ex: com.handmark.pulltorefresh.library.internal.DefaultGoogleStyleProgressLayout ) */ public String getGoogleStyleProgressLayoutClazzName(String layoutCode) { assertInitialized(); if ( isNodeNull() ) { return null; } return node.getGoogleStyleProgressLayoutClazzName(layoutCode); } /** * @return true if {@code node} is null */ private boolean isNodeNull() { return node == null; } /** * @return true if {@link #init(Context)} method has not been called */ private boolean notInitialized() { return !initialized; } /** * @return throw an exception if {@link #init(Context)} method has not been called */ private void assertInitialized() { if ( notInitialized() ) { throw new IllegalStateException(PullToRefreshXmlConfiguration.class.getName()+" has not initialized. Call init() method first."); } } }