FileDocCategorySizeDatePackage
CustomViewDescriptorService.javaAPI DocAndroid 1.5 API12200Wed May 06 22:41:10 BST 2009com.android.ide.eclipse.editors.layout.descriptors

CustomViewDescriptorService

public final class CustomViewDescriptorService extends Object
Service responsible for creating/managing {@link ElementDescriptor} objects for custom View classes per project.

The service provides an on-demand monitoring of custom classes to check for changes. Monitoring starts once a request for an {@link ElementDescriptor} object has been done for a specific class.
The monitoring will notify a listen of any changes in the class triggering a change in its associated {@link ElementDescriptor} object.

If the custom class does not exist, no monitoring is put in place to avoid having to listen to all class changes in the projects.

Fields Summary
private static CustomViewDescriptorService
sThis
private HashMap
mCustomDescriptorMap
Map where keys are the project, and values are another map containing all the known custom View class for this project. The custom View class are stored in a map where the keys are the fully qualified class name, and the values are their associated {@link ElementDescriptor}.
private ICustomViewDescriptorListener
mListener
TODO will be used to update the ElementDescriptor of the custom view when it is modified (either the class itself or its attributes.xml)
Constructors Summary
Methods Summary
private com.android.ide.eclipse.editors.descriptors.AttributeDescriptor[]getAttributeDescriptor(org.eclipse.jdt.core.IType type, com.android.ide.eclipse.editors.descriptors.ElementDescriptor parentDescriptor)
Returns the array of {@link AttributeDescriptor} for the specified {@link IType}.

The array should contain the descriptor for this type and all its supertypes.

param
type the type for which the {@link AttributeDescriptor} are returned.
param
parentDescriptor the {@link ElementDescriptor} of the direct superclass.

        // TODO add the class attribute descriptors to the parent descriptors.
        return parentDescriptor.getAttributes();
    
public com.android.ide.eclipse.editors.descriptors.ElementDescriptorgetDescriptor(org.eclipse.core.resources.IProject project, java.lang.String fqClassName)
Returns the {@link ElementDescriptor} for a particular project/class.

If it is the first time the ElementDescriptor is requested, the method will check that the specified class is in fact a custom View class. Once this is established, a monitoring for that particular class is initiated. Any change will trigger a notification to the {@link ICustomViewDescriptorListener}.

param
project the project containing the class.
param
fqClassName the fully qualified name of the class.
return
a ElementDescriptor or null if the class was not a custom View class.

        // look in the map first
        synchronized (mCustomDescriptorMap) {
            HashMap<String, ElementDescriptor> map = mCustomDescriptorMap.get(project);
            
            if (map != null) {
                ElementDescriptor descriptor = map.get(fqClassName);
                if (descriptor != null) {
                    return descriptor;
                }
            }
        
            // if we step here, it looks like we haven't created it yet.
            // First lets check this is in fact a valid type in the project
            
            try {
                // We expect the project to be both opened and of java type (since it's an android
                // project), so we can create a IJavaProject object from our IProject.
                IJavaProject javaProject = JavaCore.create(project);
                
                // replace $ by . in the class name
                String javaClassName = fqClassName.replaceAll("\\$", "\\."); //$NON-NLS-1$ //$NON-NLS-2$
        
                // look for the IType object for this class
                IType type = javaProject.findType(javaClassName);
                if (type != null && type.exists()) {
                    // the type exists. Let's get the parent class and its ViewClassInfo.
                    
                    // get the type hierarchy
                    ITypeHierarchy hierarchy = type.newSupertypeHierarchy(
                            new NullProgressMonitor());
                    
                    ElementDescriptor parentDescriptor = getDescriptor(
                            hierarchy.getSuperclass(type), project, hierarchy);
                    
                    if (parentDescriptor != null) {
                        // we have a valid parent, lets create a new ElementDescriptor.

                        ViewElementDescriptor descriptor = new ViewElementDescriptor(fqClassName,
                                fqClassName, // ui_name
                                fqClassName, // canonical class name
                                null, // tooltip
                                null, // sdk_url
                                getAttributeDescriptor(type, parentDescriptor),
                                null, // layout attributes
                                null, // children
                                false /* mandatory */);

                        synchronized (mCustomDescriptorMap) {
                            map = mCustomDescriptorMap.get(project);
                            if (map == null) {
                                map = new HashMap<String, ElementDescriptor>();
                                mCustomDescriptorMap.put(project, map);
                            }
                        
                            map.put(fqClassName, descriptor);
                        }
                        
                        //TODO setup listener on this resource change.
                        
                        return descriptor;
                    }
                }
            } catch (JavaModelException e) {
                // there was an error accessing any of the IType, we'll just return null;
            }
        }


        return null;
    
