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

WidgetClassLoader

public final class WidgetClassLoader extends Object implements IAndroidClassLoader
Parser for the text file containing the list of widgets, layouts and layout params.

The file is a straight text file containing one class per line.
Each line is in the following format
[code][class name] [super class name] [super class name]... where code is a single letter (W for widget, L for layout, P for layout params), and class names are the fully qualified name of the classes.

Fields Summary
private BufferedReader
mReader
private final Map
mMap
Output map of FQCN => descriptor on all classes
private final Map
mWidgetMap
Output map of FQCN => descriptor on View classes
private final Map
mLayoutMap
Output map of FQCN => descriptor on ViewGroup classes
private final Map
mLayoutParamsMap
Output map of FQCN => descriptor on LayoutParams classes
private String
mOsFilePath
File path of the source text file
Constructors Summary
WidgetClassLoader(String osFilePath)
Creates a loader with a given file path.

param
osFilePath the OS path of the file to load.
throws
FileNotFoundException if the file is not found.


                                   
        
        mOsFilePath = osFilePath;
        mReader = new BufferedReader(new FileReader(osFilePath));
    
Methods Summary
public java.util.HashMapfindClassesDerivingFrom(java.lang.String rootPackage, java.lang.String[] superClasses)
Finds and loads all classes that derive from a given set of super classes.

param
rootPackage Root package of classes to find. Use an empty string to find everyting.
param
superClasses The super classes of all the classes to find.
return
An hash map which keys are the super classes looked for and which values are ArrayList of the classes found. The array lists are always created for all the valid keys, they are simply empty if no deriving class is found for a given super class.
throws
IOException
throws
InvalidAttributeValueException
throws
ClassFormatError

        HashMap<String, ArrayList<IClassDescriptor>> map =
                new HashMap<String, ArrayList<IClassDescriptor>>();
        
        ArrayList<IClassDescriptor> list = new ArrayList<IClassDescriptor>();
        list.addAll(mWidgetMap.values());
        map.put(AndroidConstants.CLASS_VIEW, list);
        
        list = new ArrayList<IClassDescriptor>();
        list.addAll(mLayoutMap.values());
        map.put(AndroidConstants.CLASS_VIEWGROUP, list);

        list = new ArrayList<IClassDescriptor>();
        list.addAll(mLayoutParamsMap.values());
        map.put(AndroidConstants.CLASS_VIEWGROUP_LAYOUTPARAMS, list);

        return map;
    
public IClassDescriptorgetClass(java.lang.String className)
Returns a {@link IAndroidClassLoader.IClassDescriptor} by its fully-qualified name.

param
className the fully-qualified name of the class to return.
throws
ClassNotFoundException

        return mMap.get(className);
    
private java.lang.StringgetEnclosedName(java.lang.String fqcn)

        int index = fqcn.lastIndexOf('.");
        return fqcn.substring(0, index);
    
public java.lang.StringgetSource()

        return mOsFilePath;
    
booleanparseWidgetList(org.eclipse.core.runtime.IProgressMonitor monitor)
Parses the text file and return true if the file was successfully parsed.

param
monitor

        try {
            String line;
            while ((line = mReader.readLine()) != null) {
                if (line.length() > 0) {
                    char prefix = line.charAt(0);
                    String[] classes = null;
                    ClassDescriptor clazz = null;
                    switch (prefix) {
                        case 'W":
                            classes = line.substring(1).split(" ");
                            clazz = processClass(classes, 0, null /* map */);
                            if (clazz != null) {
                                clazz.setInstantiable(true);
                                mWidgetMap.put(classes[0], clazz);
                            }
                            break;
                        case 'L":
                            classes = line.substring(1).split(" ");
                            clazz = processClass(classes, 0, null /* map */);
                            if (clazz != null) {
                                clazz.setInstantiable(true);
                                mLayoutMap.put(classes[0], clazz);
                            }
                            break;
                        case 'P":
                            classes = line.substring(1).split(" ");
                            clazz = processClass(classes, 0, mLayoutParamsMap);
                            if (clazz != null) {
                                clazz.setInstantiable(true);
                            }
                            break;
                        case '#":
                            // comment, do nothing
                            break;
                        default:
                                throw new IllegalArgumentException();
                    }
                }
            }
            
            // reconciliate the layout and their layout params
            postProcess();
            
            return true;
        } catch (IOException e) {
        } finally {
            try {
                mReader.close();
            } catch (IOException e) {
            }
        }
        
        return false;
    
private voidpostProcess()
Goes through the layout params and look for the enclosed class. If the layout params has no known enclosed type it is dropped.

        Collection<ClassDescriptor> params = mLayoutParamsMap.values();

        for (ClassDescriptor param : params) {
            String fqcn = param.getCanonicalName();
            
            // get the enclosed name.
            String enclosed = getEnclosedName(fqcn);
            
            // look for a match in the layouts. We don't use the layout map as it only contains the
            // end classes, but in this case we also need to process the layout params for the base
            // layout classes.
            ClassDescriptor enclosingType = mMap.get(enclosed);
            if (enclosingType != null) {
                param.setEnclosingClass(enclosingType);
                
                // remove the class from the map, and put it back with the fixed name
                mMap.remove(fqcn);
                mMap.put(param.getCanonicalName(), param);
            }
        }
    
private com.android.ide.eclipse.adt.sdk.WidgetClassLoader$ClassDescriptorprocessClass(java.lang.String[] classes, int index, java.util.Map map)
Parses a View class and adds a ViewClassInfo for it in mWidgetMap. It calls itself recursively to handle super classes which are also Views.

param
classes the inheritance list of the class to process.
param
index the index of the class to process in the classes array.
param
map an optional map in which to put every {@link ClassDescriptor} created.

        if (index >= classes.length) {
            return null;
        }
        
        String fqcn = classes[index];
        
        if ("java.lang.Object".equals(fqcn)) { //$NON-NLS-1$
            return null;
        }

        // check if the ViewInfoClass has not yet been created.
        if (mMap.containsKey(fqcn)) {
            return mMap.get(fqcn);
        }

        // create the custom class.
        ClassDescriptor clazz = new ClassDescriptor(fqcn);
        mMap.put(fqcn, clazz);
        if (map != null) {
            map.put(fqcn, clazz);
        }
        
        // get the super class
        ClassDescriptor superClass = processClass(classes, index+1, map);
        if (superClass != null) {
            clazz.setSuperClass(superClass);
        }
        
        return clazz;