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 AndroidTargetData(IAndroidTarget androidTarget)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 */ setAttributeMap(@onNull Map<String, AttributeInfo> attributeMap)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 getAttributeMap()118 public Map<String, AttributeInfo> getAttributeMap() { 119 return mAttributeMap; 120 } 121 122 /** 123 * Creates an AndroidTargetData object. 124 */ 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)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 */ getDescriptorProvider(int descriptorId)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 */ getManifestDescriptors()204 public AndroidManifestDescriptors getManifestDescriptors() { 205 return mManifestDescriptors; 206 } 207 208 /** 209 * Returns the drawable descriptors 210 */ getDrawableDescriptors()211 public DrawableDescriptors getDrawableDescriptors() { 212 return mDrawableDescriptors; 213 } 214 215 /** 216 * Returns the animation descriptors 217 */ getAnimDescriptors()218 public AnimDescriptors getAnimDescriptors() { 219 return mAnimDescriptors; 220 } 221 222 /** 223 * Returns the color descriptors 224 */ getColorDescriptors()225 public ColorDescriptors getColorDescriptors() { 226 return mColorDescriptors; 227 } 228 229 /** 230 * Returns the animator descriptors 231 */ getAnimatorDescriptors()232 public AnimatorDescriptors getAnimatorDescriptors() { 233 return mAnimatorDescriptors; 234 } 235 236 /** 237 * Returns the layout Descriptors. 238 */ getLayoutDescriptors()239 public LayoutDescriptors getLayoutDescriptors() { 240 return mLayoutDescriptors; 241 } 242 243 /** 244 * Returns the menu descriptors. 245 */ getMenuDescriptors()246 public MenuDescriptors getMenuDescriptors() { 247 return mMenuDescriptors; 248 } 249 250 /** 251 * Returns the XML descriptors 252 */ getXmlDescriptors()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 */ getAttributeValues(String elementName, String attributeName)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 */ getAttributeValues(String elementName, String attributeName, String greatGrandParentElementName)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 */ getEnumValueMap()307 public Map<String, Map<String, Integer>> getEnumValueMap() { 308 return mEnumValueMap; 309 } 310 311 /** 312 * Returns the {@link ProjectResources} containing the Framework Resources. 313 */ getFrameworkResources()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 */ getLayoutLibrary()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 */ setPermissions(String[] permissionValues)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 setIntentFilterActionsAndCategories(String[] activityIntentActions, String[] broadcastIntentActions, String[] serviceIntentActions, String[] intentCategoryValues)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 setOptionalLibraries(String[] platformLibraries, IOptionalLibrary[] optionalLibraries)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 */ setValues(String name, String[] values)407 private void setValues(String name, String[] values) { 408 mAttributeValues.remove(name); 409 mAttributeValues.put(name, values); 410 } 411 dispose()412 public void dispose() { 413 if (mLayoutLibrary != null) { 414 mLayoutLibrary.dispose(); 415 } 416 } 417 } 418