173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin/*
273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin * Copyright (C) 2010 The Android Open Source Project
373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin *
473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin * Licensed under the Apache License, Version 2.0 (the "License");
573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin * you may not use this file except in compliance with the License.
673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin * You may obtain a copy of the License at
773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin *
873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin *      http://www.apache.org/licenses/LICENSE-2.0
973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin *
1073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin * Unless required by applicable law or agreed to in writing, software
1173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin * distributed under the License is distributed on an "AS IS" BASIS,
1273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin * See the License for the specific language governing permissions and
1473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin * limitations under the License.
1573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin */
1673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
1773e782de608cbe2ddffd75c055009ff2e208f78bOwen Linpackage com.android.camera;
1873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
1973e782de608cbe2ddffd75c055009ff2e208f78bOwen Linimport org.xmlpull.v1.XmlPullParser;
2073e782de608cbe2ddffd75c055009ff2e208f78bOwen Linimport org.xmlpull.v1.XmlPullParserException;
2173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
2273e782de608cbe2ddffd75c055009ff2e208f78bOwen Linimport java.io.IOException;
2373e782de608cbe2ddffd75c055009ff2e208f78bOwen Linimport java.lang.reflect.Constructor;
2473e782de608cbe2ddffd75c055009ff2e208f78bOwen Linimport java.util.ArrayList;
2573e782de608cbe2ddffd75c055009ff2e208f78bOwen Linimport java.util.HashMap;
2673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
2773e782de608cbe2ddffd75c055009ff2e208f78bOwen Linimport android.content.Context;
2873e782de608cbe2ddffd75c055009ff2e208f78bOwen Linimport android.util.AttributeSet;
2973e782de608cbe2ddffd75c055009ff2e208f78bOwen Linimport android.util.Xml;
3073e782de608cbe2ddffd75c055009ff2e208f78bOwen Linimport android.view.InflateException;
3173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
3273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin/**
3373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin * Inflate <code>CameraPreference</code> from XML resource.
3473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin */
3573e782de608cbe2ddffd75c055009ff2e208f78bOwen Linpublic class PreferenceInflater {
3673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    private static final String PACKAGE_NAME =
3773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            PreferenceInflater.class.getPackage().getName();
3873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
3973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    private static final Class<?>[] CTOR_SIGNATURE =
4073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            new Class[] {Context.class, AttributeSet.class};
4173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    private static final HashMap<String, Constructor<?>> sConstructorMap =
4273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            new HashMap<String, Constructor<?>>();
4373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
4473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    private Context mContext;
4573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
4673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    public PreferenceInflater(Context context) {
4773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        mContext = context;
4873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    }
4973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
5073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    public CameraPreference inflate(int resId) {
5173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        return inflate(mContext.getResources().getXml(resId));
5273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    }
5373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
5473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    private CameraPreference newPreference(String tagName, Object[] args) {
5573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        String name = PACKAGE_NAME + "." + tagName;
5673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        Constructor<?> constructor = sConstructorMap.get(name);
5773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        try {
5873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            if (constructor == null) {
5973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                // Class not found in the cache, see if it's real, and try to
6073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                // add it
6173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                Class<?> clazz = mContext.getClassLoader().loadClass(name);
6273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                constructor = clazz.getConstructor(CTOR_SIGNATURE);
6373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                sConstructorMap.put(name, constructor);
6473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            }
6573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            return (CameraPreference) constructor.newInstance(args);
6673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        } catch (NoSuchMethodException e) {
6773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            throw new InflateException("Error inflating class " + name, e);
6873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        } catch (ClassNotFoundException e) {
6973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            throw new InflateException("No such class: " + name, e);
7073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        } catch (Exception e) {
7173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            throw new InflateException("While create instance of" + name, e);
7273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        }
7373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    }
7473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
7573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    private CameraPreference inflate(XmlPullParser parser) {
7673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
7773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        AttributeSet attrs = Xml.asAttributeSet(parser);
7873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        ArrayList<CameraPreference> list = new ArrayList<CameraPreference>();
7973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        Object args[] = new Object[]{mContext, attrs};
8073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
8173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        try {
8273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            for (int type = parser.next();
8373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                    type != XmlPullParser.END_DOCUMENT; type = parser.next()) {
8473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                if (type != XmlPullParser.START_TAG) continue;
8573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                CameraPreference pref = newPreference(parser.getName(), args);
8673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
8773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                int depth = parser.getDepth();
8873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                if (depth > list.size()) {
8973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                    list.add(pref);
9073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                } else {
9173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                    list.set(depth - 1, pref);
9273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                }
9373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                if (depth > 1) {
9473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                    ((PreferenceGroup) list.get(depth - 2)).addChild(pref);
9573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                }
9673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            }
9773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
9873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            if (list.size() == 0) {
9973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin                throw new InflateException("No root element found");
10073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            }
10173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            return list.get(0);
10273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        } catch (XmlPullParserException e) {
10373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            throw new InflateException(e);
10473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        } catch (IOException e) {
10573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin            throw new InflateException(parser.getPositionDescription(), e);
10673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        }
10773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    }
10873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin}
109