FileDocCategorySizeDatePackage
LayoutParamsParser.javaAPI DocAndroid 1.5 API14509Wed May 06 22:41:10 BST 2009com.android.ide.eclipse.adt.sdk

LayoutParamsParser

public class LayoutParamsParser extends Object
Parser for the framework library.

This gather the following information:

  • Resource ID from android.R
  • The list of permissions values from android.Manifest$permission

Fields Summary
protected com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor
mTopViewClass
Reference to android.view.View
protected com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor
mTopGroupClass
Reference to android.view.ViewGroup
protected com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor
mTopLayoutParamsClass
Reference to android.view.ViewGroup$LayoutParams
protected ArrayList
mViewList
Input list of all classes deriving from android.view.View
protected ArrayList
mGroupList
Input list of all classes deriving from android.view.ViewGroup
protected TreeMap
mViewMap
Output map of FQCN => info on View classes
protected TreeMap
mGroupMap
Output map of FQCN => info on ViewGroup classes
protected HashMap
mLayoutParamsMap
Output map of FQCN => info on LayoutParams classes
protected com.android.ide.eclipse.common.resources.AttrsXmlParser
mAttrsXmlParser
The attrs.xml parser
protected IAndroidClassLoader
mClassLoader
The android.jar class loader
Constructors Summary
public LayoutParamsParser(IAndroidClassLoader classLoader, com.android.ide.eclipse.common.resources.AttrsXmlParser attrsXmlParser)
Instantiate a new LayoutParamsParser.

param
classLoader The android.jar class loader
param
attrsXmlParser The parser of the attrs.xml file

        mClassLoader = classLoader;
        mAttrsXmlParser = attrsXmlParser;
    
Methods Summary
private com.android.ide.eclipse.adt.sdk.LayoutParamsParser$ExtViewClassInfoaddGroup(com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor groupClass)
Parses a ViewGroup class and adds a ExtViewClassInfo for it in mGroupMap. It calls itself recursively to handle super classes which are also ViewGroups.

        String fqcn = groupClass.getCanonicalName();
        if (mGroupMap.containsKey(fqcn)) {
            return mGroupMap.get(fqcn);
        }

        ExtViewClassInfo info = new ExtViewClassInfo(groupClass.isInstantiable(),
                true /* layout */, fqcn, groupClass.getSimpleName());
        mGroupMap.put(fqcn, info);

        // All groups derive from android.view.ViewGroup, which in turns derives from
        // android.view.View (i.e. mTopViewClass here). So the only group that can have View as
        // its super class is the ViewGroup base class and we don't try to resolve it since groups
        // are loaded before views.
        IClassDescriptor superClass = groupClass.getSuperclass(); 
        
        // Assertion: at this point, we should have
        //   superClass != mTopViewClass || fqcn.equals(AndroidConstants.CLASS_VIEWGROUP);

        if (superClass != null && superClass.equals(mTopViewClass) == false) {
            ExtViewClassInfo superClassInfo = addGroup(superClass);
            
            // Assertion: we should have superClassInfo != null && superClassInfo != info;
            if (superClassInfo != null && superClassInfo != info) {
                info.setSuperClass(superClassInfo);
            }
        }

        mAttrsXmlParser.loadViewAttributes(info);
        if (mTopLayoutParamsClass != null) {
            info.setLayoutParams(addLayoutParams(groupClass));
        }
        return info;
    
private com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfoaddLayoutParams(com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor groupClass)
Parses a ViewGroup class and returns an info object on its inner LayoutParams.

return
The {@link LayoutParamsInfo} for the ViewGroup class or null.


        // Is there a LayoutParams in this group class?
        IClassDescriptor layoutParamsClass = findLayoutParams(groupClass);

        // if there's no layout data in the group class, link to the one from the
        // super class.
        if (layoutParamsClass == null) {
            for (IClassDescriptor superClass = groupClass.getSuperclass();
                    layoutParamsClass == null &&
                        superClass != null &&
                        superClass.equals(mTopViewClass) == false;
                    superClass = superClass.getSuperclass()) {
                layoutParamsClass = findLayoutParams(superClass);
            }
        }

        if (layoutParamsClass != null) {
            return getLayoutParamsInfo(layoutParamsClass);
        }
        
        return null;
    
