aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java
blob: 85ae9fdc0c24f617b6fdf193bf3ad57bc5b35f38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.eclipse.org/org/documents/epl-v10.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.ide.eclipse.adt.internal.sdk;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.rendering.LayoutLibrary;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.resources.ResourceRepository;
import com.android.ide.common.resources.platform.AttributeInfo;
import com.android.ide.common.sdk.LoadStatus;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.animator.AnimDescriptors;
import com.android.ide.eclipse.adt.internal.editors.animator.AnimatorDescriptors;
import com.android.ide.eclipse.adt.internal.editors.color.ColorDescriptors;
import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableDescriptors;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors;
import com.android.ide.eclipse.adt.internal.editors.otherxml.descriptors.OtherXmlDescriptors;
import com.android.ide.eclipse.adt.internal.editors.values.descriptors.ValuesDescriptors;
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.IAndroidTarget.IOptionalLibrary;

import org.eclipse.core.runtime.IStatus;

import java.io.File;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Map;

/**
 * This class contains the data of an Android Target as loaded from the SDK.
 */
public class AndroidTargetData {

    public final static int DESCRIPTOR_MANIFEST = 1;
    public final static int DESCRIPTOR_LAYOUT = 2;
    public final static int DESCRIPTOR_MENU = 3;
    public final static int DESCRIPTOR_OTHER_XML = 4;
    public final static int DESCRIPTOR_RESOURCES = 5;
    public final static int DESCRIPTOR_SEARCHABLE = 6;
    public final static int DESCRIPTOR_PREFERENCES = 7;
    public final static int DESCRIPTOR_APPWIDGET_PROVIDER = 8;
    public final static int DESCRIPTOR_DRAWABLE = 9;
    public final static int DESCRIPTOR_ANIMATOR = 10;
    public final static int DESCRIPTOR_ANIM = 11;
    public final static int DESCRIPTOR_COLOR = 12;

    private final IAndroidTarget mTarget;

    /**
     * mAttributeValues is a map { key => list [ values ] }.
     * The key for the map is "(element-xml-name,attribute-namespace:attribute-xml-local-name)".
     * The attribute namespace prefix must be:
     * - "android" for SdkConstants.NS_RESOURCES
     * - "xmlns" for the XMLNS URI.
     *
     * This is used for attributes that do not have a unique name, but still need to be populated
     * with values in the UI. Uniquely named attributes have their values in {@link #mEnumValueMap}.
     */
    private Hashtable<String, String[]> mAttributeValues = new Hashtable<String, String[]>();

    private AndroidManifestDescriptors mManifestDescriptors;
    private DrawableDescriptors mDrawableDescriptors;
    private AnimatorDescriptors mAnimatorDescriptors;
    private AnimDescriptors mAnimDescriptors;
    private ColorDescriptors mColorDescriptors;
    private LayoutDescriptors mLayoutDescriptors;
    private MenuDescriptors mMenuDescriptors;
    private OtherXmlDescriptors mOtherXmlDescriptors;

    private Map<String, Map<String, Integer>> mEnumValueMap;

    private ResourceRepository mFrameworkResources;
    private LayoutLibrary mLayoutLibrary;
    private Map<String, AttributeInfo> mAttributeMap;

    private boolean mLayoutBridgeInit = false;

    AndroidTargetData(IAndroidTarget androidTarget) {
        mTarget = androidTarget;
    }

    /**
     * Sets the associated map from string attribute name to
     * {@link AttributeInfo}
     *
     * @param attributeMap the map
     */
    public void setAttributeMap(@NonNull Map<String, AttributeInfo> attributeMap) {
        mAttributeMap = attributeMap;
    }

    /**
     * Returns the associated map from string attribute name to
     * {@link AttributeInfo}
     *
     * @return the map
     */
    @Nullable
    public Map<String, AttributeInfo> getAttributeMap() {
        return mAttributeMap;
    }

