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