Home | History | Annotate | Download | only in sdk
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ide.eclipse.adt.internal.sdk;
     18 
     19 import com.android.ide.common.rendering.LayoutLibrary;
     20 import com.android.ide.common.rendering.api.LayoutLog;
     21 import com.android.ide.common.resources.ResourceRepository;
     22 import com.android.ide.common.sdk.LoadStatus;
     23 import com.android.ide.eclipse.adt.AdtPlugin;
     24 import com.android.ide.eclipse.adt.internal.editors.animator.AnimDescriptors;
     25 import com.android.ide.eclipse.adt.internal.editors.animator.AnimatorDescriptors;
     26 import com.android.ide.eclipse.adt.internal.editors.color.ColorDescriptors;
     27 import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
     28 import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableDescriptors;
     29 import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
     30 import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
     31 import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors;
     32 import com.android.ide.eclipse.adt.internal.editors.otherxml.descriptors.OtherXmlDescriptors;
     33 import com.android.ide.eclipse.adt.internal.editors.values.descriptors.ValuesDescriptors;
     34 import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
     35 import com.android.sdklib.IAndroidTarget;
     36 import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
     37 
     38 import org.eclipse.core.runtime.IStatus;
     39 
     40 import java.io.File;
     41 import java.util.ArrayList;
     42 import java.util.Hashtable;
     43 import java.util.Map;
     44 
     45 /**
     46  * This class contains the data of an Android Target as loaded from the SDK.
     47  */
     48 public class AndroidTargetData {
     49 
     50     public final static int DESCRIPTOR_MANIFEST = 1;
     51     public final static int DESCRIPTOR_LAYOUT = 2;
     52     public final static int DESCRIPTOR_MENU = 3;
     53     public final static int DESCRIPTOR_OTHER_XML = 4;
     54     public final static int DESCRIPTOR_RESOURCES = 5;
     55     public final static int DESCRIPTOR_SEARCHABLE = 6;
     56     public final static int DESCRIPTOR_PREFERENCES = 7;
     57     public final static int DESCRIPTOR_APPWIDGET_PROVIDER = 8;
     58     public final static int DESCRIPTOR_DRAWABLE = 9;
     59     public final static int DESCRIPTOR_ANIMATOR = 10;
     60     public final static int DESCRIPTOR_ANIM = 11;
     61     public final static int DESCRIPTOR_COLOR = 12;
     62 
     63     private final IAndroidTarget mTarget;
     64 
     65     /**
     66      * mAttributeValues is a map { key => list [ values ] }.
     67      * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)".
     68      * The attribute namespace prefix must be:
     69      * - "android" for AndroidConstants.NS_RESOURCES
     70      * - "xmlns" for the XMLNS URI.
     71      *
     72      * This is used for attributes that do not have a unique name, but still need to be populated
     73      * with values in the UI. Uniquely named attributes have their values in {@link #mEnumValueMap}.
     74      */
     75     private Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>();
     76 
     77     private AndroidManifestDescriptors mManifestDescriptors;
     78     private DrawableDescriptors mDrawableDescriptors;
     79     private AnimatorDescriptors mAnimatorDescriptors;
     80     private AnimDescriptors mAnimDescriptors;
     81     private ColorDescriptors mColorDescriptors;
     82     private LayoutDescriptors mLayoutDescriptors;
     83     private MenuDescriptors mMenuDescriptors;
     84     private OtherXmlDescriptors mOtherXmlDescriptors;
     85 
     86     private Map<String, Map<String, Integer>> mEnumValueMap;
     87 
     88     private ResourceRepository mFrameworkResources;
     89     private LayoutLibrary mLayoutLibrary;
     90 
     91     private boolean mLayoutBridgeInit = false;
     92 
     93     AndroidTargetData(IAndroidTarget androidTarget) {
     94         mTarget = androidTarget;
     95     }
     96 
     97     /**
     98      * Creates an AndroidTargetData object.
     99      */
    100     void setExtraData(
    101             AndroidManifestDescriptors manifestDescriptors,
    102             LayoutDescriptors layoutDescriptors,
    103             MenuDescriptors menuDescriptors,
    104             OtherXmlDescriptors otherXmlDescriptors,
    105             DrawableDescriptors drawableDescriptors,
    106             AnimatorDescriptors animatorDescriptors,
    107             AnimDescriptors animDescriptors,
    108             ColorDescriptors colorDescriptors,
    109             Map<String, Map<String, Integer>> enumValueMap,
    110             String[] permissionValues,
    111             String[] activityIntentActionValues,
    112             String[] broadcastIntentActionValues,
    113             String[] serviceIntentActionValues,
    114             String[] intentCategoryValues,
    115             String[] platformLibraries,
    116             IOptionalLibrary[] optionalLibraries,
    117             ResourceRepository frameworkResources,
    118             LayoutLibrary layoutLibrary) {
    119 
    120         mManifestDescriptors = manifestDescriptors;
    121         mDrawableDescriptors = drawableDescriptors;
    122         mAnimatorDescriptors = animatorDescriptors;
    123         mAnimDescriptors = animDescriptors;
    124         mColorDescriptors = colorDescriptors;
    125         mLayoutDescriptors = layoutDescriptors;
    126         mMenuDescriptors = menuDescriptors;
    127         mOtherXmlDescriptors = otherXmlDescriptors;
    128         mEnumValueMap = enumValueMap;
    129         mFrameworkResources = frameworkResources;
    130         mLayoutLibrary = layoutLibrary;
    131 
    132         setPermissions(permissionValues);
    133         setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues,
    134                 serviceIntentActionValues, intentCategoryValues);
    135         setOptionalLibraries(platformLibraries, optionalLibraries);
    136     }
    137 
    138     /**
    139      * Returns an {@link IDescriptorProvider} from a given Id.
    140      * The Id can be one of {@link #DESCRIPTOR_MANIFEST}, {@link #DESCRIPTOR_LAYOUT},
    141      * {@link #DESCRIPTOR_MENU}, or {@link #DESCRIPTOR_OTHER_XML}.
    142      * All other values will throw an {@link IllegalArgumentException}.
    143      */
    144     public IDescriptorProvider getDescriptorProvider(int descriptorId) {
    145         switch (descriptorId) {
    146             case DESCRIPTOR_MANIFEST:
    147                 return mManifestDescriptors;
    148             case DESCRIPTOR_LAYOUT:
    149                 return mLayoutDescriptors;
    150             case DESCRIPTOR_MENU:
    151                 return mMenuDescriptors;
    152             case DESCRIPTOR_OTHER_XML:
    153                 return mOtherXmlDescriptors;
    154             case DESCRIPTOR_RESOURCES:
    155                 // FIXME: since it's hard-coded the Resources Descriptors are not platform dependent.
    156                 return ValuesDescriptors.getInstance();
    157             case DESCRIPTOR_PREFERENCES:
    158                 return mOtherXmlDescriptors.getPreferencesProvider();
    159             case DESCRIPTOR_APPWIDGET_PROVIDER:
    160                 return mOtherXmlDescriptors.getAppWidgetProvider();
    161             case DESCRIPTOR_SEARCHABLE:
    162                 return mOtherXmlDescriptors.getSearchableProvider();
    163             case DESCRIPTOR_DRAWABLE:
    164                 return mDrawableDescriptors;
    165             case DESCRIPTOR_ANIMATOR:
    166                 return mAnimatorDescriptors;
    167             case DESCRIPTOR_ANIM:
    168                 return mAnimDescriptors;
    169             case DESCRIPTOR_COLOR:
    170                 return mColorDescriptors;
    171             default :
    172                  throw new IllegalArgumentException();
    173         }
    174     }
    175 
    176     /**
    177      * Returns the manifest descriptors.
    178      */
    179     public AndroidManifestDescriptors getManifestDescriptors() {
    180         return mManifestDescriptors;
    181     }
    182 
    183     /**
    184      * Returns the drawable descriptors
    185      */
    186     public DrawableDescriptors getDrawableDescriptors() {
    187         return mDrawableDescriptors;
    188     }
    189 
    190     /**
    191      * Returns the animation descriptors
    192      */
    193     public AnimDescriptors getAnimDescriptors() {
    194         return mAnimDescriptors;
    195     }
    196 
    197     /**
    198      * Returns the color descriptors
    199      */
    200     public ColorDescriptors getColorDescriptors() {
    201         return mColorDescriptors;
    202     }
    203 
    204     /**
    205      * Returns the animator descriptors
    206      */
    207     public AnimatorDescriptors getAnimatorDescriptors() {
    208         return mAnimatorDescriptors;
    209     }
    210 
    211     /**
    212      * Returns the layout Descriptors.
    213      */
    214     public LayoutDescriptors getLayoutDescriptors() {
    215         return mLayoutDescriptors;
    216     }
    217 
    218     /**
    219      * Returns the menu descriptors.
    220      */
    221     public MenuDescriptors getMenuDescriptors() {
    222         return mMenuDescriptors;
    223     }
    224 
    225     /**
    226      * Returns the XML descriptors
    227      */
    228     public OtherXmlDescriptors getXmlDescriptors() {
    229         return mOtherXmlDescriptors;
    230     }
    231 
    232     /**
    233      * Returns this list of possible values for an XML attribute.
    234      * <p/>This should only be called for attributes for which possible values depend on the
    235      * parent element node.
    236      * <p/>For attributes that have the same values no matter the parent node, use
    237      * {@link #getEnumValueMap()}.
    238      * @param elementName the name of the element containing the attribute.
    239      * @param attributeName the name of the attribute
    240      * @return an array of String with the possible values, or <code>null</code> if no values were
    241      * found.
    242      */
    243     public String[] getAttributeValues(String elementName, String attributeName) {
    244         String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$
    245         return mAttributeValues.get(key);
    246     }
    247 
    248     /**
    249      * Returns this list of possible values for an XML attribute.
    250      * <p/>This should only be called for attributes for which possible values depend on the
    251      * parent and great-grand-parent element node.
    252      * <p/>The typical example of this is for the 'name' attribute under
    253      * activity/intent-filter/action
    254      * <p/>For attributes that have the same values no matter the parent node, use
    255      * {@link #getEnumValueMap()}.
    256      * @param elementName the name of the element containing the attribute.
    257      * @param attributeName the name of the attribute
    258      * @param greatGrandParentElementName the great-grand-parent node.
    259      * @return an array of String with the possible values, or <code>null</code> if no values were
    260      * found.
    261      */
    262     public String[] getAttributeValues(String elementName, String attributeName,
    263             String greatGrandParentElementName) {
    264         if (greatGrandParentElementName != null) {
    265             String key = String.format("(%1$s,%2$s,%3$s)", //$NON-NLS-1$
    266                     greatGrandParentElementName, elementName, attributeName);
    267             String[] values = mAttributeValues.get(key);
    268             if (values != null) {
    269                 return values;
    270             }
    271         }
    272 
    273         return getAttributeValues(elementName, attributeName);
    274     }
    275 
    276     /**
    277      * Returns the enum values map.
    278      * <p/>The map defines the possible values for XML attributes. The key is the attribute name
    279      * and the value is a map of (string, integer) in which the key (string) is the name of
    280      * the value, and the Integer is the numerical value in the compiled binary XML files.
    281      */
    282     public Map<String, Map<String, Integer>> getEnumValueMap() {
    283         return mEnumValueMap;
    284     }
    285 
    286     /**
    287      * Returns the {@link ProjectResources} containing the Framework Resources.
    288      */
    289     public ResourceRepository getFrameworkResources() {
    290         return mFrameworkResources;
    291     }
    292 
    293     /**
    294      * Returns a {@link LayoutLibrary} object possibly containing a {@link LayoutBridge} object.
    295      * <p/>If {@link LayoutLibrary#getBridge()} is <code>null</code>,
    296      * {@link LayoutBridge#getStatus()} will contain the reason (either {@link LoadStatus#LOADING}
    297      * or {@link LoadStatus#FAILED}).
    298      * <p/>Valid {@link LayoutBridge} objects are always initialized before being returned.
    299      */
    300     public synchronized LayoutLibrary getLayoutLibrary() {
    301         if (mLayoutBridgeInit == false && mLayoutLibrary.getStatus() == LoadStatus.LOADED) {
    302             boolean ok = mLayoutLibrary.init(
    303                     mTarget.getProperties(),
    304                     new File(mTarget.getPath(IAndroidTarget.FONTS)),
    305                     getEnumValueMap(),
    306                     new LayoutLog() {
    307 
    308                         @Override
    309                         public void error(String tag, String message, Throwable throwable,
    310                                 Object data) {
    311                             AdtPlugin.log(throwable, message);
    312                         }
    313 
    314                         @Override
    315                         public void error(String tag, String message, Object data) {
    316                             AdtPlugin.log(IStatus.ERROR, message);
    317                         }
    318 
    319                         @Override
    320                         public void warning(String tag, String message, Object data) {
    321                             AdtPlugin.log(IStatus.WARNING, message);
    322                         }
    323                     });
    324             if (!ok) {
    325                 AdtPlugin.log(IStatus.ERROR,
    326                         "LayoutLibrary initialization failed");
    327             }
    328             mLayoutBridgeInit = true;
    329         }
    330 
    331         return mLayoutLibrary;
    332     }
    333 
    334     /**
    335      * Sets the permission values
    336      * @param permissionValues the list of permissions
    337      */
    338     private void setPermissions(String[] permissionValues) {
    339         setValues("(uses-permission,android:name)", permissionValues);   //$NON-NLS-1$
    340         setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$
    341         setValues("(activity,android:permission)", permissionValues);    //$NON-NLS-1$
    342         setValues("(receiver,android:permission)", permissionValues);    //$NON-NLS-1$
    343         setValues("(service,android:permission)", permissionValues);     //$NON-NLS-1$
    344         setValues("(provider,android:permission)", permissionValues);    //$NON-NLS-1$
    345     }
    346 
    347     private void setIntentFilterActionsAndCategories(String[] activityIntentActions,
    348             String[] broadcastIntentActions, String[] serviceIntentActions,
    349             String[] intentCategoryValues) {
    350         setValues("(activity,action,android:name)", activityIntentActions);  //$NON-NLS-1$
    351         setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$
    352         setValues("(service,action,android:name)", serviceIntentActions);    //$NON-NLS-1$
    353         setValues("(category,android:name)", intentCategoryValues);          //$NON-NLS-1$
    354     }
    355 
    356     private void setOptionalLibraries(String[] platformLibraries,
    357             IOptionalLibrary[] optionalLibraries) {
    358 
    359         ArrayList<String> libs = new ArrayList<String>();
    360 
    361         if (platformLibraries != null) {
    362             for (String name : platformLibraries) {
    363                 libs.add(name);
    364             }
    365         }
    366 
    367         if (optionalLibraries != null) {
    368             for (int i = 0; i < optionalLibraries.length; i++) {
    369                 libs.add(optionalLibraries[i].getName());
    370             }
    371         }
    372         setValues("(uses-library,android:name)",  libs.toArray(new String[libs.size()]));
    373     }
    374 
    375     /**
    376      * Sets a (name, values) pair in the hash map.
    377      * <p/>
    378      * If the name is already present in the map, it is first removed.
    379      * @param name the name associated with the values.
    380      * @param values The values to add.
    381      */
    382     private void setValues(String name, String[] values) {
    383         mAttributeValues.remove(name);
    384         mAttributeValues.put(name, values);
    385     }
    386 
    387     public void dispose() {
    388         if (mLayoutLibrary != null) {
    389             mLayoutLibrary.dispose();
    390         }
    391     }
    392 }
    393