private com.android.ide.eclipse.adt.sdk.LayoutParamsParser$ExtViewClassInfoaddView(com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor viewClass)
Parses a View class and adds a ExtViewClassInfo for it in mViewMap. It calls itself recursively to handle super classes which are also Views.

        String fqcn = viewClass.getCanonicalName();
        if (mViewMap.containsKey(fqcn)) {
            return mViewMap.get(fqcn);
        } else if (mGroupMap.containsKey(fqcn)) {
            return mGroupMap.get(fqcn);
        }

        ExtViewClassInfo info = new ExtViewClassInfo(viewClass.isInstantiable(),
                false /* layout */, fqcn, viewClass.getSimpleName());
        mViewMap.put(fqcn, info);

        // All view classes derive from mTopViewClass by design.
        // Do not lookup the super class for mTopViewClass itself.
        if (viewClass.equals(mTopViewClass) == false) {
            IClassDescriptor superClass = viewClass.getSuperclass(); 
            ExtViewClassInfo superClassInfo = addView(superClass);
            info.setSuperClass(superClassInfo);
        }

        mAttrsXmlParser.loadViewAttributes(info);
        return info;
    
private com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptorfindLayoutParams(com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor groupClass)
Given a ViewGroup-derived class, looks for an inner class named LayoutParams and if found returns its class definition.

This uses the actual defined inner classes and does not look at inherited classes.

param
groupClass The ViewGroup derived class
return
The Class of the inner LayoutParams or null if none is declared.

        IClassDescriptor[] innerClasses = groupClass.getDeclaredClasses();
        for (IClassDescriptor innerClass : innerClasses) {
            if (innerClass.getSimpleName().equals(AndroidConstants.CLASS_NAME_LAYOUTPARAMS)) {
                return innerClass;
            }
        }
        return null;
    
public java.util.ListgetGroups()
Returns the map of FQCN => info on ViewGroup classes

        return getInstantiables(mGroupMap);
    
private java.util.ListgetInstantiables(java.util.SortedMap map)
Computes and return a list of ViewClassInfo from a map by filtering out the class that cannot be instantiated.

        Collection<ExtViewClassInfo> values = map.values();
        ArrayList<ViewClassInfo> list = new ArrayList<ViewClassInfo>();
        
        for (ExtViewClassInfo info : values) {
            if (info.isInstantiable()) {
                list.add(info);
            }
        }
        
        return list;
    
private com.android.ide.eclipse.common.resources.ViewClassInfo.LayoutParamsInfogetLayoutParamsInfo(com.android.ide.eclipse.adt.sdk.IAndroidClassLoader.IClassDescriptor layoutParamsClass)
Parses a LayoutParams class and returns a LayoutParamsInfo object for it. It calls itself recursively to handle the super class of the LayoutParams.

        String fqcn = layoutParamsClass.getCanonicalName();
        LayoutParamsInfo layoutParamsInfo = mLayoutParamsMap.get(fqcn);

        if (layoutParamsInfo != null) {
            return layoutParamsInfo;
        }
        
        // Find the link on the LayoutParams super class 
        LayoutParamsInfo superClassInfo = null;
        if (layoutParamsClass.equals(mTopLayoutParamsClass) == false) {
            IClassDescriptor superClass = layoutParamsClass.getSuperclass(); 
            superClassInfo = getLayoutParamsInfo(superClass);
        }
        
        // Find the link on the enclosing ViewGroup
        ExtViewClassInfo enclosingGroupInfo = addGroup(layoutParamsClass.getEnclosingClass());

        layoutParamsInfo = new ExtViewClassInfo.LayoutParamsInfo(
                enclosingGroupInfo, layoutParamsClass.getSimpleName(), superClassInfo);
        mLayoutParamsMap.put(fqcn, layoutParamsInfo);

        mAttrsXmlParser.loadLayoutParamsAttributes(layoutParamsInfo);

        return layoutParamsInfo;
    
