All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.holoeverywhere.internal.GenericInflater Maven / Gradle / Ivy

The newest version!

package org.holoeverywhere.internal;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.content.Context;
import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.InflateException;

public abstract class GenericInflater> {
    public interface Factory {
        public T onCreateItem(String name, Context context, AttributeSet attrs);
    }

    public interface Parent {
        public void addItemFromInflater(T child);
    }

    private static final HashMap, Constructor> sConstructorMap = new HashMap, Constructor>();
    private ClassLoader mClassLoader;
    protected final Object[] mConstructorArgs = new Object[2];
    protected final Class[] mConstructorSignature = new Class[] {
            Context.class, AttributeSet.class
    };
    private final Context mContext;
    private final List> mFactoryList;
    private final List mPackages = new ArrayList();

    protected GenericInflater(Context context) {
        mContext = context;
        mFactoryList = new ArrayList>();
    }

    protected GenericInflater(GenericInflater original, Context newContext) {
        mContext = newContext;
        mFactoryList = new ArrayList>(original.mFactoryList);
    }

    public void addFactory(Factory factory) {
        mFactoryList.add(factory);
    }

    public abstract GenericInflater cloneInContext(Context newContext);

    @SuppressWarnings("unchecked")
    public final T createItem(String name, String prefix, AttributeSet attrs)
            throws ClassNotFoundException, InflateException {
        if (prefix != null) {
            name = prefix + name;
        }
        Constructor constructor = GenericInflater.sConstructorMap.get(name);
        try {
            if (constructor == null) {
                if (mClassLoader == null) {
                    mClassLoader = getClassLoader();
                    if (mClassLoader == null) {
                        mClassLoader = mContext.getClassLoader();
                    }
                }
                Class clazz = mClassLoader.loadClass(name);
                constructor = findConstructor(clazz);
                GenericInflater.sConstructorMap.put(clazz, constructor);
            }
            return (T) constructor.newInstance(obtainConstructorArgs(name, attrs,
                    constructor));
        } catch (NoSuchMethodException e) {
            InflateException ie = new InflateException(
                    attrs.getPositionDescription() + ": Error inflating class " + name);
            ie.initCause(e);
            throw ie;
        } catch (Exception e) {
            InflateException ie = new InflateException(
                    attrs.getPositionDescription() + ": Error inflating class "
                            + constructor.toString());
            ie.initCause(e);
            throw ie;
        }
    }

    private final T createItemFromTag(XmlPullParser parser, String name,
            AttributeSet attrs) {
        try {
            T item = null;
            for (Factory factory : mFactoryList) {
                try {
                    item = factory.onCreateItem(name, mContext, attrs);
                    if (item != null) {
                        break;
                    }
                } catch (Exception e) {
                }
            }
            if (item == null) {
                if (name.indexOf('.') < 0) {
                    item = onCreateItem(name, attrs);
                } else {
                    item = createItem(name, null, attrs);
                }
            }
            return item;
        } catch (InflateException e) {
            throw e;
        } catch (ClassNotFoundException e) {
            InflateException ie = new InflateException(
                    attrs.getPositionDescription() + ": Error inflating class "
                            + name);
            ie.initCause(e);
            throw ie;
        } catch (Exception e) {
            InflateException ie = new InflateException(
                    attrs.getPositionDescription() + ": Error inflating class "
                            + name);
            ie.initCause(e);
            throw ie;
        }
    }

    protected Constructor findConstructor(Class clazz)
            throws NoSuchMethodException {
        return clazz.getConstructor(mConstructorSignature);
    }

    public ClassLoader getClassLoader() {
        return mClassLoader;
    }

    public Context getContext() {
        return mContext;
    }

    @Deprecated
    public final Factory getFactory() {
        return getFactory(0);
    }

    public final Factory getFactory(int position) {
        return mFactoryList.get(position);
    }

    public final int getFactoryCount() {
        return mFactoryList.size();
    }

    public T inflate(int resource) {
        return inflate(resource, null, false);
    }

    public T inflate(int resource, P root) {
        return inflate(resource, root, root != null);
    }

    public T inflate(int resource, P root, boolean attachToRoot) {
        XmlResourceParser parser = getContext().getResources().getXml(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }

    public T inflate(XmlPullParser parser) {
        return inflate(parser, null, false);
    }

    public T inflate(XmlPullParser parser, P root) {
        return inflate(parser, root, root != null);
    }

    @SuppressWarnings("unchecked")
    public synchronized T inflate(XmlPullParser parser, P root, boolean attachToRoot) {
        final AttributeSet attrs = Xml.asAttributeSet(parser);
        T result = (T) root;
        try {
            int type;
            while ((type = parser.next()) != XmlPullParser.START_TAG
                    && type != XmlPullParser.END_DOCUMENT) {
                ;
            }
            if (type != XmlPullParser.START_TAG) {
                throw new InflateException(parser.getPositionDescription()
                        + ": No start tag found!");
            }
            T xmlRoot = createItemFromTag(parser, parser.getName(), attrs);
            result = (T) onMergeRoots(root, attachToRoot, (P) xmlRoot);
            rInflate(parser, result, attrs);
        } catch (InflateException e) {
            throw e;
        } catch (XmlPullParserException e) {
            InflateException ex = new InflateException(e.getMessage());
            ex.initCause(e);
            throw ex;
        } catch (IOException e) {
            InflateException ex = new InflateException(
                    parser.getPositionDescription() + ": " + e.getMessage());
            ex.initCause(e);
            throw ex;
        }
        return result;
    }

    protected Object[] obtainConstructorArgs(String name, AttributeSet attrs,
            Constructor constructor) {
        final Object[] args = mConstructorArgs;
        args[0] = mContext;
        args[1] = attrs;
        return args;
    }

    protected boolean onCreateCustomFromTag(XmlPullParser parser, T parent,
            final AttributeSet attrs) throws XmlPullParserException {
        return false;
    }

    protected T onCreateItem(String name, AttributeSet attrs)
            throws ClassNotFoundException {
        for (String sPackage : mPackages) {
            return createItem(name, sPackage + ".", attrs);
        }
        return null;
    }

    protected P onMergeRoots(P givenRoot, boolean attachToGivenRoot, P xmlRoot) {
        return xmlRoot;
    }

    public void registerPackage(String name) {
        name = Package.getPackage(name).getName();
        if (!mPackages.contains(name)) {
            mPackages.add(name);
        }
    }

    public void removeFactory(Factory factory) {
        mFactoryList.remove(factory);
    }

    @SuppressWarnings("unchecked")
    private void rInflate(XmlPullParser parser, T parent,
            final AttributeSet attrs) throws XmlPullParserException,
            IOException {
        final int depth = parser.getDepth();
        int type;
        while (((type = parser.next()) != XmlPullParser.END_TAG || parser
                .getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
            if (type != XmlPullParser.START_TAG) {
                continue;
            }
            if (onCreateCustomFromTag(parser, parent, attrs)) {
                continue;
            }
            String name = parser.getName();
            T item = createItemFromTag(parser, name, attrs);
            ((P) parent).addItemFromInflater(item);
            rInflate(parser, item, attrs);
        }
    }

    public void setClassLoader(ClassLoader classLoader) {
        mClassLoader = classLoader;
    }

    public void setFactory(Factory factory) {
        mFactoryList.add(0, factory);
    }

    public void unregisterPackage(String string) {
        mPackages.remove(string);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy