OSDN Git Service

android-2.1_r1 snapshot
[android-x86/sdk.git] / eclipse / plugins / com.android.ide.eclipse.adt / src / com / android / ide / eclipse / adt / internal / editors / xml / descriptors / XmlDescriptors.java
1 /*
2  * Copyright (C) 2008 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.editors.xml.descriptors;
18
19 import com.android.ide.eclipse.adt.AndroidConstants;
20 import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
21 import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
22 import com.android.ide.eclipse.adt.internal.editors.descriptors.DocumentDescriptor;
23 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
24 import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
25 import com.android.ide.eclipse.adt.internal.editors.descriptors.SeparatorAttributeDescriptor;
26 import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
27 import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
28 import com.android.ide.eclipse.adt.internal.resources.DeclareStyleableInfo;
29 import com.android.ide.eclipse.adt.internal.resources.ViewClassInfo;
30 import com.android.ide.eclipse.adt.internal.resources.DeclareStyleableInfo.AttributeInfo;
31 import com.android.sdklib.SdkConstants;
32
33 import java.util.ArrayList;
34 import java.util.Map;
35
36
37 /**
38  * Description of the /res/xml structure.
39  * Currently supports the <searchable> and <preferences> root nodes.
40  */
41 public final class XmlDescriptors implements IDescriptorProvider {
42
43     // Public attributes names, attributes descriptors and elements descriptors referenced
44     // elsewhere.
45     public static final String PREF_KEY_ATTR = "key"; //$NON-NLS-1$
46
47     /** The root document descriptor for both searchable and preferences. */
48     private DocumentDescriptor mDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ 
49
50     /** The root document descriptor for searchable. */
51     private DocumentDescriptor mSearchDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ 
52
53     /** The root document descriptor for preferences. */
54     private DocumentDescriptor mPrefDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ 
55
56     /** The root document descriptor for widget provider. */
57     private DocumentDescriptor mAppWidgetDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$ 
58
59     /** @return the root descriptor for both searchable and preferences. */
60     public DocumentDescriptor getDescriptor() {
61         return mDescriptor;
62     }
63     
64     public ElementDescriptor[] getRootElementDescriptors() {
65         return mDescriptor.getChildren();
66     }
67     
68     /** @return the root descriptor for searchable. */
69     public DocumentDescriptor getSearchableDescriptor() {
70         return mSearchDescriptor;
71     }
72     
73     /** @return the root descriptor for preferences. */
74     public DocumentDescriptor getPreferencesDescriptor() {
75         return mPrefDescriptor;
76     }
77     
78     /** @return the root descriptor for widget providers. */
79     public DocumentDescriptor getAppWidgetDescriptor() {
80         return mAppWidgetDescriptor;
81     }
82     
83     public IDescriptorProvider getSearchableProvider() {
84         return new IDescriptorProvider() {
85             public ElementDescriptor getDescriptor() {
86                 return mSearchDescriptor;
87             }
88
89             public ElementDescriptor[] getRootElementDescriptors() {
90                 return mSearchDescriptor.getChildren();
91             }
92         };
93     }
94
95     public IDescriptorProvider getPreferencesProvider() {
96         return new IDescriptorProvider() {
97             public ElementDescriptor getDescriptor() {
98                 return mPrefDescriptor;
99             }
100
101             public ElementDescriptor[] getRootElementDescriptors() {
102                 return mPrefDescriptor.getChildren();
103             }
104         };
105     }
106
107     public IDescriptorProvider getAppWidgetProvider() {
108         return new IDescriptorProvider() {
109             public ElementDescriptor getDescriptor() {
110                 return mAppWidgetDescriptor;
111             }
112
113             public ElementDescriptor[] getRootElementDescriptors() {
114                 return mAppWidgetDescriptor.getChildren();
115             }
116         };
117     }
118
119     /**
120      * Updates the document descriptor.
121      * <p/>
122      * It first computes the new children of the descriptor and then updates them
123      * all at once.
124      * 
125      * @param searchableStyleMap The map style=>attributes for <searchable> from the attrs.xml file
126      * @param appWidgetStyleMap The map style=>attributes for <appwidget-provider> from the attrs.xml file
127      * @param prefs The list of non-group preference descriptions 
128      * @param prefGroups The list of preference group descriptions
129      */
130     public synchronized void updateDescriptors(
131             Map<String, DeclareStyleableInfo> searchableStyleMap,
132             Map<String, DeclareStyleableInfo> appWidgetStyleMap,
133             ViewClassInfo[] prefs, ViewClassInfo[] prefGroups) {
134
135         XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(
136                 "android", //$NON-NLS-1$
137                 SdkConstants.NS_RESOURCES); 
138
139         ElementDescriptor searchable = createSearchable(searchableStyleMap, xmlns);
140         ElementDescriptor appWidget = createAppWidgetProviderInfo(appWidgetStyleMap, xmlns);
141         ElementDescriptor preferences = createPreference(prefs, prefGroups, xmlns);
142         ArrayList<ElementDescriptor> list =  new ArrayList<ElementDescriptor>();
143         if (searchable != null) {
144             list.add(searchable);
145             mSearchDescriptor.setChildren(new ElementDescriptor[]{ searchable });
146         }
147         if (appWidget != null) {
148             list.add(appWidget);
149             mAppWidgetDescriptor.setChildren(new ElementDescriptor[]{ appWidget });
150         }
151         if (preferences != null) {
152             list.add(preferences);
153             mPrefDescriptor.setChildren(new ElementDescriptor[]{ preferences });
154         }
155
156         if (list.size() > 0) {
157             mDescriptor.setChildren(list.toArray(new ElementDescriptor[list.size()]));
158         }
159     }
160
161     //-------------------------
162     // Creation of <searchable>
163     //-------------------------
164     
165     /**
166      * Returns the new ElementDescriptor for <searchable>
167      */
168     private ElementDescriptor createSearchable(
169             Map<String, DeclareStyleableInfo> searchableStyleMap,
170             XmlnsAttributeDescriptor xmlns) {
171
172         ElementDescriptor action_key = createElement(searchableStyleMap,
173                 "SearchableActionKey", //$NON-NLS-1$ styleName
174                 "actionkey", //$NON-NLS-1$ xmlName
175                 "Action Key", // uiName
176                 null, // sdk url
177                 null, // extraAttribute
178                 null, // childrenElements
179                 false /* mandatory */ );
180
181         ElementDescriptor searchable = createElement(searchableStyleMap,
182                 "Searchable", //$NON-NLS-1$ styleName
183                 "searchable", //$NON-NLS-1$ xmlName
184                 "Searchable", // uiName
185                 null, // sdk url
186                 xmlns, // extraAttribute
187                 new ElementDescriptor[] { action_key }, // childrenElements
188                 false /* mandatory */ );
189         return searchable;
190     }
191     
192     /**
193      * Returns the new ElementDescriptor for <appwidget-provider>
194      */
195     private ElementDescriptor createAppWidgetProviderInfo(
196             Map<String, DeclareStyleableInfo> appWidgetStyleMap,
197             XmlnsAttributeDescriptor xmlns) {
198
199         if (appWidgetStyleMap == null) {
200             return null;
201         }
202         
203         ElementDescriptor appWidget = createElement(appWidgetStyleMap,
204                 "AppWidgetProviderInfo", //$NON-NLS-1$ styleName
205                 "appwidget-provider", //$NON-NLS-1$ xmlName
206                 "AppWidget Provider", // uiName
207                 null, // sdk url
208                 xmlns, // extraAttribute
209                 null, // childrenElements
210                 false /* mandatory */ );
211         return appWidget;
212     }
213
214     /**
215      * Returns a new ElementDescriptor constructed from the information given here
216      * and the javadoc & attributes extracted from the style map if any.
217      */
218     private ElementDescriptor createElement(
219             Map<String, DeclareStyleableInfo> styleMap, String styleName,
220             String xmlName, String uiName, String sdkUrl,
221             AttributeDescriptor extraAttribute,
222             ElementDescriptor[] childrenElements, boolean mandatory) {
223
224         ElementDescriptor element = new ElementDescriptor(xmlName, uiName, null, sdkUrl,
225                 null, childrenElements, mandatory);
226
227         return updateElement(element, styleMap, styleName, extraAttribute);
228     }
229
230     /**
231      * Updates an ElementDescriptor with the javadoc & attributes extracted from the style
232      * map if any.
233      */
234     private ElementDescriptor updateElement(ElementDescriptor element,
235             Map<String, DeclareStyleableInfo> styleMap,
236             String styleName,
237             AttributeDescriptor extraAttribute) {
238         ArrayList<AttributeDescriptor> descs = new ArrayList<AttributeDescriptor>();
239
240         DeclareStyleableInfo style = styleMap != null ? styleMap.get(styleName) : null;
241         if (style != null) {
242             DescriptorsUtils.appendAttributes(descs,
243                     null,   // elementName
244                     SdkConstants.NS_RESOURCES,
245                     style.getAttributes(),
246                     null,   // requiredAttributes
247                     null);  // overrides
248             element.setTooltip(style.getJavaDoc());
249         }
250
251         if (extraAttribute != null) {
252             descs.add(extraAttribute);
253         }
254
255         element.setAttributes(descs.toArray(new AttributeDescriptor[descs.size()]));
256         return element;
257     }
258
259     //--------------------------
260     // Creation of <Preferences>
261     //--------------------------
262
263     /**
264      * Returns the new ElementDescriptor for <Preferences>
265      */
266     private ElementDescriptor createPreference(ViewClassInfo[] prefs,
267             ViewClassInfo[] prefGroups, XmlnsAttributeDescriptor xmlns) {
268
269         ArrayList<ElementDescriptor> newPrefs = new ArrayList<ElementDescriptor>();
270         if (prefs != null) {
271             for (ViewClassInfo info : prefs) {
272                 ElementDescriptor desc = convertPref(info);
273                 newPrefs.add(desc);
274             }
275         }
276
277         ElementDescriptor topPreferences = null;
278         
279         ArrayList<ElementDescriptor> newGroups = new ArrayList<ElementDescriptor>();
280         if (prefGroups != null) {
281             for (ViewClassInfo info : prefGroups) {
282                 ElementDescriptor desc = convertPref(info);
283                 newGroups.add(desc);
284                 
285                 if (info.getCanonicalClassName() == AndroidConstants.CLASS_PREFERENCES) {
286                     topPreferences = desc;
287                 }
288             }
289         }
290
291         ArrayList<ElementDescriptor> everything = new ArrayList<ElementDescriptor>();
292         everything.addAll(newGroups);
293         everything.addAll(newPrefs);
294         ElementDescriptor[] newArray = everything.toArray(new ElementDescriptor[everything.size()]);
295
296         // Link all groups to everything else here.. recursively
297         for (ElementDescriptor layoutDesc : newGroups) {
298             layoutDesc.setChildren(newArray);
299         }
300
301         // The "top" element to be returned corresponds to the class "Preferences".
302         // Its descriptor has already been created. However the root one also needs
303         // the hidden xmlns:android definition..
304         if (topPreferences != null) {
305             AttributeDescriptor[] attrs = topPreferences.getAttributes();
306             AttributeDescriptor[] newAttrs = new AttributeDescriptor[attrs.length + 1];
307             System.arraycopy(attrs, 0, newAttrs, 0, attrs.length);
308             newAttrs[attrs.length] = xmlns;
309             return new ElementDescriptor(
310                     topPreferences.getXmlName(),
311                     topPreferences.getUiName(),
312                     topPreferences.getTooltip(),
313                     topPreferences.getSdkUrl(),
314                     newAttrs,
315                     topPreferences.getChildren(),
316                     false /* mandatory */);
317         } else {
318             return null;
319         }
320     }
321
322     /**
323      * Creates an element descriptor from a given {@link ViewClassInfo}.
324      */
325     private ElementDescriptor convertPref(ViewClassInfo info) {
326         String xml_name = info.getShortClassName();
327         String tooltip = info.getJavaDoc();
328         
329         // Process all Preference attributes
330         ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>();
331         DescriptorsUtils.appendAttributes(attributes,
332                 null,   // elementName
333                 SdkConstants.NS_RESOURCES,
334                 info.getAttributes(),
335                 null,   // requiredAttributes
336                 null);  // overrides
337         
338         for (ViewClassInfo link = info.getSuperClass();
339                 link != null;
340                 link = link.getSuperClass()) {
341             AttributeInfo[] attrList = link.getAttributes();
342             if (attrList.length > 0) {
343                 attributes.add(new SeparatorAttributeDescriptor(
344                         String.format("Attributes from %1$s", link.getShortClassName()))); 
345                 DescriptorsUtils.appendAttributes(attributes,
346                         null,   // elementName
347                         SdkConstants.NS_RESOURCES,
348                         attrList,
349                         null,   // requiredAttributes
350                         null);  // overrides
351             }
352         }
353
354         return new ViewElementDescriptor(xml_name,
355                 xml_name, // ui_name
356                 info.getCanonicalClassName(),
357                 tooltip,
358                 null, // sdk_url
359                 attributes.toArray(new AttributeDescriptor[attributes.size()]),
360                 null,
361                 null, // children
362                 false /* mandatory */);
363     }
364 }