private ViewElementDescriptorgetDescriptor(org.eclipse.jdt.core.IType type, org.eclipse.core.resources.IProject project, org.eclipse.jdt.core.ITypeHierarchy typeHierarchy)
Computes (if needed) and returns the {@link ElementDescriptor} for the specified type.

param
type
param
project
param
typeHierarchy
return
A ViewElementDescriptor or null if type or typeHierarchy is null.

        // check if the type is a built-in View class.
        List<ElementDescriptor> builtInList = null;

        Sdk currentSdk = Sdk.getCurrent();
        IAndroidTarget target = currentSdk == null ? null : currentSdk.getTarget(project);
        if (target != null) {
            AndroidTargetData data = currentSdk.getTargetData(target);
            builtInList = data.getLayoutDescriptors().getViewDescriptors();
        }

        // give up if there's no type
        if (type == null) {
            return null;
        }

        String canonicalName = type.getFullyQualifiedName();
        
        if (builtInList != null) {
            for (ElementDescriptor desc : builtInList) {
                if (desc instanceof ViewElementDescriptor) {
                    ViewElementDescriptor viewDescriptor = (ViewElementDescriptor)desc;
                    if (canonicalName.equals(viewDescriptor.getCanonicalClassName())) {
                        return viewDescriptor;
                    }
                }
            }
        }
        
        // it's not a built-in class? Lets look if the superclass is built-in
        // give up if there's no type
        if (typeHierarchy == null) {
            return null;
        }

        IType parentType = typeHierarchy.getSuperclass(type);
        if (parentType != null) {
            ViewElementDescriptor parentDescriptor = getDescriptor(parentType, project,
                    typeHierarchy);
            
            if (parentDescriptor != null) {
                // parent class is a valid View class with a descriptor, so we create one
                // for this class.
                ViewElementDescriptor descriptor = new ViewElementDescriptor(canonicalName,
                        canonicalName, // ui_name
                        canonicalName, // canonical name
                        null, // tooltip
                        null, // sdk_url
                        getAttributeDescriptor(type, parentDescriptor),
                        null, // layout attributes
                        null, // children
                        false /* mandatory */);
                
                // add it to the map
                synchronized (mCustomDescriptorMap) {
                    HashMap<String, ElementDescriptor> map = mCustomDescriptorMap.get(project);
                    
                    if (map == null) {
                        map = new HashMap<String, ElementDescriptor>();
                        mCustomDescriptorMap.put(project, map);
                    }
                    
                    map.put(canonicalName, descriptor);
                    
                }

                //TODO setup listener on this resource change.
                
                return descriptor;
            }
        }
        
        // class is neither a built-in view class, nor extend one. return null.
        return null;
    
public static com.android.ide.eclipse.editors.layout.descriptors.CustomViewDescriptorServicegetInstance()
Returns the singleton instance of {@link CustomViewDescriptorService}.

        return sThis;
    
public voidsetListener(com.android.ide.eclipse.editors.layout.descriptors.CustomViewDescriptorService$ICustomViewDescriptorListener listener)
Sets the listener receiving custom View class modification notifications.

param
listener the listener to receive the notifications. TODO will be used to update the ElementDescriptor of the custom view when it is modified (either the class itself or its attributes.xml)

        mListener = listener;