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