    /**
     * Creates an AndroidTargetData object.
     */
    void setExtraData(
            AndroidManifestDescriptors manifestDescriptors,
            LayoutDescriptors layoutDescriptors,
            MenuDescriptors menuDescriptors,
            OtherXmlDescriptors otherXmlDescriptors,
            DrawableDescriptors drawableDescriptors,
            AnimatorDescriptors animatorDescriptors,
            AnimDescriptors animDescriptors,
            ColorDescriptors colorDescriptors,
            Map<String, Map<String, Integer>> enumValueMap,
            String[] permissionValues,
            String[] activityIntentActionValues,
            String[] broadcastIntentActionValues,
            String[] serviceIntentActionValues,
            String[] intentCategoryValues,
            String[] platformLibraries,
            IOptionalLibrary[] optionalLibraries,
            ResourceRepository frameworkResources,
            LayoutLibrary layoutLibrary) {

        mManifestDescriptors = manifestDescriptors;
        mDrawableDescriptors = drawableDescriptors;
        mAnimatorDescriptors = animatorDescriptors;
        mAnimDescriptors = animDescriptors;
        mColorDescriptors = colorDescriptors;
        mLayoutDescriptors = layoutDescriptors;
        mMenuDescriptors = menuDescriptors;
        mOtherXmlDescriptors = otherXmlDescriptors;
        mEnumValueMap = enumValueMap;
        mFrameworkResources = frameworkResources;
        mLayoutLibrary = layoutLibrary;

        setPermissions(permissionValues);
        setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues,
                serviceIntentActionValues, intentCategoryValues);
        setOptionalLibraries(platformLibraries, optionalLibraries);
    }

    /**
     * Returns an {@link IDescriptorProvider} from a given Id.
     * The Id can be one of {@link #DESCRIPTOR_MANIFEST}, {@link #DESCRIPTOR_LAYOUT},
     * {@link #DESCRIPTOR_MENU}, or {@link #DESCRIPTOR_OTHER_XML}.
     * All other values will throw an {@link IllegalArgumentException}.
     */
    public IDescriptorProvider getDescriptorProvider(int descriptorId) {
        switch (descriptorId) {
            case DESCRIPTOR_MANIFEST:
                return mManifestDescriptors;
            case DESCRIPTOR_LAYOUT:
                return mLayoutDescriptors;
            case DESCRIPTOR_MENU:
                return mMenuDescriptors;
            case DESCRIPTOR_OTHER_XML:
                return mOtherXmlDescriptors;
            case DESCRIPTOR_RESOURCES:
                // FIXME: since it's hard-coded the Resources Descriptors are not platform dependent.
                return ValuesDescriptors.getInstance();
            case DESCRIPTOR_PREFERENCES:
                return mOtherXmlDescriptors.getPreferencesProvider();
            case DESCRIPTOR_APPWIDGET_PROVIDER:
                return mOtherXmlDescriptors.getAppWidgetProvider();
            case DESCRIPTOR_SEARCHABLE:
                return mOtherXmlDescriptors.getSearchableProvider();
            case DESCRIPTOR_DRAWABLE:
                return mDrawableDescriptors;
            case DESCRIPTOR_ANIMATOR:
                return mAnimatorDescriptors;
            case DESCRIPTOR_ANIM:
                return mAnimDescriptors;
            case DESCRIPTOR_COLOR:
                return mColorDescriptors;
            default :
                 throw new IllegalArgumentException();
        }
    }

    /**
     * Returns the manifest descriptors.
     */
    public AndroidManifestDescriptors getManifestDescriptors() {
        return mManifestDescriptors;
    }

    /**
     * Returns the drawable descriptors
     */
    public DrawableDescriptors getDrawableDescriptors() {
        return mDrawableDescriptors;
    }

    /**
     * Returns the animation descriptors
     */
    public AnimDescriptors getAnimDescriptors() {
        return mAnimDescriptors;
    }

    /**
     * Returns the color descriptors
     */
    public ColorDescriptors getColorDescriptors() {
        return mColorDescriptors;
    }

    /**
     * Returns the animator descriptors
     */
    public AnimatorDescriptors getAnimatorDescriptors() {
        return mAnimatorDescriptors;
    }

    /**
     * Returns the layout Descriptors.
     */
    public LayoutDescriptors getLayoutDescriptors() {
        return mLayoutDescriptors;
    }

    /**
     * Returns the menu descriptors.
     */
    public MenuDescriptors getMenuDescriptors() {
        return mMenuDescriptors;
    }

    /**
     * Returns the XML descriptors
     */
    public OtherXmlDescriptors getXmlDescriptors() {
        return mOtherXmlDescriptors;
    }

    /**
     * Returns this list of possible values for an XML attribute.
     * <p/>This should only be called for attributes for which possible values depend on the
     * parent element node.
     * <p/>For attributes that have the same values no matter the parent node, use
     * {@link #getEnumValueMap()}.
     * @param elementName the name of the element containing the attribute.
     * @param attributeName the name of the attribute
     * @return an array of String with the possible values, or <code>null</code> if no values were
     * found.
     */
    public String[] getAttributeValues(String elementName, String attributeName) {
        String key = String.format("(%1$s,%2$s)", elementName, attributeName); //$NON-NLS-1$
        return mAttributeValues.get(key);
    }

    /**
     * Returns this list of possible values for an XML attribute.
     * <p/>This should only be called for attributes for which possible values depend on the
     * parent and great-grand-parent element node.
     * <p/>The typical example of this is for the 'name' attribute under
     * activity/intent-filter/action
     * <p/>For attributes that have the same values no matter the parent node, use
     * {@link #getEnumValueMap()}.
     * @param elementName the name of the element containing the attribute.
     * @param attributeName the name of the attribute
     * @param greatGrandParentElementName the great-grand-parent node.
     * @return an array of String with the possible values, or <code>null</code> if no values were
     * found.
     */
    public String[] getAttributeValues(String elementName, String attributeName,
            String greatGrandParentElementName) {
        if (greatGrandParentElementName != null) {
            String key = String.format("(%1$s,%2$s,%3$s)", //$NON-NLS-1$
                    greatGrandParentElementName, elementName, attributeName);
            String[] values = mAttributeValues.get(key);
            if (values != null) {
                return values;
            }
        }

        return getAttributeValues(elementName, attributeName);
    }

    /**
     * Returns the enum values map.
     * <p/>The map defines the possible values for XML attributes. The key is the attribute name
     * and the value is a map of (string, integer) in which the key (string) is the name of
     * the value, and the Integer is the numerical value in the compiled binary XML files.
     */
    public Map<String, Map<String, Integer>> getEnumValueMap() {
        return mEnumValueMap;
    }

    /**
     * Returns the {@link ProjectResources} containing the Framework Resources.
     */
    public ResourceRepository getFrameworkResources() {
        return mFrameworkResources;
    }

    /**
     * Returns a {@link LayoutLibrary} object possibly containing a {@link LayoutBridge} object.
     * <p/>If {@link LayoutLibrary#getBridge()} is <code>null</code>,
     * {@link LayoutBridge#getStatus()} will contain the reason (either {@link LoadStatus#LOADING}
     * or {@link LoadStatus#FAILED}).
     * <p/>Valid {@link LayoutBridge} objects are always initialized before being returned.
     */
    public synchronized LayoutLibrary getLayoutLibrary() {
        if (mLayoutBridgeInit == false && mLayoutLibrary.getStatus() == LoadStatus.LOADED) {
            boolean ok = mLayoutLibrary.init(
                    mTarget.getProperties(),
                    new File(mTarget.getPath(IAndroidTarget.FONTS)),
                    getEnumValueMap(),
                    new LayoutLog() {

                        @Override
                        public void error(String tag, String message, Throwable throwable,
                                Object data) {
                            AdtPlugin.log(throwable, message);
                        }

                        @Override
                        public void error(String tag, String message, Object data) {
                            AdtPlugin.log(IStatus.ERROR, message);
                        }

                        @Override
                        public void warning(String tag, String message, Object data) {
                            AdtPlugin.log(IStatus.WARNING, message);
                        }
                    });
            if (!ok) {
                AdtPlugin.log(IStatus.ERROR,
                        "LayoutLibrary initialization failed");
            }
            mLayoutBridgeInit = true;
        }

        return mLayoutLibrary;
    }

    /**
     * Sets the permission values
     * @param permissionValues the list of permissions
     */
    private void setPermissions(String[] permissionValues) {
        setValues("(uses-permission,android:name)", permissionValues);   //$NON-NLS-1$
        setValues("(application,android:permission)", permissionValues); //$NON-NLS-1$
        setValues("(activity,android:permission)", permissionValues);    //$NON-NLS-1$
        setValues("(receiver,android:permission)", permissionValues);    //$NON-NLS-1$
        setValues("(service,android:permission)", permissionValues);     //$NON-NLS-1$
        setValues("(provider,android:permission)", permissionValues);    //$NON-NLS-1$
    }

    private void setIntentFilterActionsAndCategories(String[] activityIntentActions,
            String[] broadcastIntentActions, String[] serviceIntentActions,
            String[] intentCategoryValues) {
        setValues("(activity,action,android:name)", activityIntentActions);  //$NON-NLS-1$
        setValues("(receiver,action,android:name)", broadcastIntentActions); //$NON-NLS-1$
        setValues("(service,action,android:name)", serviceIntentActions);    //$NON-NLS-1$
        setValues("(category,android:name)", intentCategoryValues);          //$NON-NLS-1$
    }

    private void setOptionalLibraries(String[] platformLibraries,
            IOptionalLibrary[] optionalLibraries) {

        ArrayList<String> libs = new ArrayList<String>();

        if (platformLibraries != null) {
            for (String name : platformLibraries) {
                libs.add(name);
            }
        }

        if (optionalLibraries != null) {
            for (int i = 0; i < optionalLibraries.length; i++) {
                libs.add(optionalLibraries[i].getName());
            }
        }
        setValues("(uses-library,android:name)",  libs.toArray(new String[libs.size()]));
    }

    /**
     * Sets a (name, values) pair in the hash map.
     * <p/>
     * If the name is already present in the map, it is first removed.
     * @param name the name associated with the values.
     * @param values The values to add.
     */
    private void setValues(String name, String[] values) {
        mAttributeValues.remove(name);
        mAttributeValues.put(name, values);
    }

    public void dispose() {
        if (mLayoutLibrary != null) {
            mLayoutLibrary.dispose();
        }
    }
}