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