public java.util.ListgetViews()
Returns the map of FQCN => info on View classes

        return getInstantiables(mViewMap);
    
private voidparseClasses(org.eclipse.core.runtime.IProgressMonitor monitor, java.lang.String rootClassName, java.lang.String groupClassName, java.lang.String paramsClassName)

        try {
            SubMonitor progress = SubMonitor.convert(monitor, 100);

            String[] superClasses = new String[2 + (paramsClassName == null ? 0 : 1)];
            superClasses[0] = groupClassName;
            superClasses[1] = rootClassName;
            if (paramsClassName != null) {
                superClasses[2] = paramsClassName;
            }
            HashMap<String, ArrayList<IClassDescriptor>> found =
                    mClassLoader.findClassesDerivingFrom("android.", superClasses);  //$NON-NLS-1$
            mTopViewClass = mClassLoader.getClass(rootClassName);
            mTopGroupClass = mClassLoader.getClass(groupClassName);
            if (paramsClassName != null) {
                mTopLayoutParamsClass = mClassLoader.getClass(paramsClassName);
            }

            mViewList = found.get(rootClassName);
            mGroupList = found.get(groupClassName);

            mViewMap = new TreeMap<String, ExtViewClassInfo>();
            mGroupMap = new TreeMap<String, ExtViewClassInfo>();
            if (mTopLayoutParamsClass != null) {
                mLayoutParamsMap = new HashMap<String, LayoutParamsInfo>();
            }
            
            // Add top classes to the maps since by design they are not listed in classes deriving
            // from themselves.
            addGroup(mTopGroupClass);
            addView(mTopViewClass);

            // ViewGroup derives from View
            mGroupMap.get(groupClassName).setSuperClass(mViewMap.get(rootClassName));

            progress.setWorkRemaining(mGroupList.size() + mViewList.size());
            
            for (IClassDescriptor groupChild : mGroupList) {
                addGroup(groupChild);
                progress.worked(1);
            }

            for (IClassDescriptor viewChild : mViewList) {
                if (viewChild != mTopGroupClass) {
                    addView(viewChild);
                }
                progress.worked(1);
            }
        } catch (ClassNotFoundException e) {
            AdtPlugin.log(e, "Problem loading class %1$s or %2$s",  //$NON-NLS-1$
                    rootClassName, groupClassName);
        } catch (InvalidAttributeValueException e) {
            AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
        } catch (ClassFormatError e) {
            AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
        } catch (IOException e) {
            AdtPlugin.log(e, "Problem loading classes"); //$NON-NLS-1$
        }
    
public voidparseLayoutClasses(org.eclipse.core.runtime.IProgressMonitor monitor)
TODO: doc here.

Note: on output we should have NO dependency on {@link IClassDescriptor}, otherwise we wouldn't be able to unload the class loader later.

Note on Vocabulary: FQCN=Fully Qualified Class Name (e.g. "my.package.class$innerClass")

param
monitor A progress monitor. Can be null. Caller is responsible for calling done.

        parseClasses(monitor,
                AndroidConstants.CLASS_VIEW,
                AndroidConstants.CLASS_VIEWGROUP,
                AndroidConstants.CLASS_VIEWGROUP_LAYOUTPARAMS);
    
public voidparsePreferencesClasses(org.eclipse.core.runtime.IProgressMonitor monitor)

        parseClasses(monitor,
                AndroidConstants.CLASS_PREFERENCE,
                AndroidConstants.CLASS_PREFERENCEGROUP,
                null /* paramsClassName */ );