diff options
author | Siva Velusamy <vsiva@google.com> | 2012-09-18 14:51:46 -0700 |
---|---|---|
committer | Siva Velusamy <vsiva@google.com> | 2012-09-18 15:09:33 -0700 |
commit | 6837aad30d6c51783ca1dc784ca6bdcc8a3d9f2d (patch) | |
tree | 90af15ddcc9f0bbc3151a0978b3e637f77fdd54a /ide_common/src/com/android | |
parent | 6184f12fa097e1c5bddfe50700b3b0740c736a5a (diff) | |
download | sdk-6837aad30d6c51783ca1dc784ca6bdcc8a3d9f2d.zip sdk-6837aad30d6c51783ca1dc784ca6bdcc8a3d9f2d.tar.gz sdk-6837aad30d6c51783ca1dc784ca6bdcc8a3d9f2d.tar.bz2 |
Rename ide_common to sdk_common
Change-Id: I1b39ee439a532f3f6758be35b569948e2e906665
Diffstat (limited to 'ide_common/src/com/android')
48 files changed, 0 insertions, 9666 deletions
diff --git a/ide_common/src/com/android/ide/common/rendering/LayoutLibrary.java b/ide_common/src/com/android/ide/common/rendering/LayoutLibrary.java deleted file mode 100644 index 0a353f9..0000000 --- a/ide_common/src/com/android/ide/common/rendering/LayoutLibrary.java +++ /dev/null @@ -1,755 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.rendering; - -import static com.android.ide.common.rendering.api.Result.Status.ERROR_REFLECTION; - -import com.android.ide.common.rendering.api.Bridge; -import com.android.ide.common.rendering.api.Capability; -import com.android.ide.common.rendering.api.DrawableParams; -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.Result.Status; -import com.android.ide.common.rendering.api.SessionParams; -import com.android.ide.common.rendering.api.SessionParams.RenderingMode; -import com.android.ide.common.rendering.api.ViewInfo; -import com.android.ide.common.rendering.legacy.ILegacyPullParser; -import com.android.ide.common.rendering.legacy.LegacyCallback; -import com.android.ide.common.resources.ResourceResolver; -import com.android.ide.common.sdk.LoadStatus; -import com.android.layoutlib.api.ILayoutBridge; -import com.android.layoutlib.api.ILayoutLog; -import com.android.layoutlib.api.ILayoutResult; -import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo; -import com.android.layoutlib.api.IProjectCallback; -import com.android.layoutlib.api.IResourceValue; -import com.android.layoutlib.api.IXmlPullParser; -import com.android.resources.ResourceType; -import com.android.utils.ILogger; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.net.URI; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Class to use the Layout library. - * <p/> - * Use {@link #load(String, ILogger)} to load the jar file. - * <p/> - * Use the layout library with: - * {@link #init(String, Map)}, {@link #supports(Capability)}, {@link #createSession(SessionParams)}, - * {@link #dispose()}, {@link #clearCaches(Object)}. - * - * <p/> - * For client wanting to access both new and old (pre API level 5) layout libraries, it is - * important that the following interfaces be used:<br> - * {@link ILegacyPullParser} instead of {@link ILayoutPullParser}<br> - * {@link LegacyCallback} instead of {@link com.android.ide.common.rendering.api.IProjectCallback}. - * <p/> - * These interfaces will ensure that both new and older Layout libraries can be accessed. - */ -@SuppressWarnings("deprecation") -public class LayoutLibrary { - - public final static String CLASS_BRIDGE = "com.android.layoutlib.bridge.Bridge"; //$NON-NLS-1$ - - /** Link to the layout bridge */ - private final Bridge mBridge; - /** Link to a ILayoutBridge in case loaded an older library */ - private final ILayoutBridge mLegacyBridge; - /** Status of the layoutlib.jar loading */ - private final LoadStatus mStatus; - /** Message associated with the {@link LoadStatus}. This is mostly used when - * {@link #getStatus()} returns {@link LoadStatus#FAILED}. - */ - private final String mLoadMessage; - /** classloader used to load the jar file */ - private final ClassLoader mClassLoader; - - // Reflection data for older Layout Libraries. - private Method mViewGetParentMethod; - private Method mViewGetBaselineMethod; - private Method mViewParentIndexOfChildMethod; - private Class<?> mMarginLayoutParamClass; - private Field mLeftMarginField; - private Field mTopMarginField; - private Field mRightMarginField; - private Field mBottomMarginField; - - /** - * Returns the {@link LoadStatus} of the loading of the layoutlib jar file. - */ - public LoadStatus getStatus() { - return mStatus; - } - - /** Returns the message associated with the {@link LoadStatus}. This is mostly used when - * {@link #getStatus()} returns {@link LoadStatus#FAILED}. - */ - public String getLoadMessage() { - return mLoadMessage; - } - - /** - * Returns the classloader used to load the classes in the layoutlib jar file. - */ - public ClassLoader getClassLoader() { - return mClassLoader; - } - - /** - * Loads the layoutlib.jar file located at the given path and returns a {@link LayoutLibrary} - * object representing the result. - * <p/> - * If loading failed {@link #getStatus()} will reflect this, and {@link #getBridge()} will - * return null. - * - * @param layoutLibJarOsPath the path of the jar file - * @param log an optional log file. - * @return a {@link LayoutLibrary} object always. - */ - public static LayoutLibrary load(String layoutLibJarOsPath, ILogger log, String toolName) { - - LoadStatus status = LoadStatus.LOADING; - String message = null; - Bridge bridge = null; - ILayoutBridge legacyBridge = null; - ClassLoader classLoader = null; - - try { - // get the URL for the file. - File f = new File(layoutLibJarOsPath); - if (f.isFile() == false) { - if (log != null) { - log.error(null, "layoutlib.jar is missing!"); //$NON-NLS-1$ - } - } else { - URI uri = f.toURI(); - URL url = uri.toURL(); - - // create a class loader. Because this jar reference interfaces - // that are in the editors plugin, it's important to provide - // a parent class loader. - classLoader = new URLClassLoader( - new URL[] { url }, - LayoutLibrary.class.getClassLoader()); - - // load the class - Class<?> clazz = classLoader.loadClass(CLASS_BRIDGE); - if (clazz != null) { - // instantiate an object of the class. - Constructor<?> constructor = clazz.getConstructor(); - if (constructor != null) { - Object bridgeObject = constructor.newInstance(); - if (bridgeObject instanceof Bridge) { - bridge = (Bridge)bridgeObject; - } else if (bridgeObject instanceof ILayoutBridge) { - legacyBridge = (ILayoutBridge) bridgeObject; - } - } - } - - if (bridge == null && legacyBridge == null) { - status = LoadStatus.FAILED; - message = "Failed to load " + CLASS_BRIDGE; //$NON-NLS-1$ - if (log != null) { - log.error(null, - "Failed to load " + //$NON-NLS-1$ - CLASS_BRIDGE + - " from " + //$NON-NLS-1$ - layoutLibJarOsPath); - } - } else { - // mark the lib as loaded, unless it's overridden below. - status = LoadStatus.LOADED; - - // check the API, only if it's not a legacy bridge - if (bridge != null) { - int api = bridge.getApiLevel(); - if (api > Bridge.API_CURRENT) { - status = LoadStatus.FAILED; - message = String.format( - "This version of the rendering library is more recent than your version of %1$s. Please update %1$s", toolName); - } - } - } - } - } catch (Throwable t) { - status = LoadStatus.FAILED; - Throwable cause = t; - while (cause.getCause() != null) { - cause = cause.getCause(); - } - message = "Failed to load the LayoutLib: " + cause.getMessage(); - // log the error. - if (log != null) { - log.error(t, message); - } - } - - return new LayoutLibrary(bridge, legacyBridge, classLoader, status, message); - } - - // ------ Layout Lib API proxy - - /** - * Returns the API level of the layout library. - */ - public int getApiLevel() { - if (mBridge != null) { - return mBridge.getApiLevel(); - } - - if (mLegacyBridge != null) { - return getLegacyApiLevel(); - } - - return 0; - } - - /** - * Returns the revision of the library inside a given (layoutlib) API level. - * The true version number of the library is {@link #getApiLevel()}.{@link #getRevision()} - */ - public int getRevision() { - if (mBridge != null) { - return mBridge.getRevision(); - } - - return 0; - } - - /** - * Returns whether the LayoutLibrary supports a given {@link Capability}. - * @return true if it supports it. - * - * @see Bridge#getCapabilities() - * - */ - public boolean supports(Capability capability) { - if (mBridge != null) { - return mBridge.getCapabilities().contains(capability); - } - - if (mLegacyBridge != null) { - switch (capability) { - case UNBOUND_RENDERING: - // legacy stops at 4. 5 is new API. - return getLegacyApiLevel() == 4; - } - } - - return false; - } - - /** - * Initializes the Layout Library object. This must be called before any other action is taken - * on the instance. - * - * @param platformProperties The build properties for the platform. - * @param fontLocation the location of the fonts in the SDK target. - * @param enumValueMap map attrName => { map enumFlagName => Integer value }. This is typically - * read from attrs.xml in the SDK target. - * @param log a {@link LayoutLog} object. Can be null. - * @return true if success. - * - * @see Bridge#init(String, Map) - */ - public boolean init(Map<String, String> platformProperties, - File fontLocation, - Map<String, Map<String, Integer>> enumValueMap, - LayoutLog log) { - if (mBridge != null) { - return mBridge.init(platformProperties, fontLocation, enumValueMap, log); - } else if (mLegacyBridge != null) { - return mLegacyBridge.init(fontLocation.getAbsolutePath(), enumValueMap); - } - - return false; - } - - /** - * Prepares the layoutlib to unloaded. - * - * @see Bridge#dispose() - */ - public boolean dispose() { - if (mBridge != null) { - return mBridge.dispose(); - } - - return true; - } - - /** - * Starts a layout session by inflating and rendering it. The method returns a - * {@link RenderSession} on which further actions can be taken. - * <p/> - * Before taking further actions on the scene, it is recommended to use - * {@link #supports(Capability)} to check what the scene can do. - * - * @return a new {@link ILayoutScene} object that contains the result of the scene creation and - * first rendering or null if {@link #getStatus()} doesn't return {@link LoadStatus#LOADED}. - * - * @see Bridge#createSession(SessionParams) - */ - public RenderSession createSession(SessionParams params) { - if (mBridge != null) { - RenderSession session = mBridge.createSession(params); - if (params.getExtendedViewInfoMode() && - mBridge.getCapabilities().contains(Capability.EXTENDED_VIEWINFO) == false) { - // Extended view info was requested but the layoutlib does not support it. - // Add it manually. - List<ViewInfo> infoList = session.getRootViews(); - if (infoList != null) { - for (ViewInfo info : infoList) { - addExtendedViewInfo(info); - } - } - } - - return session; - } else if (mLegacyBridge != null) { - return createLegacySession(params); - } - - return null; - } - - /** - * Renders a Drawable. If the rendering is successful, the result image is accessible through - * {@link Result#getData()}. It is of type {@link BufferedImage} - * @param params the rendering parameters. - * @return the result of the action. - */ - public Result renderDrawable(DrawableParams params) { - if (mBridge != null) { - return mBridge.renderDrawable(params); - } - - return Status.NOT_IMPLEMENTED.createResult(); - } - - /** - * Clears the resource cache for a specific project. - * <p/>This cache contains bitmaps and nine patches that are loaded from the disk and reused - * until this method is called. - * <p/>The cache is not configuration dependent and should only be cleared when a - * resource changes (at this time only bitmaps and 9 patches go into the cache). - * - * @param projectKey the key for the project. - * - * @see Bridge#clearCaches(Object) - */ - public void clearCaches(Object projectKey) { - if (mBridge != null) { - mBridge.clearCaches(projectKey); - } else if (mLegacyBridge != null) { - mLegacyBridge.clearCaches(projectKey); - } - } - - /** - * Utility method returning the parent of a given view object. - * - * @param viewObject the object for which to return the parent. - * - * @return a {@link Result} indicating the status of the action, and if success, the parent - * object in {@link Result#getData()} - */ - public Result getViewParent(Object viewObject) { - if (mBridge != null) { - Result r = mBridge.getViewParent(viewObject); - if (r.isSuccess()) { - return r; - } - } - - return getViewParentWithReflection(viewObject); - } - - /** - * Utility method returning the index of a given view in its parent. - * @param viewObject the object for which to return the index. - * - * @return a {@link Result} indicating the status of the action, and if success, the index in - * the parent in {@link Result#getData()} - */ - public Result getViewIndex(Object viewObject) { - if (mBridge != null) { - Result r = mBridge.getViewIndex(viewObject); - if (r.isSuccess()) { - return r; - } - } - - return getViewIndexReflection(viewObject); - } - - // ------ Implementation - - private LayoutLibrary(Bridge bridge, ILayoutBridge legacyBridge, ClassLoader classLoader, - LoadStatus status, String message) { - mBridge = bridge; - mLegacyBridge = legacyBridge; - mClassLoader = classLoader; - mStatus = status; - mLoadMessage = message; - } - - /** - * Returns the API level of the legacy bridge. - * <p/> - * This handles the case where ILayoutBridge does not have a {@link ILayoutBridge#getApiLevel()} - * (at API level 1). - * <p/> - * {@link ILayoutBridge#getApiLevel()} should never called directly. - * - * @return the api level of {@link #mLegacyBridge}. - */ - private int getLegacyApiLevel() { - int apiLevel = 1; - try { - apiLevel = mLegacyBridge.getApiLevel(); - } catch (AbstractMethodError e) { - // the first version of the api did not have this method - // so this is 1 - } - - return apiLevel; - } - - private RenderSession createLegacySession(SessionParams params) { - if (params.getLayoutDescription() instanceof IXmlPullParser == false) { - throw new IllegalArgumentException("Parser must be of type ILegacyPullParser"); - } - if (params.getProjectCallback() instanceof - com.android.layoutlib.api.IProjectCallback == false) { - throw new IllegalArgumentException("Project callback must be of type ILegacyCallback"); - } - - if (params.getResources() instanceof ResourceResolver == false) { - throw new IllegalArgumentException("RenderResources object must be of type ResourceResolver"); - } - - ResourceResolver resources = (ResourceResolver) params.getResources(); - - int apiLevel = getLegacyApiLevel(); - - // create a log wrapper since the older api requires a ILayoutLog - final LayoutLog log = params.getLog(); - ILayoutLog logWrapper = new ILayoutLog() { - - @Override - public void warning(String message) { - log.warning(null, message, null /*data*/); - } - - @Override - public void error(Throwable t) { - log.error(null, "error!", t, null /*data*/); - } - - @Override - public void error(String message) { - log.error(null, message, null /*data*/); - } - }; - - - // convert the map of ResourceValue into IResourceValue. Super ugly but works. - - Map<String, Map<String, IResourceValue>> projectMap = convertMap( - resources.getProjectResources()); - Map<String, Map<String, IResourceValue>> frameworkMap = convertMap( - resources.getFrameworkResources()); - - ILayoutResult result = null; - - if (apiLevel == 4) { - // Final ILayoutBridge API added support for "render full height" - result = mLegacyBridge.computeLayout( - (IXmlPullParser) params.getLayoutDescription(), - params.getProjectKey(), - params.getScreenWidth(), params.getScreenHeight(), - params.getRenderingMode() == RenderingMode.FULL_EXPAND ? true : false, - params.getDensity().getDpiValue(), params.getXdpi(), params.getYdpi(), - resources.getThemeName(), resources.isProjectTheme(), - projectMap, frameworkMap, - (IProjectCallback) params.getProjectCallback(), - logWrapper); - } else if (apiLevel == 3) { - // api 3 add density support. - result = mLegacyBridge.computeLayout( - (IXmlPullParser) params.getLayoutDescription(), params.getProjectKey(), - params.getScreenWidth(), params.getScreenHeight(), - params.getDensity().getDpiValue(), params.getXdpi(), params.getYdpi(), - resources.getThemeName(), resources.isProjectTheme(), - projectMap, frameworkMap, - (IProjectCallback) params.getProjectCallback(), logWrapper); - } else if (apiLevel == 2) { - // api 2 added boolean for separation of project/framework theme - result = mLegacyBridge.computeLayout( - (IXmlPullParser) params.getLayoutDescription(), params.getProjectKey(), - params.getScreenWidth(), params.getScreenHeight(), - resources.getThemeName(), resources.isProjectTheme(), - projectMap, frameworkMap, - (IProjectCallback) params.getProjectCallback(), logWrapper); - } else { - // First api with no density/dpi, and project theme boolean mixed - // into the theme name. - - // change the string if it's a custom theme to make sure we can - // differentiate them - String themeName = resources.getThemeName(); - if (resources.isProjectTheme()) { - themeName = "*" + themeName; //$NON-NLS-1$ - } - - result = mLegacyBridge.computeLayout( - (IXmlPullParser) params.getLayoutDescription(), params.getProjectKey(), - params.getScreenWidth(), params.getScreenHeight(), - themeName, - projectMap, frameworkMap, - (IProjectCallback) params.getProjectCallback(), logWrapper); - } - - // clean up that is not done by the ILayoutBridge itself - legacyCleanUp(); - - return convertToScene(result); - } - - @SuppressWarnings("unchecked") - private Map<String, Map<String, IResourceValue>> convertMap( - Map<ResourceType, Map<String, ResourceValue>> map) { - Map<String, Map<String, IResourceValue>> result = - new HashMap<String, Map<String, IResourceValue>>(); - - for (Entry<ResourceType, Map<String, ResourceValue>> entry : map.entrySet()) { - // ugly case but works. - result.put(entry.getKey().getName(), - (Map) entry.getValue()); - } - - return result; - } - - /** - * Converts a {@link ILayoutResult} to a {@link RenderSession}. - */ - private RenderSession convertToScene(ILayoutResult result) { - - Result sceneResult; - ViewInfo rootViewInfo = null; - - if (result.getSuccess() == ILayoutResult.SUCCESS) { - sceneResult = Status.SUCCESS.createResult(); - ILayoutViewInfo oldRootView = result.getRootView(); - if (oldRootView != null) { - rootViewInfo = convertToViewInfo(oldRootView); - } - } else { - sceneResult = Status.ERROR_UNKNOWN.createResult(result.getErrorMessage()); - } - - // create a BasicLayoutScene. This will return the given values but return the default - // implementation for all method. - // ADT should gracefully handle the default implementations of LayoutScene - return new StaticRenderSession(sceneResult, rootViewInfo, result.getImage()); - } - - /** - * Converts a {@link ILayoutViewInfo} (and its children) to a {@link ViewInfo}. - */ - private ViewInfo convertToViewInfo(ILayoutViewInfo view) { - // create the view info. - ViewInfo viewInfo = new ViewInfo(view.getName(), view.getViewKey(), - view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); - - // then convert the children - ILayoutViewInfo[] children = view.getChildren(); - if (children != null) { - ArrayList<ViewInfo> convertedChildren = new ArrayList<ViewInfo>(children.length); - for (ILayoutViewInfo child : children) { - convertedChildren.add(convertToViewInfo(child)); - } - viewInfo.setChildren(convertedChildren); - } - - return viewInfo; - } - - /** - * Post rendering clean-up that must be done here because it's not done in any layoutlib using - * {@link ILayoutBridge}. - */ - private void legacyCleanUp() { - try { - Class<?> looperClass = mClassLoader.loadClass("android.os.Looper"); //$NON-NLS-1$ - Field threadLocalField = looperClass.getField("sThreadLocal"); //$NON-NLS-1$ - if (threadLocalField != null) { - threadLocalField.setAccessible(true); - // get object. Field is static so no need to pass an object - ThreadLocal<?> threadLocal = (ThreadLocal<?>) threadLocalField.get(null); - if (threadLocal != null) { - threadLocal.remove(); - } - } - } catch (Exception e) { - // do nothing. - } - } - - private Result getViewParentWithReflection(Object viewObject) { - // default implementation using reflection. - try { - if (mViewGetParentMethod == null) { - Class<?> viewClass = Class.forName("android.view.View"); - mViewGetParentMethod = viewClass.getMethod("getParent"); - } - - return Status.SUCCESS.createResult(mViewGetParentMethod.invoke(viewObject)); - } catch (Exception e) { - // Catch all for the reflection calls. - return ERROR_REFLECTION.createResult(null, e); - } - } - - /** - * Utility method returning the index of a given view in its parent. - * @param viewObject the object for which to return the index. - * - * @return a {@link Result} indicating the status of the action, and if success, the index in - * the parent in {@link Result#getData()} - */ - private Result getViewIndexReflection(Object viewObject) { - // default implementation using reflection. - try { - Class<?> viewClass = Class.forName("android.view.View"); - - if (mViewGetParentMethod == null) { - mViewGetParentMethod = viewClass.getMethod("getParent"); - } - - Object parentObject = mViewGetParentMethod.invoke(viewObject); - - if (mViewParentIndexOfChildMethod == null) { - Class<?> viewParentClass = Class.forName("android.view.ViewParent"); - mViewParentIndexOfChildMethod = viewParentClass.getMethod("indexOfChild", - viewClass); - } - - return Status.SUCCESS.createResult( - mViewParentIndexOfChildMethod.invoke(parentObject, viewObject)); - } catch (Exception e) { - // Catch all for the reflection calls. - return ERROR_REFLECTION.createResult(null, e); - } - } - - private void addExtendedViewInfo(ViewInfo info) { - computeExtendedViewInfo(info); - - List<ViewInfo> children = info.getChildren(); - for (ViewInfo child : children) { - addExtendedViewInfo(child); - } - } - - private void computeExtendedViewInfo(ViewInfo info) { - Object viewObject = info.getViewObject(); - Object params = info.getLayoutParamsObject(); - - int baseLine = getViewBaselineReflection(viewObject); - int leftMargin = 0; - int topMargin = 0; - int rightMargin = 0; - int bottomMargin = 0; - - try { - if (mMarginLayoutParamClass == null) { - mMarginLayoutParamClass = Class.forName( - "android.view.ViewGroup$MarginLayoutParams"); - - mLeftMarginField = mMarginLayoutParamClass.getField("leftMargin"); - mTopMarginField = mMarginLayoutParamClass.getField("topMargin"); - mRightMarginField = mMarginLayoutParamClass.getField("rightMargin"); - mBottomMarginField = mMarginLayoutParamClass.getField("bottomMargin"); - } - - if (mMarginLayoutParamClass.isAssignableFrom(params.getClass())) { - - leftMargin = (Integer)mLeftMarginField.get(params); - topMargin = (Integer)mTopMarginField.get(params); - rightMargin = (Integer)mRightMarginField.get(params); - bottomMargin = (Integer)mBottomMarginField.get(params); - } - - } catch (Exception e) { - // just use 'unknown' value. - leftMargin = Integer.MIN_VALUE; - topMargin = Integer.MIN_VALUE; - rightMargin = Integer.MIN_VALUE; - bottomMargin = Integer.MIN_VALUE; - } - - info.setExtendedInfo(baseLine, leftMargin, topMargin, rightMargin, bottomMargin); - } - - /** - * Utility method returning the baseline value for a given view object. This basically returns - * View.getBaseline(). - * - * @param viewObject the object for which to return the index. - * - * @return the baseline value or -1 if not applicable to the view object or if this layout - * library does not implement this method. - */ - private int getViewBaselineReflection(Object viewObject) { - // default implementation using reflection. - try { - if (mViewGetBaselineMethod == null) { - Class<?> viewClass = Class.forName("android.view.View"); - mViewGetBaselineMethod = viewClass.getMethod("getBaseline"); - } - - Object result = mViewGetBaselineMethod.invoke(viewObject); - if (result instanceof Integer) { - return ((Integer)result).intValue(); - } - - } catch (Exception e) { - // Catch all for the reflection calls. - } - - return Integer.MIN_VALUE; - } -} diff --git a/ide_common/src/com/android/ide/common/rendering/StaticRenderSession.java b/ide_common/src/com/android/ide/common/rendering/StaticRenderSession.java deleted file mode 100644 index c122c1c..0000000 --- a/ide_common/src/com/android/ide/common/rendering/StaticRenderSession.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.rendering; - -import com.android.ide.common.rendering.api.RenderSession; -import com.android.ide.common.rendering.api.Result; -import com.android.ide.common.rendering.api.ViewInfo; - -import java.awt.image.BufferedImage; -import java.util.Collections; -import java.util.List; - -/** - * Static {@link RenderSession} returning a given {@link Result}, {@link ViewInfo} and - * {@link BufferedImage}. - * <p/> - * All other methods are untouched from the base implementation provided by the API. - * <p/> - * This is meant to be used as a wrapper around the static results. No further operations are - * possible. - * - */ -public class StaticRenderSession extends RenderSession { - - private final Result mResult; - private final List<ViewInfo> mRootViewInfo; - private final BufferedImage mImage; - - public StaticRenderSession(Result result, ViewInfo rootViewInfo, BufferedImage image) { - mResult = result; - mRootViewInfo = Collections.singletonList(rootViewInfo); - mImage = image; - } - - @Override - public Result getResult() { - return mResult; - } - - @Override - public List<ViewInfo> getRootViews() { - return mRootViewInfo; - } - - @Override - public BufferedImage getImage() { - return mImage; - } -} diff --git a/ide_common/src/com/android/ide/common/rendering/legacy/ILegacyPullParser.java b/ide_common/src/com/android/ide/common/rendering/legacy/ILegacyPullParser.java deleted file mode 100644 index a71e190..0000000 --- a/ide_common/src/com/android/ide/common/rendering/legacy/ILegacyPullParser.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.rendering.legacy; - -import com.android.ide.common.rendering.api.ILayoutPullParser; -import com.android.layoutlib.api.IXmlPullParser; - -/** - * Intermediary interface extending both old and new project pull parsers from the layout lib API. - * - * Clients should use this instead of {@link ILayoutPullParser} or {@link IXmlPullParser}. - * - */ -@SuppressWarnings("deprecation") -public interface ILegacyPullParser extends ILayoutPullParser, IXmlPullParser { - -} diff --git a/ide_common/src/com/android/ide/common/rendering/legacy/LegacyCallback.java b/ide_common/src/com/android/ide/common/rendering/legacy/LegacyCallback.java deleted file mode 100644 index 67e6a7b..0000000 --- a/ide_common/src/com/android/ide/common/rendering/legacy/LegacyCallback.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.rendering.legacy; - -import com.android.ide.common.rendering.api.IProjectCallback; -import com.android.resources.ResourceType; -import com.android.util.Pair; - -/** - * Intermediary class implementing parts of both the old and new project call back from the - * layout lib API. - * - * Clients should use this instead of {@link IProjectCallback} to target both old and new - * Layout Libraries. - * - */ -@SuppressWarnings("deprecation") -public abstract class LegacyCallback implements - com.android.ide.common.rendering.api.IProjectCallback, - com.android.layoutlib.api.IProjectCallback { - - // ------ implementation of the old interface using the new interface. - - @Override - public final Integer getResourceValue(String type, String name) { - return getResourceId(ResourceType.getEnum(type), name); - } - - @Override - public final String[] resolveResourceValue(int id) { - Pair<ResourceType, String> info = resolveResourceId(id); - if (info != null) { - return new String[] { info.getSecond(), info.getFirst().getName() }; - } - - return null; - } - - @Override - public final String resolveResourceValue(int[] id) { - return resolveResourceId(id); - } - - // ------ -} diff --git a/ide_common/src/com/android/ide/common/resources/FrameworkResourceItem.java b/ide_common/src/com/android/ide/common/resources/FrameworkResourceItem.java deleted file mode 100644 index 70bbcef..0000000 --- a/ide_common/src/com/android/ide/common/resources/FrameworkResourceItem.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -/** - * A custom {@link ResourceItem} for resources provided by the framework. - * - * The main change is that {@link #isEditableDirectly()} returns false. - */ -class FrameworkResourceItem extends ResourceItem { - - FrameworkResourceItem(String name) { - super(name); - } - - @Override - public boolean isEditableDirectly() { - return false; - } - - @Override - public String toString() { - return "FrameworkResourceItem [mName=" + getName() + ", mFiles=" //$NON-NLS-1$ //$NON-NLS-2$ - + getSourceFileList() + "]"; //$NON-NLS-1$ - } -} diff --git a/ide_common/src/com/android/ide/common/resources/FrameworkResources.java b/ide_common/src/com/android/ide/common/resources/FrameworkResources.java deleted file mode 100755 index fbf5926..0000000 --- a/ide_common/src/com/android/ide/common/resources/FrameworkResources.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.io.IAbstractFile; -import com.android.io.IAbstractFolder; -import com.android.resources.ResourceType; -import com.android.utils.ILogger; - -import org.kxml2.io.KXmlParser; -import org.xmlpull.v1.XmlPullParser; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; - -/** - * Framework resources repository. - * - * This behaves the same as {@link ResourceRepository} except that it differentiates between - * resources that are public and non public. - * {@link #getResources(ResourceType)} and {@link #hasResourcesOfType(ResourceType)} only return - * public resources. This is typically used to display resource lists in the UI. - * - * {@link #getConfiguredResources(com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration)} - * returns all resources, even the non public ones so that this can be used for rendering. - */ -public class FrameworkResources extends ResourceRepository { - - /** - * Map of {@link ResourceType} to list of items. It is guaranteed to contain a list for all - * possible values of ResourceType. - */ - protected final Map<ResourceType, List<ResourceItem>> mPublicResourceMap = - new EnumMap<ResourceType, List<ResourceItem>>(ResourceType.class); - - public FrameworkResources() { - super(true /*isFrameworkRepository*/); - } - - /** - * Returns a {@link Collection} (always non null, but can be empty) of <b>public</b> - * {@link ResourceItem} matching a given {@link ResourceType}. - * - * @param type the type of the resources to return - * @return a collection of items, possible empty. - */ - @Override - @NonNull - public List<ResourceItem> getResourceItemsOfType(@NonNull ResourceType type) { - return mPublicResourceMap.get(type); - } - - /** - * Returns whether the repository has <b>public</b> resources of a given {@link ResourceType}. - * @param type the type of resource to check. - * @return true if the repository contains resources of the given type, false otherwise. - */ - @Override - public boolean hasResourcesOfType(@NonNull ResourceType type) { - return mPublicResourceMap.get(type).size() > 0; - } - - @Override - @NonNull - protected ResourceItem createResourceItem(@NonNull String name) { - return new FrameworkResourceItem(name); - } - - /** - * Reads the public.xml file in data/res/values/ for a given resource folder and builds up - * a map of public resources. - * - * This map is a subset of the full resource map that only contains framework resources - * that are public. - * - * @param resFolder The root folder of the resources - * @param logger a logger to report issues to - */ - public void loadPublicResources(@NonNull IAbstractFolder resFolder, @Nullable ILogger logger) { - IAbstractFolder valueFolder = resFolder.getFolder(SdkConstants.FD_RES_VALUES); - if (valueFolder.exists() == false) { - return; - } - - IAbstractFile publicXmlFile = valueFolder.getFile("public.xml"); //$NON-NLS-1$ - if (publicXmlFile.exists()) { - Reader reader = null; - try { - reader = new BufferedReader(new InputStreamReader(publicXmlFile.getContents(), - "UTF-8")); //$NON-NLS-1$ - KXmlParser parser = new KXmlParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); - parser.setInput(reader); - - ResourceType lastType = null; - String lastTypeName = ""; - while (true) { - int event = parser.next(); - if (event == XmlPullParser.START_TAG) { - // As of API 15 there are a number of "java-symbol" entries here - if (!parser.getName().equals("public")) { //$NON-NLS-1$ - continue; - } - - String name = null; - String typeName = null; - for (int i = 0, n = parser.getAttributeCount(); i < n; i++) { - String attribute = parser.getAttributeName(i); - - if (attribute.equals("name")) { //$NON-NLS-1$ - name = parser.getAttributeValue(i); - if (typeName != null) { - // Skip id attribute processing - break; - } - } else if (attribute.equals("type")) { //$NON-NLS-1$ - typeName = parser.getAttributeValue(i); - } - } - - if (name != null && typeName != null) { - ResourceType type = null; - if (typeName.equals(lastTypeName)) { - type = lastType; - } else { - type = ResourceType.getEnum(typeName); - lastType = type; - lastTypeName = typeName; - } - if (type != null) { - ResourceItem match = null; - Map<String, ResourceItem> map = mResourceMap.get(type); - if (map != null) { - match = map.get(name); - } - - if (match != null) { - List<ResourceItem> publicList = mPublicResourceMap.get(type); - if (publicList == null) { - // Pick initial size for the list to hold the public - // resources. We could just use map.size() here, - // but they're usually much bigger; for example, - // in one platform version, there are 1500 drawables - // and 1200 strings but only 175 and 25 public ones - // respectively. - int size; - switch (type) { - case STYLE: size = 500; break; - case ATTR: size = 1000; break; - case DRAWABLE: size = 200; break; - case ID: size = 50; break; - case LAYOUT: - case COLOR: - case STRING: - case ANIM: - case INTERPOLATOR: - size = 30; - break; - default: - size = 10; - break; - } - publicList = new ArrayList<ResourceItem>(size); - mPublicResourceMap.put(type, publicList); - } - - publicList.add(match); - } else { - // log that there's a public resource that doesn't actually - // exist? - } - } else { - // log that there was a reference to a typo that doesn't actually - // exist? - } - } - } else if (event == XmlPullParser.END_DOCUMENT) { - break; - } - } - } catch (Exception e) { - if (logger != null) { - logger.error(e, "Can't read and parse public attribute list"); - } - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - // Nothing to be done here - we don't care if it closed or not. - } - } - } - } - - // put unmodifiable list for all res type in the public resource map - // this will simplify access - for (ResourceType type : ResourceType.values()) { - List<ResourceItem> list = mPublicResourceMap.get(type); - if (list == null) { - list = Collections.emptyList(); - } else { - list = Collections.unmodifiableList(list); - } - - // put the new list in the map - mPublicResourceMap.put(type, list); - } - } -} - diff --git a/ide_common/src/com/android/ide/common/resources/IdGeneratingResourceFile.java b/ide_common/src/com/android/ide/common/resources/IdGeneratingResourceFile.java deleted file mode 100644 index 9ff1748..0000000 --- a/ide_common/src/com/android/ide/common/resources/IdGeneratingResourceFile.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import com.android.ide.common.rendering.api.DensityBasedResourceValue; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.resources.ValueResourceParser.IValueResourceRepository; -import com.android.ide.common.resources.configuration.DensityQualifier; -import com.android.io.IAbstractFile; -import com.android.io.StreamException; -import com.android.resources.ResourceType; - -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Represents a resource file that also generates ID resources. - * <p/> - * This is typically an XML file in res/layout or res/menu - */ -public final class IdGeneratingResourceFile extends ResourceFile - implements IValueResourceRepository { - - private final Map<String, ResourceValue> mIdResources = - new HashMap<String, ResourceValue>(); - - private final Collection<ResourceType> mResourceTypeList; - - private final String mFileName; - - private final ResourceType mFileType; - - private final ResourceValue mFileValue; - - public IdGeneratingResourceFile(IAbstractFile file, ResourceFolder folder, ResourceType type) { - super(file, folder); - - mFileType = type; - - // Set up our resource types - mResourceTypeList = new HashSet<ResourceType>(); - mResourceTypeList.add(mFileType); - mResourceTypeList.add(ResourceType.ID); - - // compute the resource name - mFileName = getFileName(type); - - // Get the resource value of this file as a whole layout - mFileValue = getFileValue(file, folder); - } - - @Override - protected void load(ScanningContext context) { - // Parse the file and look for @+id/ entries - parseFileForIds(context); - - // create the resource items in the repository - updateResourceItems(context); - } - - @Override - protected void update(ScanningContext context) { - // Copy the previous list of ID names - Set<String> oldIdNames = new HashSet<String>(mIdResources.keySet()); - - // reset current content. - mIdResources.clear(); - - // need to parse the file and find the IDs. - if (!parseFileForIds(context)) { - context.requestFullAapt(); - // Continue through to updating the resource item here since it - // will make for example layout rendering more accurate until - // aapt is re-run - } - - // We only need to update the repository if our IDs have changed - Set<String> keySet = mIdResources.keySet(); - assert keySet != oldIdNames; - if (oldIdNames.equals(keySet) == false) { - updateResourceItems(context); - } - } - - @Override - protected void dispose(ScanningContext context) { - ResourceRepository repository = getRepository(); - - // Remove declarations from this file from the repository - repository.removeFile(mResourceTypeList, this); - - // Ask for an ID refresh since we'll be taking away ID generating items - context.requestFullAapt(); - } - - @Override - public Collection<ResourceType> getResourceTypes() { - return mResourceTypeList; - } - - @Override - public boolean hasResources(ResourceType type) { - return (type == mFileType) || (type == ResourceType.ID && !mIdResources.isEmpty()); - } - - @Override - public ResourceValue getValue(ResourceType type, String name) { - // Check to see if they're asking for one of the right types: - if (type != mFileType && type != ResourceType.ID) { - return null; - } - - // If they're looking for a resource of this type with this name give them the whole file - if (type == mFileType && name.equals(mFileName)) { - return mFileValue; - } else { - // Otherwise try to return them an ID - // the map will return null if it's not found - return mIdResources.get(name); - } - } - - /** - * Looks through the file represented for Ids and adds them to - * our id repository - * - * @return true if parsing succeeds and false if it fails - */ - private boolean parseFileForIds(ScanningContext context) { - IdResourceParser parser = new IdResourceParser(this, context, isFramework()); - try { - IAbstractFile file = getFile(); - return parser.parse(mFileType, file.getOsLocation(), file.getContents()); - } catch (IOException e) { - // Pass - } catch (StreamException e) { - // Pass - } - - return false; - } - - /** - * Add the resources represented by this file to the repository - */ - private void updateResourceItems(ScanningContext context) { - ResourceRepository repository = getRepository(); - - // remove this file from all existing ResourceItem. - repository.removeFile(mResourceTypeList, this); - - // First add this as a layout file - ResourceItem item = repository.getResourceItem(mFileType, mFileName); - item.add(this); - - // Now iterate through our IDs and add - for (String idName : mIdResources.keySet()) { - item = repository.getResourceItem(ResourceType.ID, idName); - // add this file to the list of files generating ID resources. - item.add(this); - } - - // Ask the repository for an ID refresh - context.requestFullAapt(); - } - - /** - * Returns the resource value associated with this whole file as a layout resource - * @param file the file handler that represents this file - * @param folder the folder this file is under - * @return a resource value associated with this layout - */ - private ResourceValue getFileValue(IAbstractFile file, ResourceFolder folder) { - // test if there's a density qualifier associated with the resource - DensityQualifier qualifier = folder.getConfiguration().getDensityQualifier(); - - ResourceValue value; - if (qualifier == null) { - value = new ResourceValue(mFileType, mFileName, - file.getOsLocation(), isFramework()); - } else { - value = new DensityBasedResourceValue( - mFileType, mFileName, - file.getOsLocation(), - qualifier.getValue(), - isFramework()); - } - return value; - } - - - /** - * Returns the name of this resource. - */ - private String getFileName(ResourceType type) { - // get the name from the filename. - String name = getFile().getName(); - - int pos = name.indexOf('.'); - if (pos != -1) { - name = name.substring(0, pos); - } - - return name; - } - - @Override - public void addResourceValue(ResourceValue value) { - // Just overwrite collisions. We're only interested in the unique - // IDs declared - mIdResources.put(value.getName(), value); - } - - @Override - public boolean hasResourceValue(ResourceType type, String name) { - if (type == ResourceType.ID) { - return mIdResources.containsKey(name); - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/IdResourceParser.java b/ide_common/src/com/android/ide/common/resources/IdResourceParser.java deleted file mode 100644 index 1de664e..0000000 --- a/ide_common/src/com/android/ide/common/resources/IdResourceParser.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.resources.ValueResourceParser.IValueResourceRepository; -import com.android.resources.ResourceType; - -import org.kxml2.io.KXmlParser; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * Parser for scanning an id-generating resource file such as a layout or a menu - * file, which registers any ids it encounters with an - * {@link IValueResourceRepository}, and which registers errors with a - * {@link ScanningContext}. - */ -public class IdResourceParser { - private final IValueResourceRepository mRepository; - private final boolean mIsFramework; - private ScanningContext mContext; - - /** - * Creates a new {@link IdResourceParser} - * - * @param repository value repository for registering resource declaration - * @param context a context object with state for the current update, such - * as a place to stash errors encountered - * @param isFramework true if scanning a framework resource - */ - public IdResourceParser(IValueResourceRepository repository, ScanningContext context, - boolean isFramework) { - mRepository = repository; - mContext = context; - mIsFramework = isFramework; - } - - /** - * Parse the given input and register ids with the given - * {@link IValueResourceRepository}. - * - * @param type the type of resource being scanned - * @param path the full OS path to the file being parsed - * @param input the input stream of the XML to be parsed - * @return true if parsing succeeds and false if it fails - * @throws IOException if reading the contents fails - */ - public boolean parse(ResourceType type, final String path, InputStream input) - throws IOException { - KXmlParser parser = new KXmlParser(); - try { - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - - if (input instanceof FileInputStream) { - input = new BufferedInputStream(input); - } - parser.setInput(input, "UTF-8"); //$NON-NLS-1$ - - return parse(type, path, parser); - } catch (XmlPullParserException e) { - String message = e.getMessage(); - - // Strip off position description - int index = message.indexOf("(position:"); //$NON-NLS-1$ (Hardcoded in KXml) - if (index != -1) { - message = message.substring(0, index); - } - - String error = String.format("%1$s:%2$d: Error: %3$s", //$NON-NLS-1$ - path, parser.getLineNumber(), message); - mContext.addError(error); - return false; - } catch (RuntimeException e) { - // Some exceptions are thrown by the KXmlParser that are not XmlPullParserExceptions, - // such as this one: - // java.lang.RuntimeException: Undefined Prefix: w in org.kxml2.io.KXmlParser@... - // at org.kxml2.io.KXmlParser.adjustNsp(Unknown Source) - // at org.kxml2.io.KXmlParser.parseStartTag(Unknown Source) - String message = e.getMessage(); - String error = String.format("%1$s:%2$d: Error: %3$s", //$NON-NLS-1$ - path, parser.getLineNumber(), message); - mContext.addError(error); - return false; - } - } - - private boolean parse(ResourceType type, String path, KXmlParser parser) - throws XmlPullParserException, IOException { - boolean valid = true; - ResourceRepository resources = mContext.getRepository(); - boolean checkForErrors = !mIsFramework && !mContext.needsFullAapt(); - - while (true) { - int event = parser.next(); - if (event == XmlPullParser.START_TAG) { - for (int i = 0, n = parser.getAttributeCount(); i < n; i++) { - String attribute = parser.getAttributeName(i); - String value = parser.getAttributeValue(i); - assert value != null : attribute; - - if (value.startsWith("@")) { //$NON-NLS-1$ - // Gather IDs - if (value.startsWith("@+")) { //$NON-NLS-1$ - // Strip out the @+id/ or @+android:id/ section - String id = value.substring(value.indexOf('/') + 1); - ResourceValue newId = new ResourceValue(ResourceType.ID, id, - mIsFramework); - mRepository.addResourceValue(newId); - } else if (checkForErrors){ - // Validate resource references (unless we're scanning a framework - // resource or if we've already scheduled a full aapt run) - boolean exists = resources.hasResourceItem(value); - if (!exists && !mRepository.hasResourceValue(ResourceType.ID, - value.substring(value.indexOf('/') + 1))) { - String error = String.format( - // Don't localize because the exact pattern matches AAPT's - // output which has hardcoded regexp matching in - // AaptParser. - "%1$s:%2$d: Error: No resource found that matches " + //$NON-NLS-1$ - "the given name (at '%3$s' with value '%4$s')", //$NON-NLS-1$ - path, parser.getLineNumber(), - attribute, value); - mContext.addError(error); - valid = false; - } - } - } - } - } else if (event == XmlPullParser.END_DOCUMENT) { - break; - } - } - - return valid; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/InlineResourceItem.java b/ide_common/src/com/android/ide/common/resources/InlineResourceItem.java deleted file mode 100644 index 37fdc81..0000000 --- a/ide_common/src/com/android/ide/common/resources/InlineResourceItem.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.resources.configuration.FolderConfiguration; -import com.android.resources.ResourceType; - - -/** - * Represents a resource item that has been declared inline in another resource file. - * - * This covers the typical ID declaration of "@+id/foo", but does not cover normal value - * resources declared in strings.xml or other similar value files. - * - * This resource will return {@code true} for {@link #isDeclaredInline()} and {@code false} for - * {@link #isEditableDirectly()}. - */ -public class InlineResourceItem extends ResourceItem { - - private ResourceValue mValue = null; - - /** - * Constructs a new inline ResourceItem. - * @param name the name of the resource as it appears in the XML and R.java files. - */ - public InlineResourceItem(String name) { - super(name); - } - - @Override - public boolean isDeclaredInline() { - return true; - } - - @Override - public boolean isEditableDirectly() { - return false; - } - - @Override - public ResourceValue getResourceValue(ResourceType type, FolderConfiguration referenceConfig, - boolean isFramework) { - assert type == ResourceType.ID; - if (mValue == null) { - mValue = new ResourceValue(type, getName(), isFramework); - } - - return mValue; - } - - @Override - public String toString() { - return "InlineResourceItem [mName=" + getName() + ", mFiles=" //$NON-NLS-1$ //$NON-NLS-2$ - + getSourceFileList() + "]"; //$NON-NLS-1$ - } -} diff --git a/ide_common/src/com/android/ide/common/resources/IntArrayWrapper.java b/ide_common/src/com/android/ide/common/resources/IntArrayWrapper.java deleted file mode 100644 index 668c677..0000000 --- a/ide_common/src/com/android/ide/common/resources/IntArrayWrapper.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import java.util.Arrays; - - -/** - * Wrapper around a int[] to provide hashCode/equals support. - */ -public final class IntArrayWrapper { - - private int[] mData; - - public IntArrayWrapper(int[] data) { - mData = data; - } - - public void set(int[] data) { - mData = data; - } - - @Override - public int hashCode() { - return Arrays.hashCode(mData); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass().equals(obj.getClass())) { - return Arrays.equals(mData, ((IntArrayWrapper)obj).mData); - } - - return super.equals(obj); - } -} diff --git a/ide_common/src/com/android/ide/common/resources/MultiResourceFile.java b/ide_common/src/com/android/ide/common/resources/MultiResourceFile.java deleted file mode 100644 index c9a8bc7..0000000 --- a/ide_common/src/com/android/ide/common/resources/MultiResourceFile.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.resources.ValueResourceParser.IValueResourceRepository; -import com.android.io.IAbstractFile; -import com.android.io.StreamException; -import com.android.resources.ResourceType; - -import org.xml.sax.SAXException; - -import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -/** - * Represents a resource file able to declare multiple resources, which could be of - * different {@link ResourceType}. - * <p/> - * This is typically an XML file inside res/values. - */ -public final class MultiResourceFile extends ResourceFile implements IValueResourceRepository { - - private final static SAXParserFactory sParserFactory = SAXParserFactory.newInstance(); - - private final Map<ResourceType, Map<String, ResourceValue>> mResourceItems = - new EnumMap<ResourceType, Map<String, ResourceValue>>(ResourceType.class); - - private Collection<ResourceType> mResourceTypeList = null; - - public MultiResourceFile(IAbstractFile file, ResourceFolder folder) { - super(file, folder); - } - - // Boolean flag to track whether a named element has been added or removed, thus requiring - // a new ID table to be generated - private boolean mNeedIdRefresh; - - @Override - protected void load(ScanningContext context) { - // need to parse the file and find the content. - parseFile(); - - // create new ResourceItems for the new content. - mResourceTypeList = Collections.unmodifiableCollection(mResourceItems.keySet()); - - // We need an ID generation step - mNeedIdRefresh = true; - - // create/update the resource items. - updateResourceItems(context); - } - - @Override - protected void update(ScanningContext context) { - // Reset the ID generation flag - mNeedIdRefresh = false; - - // Copy the previous version of our list of ResourceItems and types - Map<ResourceType, Map<String, ResourceValue>> oldResourceItems - = new EnumMap<ResourceType, Map<String, ResourceValue>>(mResourceItems); - - // reset current content. - mResourceItems.clear(); - - // need to parse the file and find the content. - parseFile(); - - // create new ResourceItems for the new content. - mResourceTypeList = Collections.unmodifiableCollection(mResourceItems.keySet()); - - // Check to see if any names have changed. If so, mark the flag so updateResourceItems - // can notify the ResourceRepository that an ID refresh is needed - if (oldResourceItems.keySet().equals(mResourceItems.keySet())) { - for (ResourceType type : mResourceTypeList) { - // We just need to check the names of the items. - // If there are new or removed names then we'll have to regenerate IDs - if (mResourceItems.get(type).keySet() - .equals(oldResourceItems.get(type).keySet()) == false) { - mNeedIdRefresh = true; - } - } - } else { - // If our type list is different, obviously the names will be different - mNeedIdRefresh = true; - } - // create/update the resource items. - updateResourceItems(context); - } - - @Override - protected void dispose(ScanningContext context) { - ResourceRepository repository = getRepository(); - - // only remove this file from all existing ResourceItem. - repository.removeFile(mResourceTypeList, this); - - // We'll need an ID refresh because we deleted items - context.requestFullAapt(); - - // don't need to touch the content, it'll get reclaimed as this objects disappear. - // In the mean time other objects may need to access it. - } - - @Override - public Collection<ResourceType> getResourceTypes() { - return mResourceTypeList; - } - - @Override - public boolean hasResources(ResourceType type) { - Map<String, ResourceValue> list = mResourceItems.get(type); - return (list != null && list.size() > 0); - } - - private void updateResourceItems(ScanningContext context) { - ResourceRepository repository = getRepository(); - - // remove this file from all existing ResourceItem. - repository.removeFile(mResourceTypeList, this); - - for (ResourceType type : mResourceTypeList) { - Map<String, ResourceValue> list = mResourceItems.get(type); - - if (list != null) { - Collection<ResourceValue> values = list.values(); - for (ResourceValue res : values) { - ResourceItem item = repository.getResourceItem(type, res.getName()); - - // add this file to the list of files generating this resource item. - item.add(this); - } - } - } - - // If we need an ID refresh, ask the repository for that now - if (mNeedIdRefresh) { - context.requestFullAapt(); - } - } - - /** - * Parses the file and creates a list of {@link ResourceType}. - */ - private void parseFile() { - try { - SAXParser parser = sParserFactory.newSAXParser(); - parser.parse(getFile().getContents(), new ValueResourceParser(this, isFramework())); - } catch (ParserConfigurationException e) { - } catch (SAXException e) { - } catch (IOException e) { - } catch (StreamException e) { - } - } - - /** - * Adds a resource item to the list - * @param value The value of the resource. - */ - @Override - public void addResourceValue(ResourceValue value) { - ResourceType resType = value.getResourceType(); - - Map<String, ResourceValue> list = mResourceItems.get(resType); - - // if the list does not exist, create it. - if (list == null) { - list = new HashMap<String, ResourceValue>(); - mResourceItems.put(resType, list); - } else { - // look for a possible value already existing. - ResourceValue oldValue = list.get(value.getName()); - - if (oldValue != null) { - oldValue.replaceWith(value); - return; - } - } - - // empty list or no match found? add the given resource - list.put(value.getName(), value); - } - - @Override - public boolean hasResourceValue(ResourceType type, String name) { - Map<String, ResourceValue> map = mResourceItems.get(type); - return map != null && map.containsKey(name); - } - - @Override - public ResourceValue getValue(ResourceType type, String name) { - // get the list for the given type - Map<String, ResourceValue> list = mResourceItems.get(type); - - if (list != null) { - return list.get(name); - } - - return null; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/ResourceDeltaKind.java b/ide_common/src/com/android/ide/common/resources/ResourceDeltaKind.java deleted file mode 100644 index 769b6ea..0000000 --- a/ide_common/src/com/android/ide/common/resources/ResourceDeltaKind.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -/** - * Enum indicating a type of resource change. - * - * This is similar, and can be easily mapped to Eclipse's integer constants in IResourceDelta. - */ -public enum ResourceDeltaKind { - CHANGED, ADDED, REMOVED; -} diff --git a/ide_common/src/com/android/ide/common/resources/ResourceFile.java b/ide_common/src/com/android/ide/common/resources/ResourceFile.java deleted file mode 100644 index 378602a..0000000 --- a/ide_common/src/com/android/ide/common/resources/ResourceFile.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.resources.configuration.Configurable; -import com.android.ide.common.resources.configuration.FolderConfiguration; -import com.android.io.IAbstractFile; -import com.android.resources.ResourceType; - -import java.util.Collection; - -/** - * Represents a Resource file (a file under $Project/res/) - */ -public abstract class ResourceFile implements Configurable { - - private final IAbstractFile mFile; - private final ResourceFolder mFolder; - - protected ResourceFile(IAbstractFile file, ResourceFolder folder) { - mFile = file; - mFolder = folder; - } - - protected abstract void load(ScanningContext context); - protected abstract void update(ScanningContext context); - protected abstract void dispose(ScanningContext context); - - @Override - public FolderConfiguration getConfiguration() { - return mFolder.getConfiguration(); - } - - /** - * Returns the IFile associated with the ResourceFile. - */ - public final IAbstractFile getFile() { - return mFile; - } - - /** - * Returns the parent folder as a {@link ResourceFolder}. - */ - public final ResourceFolder getFolder() { - return mFolder; - } - - public final ResourceRepository getRepository() { - return mFolder.getRepository(); - } - - /** - * Returns whether the resource is a framework resource. - */ - public final boolean isFramework() { - return mFolder.getRepository().isFrameworkRepository(); - } - - /** - * Returns the list of {@link ResourceType} generated by the file. This is never null. - */ - public abstract Collection<ResourceType> getResourceTypes(); - - /** - * Returns whether the file generated a resource of a specific type. - * @param type The {@link ResourceType} - */ - public abstract boolean hasResources(ResourceType type); - - /** - * Returns the value of a resource generated by this file by {@link ResourceType} and name. - * <p/>If no resource match, <code>null</code> is returned. - * @param type the type of the resource. - * @param name the name of the resource. - */ - public abstract ResourceValue getValue(ResourceType type, String name); - - @Override - public String toString() { - return mFile.toString(); - } -} - diff --git a/ide_common/src/com/android/ide/common/resources/ResourceFolder.java b/ide_common/src/com/android/ide/common/resources/ResourceFolder.java deleted file mode 100644 index d6464c8..0000000 --- a/ide_common/src/com/android/ide/common/resources/ResourceFolder.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import com.android.annotations.VisibleForTesting; -import com.android.annotations.VisibleForTesting.Visibility; -import com.android.ide.common.resources.configuration.Configurable; -import com.android.ide.common.resources.configuration.FolderConfiguration; -import com.android.io.IAbstractFile; -import com.android.io.IAbstractFolder; -import com.android.resources.FolderTypeRelationship; -import com.android.resources.ResourceFolderType; -import com.android.resources.ResourceType; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Resource Folder class. Contains list of {@link ResourceFile}s, - * the {@link FolderConfiguration}, and a link to the {@link IAbstractFolder} object. - */ -public final class ResourceFolder implements Configurable { - final ResourceFolderType mType; - final FolderConfiguration mConfiguration; - IAbstractFolder mFolder; - List<ResourceFile> mFiles = null; - Map<String, ResourceFile> mNames = null; - private final ResourceRepository mRepository; - - /** - * Creates a new {@link ResourceFolder} - * @param type The type of the folder - * @param config The configuration of the folder - * @param folder The associated {@link IAbstractFolder} object. - * @param repository The associated {@link ResourceRepository} - */ - protected ResourceFolder(ResourceFolderType type, FolderConfiguration config, - IAbstractFolder folder, ResourceRepository repository) { - mType = type; - mConfiguration = config; - mFolder = folder; - mRepository = repository; - } - - /** - * Processes a file and adds it to its parent folder resource. - * - * @param file the underlying resource file. - * @param kind the file change kind. - * @param context a context object with state for the current update, such - * as a place to stash errors encountered - * @return the {@link ResourceFile} that was created. - */ - public ResourceFile processFile(IAbstractFile file, ResourceDeltaKind kind, - ScanningContext context) { - // look for this file if it's already been created - ResourceFile resFile = getFile(file, context); - - if (resFile == null) { - if (kind != ResourceDeltaKind.REMOVED) { - // create a ResourceFile for it. - - resFile = createResourceFile(file); - resFile.load(context); - - // add it to the folder - addFile(resFile); - } - } else { - if (kind == ResourceDeltaKind.REMOVED) { - removeFile(resFile, context); - } else { - resFile.update(context); - } - } - - return resFile; - } - - private ResourceFile createResourceFile(IAbstractFile file) { - // check if that's a single or multi resource type folder. For now we define this by - // the number of possible resource type output by files in the folder. - // We have a special case for layout/menu folders which can also generate IDs. - // This does - // not make the difference between several resource types from a single file or - // the ability to have 2 files in the same folder generating 2 different types of - // resource. The former is handled by MultiResourceFile properly while we don't - // handle the latter. If we were to add this behavior we'd have to change this call. - List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(mType); - - ResourceFile resFile = null; - if (types.size() == 1) { - resFile = new SingleResourceFile(file, this); - } else if (types.contains(ResourceType.LAYOUT)) { - resFile = new IdGeneratingResourceFile(file, this, ResourceType.LAYOUT); - } else if (types.contains(ResourceType.MENU)) { - resFile = new IdGeneratingResourceFile(file, this, ResourceType.MENU); - } else { - resFile = new MultiResourceFile(file, this); - } - return resFile; - } - - /** - * Adds a {@link ResourceFile} to the folder. - * @param file The {@link ResourceFile}. - */ - @VisibleForTesting(visibility=Visibility.PROTECTED) - public void addFile(ResourceFile file) { - if (mFiles == null) { - int initialSize = 16; - if (mRepository.isFrameworkRepository()) { - String name = mFolder.getName(); - // Pick some reasonable initial sizes for framework data structures - // since they are typically (a) large and (b) their sizes are roughly known - // in advance - switch (mType) { - case DRAWABLE: { - // See if it's one of the -mdpi, -hdpi etc folders which - // are large (~1250 items) - int index = name.indexOf('-'); - if (index == -1) { - initialSize = 230; // "drawable" folder - } else { - index = name.indexOf('-', index + 1); - if (index == -1) { - // One of the "drawable-<density>" folders - initialSize = 1260; - } else { - // "drawable-sw600dp-hdpi" etc - initialSize = 30; - } - } - break; - } - case LAYOUT: { - // The main layout folder has about ~185 layouts in it; - // the others are small - if (name.indexOf('-') == -1) { - initialSize = 200; - } - break; - } - case VALUES: { - if (name.indexOf('-') == -1) { - initialSize = 32; - } else { - initialSize = 4; - } - break; - } - case ANIM: initialSize = 85; break; - case COLOR: initialSize = 32; break; - case RAW: initialSize = 4; break; - default: - // Stick with the 16 default - break; - } - } - - mFiles = new ArrayList<ResourceFile>(initialSize); - mNames = new HashMap<String, ResourceFile>(initialSize, 2.0f); - } - - mFiles.add(file); - mNames.put(file.getFile().getName(), file); - } - - protected void removeFile(ResourceFile file, ScanningContext context) { - file.dispose(context); - mFiles.remove(file); - mNames.remove(file.getFile().getName()); - } - - protected void dispose(ScanningContext context) { - if (mFiles != null) { - for (ResourceFile file : mFiles) { - file.dispose(context); - } - - mFiles.clear(); - mNames.clear(); - } - } - - /** - * Returns the {@link IAbstractFolder} associated with this object. - */ - public IAbstractFolder getFolder() { - return mFolder; - } - - /** - * Returns the {@link ResourceFolderType} of this object. - */ - public ResourceFolderType getType() { - return mType; - } - - public ResourceRepository getRepository() { - return mRepository; - } - - /** - * Returns the list of {@link ResourceType}s generated by the files inside this folder. - */ - public Collection<ResourceType> getResourceTypes() { - ArrayList<ResourceType> list = new ArrayList<ResourceType>(); - - if (mFiles != null) { - for (ResourceFile file : mFiles) { - Collection<ResourceType> types = file.getResourceTypes(); - - // loop through those and add them to the main list, - // if they are not already present - for (ResourceType resType : types) { - if (list.indexOf(resType) == -1) { - list.add(resType); - } - } - } - } - - return list; - } - - @Override - public FolderConfiguration getConfiguration() { - return mConfiguration; - } - - /** - * Returns whether the folder contains a file with the given name. - * @param name the name of the file. - */ - public boolean hasFile(String name) { - if (mNames != null && mNames.containsKey(name)) { - return true; - } - - // Note: mNames.containsKey(name) is faster, but doesn't give the same result; this - // method seems to be called on this ResourceFolder before it has been processed, - // so we need to use the file system check instead: - return mFolder.hasFile(name); - } - - /** - * Returns the {@link ResourceFile} matching a {@link IAbstractFile} object. - * - * @param file The {@link IAbstractFile} object. - * @param context a context object with state for the current update, such - * as a place to stash errors encountered - * @return the {@link ResourceFile} or null if no match was found. - */ - private ResourceFile getFile(IAbstractFile file, ScanningContext context) { - assert mFolder.equals(file.getParentFolder()); - - if (mNames != null) { - ResourceFile resFile = mNames.get(file.getName()); - if (resFile != null) { - return resFile; - } - } - - // If the file actually exists, the resource folder may not have been - // scanned yet; add it lazily - if (file.exists()) { - ResourceFile resFile = createResourceFile(file); - resFile.load(context); - addFile(resFile); - return resFile; - } - - return null; - } - - /** - * Returns the {@link ResourceFile} matching a given name. - * @param filename The name of the file to return. - * @return the {@link ResourceFile} or <code>null</code> if no match was found. - */ - public ResourceFile getFile(String filename) { - if (mNames != null) { - ResourceFile resFile = mNames.get(filename); - if (resFile != null) { - return resFile; - } - } - - // If the file actually exists, the resource folder may not have been - // scanned yet; add it lazily - IAbstractFile file = mFolder.getFile(filename); - if (file != null && file.exists()) { - ResourceFile resFile = createResourceFile(file); - resFile.load(new ScanningContext(mRepository)); - addFile(resFile); - return resFile; - } - - return null; - } - - /** - * Returns whether a file in the folder is generating a resource of a specified type. - * @param type The {@link ResourceType} being looked up. - */ - public boolean hasResources(ResourceType type) { - // Check if the folder type is able to generate resource of the type that was asked. - // this is a first check to avoid going through the files. - List<ResourceFolderType> folderTypes = FolderTypeRelationship.getRelatedFolders(type); - - boolean valid = false; - for (ResourceFolderType rft : folderTypes) { - if (rft == mType) { - valid = true; - break; - } - } - - if (valid) { - if (mFiles != null) { - for (ResourceFile f : mFiles) { - if (f.hasResources(type)) { - return true; - } - } - } - } - return false; - } - - @Override - public String toString() { - return mFolder.toString(); - } -} diff --git a/ide_common/src/com/android/ide/common/resources/ResourceItem.java b/ide_common/src/com/android/ide/common/resources/ResourceItem.java deleted file mode 100644 index 49396eb..0000000 --- a/ide_common/src/com/android/ide/common/resources/ResourceItem.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.resources.configuration.FolderConfiguration; -import com.android.resources.ResourceType; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * An android resource. - * - * This is a representation of the resource, not of its value(s). It gives access to all - * the source files that generate this particular resource which then can be used to access - * the actual value(s). - * - * @see ResourceFile#getResources(ResourceType, ResourceRepository) - */ -public class ResourceItem implements Comparable<ResourceItem> { - - private final static Comparator<ResourceFile> sComparator = new Comparator<ResourceFile>() { - @Override - public int compare(ResourceFile file1, ResourceFile file2) { - // get both FolderConfiguration and compare them - FolderConfiguration fc1 = file1.getFolder().getConfiguration(); - FolderConfiguration fc2 = file2.getFolder().getConfiguration(); - - return fc1.compareTo(fc2); - } - }; - - private final String mName; - - /** - * List of files generating this ResourceItem. - */ - private final List<ResourceFile> mFiles = new ArrayList<ResourceFile>(); - - /** - * Constructs a new ResourceItem. - * @param name the name of the resource as it appears in the XML and R.java files. - */ - public ResourceItem(String name) { - mName = name; - } - - /** - * Returns the name of the resource. - */ - public final String getName() { - return mName; - } - - /** - * Compares the {@link ResourceItem} to another. - * @param other the ResourceItem to be compared to. - */ - @Override - public int compareTo(ResourceItem other) { - return mName.compareTo(other.mName); - } - - /** - * Returns whether the resource is editable directly. - * <p/> - * This is typically the case for resources that don't have alternate versions, or resources - * of type {@link ResourceType#ID} that aren't declared inline. - */ - public boolean isEditableDirectly() { - return hasAlternates() == false; - } - - /** - * Returns whether the ID resource has been declared inline inside another resource XML file. - * If the resource type is not {@link ResourceType#ID}, this will always return {@code false}. - */ - public boolean isDeclaredInline() { - return false; - } - - /** - * Returns a {@link ResourceValue} for this item based on the given configuration. - * If the ResourceItem has several source files, one will be selected based on the config. - * @param type the type of the resource. This is necessary because ResourceItem doesn't embed - * its type, but ResourceValue does. - * @param referenceConfig the config of the resource item. - * @param isFramework whether the resource is a framework value. Same as the type. - * @return a ResourceValue or null if none match the config. - */ - public ResourceValue getResourceValue(ResourceType type, FolderConfiguration referenceConfig, - boolean isFramework) { - // look for the best match for the given configuration - // the match has to be of type ResourceFile since that's what the input list contains - ResourceFile match = (ResourceFile) referenceConfig.findMatchingConfigurable(mFiles); - - if (match != null) { - // get the value of this configured resource. - return match.getValue(type, mName); - } - - return null; - } - - /** - * Adds a new source file. - * @param file the source file. - */ - protected void add(ResourceFile file) { - mFiles.add(file); - } - - /** - * Removes a file from the list of source files. - * @param file the file to remove - */ - protected void removeFile(ResourceFile file) { - mFiles.remove(file); - } - - /** - * Returns {@code true} if the item has no source file. - * @return - */ - protected boolean hasNoSourceFile() { - return mFiles.size() == 0; - } - - /** - * Reset the item by emptying its source file list. - */ - protected void reset() { - mFiles.clear(); - } - - /** - * Returns the sorted list of {@link ResourceItem} objects for this resource item. - */ - public ResourceFile[] getSourceFileArray() { - ArrayList<ResourceFile> list = new ArrayList<ResourceFile>(); - list.addAll(mFiles); - - Collections.sort(list, sComparator); - - return list.toArray(new ResourceFile[list.size()]); - } - - /** - * Returns the list of source file for this resource. - */ - public List<ResourceFile> getSourceFileList() { - return Collections.unmodifiableList(mFiles); - } - - /** - * Returns if the resource has at least one non-default version. - * - * @see ResourceFile#getConfiguration() - * @see FolderConfiguration#isDefault() - */ - public boolean hasAlternates() { - for (ResourceFile file : mFiles) { - if (file.getFolder().getConfiguration().isDefault() == false) { - return true; - } - } - - return false; - } - - /** - * Returns whether the resource has a default version, with no qualifier. - * - * @see ResourceFile#getConfiguration() - * @see FolderConfiguration#isDefault() - */ - public boolean hasDefault() { - for (ResourceFile file : mFiles) { - if (file.getFolder().getConfiguration().isDefault()) { - return true; - } - } - - // We only want to return false if there's no default and more than 0 items. - return (mFiles.size() == 0); - } - - /** - * Returns the number of alternate versions for this resource. - * - * @see ResourceFile#getConfiguration() - * @see FolderConfiguration#isDefault() - */ - public int getAlternateCount() { - int count = 0; - for (ResourceFile file : mFiles) { - if (file.getFolder().getConfiguration().isDefault() == false) { - count++; - } - } - - return count; - } - - /** - * Returns a formatted string usable in an XML to use for the {@link ResourceItem}. - * @param system Whether this is a system resource or a project resource. - * @return a string in the format @[type]/[name] - */ - public String getXmlString(ResourceType type, boolean system) { - if (type == ResourceType.ID && isDeclaredInline()) { - return (system ? "@android:" : "@+") + type.getName() + "/" + mName; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } - - return (system ? "@android:" : "@") + type.getName() + "/" + mName; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } - - @Override - public String toString() { - return "ResourceItem [mName=" + mName + ", mFiles=" + mFiles + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } -} diff --git a/ide_common/src/com/android/ide/common/resources/ResourceRepository.java b/ide_common/src/com/android/ide/common/resources/ResourceRepository.java deleted file mode 100755 index ac0614d..0000000 --- a/ide_common/src/com/android/ide/common/resources/ResourceRepository.java +++ /dev/null @@ -1,719 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.resources.configuration.Configurable; -import com.android.ide.common.resources.configuration.FolderConfiguration; -import com.android.ide.common.resources.configuration.LanguageQualifier; -import com.android.ide.common.resources.configuration.RegionQualifier; -import com.android.io.IAbstractFile; -import com.android.io.IAbstractFolder; -import com.android.io.IAbstractResource; -import com.android.resources.FolderTypeRelationship; -import com.android.resources.ResourceFolderType; -import com.android.resources.ResourceType; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; - -/** - * Base class for resource repository. - * - * A repository is both a file representation of a resource folder and a representation - * of the generated resources, organized by type. - * - * {@link #getResourceFolder(IAbstractFolder)} and {@link #getSourceFiles(ResourceType, String, FolderConfiguration)} - * give access to the folders and files of the resource folder. - * - * {@link #getResources(ResourceType)} gives access to the resources directly. - * - */ -public abstract class ResourceRepository { - - protected final Map<ResourceFolderType, List<ResourceFolder>> mFolderMap = - new EnumMap<ResourceFolderType, List<ResourceFolder>>(ResourceFolderType.class); - - protected final Map<ResourceType, Map<String, ResourceItem>> mResourceMap = - new EnumMap<ResourceType, Map<String, ResourceItem>>( - ResourceType.class); - - private final Map<Map<String, ResourceItem>, Collection<ResourceItem>> mReadOnlyListMap = - new IdentityHashMap<Map<String, ResourceItem>, Collection<ResourceItem>>(); - - private final boolean mFrameworkRepository; - - protected final IntArrayWrapper mWrapper = new IntArrayWrapper(null); - - /** - * Makes a resource repository - * @param isFrameworkRepository whether the repository is for framework resources. - */ - protected ResourceRepository(boolean isFrameworkRepository) { - mFrameworkRepository = isFrameworkRepository; - } - - public boolean isFrameworkRepository() { - return mFrameworkRepository; - } - - /** - * Adds a Folder Configuration to the project. - * @param type The resource type. - * @param config The resource configuration. - * @param folder The workspace folder object. - * @return the {@link ResourceFolder} object associated to this folder. - */ - private ResourceFolder add( - @NonNull ResourceFolderType type, - @NonNull FolderConfiguration config, - @NonNull IAbstractFolder folder) { - // get the list for the resource type - List<ResourceFolder> list = mFolderMap.get(type); - - if (list == null) { - list = new ArrayList<ResourceFolder>(); - - ResourceFolder cf = new ResourceFolder(type, config, folder, this); - list.add(cf); - - mFolderMap.put(type, list); - - return cf; - } - - // look for an already existing folder configuration. - for (ResourceFolder cFolder : list) { - if (cFolder.mConfiguration.equals(config)) { - // config already exist. Nothing to be done really, besides making sure - // the IAbstractFolder object is up to date. - cFolder.mFolder = folder; - return cFolder; - } - } - - // If we arrive here, this means we didn't find a matching configuration. - // So we add one. - ResourceFolder cf = new ResourceFolder(type, config, folder, this); - list.add(cf); - - return cf; - } - - /** - * Removes a {@link ResourceFolder} associated with the specified {@link IAbstractFolder}. - * @param type The type of the folder - * @param removedFolder the IAbstractFolder object. - * @param context the scanning context - * @return the {@link ResourceFolder} that was removed, or null if no matches were found. - */ - @Nullable - public ResourceFolder removeFolder( - @NonNull ResourceFolderType type, - @NonNull IAbstractFolder removedFolder, - @Nullable ScanningContext context) { - // get the list of folders for the resource type. - List<ResourceFolder> list = mFolderMap.get(type); - - if (list != null) { - int count = list.size(); - for (int i = 0 ; i < count ; i++) { - ResourceFolder resFolder = list.get(i); - IAbstractFolder folder = resFolder.getFolder(); - if (removedFolder.equals(folder)) { - // we found the matching ResourceFolder. we need to remove it. - list.remove(i); - - // remove its content - resFolder.dispose(context); - - return resFolder; - } - } - } - - return null; - } - - /** - * Returns true if this resource repository contains a resource of the given - * name. - * - * @param url the resource URL - * @return true if the resource is known - */ - public boolean hasResourceItem(@NonNull String url) { - assert url.startsWith("@") : url; - - int typeEnd = url.indexOf('/', 1); - if (typeEnd != -1) { - int nameBegin = typeEnd + 1; - - // Skip @ and @+ - int typeBegin = url.startsWith("@+") ? 2 : 1; //$NON-NLS-1$ - - int colon = url.lastIndexOf(':', typeEnd); - if (colon != -1) { - typeBegin = colon + 1; - } - String typeName = url.substring(typeBegin, typeEnd); - ResourceType type = ResourceType.getEnum(typeName); - if (type != null) { - String name = url.substring(nameBegin); - return hasResourceItem(type, name); - } - } - - return false; - } - - /** - * Returns true if this resource repository contains a resource of the given - * name. - * - * @param type the type of resource to look up - * @param name the name of the resource - * @return true if the resource is known - */ - public boolean hasResourceItem(@NonNull ResourceType type, @NonNull String name) { - Map<String, ResourceItem> map = mResourceMap.get(type); - - if (map != null) { - - ResourceItem resourceItem = map.get(name); - if (resourceItem != null) { - return true; - } - } - - return false; - } - - /** - * Returns a {@link ResourceItem} matching the given {@link ResourceType} and name. If none - * exist, it creates one. - * - * @param type the resource type - * @param name the name of the resource. - * @return A resource item matching the type and name. - */ - @NonNull - protected ResourceItem getResourceItem(@NonNull ResourceType type, @NonNull String name) { - // looking for an existing ResourceItem with this type and name - ResourceItem item = findDeclaredResourceItem(type, name); - - // create one if there isn't one already, or if the existing one is inlined, since - // clearly we need a non inlined one (the inline one is removed too) - if (item == null || item.isDeclaredInline()) { - ResourceItem oldItem = item != null && item.isDeclaredInline() ? item : null; - - item = createResourceItem(name); - - Map<String, ResourceItem> map = mResourceMap.get(type); - - if (map == null) { - if (isFrameworkRepository()) { - // Pick initial size for the maps. Also change the load factor to 1.0 - // to avoid rehashing the whole table when we (as expected) get near - // the known rough size of each resource type map. - int size; - switch (type) { - // Based on counts in API 16. Going back to API 10, the counts - // are roughly 25-50% smaller (e.g. compared to the top 5 types below - // the fractions are 1107 vs 1734, 831 vs 1508, 895 vs 1255, - // 733 vs 1064 and 171 vs 783. - case PUBLIC: size = 1734; break; - case DRAWABLE: size = 1508; break; - case STRING: size = 1255; break; - case ATTR: size = 1064; break; - case STYLE: size = 783; break; - case ID: size = 347; break; - case DECLARE_STYLEABLE: size = 210; break; - case LAYOUT: size = 187; break; - case COLOR: size = 120; break; - case ANIM: size = 95; break; - case DIMEN: size = 81; break; - case BOOL: size = 54; break; - case INTEGER: size = 52; break; - case ARRAY: size = 51; break; - case PLURALS: size = 20; break; - case XML: size = 14; break; - case INTERPOLATOR : size = 13; break; - case ANIMATOR: size = 8; break; - case RAW: size = 4; break; - case MENU: size = 2; break; - case MIPMAP: size = 2; break; - case FRACTION: size = 1; break; - default: - size = 2; - } - map = new HashMap<String, ResourceItem>(size, 1.0f); - } else { - map = new HashMap<String, ResourceItem>(); - } - mResourceMap.put(type, map); - } - - map.put(item.getName(), item); - - if (oldItem != null) { - map.remove(oldItem.getName()); - - } - } - - return item; - } - - /** - * Creates a resource item with the given name. - * @param name the name of the resource - * @return a new ResourceItem (or child class) instance. - */ - @NonNull - protected abstract ResourceItem createResourceItem(@NonNull String name); - - /** - * Processes a folder and adds it to the list of existing folders. - * @param folder the folder to process - * @return the ResourceFolder created from this folder, or null if the process failed. - */ - @Nullable - public ResourceFolder processFolder(@NonNull IAbstractFolder folder) { - // split the name of the folder in segments. - String[] folderSegments = folder.getName().split(SdkConstants.RES_QUALIFIER_SEP); - - // get the enum for the resource type. - ResourceFolderType type = ResourceFolderType.getTypeByName(folderSegments[0]); - - if (type != null) { - // get the folder configuration. - FolderConfiguration config = FolderConfiguration.getConfig(folderSegments); - - if (config != null) { - return add(type, config, folder); - } - } - - return null; - } - - /** - * Returns a list of {@link ResourceFolder} for a specific {@link ResourceFolderType}. - * @param type The {@link ResourceFolderType} - */ - @Nullable - public List<ResourceFolder> getFolders(@NonNull ResourceFolderType type) { - return mFolderMap.get(type); - } - - @NonNull - public List<ResourceType> getAvailableResourceTypes() { - List<ResourceType> list = new ArrayList<ResourceType>(); - - // For each key, we check if there's a single ResourceType match. - // If not, we look for the actual content to give us the resource type. - - for (ResourceFolderType folderType : mFolderMap.keySet()) { - List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(folderType); - if (types.size() == 1) { - // before we add it we check if it's not already present, since a ResourceType - // could be created from multiple folders, even for the folders that only create - // one type of resource (drawable for instance, can be created from drawable/ and - // values/) - if (list.contains(types.get(0)) == false) { - list.add(types.get(0)); - } - } else { - // there isn't a single resource type out of this folder, so we look for all - // content. - List<ResourceFolder> folders = mFolderMap.get(folderType); - if (folders != null) { - for (ResourceFolder folder : folders) { - Collection<ResourceType> folderContent = folder.getResourceTypes(); - - // then we add them, but only if they aren't already in the list. - for (ResourceType folderResType : folderContent) { - if (list.contains(folderResType) == false) { - list.add(folderResType); - } - } - } - } - } - } - - return list; - } - - /** - * Returns a list of {@link ResourceItem} matching a given {@link ResourceType}. - * @param type the type of the resource items to return - * @return a non null collection of resource items - */ - @NonNull - public Collection<ResourceItem> getResourceItemsOfType(@NonNull ResourceType type) { - Map<String, ResourceItem> map = mResourceMap.get(type); - - if (map == null) { - return Collections.emptyList(); - } - - Collection<ResourceItem> roList = mReadOnlyListMap.get(map); - if (roList == null) { - roList = Collections.unmodifiableCollection(map.values()); - mReadOnlyListMap.put(map, roList); - } - - return roList; - } - - /** - * Returns whether the repository has resources of a given {@link ResourceType}. - * @param type the type of resource to check. - * @return true if the repository contains resources of the given type, false otherwise. - */ - public boolean hasResourcesOfType(@NonNull ResourceType type) { - Map<String, ResourceItem> items = mResourceMap.get(type); - return (items != null && items.size() > 0); - } - - /** - * Returns the {@link ResourceFolder} associated with a {@link IAbstractFolder}. - * @param folder The {@link IAbstractFolder} object. - * @return the {@link ResourceFolder} or null if it was not found. - */ - @Nullable - public ResourceFolder getResourceFolder(@NonNull IAbstractFolder folder) { - Collection<List<ResourceFolder>> values = mFolderMap.values(); - - if (values.isEmpty()) { // This shouldn't be necessary, but has been observed - try { - loadResources(folder.getParentFolder()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - for (List<ResourceFolder> list : values) { - for (ResourceFolder resFolder : list) { - IAbstractFolder wrapper = resFolder.getFolder(); - if (wrapper.equals(folder)) { - return resFolder; - } - } - } - - return null; - } - - /** - * Returns the {@link ResourceFile} matching the given name, {@link ResourceFolderType} and - * configuration. - * <p/>This only works with files generating one resource named after the file (for instance, - * layouts, bitmap based drawable, xml, anims). - * @return the matching file or <code>null</code> if no match was found. - */ - @Nullable - public ResourceFile getMatchingFile(@NonNull String name, @NonNull ResourceFolderType type, - @NonNull FolderConfiguration config) { - // get the folders for the given type - List<ResourceFolder> folders = mFolderMap.get(type); - - // look for folders containing a file with the given name. - ArrayList<ResourceFolder> matchingFolders = new ArrayList<ResourceFolder>(folders.size()); - - // remove the folders that do not have a file with the given name. - for (int i = 0 ; i < folders.size(); i++) { - ResourceFolder folder = folders.get(i); - - if (folder.hasFile(name) == true) { - matchingFolders.add(folder); - } - } - - // from those, get the folder with a config matching the given reference configuration. - Configurable match = config.findMatchingConfigurable(matchingFolders); - - // do we have a matching folder? - if (match instanceof ResourceFolder) { - // get the ResourceFile from the filename - return ((ResourceFolder)match).getFile(name); - } - - return null; - } - - /** - * Returns the list of source files for a given resource. - * Optionally, if a {@link FolderConfiguration} is given, then only the best - * match for this config is returned. - * - * @param type the type of the resource. - * @param name the name of the resource. - * @param referenceConfig an optional config for which only the best match will be returned. - * - * @return a list of files generating this resource or null if it was not found. - */ - @Nullable - public List<ResourceFile> getSourceFiles(@NonNull ResourceType type, @NonNull String name, - @Nullable FolderConfiguration referenceConfig) { - - Collection<ResourceItem> items = getResourceItemsOfType(type); - - for (ResourceItem item : items) { - if (name.equals(item.getName())) { - if (referenceConfig != null) { - Configurable match = referenceConfig.findMatchingConfigurable( - item.getSourceFileList()); - - if (match instanceof ResourceFile) { - return Collections.singletonList((ResourceFile) match); - } - - return null; - } - return item.getSourceFileList(); - } - } - - return null; - } - - /** - * Returns the resources values matching a given {@link FolderConfiguration}. - * - * @param referenceConfig the configuration that each value must match. - * @return a map with guaranteed to contain an entry for each {@link ResourceType} - */ - @NonNull - public Map<ResourceType, Map<String, ResourceValue>> getConfiguredResources( - @NonNull FolderConfiguration referenceConfig) { - return doGetConfiguredResources(referenceConfig); - } - - /** - * Returns the resources values matching a given {@link FolderConfiguration} for the current - * project. - * - * @param referenceConfig the configuration that each value must match. - * @return a map with guaranteed to contain an entry for each {@link ResourceType} - */ - @NonNull - protected final Map<ResourceType, Map<String, ResourceValue>> doGetConfiguredResources( - @NonNull FolderConfiguration referenceConfig) { - - Map<ResourceType, Map<String, ResourceValue>> map = - new EnumMap<ResourceType, Map<String, ResourceValue>>(ResourceType.class); - - for (ResourceType key : ResourceType.values()) { - // get the local results and put them in the map - map.put(key, getConfiguredResource(key, referenceConfig)); - } - - return map; - } - - /** - * Returns the sorted list of languages used in the resources. - */ - @NonNull - public SortedSet<String> getLanguages() { - SortedSet<String> set = new TreeSet<String>(); - - Collection<List<ResourceFolder>> folderList = mFolderMap.values(); - for (List<ResourceFolder> folderSubList : folderList) { - for (ResourceFolder folder : folderSubList) { - FolderConfiguration config = folder.getConfiguration(); - LanguageQualifier lang = config.getLanguageQualifier(); - if (lang != null) { - set.add(lang.getShortDisplayValue()); - } - } - } - - return set; - } - - /** - * Returns the sorted list of regions used in the resources with the given language. - * @param currentLanguage the current language the region must be associated with. - */ - @NonNull - public SortedSet<String> getRegions(@NonNull String currentLanguage) { - SortedSet<String> set = new TreeSet<String>(); - - Collection<List<ResourceFolder>> folderList = mFolderMap.values(); - for (List<ResourceFolder> folderSubList : folderList) { - for (ResourceFolder folder : folderSubList) { - FolderConfiguration config = folder.getConfiguration(); - - // get the language - LanguageQualifier lang = config.getLanguageQualifier(); - if (lang != null && lang.getShortDisplayValue().equals(currentLanguage)) { - RegionQualifier region = config.getRegionQualifier(); - if (region != null) { - set.add(region.getShortDisplayValue()); - } - } - } - } - - return set; - } - - /** - * Loads the resources from a resource folder. - * <p/> - * - * @param rootFolder The folder to read the resources from. This is the top level - * resource folder (res/) - * @throws IOException - */ - public void loadResources(@NonNull IAbstractFolder rootFolder) - throws IOException { - ScanningContext context = new ScanningContext(this); - - IAbstractResource[] files = rootFolder.listMembers(); - for (IAbstractResource file : files) { - if (file instanceof IAbstractFolder) { - IAbstractFolder folder = (IAbstractFolder) file; - ResourceFolder resFolder = processFolder(folder); - - if (resFolder != null) { - // now we process the content of the folder - IAbstractResource[] children = folder.listMembers(); - - for (IAbstractResource childRes : children) { - if (childRes instanceof IAbstractFile) { - resFolder.processFile((IAbstractFile) childRes, - ResourceDeltaKind.ADDED, context); - } - } - } - } - } - } - - - protected void removeFile(@NonNull Collection<ResourceType> types, - @NonNull ResourceFile file) { - for (ResourceType type : types) { - removeFile(type, file); - } - } - - protected void removeFile(@NonNull ResourceType type, @NonNull ResourceFile file) { - Map<String, ResourceItem> map = mResourceMap.get(type); - if (map != null) { - Collection<ResourceItem> values = map.values(); - for (ResourceItem item : values) { - item.removeFile(file); - } - } - } - - /** - * Returns a map of (resource name, resource value) for the given {@link ResourceType}. - * <p/>The values returned are taken from the resource files best matching a given - * {@link FolderConfiguration}. - * @param type the type of the resources. - * @param referenceConfig the configuration to best match. - */ - @NonNull - private Map<String, ResourceValue> getConfiguredResource(@NonNull ResourceType type, - @NonNull FolderConfiguration referenceConfig) { - - // get the resource item for the given type - Map<String, ResourceItem> items = mResourceMap.get(type); - if (items == null) { - return new HashMap<String, ResourceValue>(); - } - - // create the map - HashMap<String, ResourceValue> map = new HashMap<String, ResourceValue>(items.size()); - - for (ResourceItem item : items.values()) { - ResourceValue value = item.getResourceValue(type, referenceConfig, - isFrameworkRepository()); - if (value != null) { - map.put(item.getName(), value); - } - } - - return map; - } - - - /** - * Cleans up the repository of resource items that have no source file anymore. - */ - public void postUpdateCleanUp() { - // Since removed files/folders remove source files from existing ResourceItem, loop through - // all resource items and remove the ones that have no source files. - - Collection<Map<String, ResourceItem>> maps = mResourceMap.values(); - for (Map<String, ResourceItem> map : maps) { - Set<String> keySet = map.keySet(); - Iterator<String> iterator = keySet.iterator(); - while (iterator.hasNext()) { - String name = iterator.next(); - ResourceItem resourceItem = map.get(name); - if (resourceItem.hasNoSourceFile()) { - iterator.remove(); - } - } - } - } - - /** - * Looks up an existing {@link ResourceItem} by {@link ResourceType} and name. This - * ignores inline resources. - * @param type the Resource Type. - * @param name the Resource name. - * @return the existing ResourceItem or null if no match was found. - */ - @Nullable - private ResourceItem findDeclaredResourceItem(@NonNull ResourceType type, - @NonNull String name) { - Map<String, ResourceItem> map = mResourceMap.get(type); - - if (map != null) { - ResourceItem resourceItem = map.get(name); - if (resourceItem != null && !resourceItem.isDeclaredInline()) { - return resourceItem; - } - } - - return null; - } -} - diff --git a/ide_common/src/com/android/ide/common/resources/ResourceResolver.java b/ide_common/src/com/android/ide/common/resources/ResourceResolver.java deleted file mode 100644 index d742c4a..0000000 --- a/ide_common/src/com/android/ide/common/resources/ResourceResolver.java +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import static com.android.SdkConstants.ANDROID_PREFIX; -import static com.android.SdkConstants.ANDROID_THEME_PREFIX; -import static com.android.SdkConstants.PREFIX_ANDROID; -import static com.android.SdkConstants.PREFIX_RESOURCE_REF; -import static com.android.SdkConstants.PREFIX_THEME_REF; -import static com.android.SdkConstants.REFERENCE_STYLE; - -import com.android.ide.common.rendering.api.LayoutLog; -import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.StyleResourceValue; -import com.android.resources.ResourceType; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -public class ResourceResolver extends RenderResources { - - private final Map<ResourceType, Map<String, ResourceValue>> mProjectResources; - private final Map<ResourceType, Map<String, ResourceValue>> mFrameworkResources; - - private final Map<StyleResourceValue, StyleResourceValue> mStyleInheritanceMap = - new HashMap<StyleResourceValue, StyleResourceValue>(); - - private StyleResourceValue mTheme; - - private FrameworkResourceIdProvider mFrameworkProvider; - private LayoutLog mLogger; - private String mThemeName; - private boolean mIsProjectTheme; - - private ResourceResolver( - Map<ResourceType, Map<String, ResourceValue>> projectResources, - Map<ResourceType, Map<String, ResourceValue>> frameworkResources) { - mProjectResources = projectResources; - mFrameworkResources = frameworkResources; - } - - /** - * Creates a new {@link ResourceResolver} object. - * - * @param projectResources the project resources. - * @param frameworkResources the framework resources. - * @param themeName the name of the current theme. - * @param isProjectTheme Is this a project theme? - * @return a new {@link ResourceResolver} - */ - public static ResourceResolver create( - Map<ResourceType, Map<String, ResourceValue>> projectResources, - Map<ResourceType, Map<String, ResourceValue>> frameworkResources, - String themeName, boolean isProjectTheme) { - - ResourceResolver resolver = new ResourceResolver( - projectResources, frameworkResources); - - resolver.computeStyleMaps(themeName, isProjectTheme); - - return resolver; - } - - // ---- Methods to help dealing with older LayoutLibs. - - public String getThemeName() { - return mThemeName; - } - - public boolean isProjectTheme() { - return mIsProjectTheme; - } - - public Map<ResourceType, Map<String, ResourceValue>> getProjectResources() { - return mProjectResources; - } - - public Map<ResourceType, Map<String, ResourceValue>> getFrameworkResources() { - return mFrameworkResources; - } - - // ---- RenderResources Methods - - @Override - public void setFrameworkResourceIdProvider(FrameworkResourceIdProvider provider) { - mFrameworkProvider = provider; - } - - @Override - public void setLogger(LayoutLog logger) { - mLogger = logger; - } - - @Override - public StyleResourceValue getCurrentTheme() { - return mTheme; - } - - @Override - public StyleResourceValue getTheme(String name, boolean frameworkTheme) { - ResourceValue theme = null; - - if (frameworkTheme) { - Map<String, ResourceValue> frameworkStyleMap = mFrameworkResources.get( - ResourceType.STYLE); - theme = frameworkStyleMap.get(name); - } else { - Map<String, ResourceValue> projectStyleMap = mProjectResources.get(ResourceType.STYLE); - theme = projectStyleMap.get(name); - } - - if (theme instanceof StyleResourceValue) { - return (StyleResourceValue) theme; - } - - return null; - } - - @Override - public boolean themeIsParentOf(StyleResourceValue parentTheme, StyleResourceValue childTheme) { - do { - childTheme = mStyleInheritanceMap.get(childTheme); - if (childTheme == null) { - return false; - } else if (childTheme == parentTheme) { - return true; - } - } while (true); - } - - @Override - public ResourceValue getFrameworkResource(ResourceType resourceType, String resourceName) { - return getResource(resourceType, resourceName, mFrameworkResources); - } - - @Override - public ResourceValue getProjectResource(ResourceType resourceType, String resourceName) { - return getResource(resourceType, resourceName, mProjectResources); - } - - @Override - @Deprecated - public ResourceValue findItemInStyle(StyleResourceValue style, String attrName) { - // this method is deprecated because it doesn't know about the namespace of the - // attribute so we search for the project namespace first and then in the - // android namespace if needed. - ResourceValue item = findItemInStyle(style, attrName, false /*isFrameworkAttr*/); - if (item == null) { - item = findItemInStyle(style, attrName, true /*isFrameworkAttr*/); - } - - return item; - } - - @Override - public ResourceValue findItemInStyle(StyleResourceValue style, String itemName, - boolean isFrameworkAttr) { - ResourceValue item = style.findValue(itemName, isFrameworkAttr); - - // if we didn't find it, we look in the parent style (if applicable) - if (item == null && mStyleInheritanceMap != null) { - StyleResourceValue parentStyle = mStyleInheritanceMap.get(style); - if (parentStyle != null) { - return findItemInStyle(parentStyle, itemName, isFrameworkAttr); - } - } - - return item; - } - - @Override - public ResourceValue findResValue(String reference, boolean forceFrameworkOnly) { - if (reference == null) { - return null; - } - if (reference.startsWith(PREFIX_THEME_REF)) { - // no theme? no need to go further! - if (mTheme == null) { - return null; - } - - boolean frameworkOnly = false; - - // eliminate the prefix from the string - if (reference.startsWith(ANDROID_THEME_PREFIX)) { - frameworkOnly = true; - reference = reference.substring(ANDROID_THEME_PREFIX.length()); - } else { - reference = reference.substring(PREFIX_THEME_REF.length()); - } - - // at this point, value can contain type/name (drawable/foo for instance). - // split it to make sure. - String[] segments = reference.split("\\/"); - - // we look for the referenced item name. - String referenceName = null; - - if (segments.length == 2) { - // there was a resType in the reference. If it's attr, we ignore it - // else, we assert for now. - if (ResourceType.ATTR.getName().equals(segments[0])) { - referenceName = segments[1]; - } else { - // At this time, no support for ?type/name where type is not "attr" - return null; - } - } else { - // it's just an item name. - referenceName = segments[0]; - } - - // now we look for android: in the referenceName in order to support format - // such as: ?attr/android:name - if (referenceName.startsWith(PREFIX_ANDROID)) { - frameworkOnly = true; - referenceName = referenceName.substring(PREFIX_ANDROID.length()); - } - - // Now look for the item in the theme, starting with the current one. - ResourceValue item = findItemInStyle(mTheme, referenceName, - forceFrameworkOnly || frameworkOnly); - - if (item == null && mLogger != null) { - mLogger.warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, - String.format("Couldn't find theme resource %1$s for the current theme", - reference), - new ResourceValue(ResourceType.ATTR, referenceName, frameworkOnly)); - } - - return item; - } else if (reference.startsWith(PREFIX_RESOURCE_REF)) { - boolean frameworkOnly = false; - - // check for the specific null reference value. - if (REFERENCE_NULL.equals(reference)) { - return null; - } - - // Eliminate the prefix from the string. - if (reference.startsWith(ANDROID_PREFIX)) { - frameworkOnly = true; - reference = reference.substring(ANDROID_PREFIX.length()); - } else { - reference = reference.substring(PREFIX_RESOURCE_REF.length()); - } - - // at this point, value contains type/[android:]name (drawable/foo for instance) - String[] segments = reference.split("\\/"); - - // now we look for android: in the resource name in order to support format - // such as: @drawable/android:name - if (segments[1].startsWith(PREFIX_ANDROID)) { - frameworkOnly = true; - segments[1] = segments[1].substring(PREFIX_ANDROID.length()); - } - - ResourceType type = ResourceType.getEnum(segments[0]); - - // unknown type? - if (type == null) { - return null; - } - - return findResValue(type, segments[1], - forceFrameworkOnly ? true :frameworkOnly); - } - - // Looks like the value didn't reference anything. Return null. - return null; - } - - @Override - public ResourceValue resolveValue(ResourceType type, String name, String value, - boolean isFrameworkValue) { - if (value == null) { - return null; - } - - // get the ResourceValue referenced by this value - ResourceValue resValue = findResValue(value, isFrameworkValue); - - // if resValue is null, but value is not null, this means it was not a reference. - // we return the name/value wrapper in a ResourceValue. the isFramework flag doesn't - // matter. - if (resValue == null) { - return new ResourceValue(type, name, value, isFrameworkValue); - } - - // we resolved a first reference, but we need to make sure this isn't a reference also. - return resolveResValue(resValue); - } - - @Override - public ResourceValue resolveResValue(ResourceValue resValue) { - if (resValue == null) { - return null; - } - - // if the resource value is null, we simply return it. - String value = resValue.getValue(); - if (value == null) { - return resValue; - } - - // else attempt to find another ResourceValue referenced by this one. - ResourceValue resolvedResValue = findResValue(value, resValue.isFramework()); - - // if the value did not reference anything, then we simply return the input value - if (resolvedResValue == null) { - return resValue; - } - - // detect potential loop due to mishandled namespace in attributes - if (resValue == resolvedResValue) { - if (mLogger != null) { - mLogger.error(LayoutLog.TAG_BROKEN, - String.format("Potential stackoverflow trying to resolve '%s'. Render may not be accurate.", value), - null); - } - return resValue; - } - - // otherwise, we attempt to resolve this new value as well - return resolveResValue(resolvedResValue); - } - - // ---- Private helper methods. - - /** - * Searches for, and returns a {@link ResourceValue} by its name, and type. - * @param resType the type of the resource - * @param resName the name of the resource - * @param frameworkOnly if <code>true</code>, the method does not search in the - * project resources - */ - private ResourceValue findResValue(ResourceType resType, String resName, - boolean frameworkOnly) { - // map of ResouceValue for the given type - Map<String, ResourceValue> typeMap; - - // if allowed, search in the project resources first. - if (frameworkOnly == false) { - typeMap = mProjectResources.get(resType); - ResourceValue item = typeMap.get(resName); - if (item != null) { - return item; - } - } - - // now search in the framework resources. - typeMap = mFrameworkResources.get(resType); - ResourceValue item = typeMap.get(resName); - if (item != null) { - return item; - } - - // if it was not found and the type is an id, it is possible that the ID was - // generated dynamically when compiling the framework resources. - // Look for it in the R map. - if (mFrameworkProvider != null && resType == ResourceType.ID) { - if (mFrameworkProvider.getId(resType, resName) != null) { - return new ResourceValue(resType, resName, true); - } - } - - // didn't find the resource anywhere. - if (mLogger != null) { - mLogger.warning(LayoutLog.TAG_RESOURCES_RESOLVE, - "Couldn't resolve resource @" + - (frameworkOnly ? "android:" : "") + resType + "/" + resName, - new ResourceValue(resType, resName, frameworkOnly)); - } - return null; - } - - private ResourceValue getResource(ResourceType resourceType, String resourceName, - Map<ResourceType, Map<String, ResourceValue>> resourceRepository) { - Map<String, ResourceValue> typeMap = resourceRepository.get(resourceType); - if (typeMap != null) { - ResourceValue item = typeMap.get(resourceName); - if (item != null) { - item = resolveResValue(item); - return item; - } - } - - // didn't find the resource anywhere. - return null; - - } - - /** - * Compute style information from the given list of style for the project and framework. - * @param themeName the name of the current theme. - * @param isProjectTheme Is this a project theme? - */ - private void computeStyleMaps(String themeName, boolean isProjectTheme) { - mThemeName = themeName; - mIsProjectTheme = isProjectTheme; - Map<String, ResourceValue> projectStyleMap = mProjectResources.get(ResourceType.STYLE); - Map<String, ResourceValue> frameworkStyleMap = mFrameworkResources.get(ResourceType.STYLE); - - // first, get the theme - ResourceValue theme = null; - - // project theme names have been prepended with a * - if (isProjectTheme) { - theme = projectStyleMap.get(themeName); - } else { - theme = frameworkStyleMap.get(themeName); - } - - if (theme instanceof StyleResourceValue) { - // compute the inheritance map for both the project and framework styles - computeStyleInheritance(projectStyleMap.values(), projectStyleMap, - frameworkStyleMap); - - // Compute the style inheritance for the framework styles/themes. - // Since, for those, the style parent values do not contain 'android:' - // we want to force looking in the framework style only to avoid using - // similarly named styles from the project. - // To do this, we pass null in lieu of the project style map. - computeStyleInheritance(frameworkStyleMap.values(), null /*inProjectStyleMap */, - frameworkStyleMap); - - mTheme = (StyleResourceValue) theme; - } - } - - - - /** - * Compute the parent style for all the styles in a given list. - * @param styles the styles for which we compute the parent. - * @param inProjectStyleMap the map of project styles. - * @param inFrameworkStyleMap the map of framework styles. - * @param outInheritanceMap the map of style inheritance. This is filled by the method. - */ - private void computeStyleInheritance(Collection<ResourceValue> styles, - Map<String, ResourceValue> inProjectStyleMap, - Map<String, ResourceValue> inFrameworkStyleMap) { - for (ResourceValue value : styles) { - if (value instanceof StyleResourceValue) { - StyleResourceValue style = (StyleResourceValue)value; - StyleResourceValue parentStyle = null; - - // first look for a specified parent. - String parentName = style.getParentStyle(); - - // no specified parent? try to infer it from the name of the style. - if (parentName == null) { - parentName = getParentName(value.getName()); - } - - if (parentName != null) { - parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap); - - if (parentStyle != null) { - mStyleInheritanceMap.put(style, parentStyle); - } - } - } - } - } - - - /** - * Computes the name of the parent style, or <code>null</code> if the style is a root style. - */ - private String getParentName(String styleName) { - int index = styleName.lastIndexOf('.'); - if (index != -1) { - return styleName.substring(0, index); - } - - return null; - } - - /** - * Searches for and returns the {@link StyleResourceValue} from a given name. - * <p/>The format of the name can be: - * <ul> - * <li>[android:]<name></li> - * <li>[android:]style/<name></li> - * <li>@[android:]style/<name></li> - * </ul> - * @param parentName the name of the style. - * @param inProjectStyleMap the project style map. Can be <code>null</code> - * @param inFrameworkStyleMap the framework style map. - * @return The matching {@link StyleResourceValue} object or <code>null</code> if not found. - */ - private StyleResourceValue getStyle(String parentName, - Map<String, ResourceValue> inProjectStyleMap, - Map<String, ResourceValue> inFrameworkStyleMap) { - boolean frameworkOnly = false; - - String name = parentName; - - // remove the useless @ if it's there - if (name.startsWith(PREFIX_RESOURCE_REF)) { - name = name.substring(PREFIX_RESOURCE_REF.length()); - } - - // check for framework identifier. - if (name.startsWith(PREFIX_ANDROID)) { - frameworkOnly = true; - name = name.substring(PREFIX_ANDROID.length()); - } - - // at this point we could have the format <type>/<name>. we want only the name as long as - // the type is style. - if (name.startsWith(REFERENCE_STYLE)) { - name = name.substring(REFERENCE_STYLE.length()); - } else if (name.indexOf('/') != -1) { - return null; - } - - ResourceValue parent = null; - - // if allowed, search in the project resources. - if (frameworkOnly == false && inProjectStyleMap != null) { - parent = inProjectStyleMap.get(name); - } - - // if not found, then look in the framework resources. - if (parent == null) { - parent = inFrameworkStyleMap.get(name); - } - - // make sure the result is the proper class type and return it. - if (parent instanceof StyleResourceValue) { - return (StyleResourceValue)parent; - } - - if (mLogger != null) { - mLogger.error(LayoutLog.TAG_RESOURCES_RESOLVE, - String.format("Unable to resolve parent style name: %s", parentName), - null /*data*/); - } - - return null; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/ScanningContext.java b/ide_common/src/com/android/ide/common/resources/ScanningContext.java deleted file mode 100644 index e4ed275..0000000 --- a/ide_common/src/com/android/ide/common/resources/ScanningContext.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2011 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.common.resources; - -import java.util.ArrayList; -import java.util.List; - -/** - * A {@link ScanningContext} keeps track of state during a resource file scan, - * such as any parsing errors encountered, whether Android ids have changed, and - * so on. - */ -public class ScanningContext { - private final ResourceRepository mRepository; - private boolean mNeedsFullAapt; - private List<String> mErrors = null; - - /** - * Constructs a new {@link ScanningContext} - * - * @param repository the associated resource repository - */ - public ScanningContext(ResourceRepository repository) { - super(); - mRepository = repository; - } - - /** - * Returns a list of errors encountered during scanning - * - * @return a list of errors encountered during scanning (or null) - */ - public List<String> getErrors() { - return mErrors; - } - - /** - * Adds the given error to the scanning context. The error should use the - * same syntax as real aapt error messages such that the aapt parser can - * properly detect the filename, line number, etc. - * - * @param error the error message, including file name and line number at - * the beginning - */ - public void addError(String error) { - if (mErrors == null) { - mErrors = new ArrayList<String>(); - } - mErrors.add(error); - } - - /** - * Returns the repository associated with this scanning context - * - * @return the associated repository, never null - */ - public ResourceRepository getRepository() { - return mRepository; - } - - /** - * Marks that a full aapt compilation of the resources is necessary because it has - * detected a change that cannot be incrementally handled. - */ - protected void requestFullAapt() { - mNeedsFullAapt = true; - } - - /** - * Returns whether this repository has been marked as "dirty"; if one or - * more of the constituent files have declared that the resource item names - * that they provide have changed. - * - * @return true if a full aapt compilation is required - */ - public boolean needsFullAapt() { - return mNeedsFullAapt; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/SingleResourceFile.java b/ide_common/src/com/android/ide/common/resources/SingleResourceFile.java deleted file mode 100644 index 6b663e9..0000000 --- a/ide_common/src/com/android/ide/common/resources/SingleResourceFile.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import com.android.ide.common.rendering.api.DensityBasedResourceValue; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.resources.configuration.DensityQualifier; -import com.android.io.IAbstractFile; -import com.android.resources.FolderTypeRelationship; -import com.android.resources.ResourceType; - -import java.util.Collection; -import java.util.List; - -import javax.xml.parsers.SAXParserFactory; - -/** - * Represents a resource file describing a single resource. - * <p/> - * This is typically an XML file inside res/anim, res/layout, or res/menu or an image file - * under res/drawable. - */ -public class SingleResourceFile extends ResourceFile { - - private final static SAXParserFactory sParserFactory = SAXParserFactory.newInstance(); - static { - sParserFactory.setNamespaceAware(true); - } - - private final String mResourceName; - private final ResourceType mType; - private ResourceValue mValue; - - public SingleResourceFile(IAbstractFile file, ResourceFolder folder) { - super(file, folder); - - // we need to infer the type of the resource from the folder type. - // This is easy since this is a single Resource file. - List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(folder.getType()); - mType = types.get(0); - - // compute the resource name - mResourceName = getResourceName(mType); - - // test if there's a density qualifier associated with the resource - DensityQualifier qualifier = folder.getConfiguration().getDensityQualifier(); - - if (qualifier == null) { - mValue = new ResourceValue(mType, getResourceName(mType), - file.getOsLocation(), isFramework()); - } else { - mValue = new DensityBasedResourceValue( - mType, - getResourceName(mType), - file.getOsLocation(), - qualifier.getValue(), - isFramework()); - } - } - - @Override - protected void load(ScanningContext context) { - // get a resource item matching the given type and name - ResourceItem item = getRepository().getResourceItem(mType, mResourceName); - - // add this file to the list of files generating this resource item. - item.add(this); - - // Ask for an ID refresh since we're adding an item that will generate an ID - context.requestFullAapt(); - } - - @Override - protected void update(ScanningContext context) { - // when this happens, nothing needs to be done since the file only generates - // a single resources that doesn't actually change (its content is the file path) - } - - @Override - protected void dispose(ScanningContext context) { - // only remove this file from the existing ResourceItem. - getFolder().getRepository().removeFile(mType, this); - - // Ask for an ID refresh since we're removing an item that previously generated an ID - context.requestFullAapt(); - - // don't need to touch the content, it'll get reclaimed as this objects disappear. - // In the mean time other objects may need to access it. - } - - @Override - public Collection<ResourceType> getResourceTypes() { - return FolderTypeRelationship.getRelatedResourceTypes(getFolder().getType()); - } - - @Override - public boolean hasResources(ResourceType type) { - return FolderTypeRelationship.match(type, getFolder().getType()); - } - - /* - * (non-Javadoc) - * @see com.android.ide.eclipse.editors.resources.manager.ResourceFile#getValue(com.android.ide.eclipse.common.resources.ResourceType, java.lang.String) - * - * This particular implementation does not care about the type or name since a - * SingleResourceFile represents a file generating only one resource. - * The value returned is the full absolute path of the file in OS form. - */ - @Override - public ResourceValue getValue(ResourceType type, String name) { - return mValue; - } - - /** - * Returns the name of the resources. - */ - private String getResourceName(ResourceType type) { - // get the name from the filename. - String name = getFile().getName(); - - int pos = name.indexOf('.'); - if (pos != -1) { - name = name.substring(0, pos); - } - - return name; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/ValueResourceParser.java b/ide_common/src/com/android/ide/common/resources/ValueResourceParser.java deleted file mode 100644 index aabfd35..0000000 --- a/ide_common/src/com/android/ide/common/resources/ValueResourceParser.java +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources; - -import com.android.ide.common.rendering.api.AttrResourceValue; -import com.android.ide.common.rendering.api.DeclareStyleableResourceValue; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.StyleResourceValue; -import com.android.resources.ResourceType; - -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -/** - * SAX handler to parser value resource files. - */ -public final class ValueResourceParser extends DefaultHandler { - - // TODO: reuse definitions from somewhere else. - private final static String NODE_RESOURCES = "resources"; - private final static String NODE_ITEM = "item"; - private final static String ATTR_NAME = "name"; - private final static String ATTR_TYPE = "type"; - private final static String ATTR_PARENT = "parent"; - private final static String ATTR_VALUE = "value"; - - private final static String DEFAULT_NS_PREFIX = "android:"; - private final static int DEFAULT_NS_PREFIX_LEN = DEFAULT_NS_PREFIX.length(); - - public interface IValueResourceRepository { - void addResourceValue(ResourceValue value); - boolean hasResourceValue(ResourceType type, String name); - } - - private boolean inResources = false; - private int mDepth = 0; - private ResourceValue mCurrentValue = null; - private StyleResourceValue mCurrentStyle = null; - private DeclareStyleableResourceValue mCurrentDeclareStyleable = null; - private AttrResourceValue mCurrentAttr; - private IValueResourceRepository mRepository; - private final boolean mIsFramework; - - public ValueResourceParser(IValueResourceRepository repository, boolean isFramework) { - mRepository = repository; - mIsFramework = isFramework; - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - if (mCurrentValue != null) { - mCurrentValue.setValue(trimXmlWhitespaces(mCurrentValue.getValue())); - } - - if (inResources && qName.equals(NODE_RESOURCES)) { - inResources = false; - } else if (mDepth == 2) { - mCurrentValue = null; - mCurrentStyle = null; - mCurrentDeclareStyleable = null; - mCurrentAttr = null; - } else if (mDepth == 3) { - mCurrentValue = null; - if (mCurrentDeclareStyleable != null) { - mCurrentAttr = null; - } - } - - mDepth--; - super.endElement(uri, localName, qName); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) - throws SAXException { - try { - mDepth++; - if (inResources == false && mDepth == 1) { - if (qName.equals(NODE_RESOURCES)) { - inResources = true; - } - } else if (mDepth == 2 && inResources == true) { - ResourceType type = getType(qName, attributes); - - if (type != null) { - // get the resource name - String name = attributes.getValue(ATTR_NAME); - if (name != null) { - switch (type) { - case STYLE: - String parent = attributes.getValue(ATTR_PARENT); - mCurrentStyle = new StyleResourceValue(type, name, parent, - mIsFramework); - mRepository.addResourceValue(mCurrentStyle); - break; - case DECLARE_STYLEABLE: - mCurrentDeclareStyleable = new DeclareStyleableResourceValue( - type, name, mIsFramework); - mRepository.addResourceValue(mCurrentDeclareStyleable); - break; - case ATTR: - mCurrentAttr = new AttrResourceValue(type, name, mIsFramework); - mRepository.addResourceValue(mCurrentAttr); - break; - default: - mCurrentValue = new ResourceValue(type, name, mIsFramework); - mRepository.addResourceValue(mCurrentValue); - break; - } - } - } - } else if (mDepth == 3) { - // get the resource name - String name = attributes.getValue(ATTR_NAME); - if (name != null) { - - if (mCurrentStyle != null) { - // is the attribute in the android namespace? - boolean isFrameworkAttr = mIsFramework; - if (name.startsWith(DEFAULT_NS_PREFIX)) { - name = name.substring(DEFAULT_NS_PREFIX_LEN); - isFrameworkAttr = true; - } - - mCurrentValue = new ResourceValue(null, name, mIsFramework); - mCurrentStyle.addValue(mCurrentValue, isFrameworkAttr); - } else if (mCurrentDeclareStyleable != null) { - // is the attribute in the android namespace? - boolean isFramework = mIsFramework; - if (name.startsWith(DEFAULT_NS_PREFIX)) { - name = name.substring(DEFAULT_NS_PREFIX_LEN); - isFramework = true; - } - - mCurrentAttr = new AttrResourceValue(ResourceType.ATTR, name, isFramework); - mCurrentDeclareStyleable.addValue(mCurrentAttr); - - // also add it to the repository. - mRepository.addResourceValue(mCurrentAttr); - - } else if (mCurrentAttr != null) { - // get the enum/flag value - String value = attributes.getValue(ATTR_VALUE); - - try { - // Integer.decode/parseInt can't deal with hex value > 0x7FFFFFFF so we - // use Long.decode instead. - mCurrentAttr.addValue(name, (int)(long)Long.decode(value)); - } catch (NumberFormatException e) { - // pass, we'll just ignore this value - } - - } - } - } else if (mDepth == 4 && mCurrentAttr != null) { - // get the enum/flag name - String name = attributes.getValue(ATTR_NAME); - String value = attributes.getValue(ATTR_VALUE); - - try { - // Integer.decode/parseInt can't deal with hex value > 0x7FFFFFFF so we - // use Long.decode instead. - mCurrentAttr.addValue(name, (int)(long)Long.decode(value)); - } catch (NumberFormatException e) { - // pass, we'll just ignore this value - } - } - } finally { - super.startElement(uri, localName, qName, attributes); - } - } - - private ResourceType getType(String qName, Attributes attributes) { - String typeValue; - - // if the node is <item>, we get the type from the attribute "type" - if (NODE_ITEM.equals(qName)) { - typeValue = attributes.getValue(ATTR_TYPE); - } else { - // the type is the name of the node. - typeValue = qName; - } - - ResourceType type = ResourceType.getEnum(typeValue); - return type; - } - - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - if (mCurrentValue != null) { - String value = mCurrentValue.getValue(); - if (value == null) { - mCurrentValue.setValue(new String(ch, start, length)); - } else { - mCurrentValue.setValue(value + new String(ch, start, length)); - } - } - } - - public static String trimXmlWhitespaces(String value) { - if (value == null) { - return null; - } - - // look for carriage return and replace all whitespace around it by just 1 space. - int index; - - while ((index = value.indexOf('\n')) != -1) { - // look for whitespace on each side - int left = index - 1; - while (left >= 0) { - if (Character.isWhitespace(value.charAt(left))) { - left--; - } else { - break; - } - } - - int right = index + 1; - int count = value.length(); - while (right < count) { - if (Character.isWhitespace(value.charAt(right))) { - right++; - } else { - break; - } - } - - // remove all between left and right (non inclusive) and replace by a single space. - String leftString = null; - if (left >= 0) { - leftString = value.substring(0, left + 1); - } - String rightString = null; - if (right < count) { - rightString = value.substring(right); - } - - if (leftString != null) { - value = leftString; - if (rightString != null) { - value += " " + rightString; - } - } else { - value = rightString != null ? rightString : ""; - } - } - - // now we un-escape the string - int length = value.length(); - char[] buffer = value.toCharArray(); - - for (int i = 0 ; i < length ; i++) { - if (buffer[i] == '\\' && i + 1 < length) { - if (buffer[i+1] == 'u') { - if (i + 5 < length) { - // this is unicode char \u1234 - int unicodeChar = Integer.parseInt(new String(buffer, i+2, 4), 16); - - // put the unicode char at the location of the \ - buffer[i] = (char)unicodeChar; - - // offset the rest of the buffer since we go from 6 to 1 char - if (i + 6 < buffer.length) { - System.arraycopy(buffer, i+6, buffer, i+1, length - i - 6); - } - length -= 5; - } - } else { - if (buffer[i+1] == 'n') { - // replace the 'n' char with \n - buffer[i+1] = '\n'; - } - - // offset the buffer to erase the \ - System.arraycopy(buffer, i+1, buffer, i, length - i - 1); - length--; - } - } else if (buffer[i] == '"') { - // if the " was escaped it would have been processed above. - // offset the buffer to erase the " - System.arraycopy(buffer, i+1, buffer, i, length - i - 1); - length--; - - // unlike when unescaping, we want to process the next char too - i--; - } - } - - return new String(buffer, 0, length); - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/Configurable.java b/ide_common/src/com/android/ide/common/resources/configuration/Configurable.java deleted file mode 100644 index 5e7f910..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/Configurable.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - - -/** - * An object that is associated with a {@link FolderConfiguration}. - */ -public interface Configurable { - /** - * Returns the {@link FolderConfiguration} for this object. - */ - public FolderConfiguration getConfiguration(); -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/CountryCodeQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/CountryCodeQualifier.java deleted file mode 100644 index eb7cc0d..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/CountryCodeQualifier.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Mobile Country Code. - */ -public final class CountryCodeQualifier extends ResourceQualifier { - /** Default pixel density value. This means the property is not set. */ - private final static int DEFAULT_CODE = -1; - - private final static Pattern sCountryCodePattern = Pattern.compile("^mcc(\\d{3})$");//$NON-NLS-1$ - - private final int mCode; - - public static final String NAME = "Mobile Country Code"; - - /** - * Creates and returns a qualifier from the given folder segment. If the segment is incorrect, - * <code>null</code> is returned. - * @param segment the folder segment from which to create a qualifier. - * @return a new {@link CountryCodeQualifier} object or <code>null</code> - */ - public static CountryCodeQualifier getQualifier(String segment) { - Matcher m = sCountryCodePattern.matcher(segment); - if (m.matches()) { - String v = m.group(1); - - int code = -1; - try { - code = Integer.parseInt(v); - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number. - return null; - } - - CountryCodeQualifier qualifier = new CountryCodeQualifier(code); - return qualifier; - } - - return null; - } - - /** - * Returns the folder name segment for the given value. This is equivalent to calling - * {@link #toString()} on a {@link CountryCodeQualifier} object. - * @param code the value of the qualifier, as returned by {@link #getCode()}. - */ - public static String getFolderSegment(int code) { - if (code != DEFAULT_CODE && code >= 100 && code <=999) { // code is 3 digit.) { - return String.format("mcc%1$d", code); //$NON-NLS-1$ - } - - return ""; //$NON-NLS-1$ - } - - public CountryCodeQualifier() { - this(DEFAULT_CODE); - } - - public CountryCodeQualifier(int code) { - mCode = code; - } - - public int getCode() { - return mCode; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Country Code"; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean isValid() { - return mCode != DEFAULT_CODE; - } - - @Override - public boolean hasFakeValue() { - return false; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - CountryCodeQualifier qualifier = getQualifier(value); - if (qualifier != null) { - config.setCountryCodeQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof CountryCodeQualifier) { - return mCode == ((CountryCodeQualifier)qualifier).mCode; - } - - return false; - } - - @Override - public int hashCode() { - return mCode; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String getFolderSegment() { - return getFolderSegment(mCode); - } - - @Override - public String getShortDisplayValue() { - if (mCode != DEFAULT_CODE) { - return String.format("MCC %1$d", mCode); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getLongDisplayValue() { - return getShortDisplayValue(); - } - -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/DensityQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/DensityQualifier.java deleted file mode 100644 index a9e4a01..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/DensityQualifier.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.Density; -import com.android.resources.ResourceEnum; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Screen Pixel Density. - */ -public final class DensityQualifier extends EnumBasedResourceQualifier { - private final static Pattern sDensityLegacyPattern = Pattern.compile("^(\\d+)dpi$");//$NON-NLS-1$ - - public static final String NAME = "Density"; - - private Density mValue = Density.MEDIUM; - - public DensityQualifier() { - // pass - } - - public DensityQualifier(Density value) { - mValue = value; - } - - public Density getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public int since() { - return 4; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - Density density = Density.getEnum(value); - if (density == null) { - - // attempt to read a legacy value. - Matcher m = sDensityLegacyPattern.matcher(value); - if (m.matches()) { - String v = m.group(1); - - try { - density = Density.getEnum(Integer.parseInt(v)); - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number - // which really shouldn't happen since the regexp would have failed. - } - } - } - - if (density != null) { - DensityQualifier qualifier = new DensityQualifier(); - qualifier.mValue = density; - config.setDensityQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean isMatchFor(ResourceQualifier qualifier) { - if (qualifier instanceof DensityQualifier) { - // as long as there's a density qualifier, it's always a match. - // The best match will be found later. - return true; - } - - return false; - } - - @Override - public boolean isBetterMatchThan(ResourceQualifier compareTo, ResourceQualifier reference) { - if (compareTo == null) { - return true; - } - - DensityQualifier compareQ = (DensityQualifier)compareTo; - DensityQualifier referenceQ = (DensityQualifier)reference; - - if (compareQ.mValue == referenceQ.mValue) { - // what we have is already the best possible match (exact match) - return false; - } else if (mValue == referenceQ.mValue) { - // got new exact value, this is the best! - return true; - } else { - // in all case we're going to prefer the higher dpi. - // if reference is high, we want highest dpi. - // if reference is medium, we'll prefer to scale down high dpi, than scale up low dpi - // if reference if low, we'll prefer to scale down high than medium (2:1 over 4:3) - return mValue.getDpiValue() > compareQ.mValue.getDpiValue(); - } - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java b/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java deleted file mode 100644 index 27eaa01..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.annotations.Nullable; -import com.android.resources.NightMode; -import com.android.resources.UiMode; -import com.android.sdklib.devices.Device; -import com.android.sdklib.devices.Hardware; -import com.android.sdklib.devices.Screen; -import com.android.sdklib.devices.State; - -public class DeviceConfigHelper { - /** - * Returns a {@link FolderConfiguration} based on the given state - * - * @param state - * The {@link State} of the {@link Device} to base the - * {@link FolderConfiguration} on. Can be null. - * @return A {@link FolderConfiguration} based on the given {@link State}. - * If the given {@link State} is null, the result is also null; - */ - @Nullable - public static FolderConfiguration getFolderConfig(@Nullable State state) { - if (state == null) { - return null; - } - - Hardware hw = state.getHardware(); - - FolderConfiguration config = new FolderConfiguration(); - config.createDefault(); - Screen screen = hw.getScreen(); - config.setDensityQualifier(new DensityQualifier(screen.getPixelDensity())); - config.setNavigationMethodQualifier(new NavigationMethodQualifier(hw.getNav())); - ScreenDimensionQualifier sdq; - if (screen.getXDimension() > screen.getYDimension()) { - sdq = new ScreenDimensionQualifier(screen.getXDimension(), screen.getYDimension()); - } else { - sdq = new ScreenDimensionQualifier(screen.getYDimension(), screen.getXDimension()); - } - config.setScreenDimensionQualifier(sdq); - config.setScreenRatioQualifier(new ScreenRatioQualifier(screen.getRatio())); - config.setScreenSizeQualifier(new ScreenSizeQualifier(screen.getSize())); - config.setTextInputMethodQualifier(new TextInputMethodQualifier(hw.getKeyboard())); - config.setTouchTypeQualifier(new TouchScreenQualifier(screen.getMechanism())); - - config.setKeyboardStateQualifier(new KeyboardStateQualifier(state.getKeyState())); - config.setNavigationStateQualifier(new NavigationStateQualifier(state.getNavState())); - config.setScreenOrientationQualifier( - new ScreenOrientationQualifier(state.getOrientation())); - - config.updateScreenWidthAndHeight(); - - // Setup some default qualifiers - config.setUiModeQualifier(new UiModeQualifier(UiMode.NORMAL)); - config.setNightModeQualifier(new NightModeQualifier(NightMode.NOTNIGHT)); - config.setCountryCodeQualifier(new CountryCodeQualifier()); - config.setLanguageQualifier(new LanguageQualifier()); - config.setNetworkCodeQualifier(new NetworkCodeQualifier()); - config.setRegionQualifier(new RegionQualifier()); - config.setVersionQualifier(new VersionQualifier()); - - return config; - } - - /** - * Returns a {@link FolderConfiguration} based on the {@link State} given by - * the {@link Device} and the state name. - * - * @param d - * The {@link Device} to base the {@link FolderConfiguration} on. - * @param stateName - * The name of the state to base the {@link FolderConfiguration} - * on. - * @return The {@link FolderConfiguration} based on the determined - * {@link State}. If there is no {@link State} with the given state - * name for the given device, null is returned. - */ - @Nullable - public static FolderConfiguration getFolderConfig(Device d, String stateName) { - return getFolderConfig(d.getState(stateName)); - } - - /** - * Returns a {@link FolderConfiguration} based on the default {@link State} - * for the given {@link Device}. - * - * @param d - * The {@link Device} to generate the {@link FolderConfiguration} - * from. - * @return A {@link FolderConfiguration} based on the default {@link State} - * for the given {@link Device} - */ - public static FolderConfiguration getFolderConfig(Device d) { - return getFolderConfig(d.getDefaultState()); - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/EnumBasedResourceQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/EnumBasedResourceQualifier.java deleted file mode 100644 index 7bfda2d..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/EnumBasedResourceQualifier.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.ResourceEnum; - -/** - * Base class for {@link ResourceQualifier} whose value is an {@link ResourceEnum}. - * - */ -abstract class EnumBasedResourceQualifier extends ResourceQualifier { - - abstract ResourceEnum getEnumValue(); - - @Override - public boolean isValid() { - return getEnumValue() != null; - } - - @Override - public boolean hasFakeValue() { - return getEnumValue().isFakeValue(); - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof EnumBasedResourceQualifier) { - return getEnumValue() == ((EnumBasedResourceQualifier)qualifier).getEnumValue(); - } - - return false; - } - - @Override - public int hashCode() { - ResourceEnum value = getEnumValue(); - if (value != null) { - return value.hashCode(); - } - - return 0; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public final String getFolderSegment() { - ResourceEnum value = getEnumValue(); - if (value != null) { - return value.getResourceValue(); - } - - return ""; //$NON-NLS-1$ - } - - - @Override - public String getShortDisplayValue() { - ResourceEnum value = getEnumValue(); - if (value != null) { - return value.getShortDisplayValue(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getLongDisplayValue() { - ResourceEnum value = getEnumValue(); - if (value != null) { - return value.getLongDisplayValue(); - } - - return ""; //$NON-NLS-1$ - } - -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/FolderConfiguration.java b/ide_common/src/com/android/ide/common/resources/configuration/FolderConfiguration.java deleted file mode 100644 index e2fe767..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/FolderConfiguration.java +++ /dev/null @@ -1,886 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.SdkConstants; -import com.android.resources.Density; -import com.android.resources.ResourceFolderType; -import com.android.resources.ScreenOrientation; - -import java.util.ArrayList; -import java.util.List; - - -/** - * Represents the configuration for Resource Folders. All the properties have a default - * value which means that the property is not set. - */ -public final class FolderConfiguration implements Comparable<FolderConfiguration> { - - private final static ResourceQualifier[] DEFAULT_QUALIFIERS; - - static { - // get the default qualifiers. - FolderConfiguration defaultConfig = new FolderConfiguration(); - defaultConfig.createDefault(); - DEFAULT_QUALIFIERS = defaultConfig.getQualifiers(); - } - - - private final ResourceQualifier[] mQualifiers = new ResourceQualifier[INDEX_COUNT]; - - private final static int INDEX_COUNTRY_CODE = 0; - private final static int INDEX_NETWORK_CODE = 1; - private final static int INDEX_LANGUAGE = 2; - private final static int INDEX_REGION = 3; - private final static int INDEX_SMALLEST_SCREEN_WIDTH = 4; - private final static int INDEX_SCREEN_WIDTH = 5; - private final static int INDEX_SCREEN_HEIGHT = 6; - private final static int INDEX_SCREEN_LAYOUT_SIZE = 7; - private final static int INDEX_SCREEN_RATIO = 8; - private final static int INDEX_SCREEN_ORIENTATION = 9; - private final static int INDEX_UI_MODE = 10; - private final static int INDEX_NIGHT_MODE = 11; - private final static int INDEX_PIXEL_DENSITY = 12; - private final static int INDEX_TOUCH_TYPE = 13; - private final static int INDEX_KEYBOARD_STATE = 14; - private final static int INDEX_TEXT_INPUT_METHOD = 15; - private final static int INDEX_NAVIGATION_STATE = 16; - private final static int INDEX_NAVIGATION_METHOD = 17; - private final static int INDEX_SCREEN_DIMENSION = 18; - private final static int INDEX_VERSION = 19; - private final static int INDEX_COUNT = 20; - - /** - * Creates a {@link FolderConfiguration} matching the folder segments. - * @param folderSegments The segments of the folder name. The first segments should contain - * the name of the folder - * @return a FolderConfiguration object, or null if the folder name isn't valid.. - */ - public static FolderConfiguration getConfig(String[] folderSegments) { - FolderConfiguration config = new FolderConfiguration(); - - // we are going to loop through the segments, and match them with the first - // available qualifier. If the segment doesn't match we try with the next qualifier. - // Because the order of the qualifier is fixed, we do not reset the first qualifier - // after each successful segment. - // If we run out of qualifier before processing all the segments, we fail. - - int qualifierIndex = 0; - int qualifierCount = DEFAULT_QUALIFIERS.length; - - for (int i = 1 ; i < folderSegments.length; i++) { - String seg = folderSegments[i]; - if (seg.length() > 0) { - while (qualifierIndex < qualifierCount && - DEFAULT_QUALIFIERS[qualifierIndex].checkAndSet(seg, config) == false) { - qualifierIndex++; - } - - // if we reached the end of the qualifier we didn't find a matching qualifier. - if (qualifierIndex == qualifierCount) { - return null; - } - - } else { - return null; - } - } - - return config; - } - - /** - * Returns the number of {@link ResourceQualifier} that make up a Folder configuration. - */ - public static int getQualifierCount() { - return INDEX_COUNT; - } - - /** - * Sets the config from the qualifiers of a given <var>config</var>. - * <p/>This is equivalent to <code>set(config, false)</code> - * @param config the configuration to set - * - * @see #set(FolderConfiguration, boolean) - */ - public void set(FolderConfiguration config) { - set(config, false /*nonFakeValuesOnly*/); - } - - /** - * Sets the config from the qualifiers of a given <var>config</var>. - * @param config the configuration to set - * @param nonFakeValuesOnly if set to true this ignore qualifiers for which the - * current value is a fake value. - * - * @see ResourceQualifier#hasFakeValue() - */ - public void set(FolderConfiguration config, boolean nonFakeValuesOnly) { - if (config != null) { - for (int i = 0 ; i < INDEX_COUNT ; i++) { - ResourceQualifier q = config.mQualifiers[i]; - if (nonFakeValuesOnly == false || q == null || q.hasFakeValue() == false) { - mQualifiers[i] = q; - } - } - } - } - - /** - * Reset the config. - * <p/>This makes qualifiers at all indices <code>null</code>. - */ - public void reset() { - for (int i = 0 ; i < INDEX_COUNT ; i++) { - mQualifiers[i] = null; - } - } - - /** - * Removes the qualifiers from the receiver if they are present (and valid) - * in the given configuration. - */ - public void substract(FolderConfiguration config) { - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (config.mQualifiers[i] != null && config.mQualifiers[i].isValid()) { - mQualifiers[i] = null; - } - } - } - - /** - * Adds the non-qualifiers from the given config. - * Qualifiers that are null in the given config do not change in the receiver. - */ - public void add(FolderConfiguration config) { - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (config.mQualifiers[i] != null) { - mQualifiers[i] = config.mQualifiers[i]; - } - } - } - - /** - * Returns the first invalid qualifier, or <code>null<code> if they are all valid (or if none - * exists). - */ - public ResourceQualifier getInvalidQualifier() { - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (mQualifiers[i] != null && mQualifiers[i].isValid() == false) { - return mQualifiers[i]; - } - } - - // all allocated qualifiers are valid, we return null. - return null; - } - - /** - * Returns whether the Region qualifier is valid. Region qualifier can only be present if a - * Language qualifier is present as well. - * @return true if the Region qualifier is valid. - */ - public boolean checkRegion() { - if (mQualifiers[INDEX_LANGUAGE] == null && mQualifiers[INDEX_REGION] != null) { - return false; - } - - return true; - } - - /** - * Adds a qualifier to the {@link FolderConfiguration} - * @param qualifier the {@link ResourceQualifier} to add. - */ - public void addQualifier(ResourceQualifier qualifier) { - if (qualifier instanceof CountryCodeQualifier) { - mQualifiers[INDEX_COUNTRY_CODE] = qualifier; - - } else if (qualifier instanceof NetworkCodeQualifier) { - mQualifiers[INDEX_NETWORK_CODE] = qualifier; - - } else if (qualifier instanceof LanguageQualifier) { - mQualifiers[INDEX_LANGUAGE] = qualifier; - - } else if (qualifier instanceof RegionQualifier) { - mQualifiers[INDEX_REGION] = qualifier; - - } else if (qualifier instanceof SmallestScreenWidthQualifier) { - mQualifiers[INDEX_SMALLEST_SCREEN_WIDTH] = qualifier; - - } else if (qualifier instanceof ScreenWidthQualifier) { - mQualifiers[INDEX_SCREEN_WIDTH] = qualifier; - - } else if (qualifier instanceof ScreenHeightQualifier) { - mQualifiers[INDEX_SCREEN_HEIGHT] = qualifier; - - } else if (qualifier instanceof ScreenSizeQualifier) { - mQualifiers[INDEX_SCREEN_LAYOUT_SIZE] = qualifier; - - } else if (qualifier instanceof ScreenRatioQualifier) { - mQualifiers[INDEX_SCREEN_RATIO] = qualifier; - - } else if (qualifier instanceof ScreenOrientationQualifier) { - mQualifiers[INDEX_SCREEN_ORIENTATION] = qualifier; - - } else if (qualifier instanceof UiModeQualifier) { - mQualifiers[INDEX_UI_MODE] = qualifier; - - } else if (qualifier instanceof NightModeQualifier) { - mQualifiers[INDEX_NIGHT_MODE] = qualifier; - - } else if (qualifier instanceof DensityQualifier) { - mQualifiers[INDEX_PIXEL_DENSITY] = qualifier; - - } else if (qualifier instanceof TouchScreenQualifier) { - mQualifiers[INDEX_TOUCH_TYPE] = qualifier; - - } else if (qualifier instanceof KeyboardStateQualifier) { - mQualifiers[INDEX_KEYBOARD_STATE] = qualifier; - - } else if (qualifier instanceof TextInputMethodQualifier) { - mQualifiers[INDEX_TEXT_INPUT_METHOD] = qualifier; - - } else if (qualifier instanceof NavigationStateQualifier) { - mQualifiers[INDEX_NAVIGATION_STATE] = qualifier; - - } else if (qualifier instanceof NavigationMethodQualifier) { - mQualifiers[INDEX_NAVIGATION_METHOD] = qualifier; - - } else if (qualifier instanceof ScreenDimensionQualifier) { - mQualifiers[INDEX_SCREEN_DIMENSION] = qualifier; - - } else if (qualifier instanceof VersionQualifier) { - mQualifiers[INDEX_VERSION] = qualifier; - - } - } - - /** - * Removes a given qualifier from the {@link FolderConfiguration}. - * @param qualifier the {@link ResourceQualifier} to remove. - */ - public void removeQualifier(ResourceQualifier qualifier) { - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (mQualifiers[i] == qualifier) { - mQualifiers[i] = null; - return; - } - } - } - - /** - * Returns a qualifier by its index. The total number of qualifiers can be accessed by - * {@link #getQualifierCount()}. - * @param index the index of the qualifier to return. - * @return the qualifier or null if there are none at the index. - */ - public ResourceQualifier getQualifier(int index) { - return mQualifiers[index]; - } - - public void setCountryCodeQualifier(CountryCodeQualifier qualifier) { - mQualifiers[INDEX_COUNTRY_CODE] = qualifier; - } - - public CountryCodeQualifier getCountryCodeQualifier() { - return (CountryCodeQualifier)mQualifiers[INDEX_COUNTRY_CODE]; - } - - public void setNetworkCodeQualifier(NetworkCodeQualifier qualifier) { - mQualifiers[INDEX_NETWORK_CODE] = qualifier; - } - - public NetworkCodeQualifier getNetworkCodeQualifier() { - return (NetworkCodeQualifier)mQualifiers[INDEX_NETWORK_CODE]; - } - - public void setLanguageQualifier(LanguageQualifier qualifier) { - mQualifiers[INDEX_LANGUAGE] = qualifier; - } - - public LanguageQualifier getLanguageQualifier() { - return (LanguageQualifier)mQualifiers[INDEX_LANGUAGE]; - } - - public void setRegionQualifier(RegionQualifier qualifier) { - mQualifiers[INDEX_REGION] = qualifier; - } - - public RegionQualifier getRegionQualifier() { - return (RegionQualifier)mQualifiers[INDEX_REGION]; - } - - public void setSmallestScreenWidthQualifier(SmallestScreenWidthQualifier qualifier) { - mQualifiers[INDEX_SMALLEST_SCREEN_WIDTH] = qualifier; - } - - public SmallestScreenWidthQualifier getSmallestScreenWidthQualifier() { - return (SmallestScreenWidthQualifier) mQualifiers[INDEX_SMALLEST_SCREEN_WIDTH]; - } - - public void setScreenWidthQualifier(ScreenWidthQualifier qualifier) { - mQualifiers[INDEX_SCREEN_WIDTH] = qualifier; - } - - public ScreenWidthQualifier getScreenWidthQualifier() { - return (ScreenWidthQualifier) mQualifiers[INDEX_SCREEN_WIDTH]; - } - - public void setScreenHeightQualifier(ScreenHeightQualifier qualifier) { - mQualifiers[INDEX_SCREEN_HEIGHT] = qualifier; - } - - public ScreenHeightQualifier getScreenHeightQualifier() { - return (ScreenHeightQualifier) mQualifiers[INDEX_SCREEN_HEIGHT]; - } - - public void setScreenSizeQualifier(ScreenSizeQualifier qualifier) { - mQualifiers[INDEX_SCREEN_LAYOUT_SIZE] = qualifier; - } - - public ScreenSizeQualifier getScreenSizeQualifier() { - return (ScreenSizeQualifier)mQualifiers[INDEX_SCREEN_LAYOUT_SIZE]; - } - - public void setScreenRatioQualifier(ScreenRatioQualifier qualifier) { - mQualifiers[INDEX_SCREEN_RATIO] = qualifier; - } - - public ScreenRatioQualifier getScreenRatioQualifier() { - return (ScreenRatioQualifier)mQualifiers[INDEX_SCREEN_RATIO]; - } - - public void setScreenOrientationQualifier(ScreenOrientationQualifier qualifier) { - mQualifiers[INDEX_SCREEN_ORIENTATION] = qualifier; - } - - public ScreenOrientationQualifier getScreenOrientationQualifier() { - return (ScreenOrientationQualifier)mQualifiers[INDEX_SCREEN_ORIENTATION]; - } - - public void setUiModeQualifier(UiModeQualifier qualifier) { - mQualifiers[INDEX_UI_MODE] = qualifier; - } - - public UiModeQualifier getUiModeQualifier() { - return (UiModeQualifier)mQualifiers[INDEX_UI_MODE]; - } - - public void setNightModeQualifier(NightModeQualifier qualifier) { - mQualifiers[INDEX_NIGHT_MODE] = qualifier; - } - - public NightModeQualifier getNightModeQualifier() { - return (NightModeQualifier)mQualifiers[INDEX_NIGHT_MODE]; - } - - public void setDensityQualifier(DensityQualifier qualifier) { - mQualifiers[INDEX_PIXEL_DENSITY] = qualifier; - } - - public DensityQualifier getDensityQualifier() { - return (DensityQualifier)mQualifiers[INDEX_PIXEL_DENSITY]; - } - - public void setTouchTypeQualifier(TouchScreenQualifier qualifier) { - mQualifiers[INDEX_TOUCH_TYPE] = qualifier; - } - - public TouchScreenQualifier getTouchTypeQualifier() { - return (TouchScreenQualifier)mQualifiers[INDEX_TOUCH_TYPE]; - } - - public void setKeyboardStateQualifier(KeyboardStateQualifier qualifier) { - mQualifiers[INDEX_KEYBOARD_STATE] = qualifier; - } - - public KeyboardStateQualifier getKeyboardStateQualifier() { - return (KeyboardStateQualifier)mQualifiers[INDEX_KEYBOARD_STATE]; - } - - public void setTextInputMethodQualifier(TextInputMethodQualifier qualifier) { - mQualifiers[INDEX_TEXT_INPUT_METHOD] = qualifier; - } - - public TextInputMethodQualifier getTextInputMethodQualifier() { - return (TextInputMethodQualifier)mQualifiers[INDEX_TEXT_INPUT_METHOD]; - } - - public void setNavigationStateQualifier(NavigationStateQualifier qualifier) { - mQualifiers[INDEX_NAVIGATION_STATE] = qualifier; - } - - public NavigationStateQualifier getNavigationStateQualifier() { - return (NavigationStateQualifier)mQualifiers[INDEX_NAVIGATION_STATE]; - } - - public void setNavigationMethodQualifier(NavigationMethodQualifier qualifier) { - mQualifiers[INDEX_NAVIGATION_METHOD] = qualifier; - } - - public NavigationMethodQualifier getNavigationMethodQualifier() { - return (NavigationMethodQualifier)mQualifiers[INDEX_NAVIGATION_METHOD]; - } - - public void setScreenDimensionQualifier(ScreenDimensionQualifier qualifier) { - mQualifiers[INDEX_SCREEN_DIMENSION] = qualifier; - } - - public ScreenDimensionQualifier getScreenDimensionQualifier() { - return (ScreenDimensionQualifier)mQualifiers[INDEX_SCREEN_DIMENSION]; - } - - public void setVersionQualifier(VersionQualifier qualifier) { - mQualifiers[INDEX_VERSION] = qualifier; - } - - public VersionQualifier getVersionQualifier() { - return (VersionQualifier)mQualifiers[INDEX_VERSION]; - } - - /** - * Updates the {@link SmallestScreenWidthQualifier}, {@link ScreenWidthQualifier}, and - * {@link ScreenHeightQualifier} based on the (required) values of - * {@link ScreenDimensionQualifier} {@link DensityQualifier}, and - * {@link ScreenOrientationQualifier}. - * - * Also the density cannot be {@link Density#NODPI} as it's not valid on a device. - */ - public void updateScreenWidthAndHeight() { - - ResourceQualifier sizeQ = mQualifiers[INDEX_SCREEN_DIMENSION]; - ResourceQualifier densityQ = mQualifiers[INDEX_PIXEL_DENSITY]; - ResourceQualifier orientQ = mQualifiers[INDEX_SCREEN_ORIENTATION]; - - if (sizeQ != null && densityQ != null && orientQ != null) { - Density density = ((DensityQualifier) densityQ).getValue(); - if (density == Density.NODPI) { - return; - } - - ScreenOrientation orientation = ((ScreenOrientationQualifier) orientQ).getValue(); - - int size1 = ((ScreenDimensionQualifier) sizeQ).getValue1(); - int size2 = ((ScreenDimensionQualifier) sizeQ).getValue2(); - - // make sure size1 is the biggest (should be the case, but make sure) - if (size1 < size2) { - int a = size1; - size1 = size2; - size2 = a; - } - - // compute the dp. round them up since we want -w480dp to match a 480.5dp screen - int dp1 = (int) Math.ceil(size1 * Density.DEFAULT_DENSITY / density.getDpiValue()); - int dp2 = (int) Math.ceil(size2 * Density.DEFAULT_DENSITY / density.getDpiValue()); - - setSmallestScreenWidthQualifier(new SmallestScreenWidthQualifier(dp2)); - - switch (orientation) { - case PORTRAIT: - setScreenWidthQualifier(new ScreenWidthQualifier(dp2)); - setScreenHeightQualifier(new ScreenHeightQualifier(dp1)); - break; - case LANDSCAPE: - setScreenWidthQualifier(new ScreenWidthQualifier(dp1)); - setScreenHeightQualifier(new ScreenHeightQualifier(dp2)); - break; - case SQUARE: - setScreenWidthQualifier(new ScreenWidthQualifier(dp2)); - setScreenHeightQualifier(new ScreenHeightQualifier(dp2)); - break; - } - } - } - - /** - * Returns whether an object is equals to the receiver. - */ - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (obj instanceof FolderConfiguration) { - FolderConfiguration fc = (FolderConfiguration)obj; - for (int i = 0 ; i < INDEX_COUNT ; i++) { - ResourceQualifier qualifier = mQualifiers[i]; - ResourceQualifier fcQualifier = fc.mQualifiers[i]; - if (qualifier != null) { - if (qualifier.equals(fcQualifier) == false) { - return false; - } - } else if (fcQualifier != null) { - return false; - } - } - - return true; - } - - return false; - } - - @Override - public int hashCode() { - return toString().hashCode(); - } - - /** - * Returns whether the Configuration has only default values. - */ - public boolean isDefault() { - for (ResourceQualifier irq : mQualifiers) { - if (irq != null) { - return false; - } - } - - return true; - } - - /** - * Returns the name of a folder with the configuration. - */ - public String getFolderName(ResourceFolderType folder) { - StringBuilder result = new StringBuilder(folder.getName()); - - for (ResourceQualifier qualifier : mQualifiers) { - if (qualifier != null) { - String segment = qualifier.getFolderSegment(); - if (segment != null && segment.length() > 0) { - result.append(SdkConstants.RES_QUALIFIER_SEP); - result.append(segment); - } - } - } - - return result.toString(); - } - - /** - * Returns {@link #toDisplayString()}. - */ - @Override - public String toString() { - return toDisplayString(); - } - - /** - * Returns a string valid for display purpose. - */ - public String toDisplayString() { - if (isDefault()) { - return "default"; - } - - StringBuilder result = null; - int index = 0; - ResourceQualifier qualifier = null; - - // pre- language/region qualifiers - while (index < INDEX_LANGUAGE) { - qualifier = mQualifiers[index++]; - if (qualifier != null) { - if (result == null) { - result = new StringBuilder(); - } else { - result.append(", "); //$NON-NLS-1$ - } - result.append(qualifier.getLongDisplayValue()); - - } - } - - // process the language/region qualifier in a custom way, if there are both non null. - if (mQualifiers[INDEX_LANGUAGE] != null && mQualifiers[INDEX_REGION] != null) { - String language = mQualifiers[INDEX_LANGUAGE].getLongDisplayValue(); - String region = mQualifiers[INDEX_REGION].getLongDisplayValue(); - - if (result == null) { - result = new StringBuilder(); - } else { - result.append(", "); //$NON-NLS-1$ - } - result.append(String.format("Locale %s_%s", language, region)); //$NON-NLS-1$ - - index += 2; - } - - // post language/region qualifiers. - while (index < INDEX_COUNT) { - qualifier = mQualifiers[index++]; - if (qualifier != null) { - if (result == null) { - result = new StringBuilder(); - } else { - result.append(", "); //$NON-NLS-1$ - } - result.append(qualifier.getLongDisplayValue()); - - } - } - - return result == null ? null : result.toString(); - } - - @Override - public int compareTo(FolderConfiguration folderConfig) { - // default are always at the top. - if (isDefault()) { - if (folderConfig.isDefault()) { - return 0; - } - return -1; - } - - // now we compare the qualifiers - for (int i = 0 ; i < INDEX_COUNT; i++) { - ResourceQualifier qualifier1 = mQualifiers[i]; - ResourceQualifier qualifier2 = folderConfig.mQualifiers[i]; - - if (qualifier1 == null) { - if (qualifier2 == null) { - continue; - } else { - return -1; - } - } else { - if (qualifier2 == null) { - return 1; - } else { - int result = qualifier1.compareTo(qualifier2); - - if (result == 0) { - continue; - } - - return result; - } - } - } - - // if we arrive here, all the qualifier matches - return 0; - } - - /** - * Returns the best matching {@link Configurable} for this configuration. - * - * @param configurables the list of {@link Configurable} to choose from. - * - * @return an item from the given list of {@link Configurable} or null. - * - * @see http://d.android.com/guide/topics/resources/resources-i18n.html#best-match - */ - public Configurable findMatchingConfigurable(List<? extends Configurable> configurables) { - // - // 1: eliminate resources that contradict the reference configuration - // 2: pick next qualifier type - // 3: check if any resources use this qualifier, if no, back to 2, else move on to 4. - // 4: eliminate resources that don't use this qualifier. - // 5: if more than one resource left, go back to 2. - // - // The precedence of the qualifiers is more important than the number of qualifiers that - // exactly match the device. - - // 1: eliminate resources that contradict - ArrayList<Configurable> matchingConfigurables = new ArrayList<Configurable>(); - for (int i = 0 ; i < configurables.size(); i++) { - Configurable res = configurables.get(i); - - if (res.getConfiguration().isMatchFor(this)) { - matchingConfigurables.add(res); - } - } - - // if there is only one match, just take it - if (matchingConfigurables.size() == 1) { - return matchingConfigurables.get(0); - } else if (matchingConfigurables.size() == 0) { - return null; - } - - // 2. Loop on the qualifiers, and eliminate matches - final int count = FolderConfiguration.getQualifierCount(); - for (int q = 0 ; q < count ; q++) { - // look to see if one configurable has this qualifier. - // At the same time also record the best match value for the qualifier (if applicable). - - // The reference value, to find the best match. - // Note that this qualifier could be null. In which case any qualifier found in the - // possible match, will all be considered best match. - ResourceQualifier referenceQualifier = getQualifier(q); - - boolean found = false; - ResourceQualifier bestMatch = null; // this is to store the best match. - for (Configurable configurable : matchingConfigurables) { - ResourceQualifier qualifier = configurable.getConfiguration().getQualifier(q); - if (qualifier != null) { - // set the flag. - found = true; - - // Now check for a best match. If the reference qualifier is null , - // any qualifier is a "best" match (we don't need to record all of them. - // Instead the non compatible ones are removed below) - if (referenceQualifier != null) { - if (qualifier.isBetterMatchThan(bestMatch, referenceQualifier)) { - bestMatch = qualifier; - } - } - } - } - - // 4. If a configurable has a qualifier at the current index, remove all the ones that - // do not have one, or whose qualifier value does not equal the best match found above - // unless there's no reference qualifier, in which case they are all considered - // "best" match. - if (found) { - for (int i = 0 ; i < matchingConfigurables.size(); ) { - Configurable configurable = matchingConfigurables.get(i); - ResourceQualifier qualifier = configurable.getConfiguration().getQualifier(q); - - if (qualifier == null) { - // this resources has no qualifier of this type: rejected. - matchingConfigurables.remove(configurable); - } else if (referenceQualifier != null && bestMatch != null && - bestMatch.equals(qualifier) == false) { - // there's a reference qualifier and there is a better match for it than - // this resource, so we reject it. - matchingConfigurables.remove(configurable); - } else { - // looks like we keep this resource, move on to the next one. - i++; - } - } - - // at this point we may have run out of matching resources before going - // through all the qualifiers. - if (matchingConfigurables.size() < 2) { - break; - } - } - } - - // Because we accept resources whose configuration have qualifiers where the reference - // configuration doesn't, we can end up with more than one match. In this case, we just - // take the first one. - if (matchingConfigurables.size() == 0) { - return null; - } - return matchingConfigurables.get(0); - } - - - /** - * Returns whether the configuration is a match for the given reference config. - * <p/>A match means that, for each qualifier of this config - * <ul> - * <li>The reference config has no value set - * <li>or, the qualifier of the reference config is a match. Depending on the qualifier type - * this does not mean the same exact value.</li> - * </ul> - * @param referenceConfig The reference configuration to test against. - * @return true if the configuration matches. - */ - public boolean isMatchFor(FolderConfiguration referenceConfig) { - if (referenceConfig == null) { - return false; - } - - for (int i = 0 ; i < INDEX_COUNT ; i++) { - ResourceQualifier testQualifier = mQualifiers[i]; - ResourceQualifier referenceQualifier = referenceConfig.mQualifiers[i]; - - // it's only a non match if both qualifiers are non-null, and they don't match. - if (testQualifier != null && referenceQualifier != null && - testQualifier.isMatchFor(referenceQualifier) == false) { - return false; - } - } - - return true; - } - - /** - * Returns the index of the first non null {@link ResourceQualifier} starting at index - * <var>startIndex</var> - * @param startIndex - * @return -1 if no qualifier was found. - */ - public int getHighestPriorityQualifier(int startIndex) { - for (int i = startIndex ; i < INDEX_COUNT ; i++) { - if (mQualifiers[i] != null) { - return i; - } - } - - return -1; - } - - /** - * Create default qualifiers. - * <p/>This creates qualifiers with no values for all indices. - */ - public void createDefault() { - mQualifiers[INDEX_COUNTRY_CODE] = new CountryCodeQualifier(); - mQualifiers[INDEX_NETWORK_CODE] = new NetworkCodeQualifier(); - mQualifiers[INDEX_LANGUAGE] = new LanguageQualifier(); - mQualifiers[INDEX_REGION] = new RegionQualifier(); - mQualifiers[INDEX_SMALLEST_SCREEN_WIDTH] = new SmallestScreenWidthQualifier(); - mQualifiers[INDEX_SCREEN_WIDTH] = new ScreenWidthQualifier(); - mQualifiers[INDEX_SCREEN_HEIGHT] = new ScreenHeightQualifier(); - mQualifiers[INDEX_SCREEN_LAYOUT_SIZE] = new ScreenSizeQualifier(); - mQualifiers[INDEX_SCREEN_RATIO] = new ScreenRatioQualifier(); - mQualifiers[INDEX_SCREEN_ORIENTATION] = new ScreenOrientationQualifier(); - mQualifiers[INDEX_UI_MODE] = new UiModeQualifier(); - mQualifiers[INDEX_NIGHT_MODE] = new NightModeQualifier(); - mQualifiers[INDEX_PIXEL_DENSITY] = new DensityQualifier(); - mQualifiers[INDEX_TOUCH_TYPE] = new TouchScreenQualifier(); - mQualifiers[INDEX_KEYBOARD_STATE] = new KeyboardStateQualifier(); - mQualifiers[INDEX_TEXT_INPUT_METHOD] = new TextInputMethodQualifier(); - mQualifiers[INDEX_NAVIGATION_STATE] = new NavigationStateQualifier(); - mQualifiers[INDEX_NAVIGATION_METHOD] = new NavigationMethodQualifier(); - mQualifiers[INDEX_SCREEN_DIMENSION] = new ScreenDimensionQualifier(); - mQualifiers[INDEX_VERSION] = new VersionQualifier(); - } - - /** - * Returns an array of all the non null qualifiers. - */ - public ResourceQualifier[] getQualifiers() { - int count = 0; - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (mQualifiers[i] != null) { - count++; - } - } - - ResourceQualifier[] array = new ResourceQualifier[count]; - int index = 0; - for (int i = 0 ; i < INDEX_COUNT ; i++) { - if (mQualifiers[i] != null) { - array[index++] = mQualifiers[i]; - } - } - - return array; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/KeyboardStateQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/KeyboardStateQualifier.java deleted file mode 100644 index 1397808..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/KeyboardStateQualifier.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.KeyboardState; -import com.android.resources.ResourceEnum; - -/** - * Resource Qualifier for keyboard state. - */ -public final class KeyboardStateQualifier extends EnumBasedResourceQualifier { - - public static final String NAME = "Keyboard State"; - - private KeyboardState mValue = null; - - public KeyboardStateQualifier() { - // pass - } - - public KeyboardStateQualifier(KeyboardState value) { - mValue = value; - } - - public KeyboardState getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Keyboard"; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - KeyboardState orientation = KeyboardState.getEnum(value); - if (orientation != null) { - KeyboardStateQualifier qualifier = new KeyboardStateQualifier(); - qualifier.mValue = orientation; - config.setKeyboardStateQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean isMatchFor(ResourceQualifier qualifier) { - if (qualifier instanceof KeyboardStateQualifier) { - KeyboardStateQualifier referenceQualifier = (KeyboardStateQualifier)qualifier; - - // special case where EXPOSED can be used for SOFT - if (referenceQualifier.mValue == KeyboardState.SOFT && - mValue == KeyboardState.EXPOSED) { - return true; - } - - return referenceQualifier.mValue == mValue; - } - - return false; - } - - @Override - public boolean isBetterMatchThan(ResourceQualifier compareTo, ResourceQualifier reference) { - if (compareTo == null) { - return true; - } - - KeyboardStateQualifier compareQualifier = (KeyboardStateQualifier)compareTo; - KeyboardStateQualifier referenceQualifier = (KeyboardStateQualifier)reference; - - if (referenceQualifier.mValue == KeyboardState.SOFT) { // only case where there could be a - // better qualifier - // only return true if it's a better value. - if (compareQualifier.mValue == KeyboardState.EXPOSED && mValue == KeyboardState.SOFT) { - return true; - } - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/LanguageQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/LanguageQualifier.java deleted file mode 100644 index 76514e2..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/LanguageQualifier.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import java.util.Locale; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Language. - */ -public final class LanguageQualifier extends ResourceQualifier { - private final static Pattern sLanguagePattern = Pattern.compile("^[a-z]{2}$"); //$NON-NLS-1$ - - public static final String FAKE_LANG_VALUE = "__"; //$NON-NLS-1$ - public static final String NAME = "Language"; - - private String mValue; - - /** - * Creates and returns a qualifier from the given folder segment. If the segment is incorrect, - * <code>null</code> is returned. - * @param segment the folder segment from which to create a qualifier. - * @return a new {@link LanguageQualifier} object or <code>null</code> - */ - public static LanguageQualifier getQualifier(String segment) { - if (sLanguagePattern.matcher(segment).matches()) { - LanguageQualifier qualifier = new LanguageQualifier(); - qualifier.mValue = segment; - - return qualifier; - } - return null; - } - - /** - * Returns the folder name segment for the given value. This is equivalent to calling - * {@link #toString()} on a {@link LanguageQualifier} object. - * @param value the value of the qualifier, as returned by {@link #getValue()}. - */ - public static String getFolderSegment(String value) { - String segment = value.toLowerCase(Locale.US); - if (sLanguagePattern.matcher(segment).matches()) { - return segment; - } - - return null; - } - - public LanguageQualifier() { - - } - - public LanguageQualifier(String value) { - mValue = value; - } - - public String getValue() { - if (mValue != null) { - return mValue; - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean isValid() { - return mValue != null; - } - - @Override - public boolean hasFakeValue() { - return FAKE_LANG_VALUE.equals(mValue); - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - LanguageQualifier qualifier = getQualifier(value); - if (qualifier != null) { - config.setLanguageQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof LanguageQualifier) { - if (mValue == null) { - return ((LanguageQualifier)qualifier).mValue == null; - } - return mValue.equals(((LanguageQualifier)qualifier).mValue); - } - - return false; - } - - @Override - public int hashCode() { - if (mValue != null) { - return mValue.hashCode(); - } - - return 0; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String getFolderSegment() { - if (mValue != null) { - return getFolderSegment(mValue); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getShortDisplayValue() { - if (mValue != null) { - return mValue; - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getLongDisplayValue() { - if (mValue != null) { - return String.format("Language %s", mValue); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/NavigationMethodQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/NavigationMethodQualifier.java deleted file mode 100644 index f40bc6c..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/NavigationMethodQualifier.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.Navigation; -import com.android.resources.ResourceEnum; - -/** - * Resource Qualifier for Navigation Method. - */ -public final class NavigationMethodQualifier extends EnumBasedResourceQualifier { - - public static final String NAME = "Navigation Method"; - - private Navigation mValue; - - public NavigationMethodQualifier() { - // pass - } - - public NavigationMethodQualifier(Navigation value) { - mValue = value; - } - - public Navigation getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - Navigation method = Navigation.getEnum(value); - if (method != null) { - NavigationMethodQualifier qualifier = new NavigationMethodQualifier(method); - config.setNavigationMethodQualifier(qualifier); - return true; - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/NavigationStateQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/NavigationStateQualifier.java deleted file mode 100644 index 91b81df..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/NavigationStateQualifier.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.NavigationState; -import com.android.resources.ResourceEnum; - -/** - * Resource Qualifier for navigation state. - */ -public final class NavigationStateQualifier extends EnumBasedResourceQualifier { - - public static final String NAME = "Navigation State"; - - private NavigationState mValue = null; - - public NavigationStateQualifier() { - // pass - } - - public NavigationStateQualifier(NavigationState value) { - mValue = value; - } - - public NavigationState getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - NavigationState state = NavigationState.getEnum(value); - if (state != null) { - NavigationStateQualifier qualifier = new NavigationStateQualifier(); - qualifier.mValue = state; - config.setNavigationStateQualifier(qualifier); - return true; - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/NetworkCodeQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/NetworkCodeQualifier.java deleted file mode 100644 index 1ef2015..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/NetworkCodeQualifier.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Mobile Network Code Pixel Density. - */ -public final class NetworkCodeQualifier extends ResourceQualifier { - /** Default pixel density value. This means the property is not set. */ - private final static int DEFAULT_CODE = -1; - - private final static Pattern sNetworkCodePattern = Pattern.compile("^mnc(\\d{1,3})$"); //$NON-NLS-1$ - - private final int mCode; - - public final static String NAME = "Mobile Network Code"; - - /** - * Creates and returns a qualifier from the given folder segment. If the segment is incorrect, - * <code>null</code> is returned. - * @param segment the folder segment from which to create a qualifier. - * @return a new {@link CountryCodeQualifier} object or <code>null</code> - */ - public static NetworkCodeQualifier getQualifier(String segment) { - Matcher m = sNetworkCodePattern.matcher(segment); - if (m.matches()) { - String v = m.group(1); - - int code = -1; - try { - code = Integer.parseInt(v); - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number. - return null; - } - - NetworkCodeQualifier qualifier = new NetworkCodeQualifier(code); - return qualifier; - } - - return null; - } - - /** - * Returns the folder name segment for the given value. This is equivalent to calling - * {@link #toString()} on a {@link NetworkCodeQualifier} object. - * @param code the value of the qualifier, as returned by {@link #getCode()}. - */ - public static String getFolderSegment(int code) { - if (code != DEFAULT_CODE && code >= 1 && code <= 999) { // code is 1-3 digit. - return String.format("mnc%1$d", code); //$NON-NLS-1$ - } - - return ""; //$NON-NLS-1$ - } - - public NetworkCodeQualifier() { - this(DEFAULT_CODE); - } - - public NetworkCodeQualifier(int code) { - mCode = code; - } - - public int getCode() { - return mCode; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Network Code"; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean isValid() { - return mCode != DEFAULT_CODE; - } - - @Override - public boolean hasFakeValue() { - return false; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - Matcher m = sNetworkCodePattern.matcher(value); - if (m.matches()) { - String v = m.group(1); - - int code = -1; - try { - code = Integer.parseInt(v); - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number. - return false; - } - - NetworkCodeQualifier qualifier = new NetworkCodeQualifier(code); - config.setNetworkCodeQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof NetworkCodeQualifier) { - return mCode == ((NetworkCodeQualifier)qualifier).mCode; - } - - return false; - } - - @Override - public int hashCode() { - return mCode; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String getFolderSegment() { - return getFolderSegment(mCode); - } - - @Override - public String getShortDisplayValue() { - if (mCode != DEFAULT_CODE) { - return String.format("MNC %1$d", mCode); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getLongDisplayValue() { - return getShortDisplayValue(); - } - -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/NightModeQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/NightModeQualifier.java deleted file mode 100644 index d3b6760..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/NightModeQualifier.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.NightMode; -import com.android.resources.ResourceEnum; - -/** - * Resource Qualifier for Navigation Method. - */ -public final class NightModeQualifier extends EnumBasedResourceQualifier { - - public static final String NAME = "Night Mode"; - - private NightMode mValue; - - public NightModeQualifier() { - // pass - } - - public NightModeQualifier(NightMode value) { - mValue = value; - } - - public NightMode getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Night Mode"; - } - - @Override - public int since() { - return 8; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - NightMode mode = NightMode.getEnum(value); - if (mode != null) { - NightModeQualifier qualifier = new NightModeQualifier(mode); - config.setNightModeQualifier(qualifier); - return true; - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/RegionQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/RegionQualifier.java deleted file mode 100644 index bd033bd..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/RegionQualifier.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Region. - */ -public final class RegionQualifier extends ResourceQualifier { - private final static Pattern sRegionPattern = Pattern.compile("^r([A-Z]{2})$"); //$NON-NLS-1$ - - public static final String FAKE_REGION_VALUE = "__"; //$NON-NLS-1$ - public static final String NAME = "Region"; - - private String mValue; - - /** - * Creates and returns a qualifier from the given folder segment. If the segment is incorrect, - * <code>null</code> is returned. - * @param segment the folder segment from which to create a qualifier. - * @return a new {@link RegionQualifier} object or <code>null</code> - */ - public static RegionQualifier getQualifier(String segment) { - Matcher m = sRegionPattern.matcher(segment); - if (m.matches()) { - RegionQualifier qualifier = new RegionQualifier(); - qualifier.mValue = m.group(1); - - return qualifier; - } - return null; - } - - /** - * Returns the folder name segment for the given value. This is equivalent to calling - * {@link #toString()} on a {@link RegionQualifier} object. - * @param value the value of the qualifier, as returned by {@link #getValue()}. - */ - public static String getFolderSegment(String value) { - if (value != null) { - // See http://developer.android.com/reference/java/util/Locale.html#default_locale - String segment = "r" + value.toUpperCase(Locale.US); //$NON-NLS-1$ - if (sRegionPattern.matcher(segment).matches()) { - return segment; - } - } - - return ""; //$NON-NLS-1$ - } - - public RegionQualifier() { - - } - - public RegionQualifier(String value) { - mValue = value; - } - - public String getValue() { - if (mValue != null) { - return mValue; - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean isValid() { - return mValue != null; - } - - @Override - public boolean hasFakeValue() { - return FAKE_REGION_VALUE.equals(mValue); - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - RegionQualifier qualifier = getQualifier(value); - if (qualifier != null) { - config.setRegionQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof RegionQualifier) { - if (mValue == null) { - return ((RegionQualifier)qualifier).mValue == null; - } - return mValue.equals(((RegionQualifier)qualifier).mValue); - } - - return false; - } - - @Override - public int hashCode() { - if (mValue != null) { - return mValue.hashCode(); - } - - return 0; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String getFolderSegment() { - return getFolderSegment(mValue); - } - - @Override - public String getShortDisplayValue() { - if (mValue != null) { - return mValue; - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getLongDisplayValue() { - if (mValue != null) { - return String.format("Region %s", mValue); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/ResourceQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/ResourceQualifier.java deleted file mode 100644 index 2997c8f..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/ResourceQualifier.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - - -/** - * Base class for resource qualifiers. - * <p/>The resource qualifier classes are designed as immutable. - */ -public abstract class ResourceQualifier implements Comparable<ResourceQualifier> { - - /** - * Returns the human readable name of the qualifier. - */ - public abstract String getName(); - - /** - * Returns a shorter human readable name for the qualifier. - * @see #getName() - */ - public abstract String getShortName(); - - /** - * Returns when this qualifier was added to Android. - */ - public abstract int since(); - - /** - * Whether this qualifier is deprecated. - */ - public boolean deprecated() { - return false; - } - - /** - * Returns whether the qualifier has a valid filter value. - */ - public abstract boolean isValid(); - - /** - * Returns whether the qualifier has a fake value. - * <p/>Fake values are used internally and should not be used as real qualifier value. - */ - public abstract boolean hasFakeValue(); - - /** - * Check if the value is valid for this qualifier, and if so sets the value - * into a Folder Configuration. - * @param value The value to check and set. Must not be null. - * @param config The folder configuration to receive the value. Must not be null. - * @return true if the value was valid and was set. - */ - public abstract boolean checkAndSet(String value, FolderConfiguration config); - - /** - * Returns a string formated to be used in a folder name. - * <p/>This is declared as abstract to force children classes to implement it. - */ - public abstract String getFolderSegment(); - - /** - * Returns whether the given qualifier is a match for the receiver. - * <p/>The default implementation returns the result of {@link #equals(Object)}. - * <p/>Children class that re-implements this must implement - * {@link #isBetterMatchThan(ResourceQualifier, ResourceQualifier)} too. - * @param qualifier the reference qualifier - * @return true if the receiver is a match. - */ - public boolean isMatchFor(ResourceQualifier qualifier) { - return equals(qualifier); - } - - /** - * Returns true if the receiver is a better match for the given <var>reference</var> than - * the given <var>compareTo</var> comparable. - * @param compareTo The {@link ResourceQualifier} to compare to. Can be null, in which - * case the method must return <code>true</code>. - * @param reference The reference qualifier value for which the match is. - * @return true if the receiver is a better match. - */ - public boolean isBetterMatchThan(ResourceQualifier compareTo, ResourceQualifier reference) { - // the default is to always return false. This gives less overhead than always returning - // true, as it would only compare same values anyway. - return false; - } - - @Override - public String toString() { - return getFolderSegment(); - } - - /** - * Returns a string formatted for display purpose. - */ - public abstract String getShortDisplayValue(); - - /** - * Returns a string formatted for display purpose. - */ - public abstract String getLongDisplayValue(); - - /** - * Returns <code>true</code> if both objects are equal. - * <p/>This is declared as abstract to force children classes to implement it. - */ - @Override - public abstract boolean equals(Object object); - - /** - * Returns a hash code value for the object. - * <p/>This is declared as abstract to force children classes to implement it. - */ - @Override - public abstract int hashCode(); - - @Override - public final int compareTo(ResourceQualifier o) { - return toString().compareTo(o.toString()); - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/ScreenDimensionQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/ScreenDimensionQualifier.java deleted file mode 100644 index dce6c68..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/ScreenDimensionQualifier.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Screen Dimension. - */ -public final class ScreenDimensionQualifier extends ResourceQualifier { - /** Default screen size value. This means the property is not set */ - final static int DEFAULT_SIZE = -1; - - private final static Pattern sDimensionPattern = Pattern.compile( - "^(\\d+)x(\\d+)$"); //$NON-NLS-1$ - - public static final String NAME = "Screen Dimension"; - - /** Screen size 1 value. This is not size X or Y because the folder name always - * contains the biggest size first. So if the qualifier is 400x200, size 1 will always be - * 400 but that'll be X in landscape and Y in portrait. - * Default value is <code>DEFAULT_SIZE</code> */ - private int mValue1 = DEFAULT_SIZE; - - /** Screen size 2 value. This is not size X or Y because the folder name always - * contains the biggest size first. So if the qualifier is 400x200, size 2 will always be - * 200 but that'll be Y in landscape and X in portrait. - * Default value is <code>DEFAULT_SIZE</code> */ - private int mValue2 = DEFAULT_SIZE; - - public ScreenDimensionQualifier() { - // pass - } - - public ScreenDimensionQualifier(int value1, int value2) { - mValue1 = value1; - mValue2 = value2; - } - - public int getValue1() { - return mValue1; - } - - public int getValue2() { - return mValue2; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Dimension"; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean deprecated() { - return true; - } - - @Override - public boolean isValid() { - return mValue1 != DEFAULT_SIZE && mValue2 != DEFAULT_SIZE; - } - - @Override - public boolean hasFakeValue() { - return false; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - Matcher m = sDimensionPattern.matcher(value); - if (m.matches()) { - String d1 = m.group(1); - String d2 = m.group(2); - - ScreenDimensionQualifier qualifier = getQualifier(d1, d2); - if (qualifier != null) { - config.setScreenDimensionQualifier(qualifier); - return true; - } - } - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof ScreenDimensionQualifier) { - ScreenDimensionQualifier q = (ScreenDimensionQualifier)qualifier; - return (mValue1 == q.mValue1 && mValue2 == q.mValue2); - } - - return false; - } - - @Override - public int hashCode() { - return toString().hashCode(); - } - - public static ScreenDimensionQualifier getQualifier(String size1, String size2) { - try { - int s1 = Integer.parseInt(size1); - int s2 = Integer.parseInt(size2); - - ScreenDimensionQualifier qualifier = new ScreenDimensionQualifier(); - - if (s1 > s2) { - qualifier.mValue1 = s1; - qualifier.mValue2 = s2; - } else { - qualifier.mValue1 = s2; - qualifier.mValue2 = s1; - } - - return qualifier; - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number. - } - - return null; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String getFolderSegment() { - return String.format("%1$dx%2$d", mValue1, mValue2); //$NON-NLS-1$ - } - - @Override - public String getShortDisplayValue() { - if (isValid()) { - return String.format("%1$dx%2$d", mValue1, mValue2); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getLongDisplayValue() { - if (isValid()) { - return String.format("Screen resolution %1$dx%2$d", mValue1, mValue2); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/ScreenHeightQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/ScreenHeightQualifier.java deleted file mode 100644 index 08bba61..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/ScreenHeightQualifier.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Screen Pixel Density. - */ -public final class ScreenHeightQualifier extends ResourceQualifier { - /** Default screen size value. This means the property is not set */ - final static int DEFAULT_SIZE = -1; - - private final static Pattern sParsePattern = Pattern.compile("^h(\\d+)dp$");//$NON-NLS-1$ - private final static String sPrintPattern = "h%1$ddp"; - - public static final String NAME = "Screen Height"; - - private int mValue = DEFAULT_SIZE; - - public ScreenHeightQualifier() { - // pass - } - - public ScreenHeightQualifier(int value) { - mValue = value; - } - - public int getValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public int since() { - return 13; - } - - @Override - public boolean hasFakeValue() { - return false; - } - - @Override - public boolean isValid() { - return mValue != DEFAULT_SIZE; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - Matcher m = sParsePattern.matcher(value); - if (m.matches()) { - String v = m.group(1); - - ScreenHeightQualifier qualifier = getQualifier(v); - if (qualifier != null) { - config.setScreenHeightQualifier(qualifier); - return true; - } - } - - return false; - } - - public static ScreenHeightQualifier getQualifier(String value) { - try { - int dp = Integer.parseInt(value); - - ScreenHeightQualifier qualifier = new ScreenHeightQualifier(); - qualifier.mValue = dp; - return qualifier; - - } catch (NumberFormatException e) { - } - - return null; - } - - @Override - public boolean isMatchFor(ResourceQualifier qualifier) { - // this is the match only of the current dp value is lower or equal to the - if (qualifier instanceof ScreenHeightQualifier) { - return mValue <= ((ScreenHeightQualifier) qualifier).mValue; - } - - return false; - } - - @Override - public boolean isBetterMatchThan(ResourceQualifier compareTo, ResourceQualifier reference) { - if (compareTo == null) { - return true; - } - - ScreenHeightQualifier compareQ = (ScreenHeightQualifier)compareTo; - ScreenHeightQualifier referenceQ = (ScreenHeightQualifier)reference; - - if (compareQ.mValue == referenceQ.mValue) { - // what we have is already the best possible match (exact match) - return false; - } else if (mValue == referenceQ.mValue) { - // got new exact value, this is the best! - return true; - } else { - // get the qualifier that has the width that is the closest to the reference, but not - // above. (which is guaranteed when this is called as isMatchFor is called first. - return mValue > compareQ.mValue; - } - } - - @Override - public String getFolderSegment() { - return String.format(sPrintPattern, mValue); - } - - @Override - public String getShortDisplayValue() { - if (isValid()) { - return getFolderSegment(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getLongDisplayValue() { - if (isValid()) { - return getFolderSegment(); - } - - return ""; //$NON-NLS-1$ - } - - - @Override - public int hashCode() { - return mValue; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ScreenHeightQualifier other = (ScreenHeightQualifier) obj; - if (mValue != other.mValue) { - return false; - } - return true; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/ScreenOrientationQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/ScreenOrientationQualifier.java deleted file mode 100644 index 732a078..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/ScreenOrientationQualifier.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.ResourceEnum; -import com.android.resources.ScreenOrientation; - -/** - * Resource Qualifier for Screen Orientation. - */ -public final class ScreenOrientationQualifier extends EnumBasedResourceQualifier { - - public static final String NAME = "Screen Orientation"; - - private ScreenOrientation mValue = null; - - public ScreenOrientationQualifier() { - } - - public ScreenOrientationQualifier(ScreenOrientation value) { - mValue = value; - } - - public ScreenOrientation getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Orientation"; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - ScreenOrientation orientation = ScreenOrientation.getEnum(value); - if (orientation != null) { - ScreenOrientationQualifier qualifier = new ScreenOrientationQualifier(orientation); - config.setScreenOrientationQualifier(qualifier); - return true; - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/ScreenRatioQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/ScreenRatioQualifier.java deleted file mode 100644 index b45946b..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/ScreenRatioQualifier.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.ResourceEnum; -import com.android.resources.ScreenRatio; - -public class ScreenRatioQualifier extends EnumBasedResourceQualifier { - - public static final String NAME = "Screen Ratio"; - - private ScreenRatio mValue = null; - - public ScreenRatioQualifier() { - } - - public ScreenRatioQualifier(ScreenRatio value) { - mValue = value; - } - - public ScreenRatio getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Ratio"; - } - - @Override - public int since() { - return 4; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - ScreenRatio size = ScreenRatio.getEnum(value); - if (size != null) { - ScreenRatioQualifier qualifier = new ScreenRatioQualifier(size); - config.setScreenRatioQualifier(qualifier); - return true; - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/ScreenSizeQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/ScreenSizeQualifier.java deleted file mode 100644 index 77193a2..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/ScreenSizeQualifier.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.ResourceEnum; -import com.android.resources.ScreenSize; - -/** - * Resource Qualifier for Screen Size. Size can be "small", "normal", "large" and "x-large" - */ -public class ScreenSizeQualifier extends EnumBasedResourceQualifier { - - public static final String NAME = "Screen Size"; - - private ScreenSize mValue = null; - - - public ScreenSizeQualifier() { - } - - public ScreenSizeQualifier(ScreenSize value) { - mValue = value; - } - - public ScreenSize getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Size"; - } - - @Override - public int since() { - return 4; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - ScreenSize size = ScreenSize.getEnum(value); - if (size != null) { - ScreenSizeQualifier qualifier = new ScreenSizeQualifier(size); - config.setScreenSizeQualifier(qualifier); - return true; - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/ScreenWidthQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/ScreenWidthQualifier.java deleted file mode 100644 index ab9134b..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/ScreenWidthQualifier.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Screen Pixel Density. - */ -public final class ScreenWidthQualifier extends ResourceQualifier { - /** Default screen size value. This means the property is not set */ - final static int DEFAULT_SIZE = -1; - - private final static Pattern sParsePattern = Pattern.compile("^w(\\d+)dp$"); //$NON-NLS-1$ - private final static String sPrintPattern = "w%1$ddp"; //$NON-NLS-1$ - - public static final String NAME = "Screen Width"; - - private int mValue = DEFAULT_SIZE; - - public ScreenWidthQualifier() { - // pass - } - - public ScreenWidthQualifier(int value) { - mValue = value; - } - - public int getValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public int since() { - return 13; - } - - @Override - public boolean hasFakeValue() { - return false; - } - - @Override - public boolean isValid() { - return mValue != DEFAULT_SIZE; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - Matcher m = sParsePattern.matcher(value); - if (m.matches()) { - String v = m.group(1); - - ScreenWidthQualifier qualifier = getQualifier(v); - if (qualifier != null) { - config.setScreenWidthQualifier(qualifier); - return true; - } - } - - return false; - } - - public static ScreenWidthQualifier getQualifier(String value) { - try { - int dp = Integer.parseInt(value); - - ScreenWidthQualifier qualifier = new ScreenWidthQualifier(); - qualifier.mValue = dp; - return qualifier; - - } catch (NumberFormatException e) { - } - - return null; - } - - @Override - public boolean isMatchFor(ResourceQualifier qualifier) { - // this is the match only of the current dp value is lower or equal to the - if (qualifier instanceof ScreenWidthQualifier) { - return mValue <= ((ScreenWidthQualifier) qualifier).mValue; - } - - return false; - } - - @Override - public boolean isBetterMatchThan(ResourceQualifier compareTo, ResourceQualifier reference) { - if (compareTo == null) { - return true; - } - - ScreenWidthQualifier compareQ = (ScreenWidthQualifier)compareTo; - ScreenWidthQualifier referenceQ = (ScreenWidthQualifier)reference; - - if (compareQ.mValue == referenceQ.mValue) { - // what we have is already the best possible match (exact match) - return false; - } else if (mValue == referenceQ.mValue) { - // got new exact value, this is the best! - return true; - } else { - // get the qualifier that has the width that is the closest to the reference, but not - // above. (which is guaranteed when this is called as isMatchFor is called first. - return mValue > compareQ.mValue; - } - } - - @Override - public String getFolderSegment() { - return String.format(sPrintPattern, mValue); - } - - @Override - public String getShortDisplayValue() { - if (isValid()) { - return getFolderSegment(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getLongDisplayValue() { - if (isValid()) { - return getFolderSegment(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public int hashCode() { - return mValue; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ScreenWidthQualifier other = (ScreenWidthQualifier) obj; - if (mValue != other.mValue) { - return false; - } - return true; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/SmallestScreenWidthQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/SmallestScreenWidthQualifier.java deleted file mode 100644 index 35d1ab1..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/SmallestScreenWidthQualifier.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Screen Pixel Density. - */ -public final class SmallestScreenWidthQualifier extends ResourceQualifier { - /** Default screen size value. This means the property is not set */ - final static int DEFAULT_SIZE = -1; - - private final static Pattern sParsePattern = Pattern.compile("^sw(\\d+)dp$"); //$NON-NLS-1$ - private final static String sPrintPattern = "sw%1$ddp"; //$NON-NLS-1$ - - public static final String NAME = "Smallest Screen Width"; - - private int mValue = DEFAULT_SIZE; - - public SmallestScreenWidthQualifier() { - // pass - } - - public SmallestScreenWidthQualifier(int value) { - mValue = value; - } - - public int getValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public int since() { - return 13; - } - - @Override - public boolean hasFakeValue() { - return false; - } - - @Override - public boolean isValid() { - return mValue != DEFAULT_SIZE; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - Matcher m = sParsePattern.matcher(value); - if (m.matches()) { - String v = m.group(1); - - SmallestScreenWidthQualifier qualifier = getQualifier(v); - if (qualifier != null) { - config.setSmallestScreenWidthQualifier(qualifier); - return true; - } - } - - return false; - } - - public static SmallestScreenWidthQualifier getQualifier(String value) { - try { - int dp = Integer.parseInt(value); - - SmallestScreenWidthQualifier qualifier = new SmallestScreenWidthQualifier(); - qualifier.mValue = dp; - return qualifier; - - } catch (NumberFormatException e) { - } - - return null; - } - - @Override - public boolean isMatchFor(ResourceQualifier qualifier) { - // this is the match only of the current dp value is lower or equal to the - if (qualifier instanceof SmallestScreenWidthQualifier) { - return mValue <= ((SmallestScreenWidthQualifier) qualifier).mValue; - } - - return false; - } - - @Override - public boolean isBetterMatchThan(ResourceQualifier compareTo, ResourceQualifier reference) { - if (compareTo == null) { - return true; - } - - SmallestScreenWidthQualifier compareQ = (SmallestScreenWidthQualifier)compareTo; - SmallestScreenWidthQualifier referenceQ = (SmallestScreenWidthQualifier)reference; - - if (compareQ.mValue == referenceQ.mValue) { - // what we have is already the best possible match (exact match) - return false; - } else if (mValue == referenceQ.mValue) { - // got new exact value, this is the best! - return true; - } else { - // get the qualifier that has the width that is the closest to the reference, but not - // above. (which is guaranteed when this is called as isMatchFor is called first. - return mValue > compareQ.mValue; - } - } - - @Override - public String getFolderSegment() { - return String.format(sPrintPattern, mValue); - } - - @Override - public String getShortDisplayValue() { - if (isValid()) { - return getFolderSegment(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getLongDisplayValue() { - if (isValid()) { - return getFolderSegment(); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public int hashCode() { - return mValue; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - SmallestScreenWidthQualifier other = (SmallestScreenWidthQualifier) obj; - if (mValue != other.mValue) { - return false; - } - return true; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/TextInputMethodQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/TextInputMethodQualifier.java deleted file mode 100644 index 784d43d..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/TextInputMethodQualifier.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.Keyboard; -import com.android.resources.ResourceEnum; - -/** - * Resource Qualifier for Text Input Method. - */ -public final class TextInputMethodQualifier extends EnumBasedResourceQualifier { - - public static final String NAME = "Text Input Method"; - - private Keyboard mValue; - - - public TextInputMethodQualifier() { - // pass - } - - public TextInputMethodQualifier(Keyboard value) { - mValue = value; - } - - public Keyboard getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Text Input"; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - Keyboard method = Keyboard.getEnum(value); - if (method != null) { - TextInputMethodQualifier qualifier = new TextInputMethodQualifier(); - qualifier.mValue = method; - config.setTextInputMethodQualifier(qualifier); - return true; - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/TouchScreenQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/TouchScreenQualifier.java deleted file mode 100644 index dce9f1d..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/TouchScreenQualifier.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.ResourceEnum; -import com.android.resources.TouchScreen; - - -/** - * Resource Qualifier for Touch Screen type. - */ -public final class TouchScreenQualifier extends EnumBasedResourceQualifier { - - public static final String NAME = "Touch Screen"; - - private TouchScreen mValue; - - public TouchScreenQualifier() { - // pass - } - - public TouchScreenQualifier(TouchScreen touchValue) { - mValue = touchValue; - } - - public TouchScreen getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - TouchScreen type = TouchScreen.getEnum(value); - if (type != null) { - TouchScreenQualifier qualifier = new TouchScreenQualifier(); - qualifier.mValue = type; - config.setTouchTypeQualifier(qualifier); - return true; - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/UiModeQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/UiModeQualifier.java deleted file mode 100644 index 1e302c5..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/UiModeQualifier.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import com.android.resources.ResourceEnum; -import com.android.resources.UiMode; - -/** - * Resource Qualifier for UI Mode. - */ -public final class UiModeQualifier extends EnumBasedResourceQualifier { - - public static final String NAME = "UI Mode"; - - private UiMode mValue; - - public UiModeQualifier() { - // pass - } - - public UiModeQualifier(UiMode value) { - mValue = value; - } - - public UiMode getValue() { - return mValue; - } - - @Override - ResourceEnum getEnumValue() { - return mValue; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return NAME; - } - - @Override - public int since() { - return 8; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - UiMode mode = UiMode.getEnum(value); - if (mode != null) { - UiModeQualifier qualifier = new UiModeQualifier(mode); - config.setUiModeQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean isMatchFor(ResourceQualifier qualifier) { - // only normal is a match for all UI mode, because it's not an actual mode. - if (mValue == UiMode.NORMAL) { - return true; - } - - // others must be an exact match - return ((UiModeQualifier)qualifier).mValue == mValue; - } - - @Override - public boolean isBetterMatchThan(ResourceQualifier compareTo, ResourceQualifier reference) { - if (compareTo == null) { - return true; - } - - UiModeQualifier compareQualifier = (UiModeQualifier)compareTo; - UiModeQualifier referenceQualifier = (UiModeQualifier)reference; - - if (compareQualifier.getValue() == referenceQualifier.getValue()) { - // what we have is already the best possible match (exact match) - return false; - } else if (mValue == referenceQualifier.mValue) { - // got new exact value, this is the best! - return true; - } else if (mValue == UiMode.NORMAL) { - // else "normal" can be a match in case there's no exact match - return true; - } - - return false; - } -} diff --git a/ide_common/src/com/android/ide/common/resources/configuration/VersionQualifier.java b/ide_common/src/com/android/ide/common/resources/configuration/VersionQualifier.java deleted file mode 100644 index 078d4af..0000000 --- a/ide_common/src/com/android/ide/common/resources/configuration/VersionQualifier.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.resources.configuration; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Resource Qualifier for Platform Version. - */ -public final class VersionQualifier extends ResourceQualifier { - /** Default pixel density value. This means the property is not set. */ - private final static int DEFAULT_VERSION = -1; - - private final static Pattern sVersionPattern = Pattern.compile("^v(\\d+)$");//$NON-NLS-1$ - - private int mVersion = DEFAULT_VERSION; - - public static final String NAME = "Platform Version"; - - /** - * Creates and returns a qualifier from the given folder segment. If the segment is incorrect, - * <code>null</code> is returned. - * @param segment the folder segment from which to create a qualifier. - * @return a new {@link VersionQualifier} object or <code>null</code> - */ - public static VersionQualifier getQualifier(String segment) { - Matcher m = sVersionPattern.matcher(segment); - if (m.matches()) { - String v = m.group(1); - - int code = -1; - try { - code = Integer.parseInt(v); - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid number. - return null; - } - - VersionQualifier qualifier = new VersionQualifier(); - qualifier.mVersion = code; - return qualifier; - } - - return null; - } - - /** - * Returns the folder name segment for the given value. This is equivalent to calling - * {@link #toString()} on a {@link VersionQualifier} object. - * @param version the value of the qualifier, as returned by {@link #getVersion()}. - */ - public static String getFolderSegment(int version) { - if (version != DEFAULT_VERSION) { - return String.format("v%1$d", version); //$NON-NLS-1$ - } - - return ""; //$NON-NLS-1$ - } - - public VersionQualifier(int apiLevel) { - mVersion = apiLevel; - } - - public VersionQualifier() { - //pass - } - - public int getVersion() { - return mVersion; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public String getShortName() { - return "Version"; - } - - @Override - public int since() { - return 1; - } - - @Override - public boolean isValid() { - return mVersion != DEFAULT_VERSION; - } - - @Override - public boolean hasFakeValue() { - return false; - } - - @Override - public boolean checkAndSet(String value, FolderConfiguration config) { - VersionQualifier qualifier = getQualifier(value); - if (qualifier != null) { - config.setVersionQualifier(qualifier); - return true; - } - - return false; - } - - @Override - public boolean equals(Object qualifier) { - if (qualifier instanceof VersionQualifier) { - return mVersion == ((VersionQualifier)qualifier).mVersion; - } - - return false; - } - - @Override - public boolean isMatchFor(ResourceQualifier qualifier) { - if (qualifier instanceof VersionQualifier) { - // it is considered a match if the api level is equal or lower to the given qualifier - return mVersion <= ((VersionQualifier) qualifier).mVersion; - } - - return false; - } - - @Override - public boolean isBetterMatchThan(ResourceQualifier compareTo, ResourceQualifier reference) { - if (compareTo == null) { - return true; - } - - VersionQualifier compareQ = (VersionQualifier)compareTo; - VersionQualifier referenceQ = (VersionQualifier)reference; - - if (compareQ.mVersion == referenceQ.mVersion) { - // what we have is already the best possible match (exact match) - return false; - } else if (mVersion == referenceQ.mVersion) { - // got new exact value, this is the best! - return true; - } else { - // in all case we're going to prefer the higher version (since they have been filtered - // to not be too high - return mVersion > compareQ.mVersion; - } - } - - @Override - public int hashCode() { - return mVersion; - } - - /** - * Returns the string used to represent this qualifier in the folder name. - */ - @Override - public String getFolderSegment() { - return getFolderSegment(mVersion); - } - - @Override - public String getShortDisplayValue() { - if (mVersion != DEFAULT_VERSION) { - return String.format("API %1$d", mVersion); - } - - return ""; //$NON-NLS-1$ - } - - @Override - public String getLongDisplayValue() { - if (mVersion != DEFAULT_VERSION) { - return String.format("API Level %1$d", mVersion); - } - - return ""; //$NON-NLS-1$ - } -} diff --git a/ide_common/src/com/android/ide/common/sdk/LoadStatus.java b/ide_common/src/com/android/ide/common/sdk/LoadStatus.java deleted file mode 100644 index babbd63..0000000 --- a/ide_common/src/com/android/ide/common/sdk/LoadStatus.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.sdk; - -/** - * Enum for loading status of various SDK parts. - */ -public enum LoadStatus { - LOADING, LOADED, FAILED; -} diff --git a/ide_common/src/com/android/ide/common/xml/AndroidManifestParser.java b/ide_common/src/com/android/ide/common/xml/AndroidManifestParser.java deleted file mode 100644 index 38dc1c4..0000000 --- a/ide_common/src/com/android/ide/common/xml/AndroidManifestParser.java +++ /dev/null @@ -1,671 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.xml; - -import com.android.SdkConstants; -import com.android.ide.common.xml.ManifestData.Activity; -import com.android.ide.common.xml.ManifestData.Instrumentation; -import com.android.ide.common.xml.ManifestData.SupportsScreens; -import com.android.ide.common.xml.ManifestData.UsesConfiguration; -import com.android.ide.common.xml.ManifestData.UsesFeature; -import com.android.ide.common.xml.ManifestData.UsesLibrary; -import com.android.io.IAbstractFile; -import com.android.io.IAbstractFolder; -import com.android.io.StreamException; -import com.android.resources.Keyboard; -import com.android.resources.Navigation; -import com.android.resources.TouchScreen; -import com.android.xml.AndroidManifest; - -import org.xml.sax.Attributes; -import org.xml.sax.ErrorHandler; -import org.xml.sax.InputSource; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.DefaultHandler; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -public class AndroidManifestParser { - - private final static int LEVEL_TOP = 0; - private final static int LEVEL_INSIDE_MANIFEST = 1; - private final static int LEVEL_INSIDE_APPLICATION = 2; - private final static int LEVEL_INSIDE_APP_COMPONENT = 3; - private final static int LEVEL_INSIDE_INTENT_FILTER = 4; - - private final static String ACTION_MAIN = "android.intent.action.MAIN"; //$NON-NLS-1$ - private final static String CATEGORY_LAUNCHER = "android.intent.category.LAUNCHER"; //$NON-NLS-1$ - - public interface ManifestErrorHandler extends ErrorHandler { - /** - * Handles a parsing error and an optional line number. - */ - void handleError(Exception exception, int lineNumber); - - /** - * Checks that a class is valid and can be used in the Android Manifest. - * <p/> - * Errors are put as {@code org.eclipse.core.resources.IMarker} on the manifest file. - * - * @param locator - * @param className the fully qualified name of the class to test. - * @param superClassName the fully qualified name of the class it is supposed to extend. - * @param testVisibility if <code>true</code>, the method will check the visibility of - * the class or of its constructors. - */ - void checkClass(Locator locator, String className, String superClassName, - boolean testVisibility); - } - - /** - * XML error & data handler used when parsing the AndroidManifest.xml file. - * <p/> - * During parsing this will fill up the {@link ManifestData} object given to the constructor - * and call out errors to the given {@link ManifestErrorHandler}. - */ - private static class ManifestHandler extends DefaultHandler { - - //--- temporary data/flags used during parsing - private final ManifestData mManifestData; - private final ManifestErrorHandler mErrorHandler; - private int mCurrentLevel = 0; - private int mValidLevel = 0; - private Activity mCurrentActivity = null; - private Locator mLocator; - - /** - * Creates a new {@link ManifestHandler}. - * - * @param manifestFile The manifest file being parsed. Can be null. - * @param manifestData Class containing the manifest info obtained during the parsing. - * @param errorHandler An optional error handler. - */ - ManifestHandler(IAbstractFile manifestFile, ManifestData manifestData, - ManifestErrorHandler errorHandler) { - super(); - mManifestData = manifestData; - mErrorHandler = errorHandler; - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator) - */ - @Override - public void setDocumentLocator(Locator locator) { - mLocator = locator; - super.setDocumentLocator(locator); - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, - * java.lang.String, org.xml.sax.Attributes) - */ - @Override - public void startElement(String uri, String localName, String name, Attributes attributes) - throws SAXException { - try { - if (mManifestData == null) { - return; - } - - // if we're at a valid level - if (mValidLevel == mCurrentLevel) { - String value; - switch (mValidLevel) { - case LEVEL_TOP: - if (AndroidManifest.NODE_MANIFEST.equals(localName)) { - // lets get the package name. - mManifestData.mPackage = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_PACKAGE, - false /* hasNamespace */); - - // and the versionCode - String tmp = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_VERSIONCODE, true); - if (tmp != null) { - try { - mManifestData.mVersionCode = Integer.valueOf(tmp); - } catch (NumberFormatException e) { - // keep null in the field. - } - } - mValidLevel++; - } - break; - case LEVEL_INSIDE_MANIFEST: - if (AndroidManifest.NODE_APPLICATION.equals(localName)) { - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_PROCESS, - true /* hasNamespace */); - if (value != null) { - mManifestData.addProcessName(value); - } - - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_DEBUGGABLE, - true /* hasNamespace*/); - if (value != null) { - mManifestData.mDebuggable = Boolean.parseBoolean(value); - } - - mValidLevel++; - } else if (AndroidManifest.NODE_USES_SDK.equals(localName)) { - mManifestData.setMinSdkVersionString(getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION, - true /* hasNamespace */)); - mManifestData.setTargetSdkVersionString(getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_TARGET_SDK_VERSION, - true /* hasNamespace */)); - } else if (AndroidManifest.NODE_INSTRUMENTATION.equals(localName)) { - processInstrumentationNode(attributes); - - } else if (AndroidManifest.NODE_SUPPORTS_SCREENS.equals(localName)) { - processSupportsScreensNode(attributes); - - } else if (AndroidManifest.NODE_USES_CONFIGURATION.equals(localName)) { - processUsesConfiguration(attributes); - - } else if (AndroidManifest.NODE_USES_FEATURE.equals(localName)) { - UsesFeature feature = new UsesFeature(); - - // get the name - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (value != null) { - feature.mName = value; - } - - // read the required attribute - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_REQUIRED, - true /*hasNamespace*/); - if (value != null) { - Boolean b = Boolean.valueOf(value); - if (b != null) { - feature.mRequired = b; - } - } - - // read the gl es attribute - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_GLESVERSION, - true /*hasNamespace*/); - if (value != null) { - try { - int version = Integer.decode(value); - feature.mGlEsVersion = version; - } catch (NumberFormatException e) { - // ignore - } - - } - - mManifestData.mFeatures.add(feature); - } - break; - case LEVEL_INSIDE_APPLICATION: - if (AndroidManifest.NODE_ACTIVITY.equals(localName)) { - processActivityNode(attributes); - mValidLevel++; - } else if (AndroidManifest.NODE_SERVICE.equals(localName)) { - processNode(attributes, SdkConstants.CLASS_SERVICE); - mValidLevel++; - } else if (AndroidManifest.NODE_RECEIVER.equals(localName)) { - processNode(attributes, SdkConstants.CLASS_BROADCASTRECEIVER); - mValidLevel++; - } else if (AndroidManifest.NODE_PROVIDER.equals(localName)) { - processNode(attributes, SdkConstants.CLASS_CONTENTPROVIDER); - mValidLevel++; - } else if (AndroidManifest.NODE_USES_LIBRARY.equals(localName)) { - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (value != null) { - UsesLibrary library = new UsesLibrary(); - library.mName = value; - - // read the required attribute - value = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_REQUIRED, - true /*hasNamespace*/); - if (value != null) { - Boolean b = Boolean.valueOf(value); - if (b != null) { - library.mRequired = b; - } - } - - mManifestData.mLibraries.add(library); - } - } - break; - case LEVEL_INSIDE_APP_COMPONENT: - // only process this level if we are in an activity - if (mCurrentActivity != null && - AndroidManifest.NODE_INTENT.equals(localName)) { - mCurrentActivity.resetIntentFilter(); - mValidLevel++; - } - break; - case LEVEL_INSIDE_INTENT_FILTER: - if (mCurrentActivity != null) { - if (AndroidManifest.NODE_ACTION.equals(localName)) { - // get the name attribute - String action = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (action != null) { - mCurrentActivity.setHasAction(true); - mCurrentActivity.setHasMainAction( - ACTION_MAIN.equals(action)); - } - } else if (AndroidManifest.NODE_CATEGORY.equals(localName)) { - String category = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (CATEGORY_LAUNCHER.equals(category)) { - mCurrentActivity.setHasLauncherCategory(true); - } - } - - // no need to increase mValidLevel as we don't process anything - // below this level. - } - break; - } - } - - mCurrentLevel++; - } finally { - super.startElement(uri, localName, name, attributes); - } - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, - * java.lang.String) - */ - @Override - public void endElement(String uri, String localName, String name) throws SAXException { - try { - if (mManifestData == null) { - return; - } - - // decrement the levels. - if (mValidLevel == mCurrentLevel) { - mValidLevel--; - } - mCurrentLevel--; - - // if we're at a valid level - // process the end of the element - if (mValidLevel == mCurrentLevel) { - switch (mValidLevel) { - case LEVEL_INSIDE_APPLICATION: - mCurrentActivity = null; - break; - case LEVEL_INSIDE_APP_COMPONENT: - // if we found both a main action and a launcher category, this is our - // launcher activity! - if (mManifestData.mLauncherActivity == null && - mCurrentActivity != null && - mCurrentActivity.isHomeActivity() && - mCurrentActivity.isExported()) { - mManifestData.mLauncherActivity = mCurrentActivity; - } - break; - default: - break; - } - - } - } finally { - super.endElement(uri, localName, name); - } - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException) - */ - @Override - public void error(SAXParseException e) { - if (mErrorHandler != null) { - mErrorHandler.handleError(e, e.getLineNumber()); - } - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException) - */ - @Override - public void fatalError(SAXParseException e) { - if (mErrorHandler != null) { - mErrorHandler.handleError(e, e.getLineNumber()); - } - } - - /* (non-Javadoc) - * @see org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException) - */ - @Override - public void warning(SAXParseException e) throws SAXException { - if (mErrorHandler != null) { - mErrorHandler.warning(e); - } - } - - /** - * Processes the activity node. - * @param attributes the attributes for the activity node. - */ - private void processActivityNode(Attributes attributes) { - // lets get the activity name, and add it to the list - String activityName = getAttributeValue(attributes, AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (activityName != null) { - activityName = AndroidManifest.combinePackageAndClassName(mManifestData.mPackage, - activityName); - - // get the exported flag. - String exportedStr = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_EXPORTED, true); - boolean exported = exportedStr == null || - exportedStr.toLowerCase(Locale.US).equals("true"); //$NON-NLS-1$ - mCurrentActivity = new Activity(activityName, exported); - mManifestData.mActivities.add(mCurrentActivity); - - if (mErrorHandler != null) { - mErrorHandler.checkClass(mLocator, activityName, SdkConstants.CLASS_ACTIVITY, - true /* testVisibility */); - } - } else { - // no activity found! Aapt will output an error, - // so we don't have to do anything - mCurrentActivity = null; - } - - String processName = getAttributeValue(attributes, AndroidManifest.ATTRIBUTE_PROCESS, - true /* hasNamespace */); - if (processName != null) { - mManifestData.addProcessName(processName); - } - } - - /** - * Processes the service/receiver/provider nodes. - * @param attributes the attributes for the activity node. - * @param superClassName the fully qualified name of the super class that this - * node is representing - */ - private void processNode(Attributes attributes, String superClassName) { - // lets get the class name, and check it if required. - String serviceName = getAttributeValue(attributes, AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (serviceName != null) { - serviceName = AndroidManifest.combinePackageAndClassName(mManifestData.mPackage, - serviceName); - - if (mErrorHandler != null) { - mErrorHandler.checkClass(mLocator, serviceName, superClassName, - false /* testVisibility */); - } - } - - String processName = getAttributeValue(attributes, AndroidManifest.ATTRIBUTE_PROCESS, - true /* hasNamespace */); - if (processName != null) { - mManifestData.addProcessName(processName); - } - } - - /** - * Processes the instrumentation node. - * @param attributes the attributes for the instrumentation node. - */ - private void processInstrumentationNode(Attributes attributes) { - // lets get the class name, and check it if required. - String instrumentationName = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_NAME, - true /* hasNamespace */); - if (instrumentationName != null) { - String instrClassName = AndroidManifest.combinePackageAndClassName( - mManifestData.mPackage, instrumentationName); - String targetPackage = getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_TARGET_PACKAGE, - true /* hasNamespace */); - mManifestData.mInstrumentations.add( - new Instrumentation(instrClassName, targetPackage)); - if (mErrorHandler != null) { - mErrorHandler.checkClass(mLocator, instrClassName, - SdkConstants.CLASS_INSTRUMENTATION, true /* testVisibility */); - } - } - } - - /** - * Processes the supports-screens node. - * @param attributes the attributes for the supports-screens node. - */ - private void processSupportsScreensNode(Attributes attributes) { - mManifestData.mSupportsScreensFromManifest = new SupportsScreens(); - - mManifestData.mSupportsScreensFromManifest.setResizeable(getAttributeBooleanValue( - attributes, AndroidManifest.ATTRIBUTE_RESIZEABLE, true /*hasNamespace*/)); - - mManifestData.mSupportsScreensFromManifest.setAnyDensity(getAttributeBooleanValue( - attributes, AndroidManifest.ATTRIBUTE_ANYDENSITY, true /*hasNamespace*/)); - - mManifestData.mSupportsScreensFromManifest.setSmallScreens(getAttributeBooleanValue( - attributes, AndroidManifest.ATTRIBUTE_SMALLSCREENS, true /*hasNamespace*/)); - - mManifestData.mSupportsScreensFromManifest.setNormalScreens(getAttributeBooleanValue( - attributes, AndroidManifest.ATTRIBUTE_NORMALSCREENS, true /*hasNamespace*/)); - - mManifestData.mSupportsScreensFromManifest.setLargeScreens(getAttributeBooleanValue( - attributes, AndroidManifest.ATTRIBUTE_LARGESCREENS, true /*hasNamespace*/)); - } - - /** - * Processes the supports-screens node. - * @param attributes the attributes for the supports-screens node. - */ - private void processUsesConfiguration(Attributes attributes) { - mManifestData.mUsesConfiguration = new UsesConfiguration(); - - mManifestData.mUsesConfiguration.mReqFiveWayNav = getAttributeBooleanValue( - attributes, - AndroidManifest.ATTRIBUTE_REQ_5WAYNAV, true /*hasNamespace*/); - mManifestData.mUsesConfiguration.mReqNavigation = Navigation.getEnum( - getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_REQ_NAVIGATION, true /*hasNamespace*/)); - mManifestData.mUsesConfiguration.mReqHardKeyboard = getAttributeBooleanValue( - attributes, - AndroidManifest.ATTRIBUTE_REQ_HARDKEYBOARD, true /*hasNamespace*/); - mManifestData.mUsesConfiguration.mReqKeyboardType = Keyboard.getEnum( - getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_REQ_KEYBOARDTYPE, true /*hasNamespace*/)); - mManifestData.mUsesConfiguration.mReqTouchScreen = TouchScreen.getEnum( - getAttributeValue(attributes, - AndroidManifest.ATTRIBUTE_REQ_TOUCHSCREEN, true /*hasNamespace*/)); - } - - /** - * Searches through the attributes list for a particular one and returns its value. - * @param attributes the attribute list to search through - * @param attributeName the name of the attribute to look for. - * @param hasNamespace Indicates whether the attribute has an android namespace. - * @return a String with the value or null if the attribute was not found. - * @see SdkConstants#NS_RESOURCES - */ - private String getAttributeValue(Attributes attributes, String attributeName, - boolean hasNamespace) { - int count = attributes.getLength(); - for (int i = 0 ; i < count ; i++) { - if (attributeName.equals(attributes.getLocalName(i)) && - ((hasNamespace && - SdkConstants.NS_RESOURCES.equals(attributes.getURI(i))) || - (hasNamespace == false && attributes.getURI(i).length() == 0))) { - return attributes.getValue(i); - } - } - - return null; - } - - /** - * Searches through the attributes list for a particular one and returns its value as a - * Boolean. If the attribute is not present, this will return null. - * @param attributes the attribute list to search through - * @param attributeName the name of the attribute to look for. - * @param hasNamespace Indicates whether the attribute has an android namespace. - * @return a String with the value or null if the attribute was not found. - * @see SdkConstants#NS_RESOURCES - */ - private Boolean getAttributeBooleanValue(Attributes attributes, String attributeName, - boolean hasNamespace) { - int count = attributes.getLength(); - for (int i = 0 ; i < count ; i++) { - if (attributeName.equals(attributes.getLocalName(i)) && - ((hasNamespace && - SdkConstants.NS_RESOURCES.equals(attributes.getURI(i))) || - (hasNamespace == false && attributes.getURI(i).length() == 0))) { - String attr = attributes.getValue(i); - if (attr != null) { - return Boolean.valueOf(attr); - } else { - return null; - } - } - } - - return null; - } - - } - - private final static SAXParserFactory sParserFactory; - - static { - sParserFactory = SAXParserFactory.newInstance(); - sParserFactory.setNamespaceAware(true); - } - - /** - * Parses the Android Manifest, and returns a {@link ManifestData} object containing the - * result of the parsing. - * - * @param manifestFile the {@link IAbstractFile} representing the manifest file. - * @param gatherData indicates whether the parsing will extract data from the manifest. If false - * the method will always return null. - * @param errorHandler an optional errorHandler. - * @return A class containing the manifest info obtained during the parsing, or null on error. - * - * @throws StreamException - * @throws IOException - * @throws SAXException - * @throws ParserConfigurationException - */ - public static ManifestData parse( - IAbstractFile manifestFile, - boolean gatherData, - ManifestErrorHandler errorHandler) - throws SAXException, IOException, StreamException, ParserConfigurationException { - if (manifestFile != null) { - SAXParser parser = sParserFactory.newSAXParser(); - - ManifestData data = null; - if (gatherData) { - data = new ManifestData(); - } - - ManifestHandler manifestHandler = new ManifestHandler(manifestFile, - data, errorHandler); - parser.parse(new InputSource(manifestFile.getContents()), manifestHandler); - - return data; - } - - return null; - } - - /** - * Parses the Android Manifest, and returns an object containing the result of the parsing. - * - * <p/> - * This is the equivalent of calling <pre>parse(manifestFile, true, null)</pre> - * - * @param manifestFile the manifest file to parse. - * - * @throws ParserConfigurationException - * @throws StreamException - * @throws IOException - * @throws SAXException - */ - public static ManifestData parse(IAbstractFile manifestFile) - throws SAXException, IOException, StreamException, ParserConfigurationException { - return parse(manifestFile, true, null); - } - - public static ManifestData parse(IAbstractFolder projectFolder) - throws SAXException, IOException, StreamException, ParserConfigurationException { - IAbstractFile manifestFile = AndroidManifest.getManifest(projectFolder); - if (manifestFile == null) { - throw new FileNotFoundException(); - } - - return parse(manifestFile, true, null); - } - - /** - * Parses the Android Manifest from an {@link InputStream}, and returns a {@link ManifestData} - * object containing the result of the parsing. - * - * @param manifestFileStream the {@link InputStream} representing the manifest file. - * @return A class containing the manifest info obtained during the parsing or null on error. - * - * @throws StreamException - * @throws IOException - * @throws SAXException - * @throws ParserConfigurationException - */ - public static ManifestData parse(InputStream manifestFileStream) - throws SAXException, IOException, StreamException, ParserConfigurationException { - if (manifestFileStream != null) { - SAXParser parser = sParserFactory.newSAXParser(); - - ManifestData data = new ManifestData(); - - ManifestHandler manifestHandler = new ManifestHandler(null, data, null); - parser.parse(new InputSource(manifestFileStream), manifestHandler); - - return data; - } - - return null; - } -} diff --git a/ide_common/src/com/android/ide/common/xml/ManifestData.java b/ide_common/src/com/android/ide/common/xml/ManifestData.java deleted file mode 100644 index 9b68d60..0000000 --- a/ide_common/src/com/android/ide/common/xml/ManifestData.java +++ /dev/null @@ -1,747 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 - * - * 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.common.xml; - -import com.android.resources.Keyboard; -import com.android.resources.Navigation; -import com.android.resources.TouchScreen; - -import java.util.ArrayList; -import java.util.Set; -import java.util.TreeSet; - -/** - * Class containing the manifest info obtained during the parsing. - */ -public final class ManifestData { - - /** - * Value returned by {@link #getMinSdkVersion()} when the value of the minSdkVersion attribute - * in the manifest is a codename and not an integer value. - */ - public final static int MIN_SDK_CODENAME = 0; - - /** - * Value returned by {@link #getGlEsVersion()} when there are no <uses-feature> node with the - * attribute glEsVersion set. - */ - public final static int GL_ES_VERSION_NOT_SET = -1; - - /** Application package */ - String mPackage; - /** Application version Code, null if the attribute is not present. */ - Integer mVersionCode = null; - /** List of all activities */ - final ArrayList<Activity> mActivities = new ArrayList<Activity>(); - /** Launcher activity */ - Activity mLauncherActivity = null; - /** list of process names declared by the manifest */ - Set<String> mProcesses = null; - /** debuggable attribute value. If null, the attribute is not present. */ - Boolean mDebuggable = null; - /** API level requirement. if null the attribute was not present. */ - private String mMinSdkVersionString = null; - /** API level requirement. Default is 1 even if missing. If value is a codename, then it'll be - * 0 instead. */ - private int mMinSdkVersion = 1; - private int mTargetSdkVersion = 0; - /** List of all instrumentations declared by the manifest */ - final ArrayList<Instrumentation> mInstrumentations = - new ArrayList<Instrumentation>(); - /** List of all libraries in use declared by the manifest */ - final ArrayList<UsesLibrary> mLibraries = new ArrayList<UsesLibrary>(); - /** List of all feature in use declared by the manifest */ - final ArrayList<UsesFeature> mFeatures = new ArrayList<UsesFeature>(); - - SupportsScreens mSupportsScreensFromManifest; - SupportsScreens mSupportsScreensValues; - UsesConfiguration mUsesConfiguration; - - /** - * Instrumentation info obtained from manifest - */ - public final static class Instrumentation { - private final String mName; - private final String mTargetPackage; - - Instrumentation(String name, String targetPackage) { - mName = name; - mTargetPackage = targetPackage; - } - - /** - * Returns the fully qualified instrumentation class name - */ - public String getName() { - return mName; - } - - /** - * Returns the Android app package that is the target of this instrumentation - */ - public String getTargetPackage() { - return mTargetPackage; - } - } - - /** - * Activity info obtained from the manifest. - */ - public final static class Activity { - private final String mName; - private final boolean mIsExported; - private boolean mHasAction = false; - private boolean mHasMainAction = false; - private boolean mHasLauncherCategory = false; - - public Activity(String name, boolean exported) { - mName = name; - mIsExported = exported; - } - - public String getName() { - return mName; - } - - public boolean isExported() { - return mIsExported; - } - - public boolean hasAction() { - return mHasAction; - } - - public boolean isHomeActivity() { - return mHasMainAction && mHasLauncherCategory; - } - - void setHasAction(boolean hasAction) { - mHasAction = hasAction; - } - - /** If the activity doesn't yet have a filter set for the launcher, this resets both - * flags. This is to handle multiple intent-filters where one could have the valid - * action, and another one of the valid category. - */ - void resetIntentFilter() { - if (isHomeActivity() == false) { - mHasMainAction = mHasLauncherCategory = false; - } - } - - void setHasMainAction(boolean hasMainAction) { - mHasMainAction = hasMainAction; - } - - void setHasLauncherCategory(boolean hasLauncherCategory) { - mHasLauncherCategory = hasLauncherCategory; - } - } - - /** - * Class representing the <code>supports-screens</code> node in the manifest. - * By default, all the getters will return null if there was no value defined in the manifest. - * - * To get an instance with all the actual values, use {@link #resolveSupportsScreensValues(int)} - */ - public final static class SupportsScreens { - private Boolean mResizeable; - private Boolean mAnyDensity; - private Boolean mSmallScreens; - private Boolean mNormalScreens; - private Boolean mLargeScreens; - - public SupportsScreens() { - } - - /** - * Instantiate an instance from a string. The string must have been created with - * {@link #getEncodedValues()}. - * @param value the string. - */ - public SupportsScreens(String value) { - String[] values = value.split("\\|"); - - mAnyDensity = Boolean.valueOf(values[0]); - mResizeable = Boolean.valueOf(values[1]); - mSmallScreens = Boolean.valueOf(values[2]); - mNormalScreens = Boolean.valueOf(values[3]); - mLargeScreens = Boolean.valueOf(values[4]); - } - - /** - * Returns an instance of {@link SupportsScreens} initialized with the default values - * based on the given targetSdkVersion. - * @param targetSdkVersion - */ - public static SupportsScreens getDefaultValues(int targetSdkVersion) { - SupportsScreens result = new SupportsScreens(); - - result.mNormalScreens = Boolean.TRUE; - // Screen size and density became available in Android 1.5/API3, so before that - // non normal screens were not supported by default. After they are considered - // supported. - result.mResizeable = result.mAnyDensity = result.mSmallScreens = result.mLargeScreens = - targetSdkVersion <= 3 ? Boolean.FALSE : Boolean.TRUE; - - return result; - } - - /** - * Returns a version of the receiver for which all values have been set, even if they - * were not present in the manifest. - * @param targetSdkVersion the target api level of the app, since this has an effect - * on default values. - */ - public SupportsScreens resolveSupportsScreensValues(int targetSdkVersion) { - SupportsScreens result = getDefaultValues(targetSdkVersion); - - // Override the default with the existing values: - if (mResizeable != null) result.mResizeable = mResizeable; - if (mAnyDensity != null) result.mAnyDensity = mAnyDensity; - if (mSmallScreens != null) result.mSmallScreens = mSmallScreens; - if (mNormalScreens != null) result.mNormalScreens = mNormalScreens; - if (mLargeScreens != null) result.mLargeScreens = mLargeScreens; - - return result; - } - - /** - * returns the value of the <code>resizeable</code> attribute or null if not present. - */ - public Boolean getResizeable() { - return mResizeable; - } - - void setResizeable(Boolean resizeable) { - mResizeable = getConstantBoolean(resizeable); - } - - /** - * returns the value of the <code>anyDensity</code> attribute or null if not present. - */ - public Boolean getAnyDensity() { - return mAnyDensity; - } - - void setAnyDensity(Boolean anyDensity) { - mAnyDensity = getConstantBoolean(anyDensity); - } - - /** - * returns the value of the <code>smallScreens</code> attribute or null if not present. - */ - public Boolean getSmallScreens() { - return mSmallScreens; - } - - void setSmallScreens(Boolean smallScreens) { - mSmallScreens = getConstantBoolean(smallScreens); - } - - /** - * returns the value of the <code>normalScreens</code> attribute or null if not present. - */ - public Boolean getNormalScreens() { - return mNormalScreens; - } - - void setNormalScreens(Boolean normalScreens) { - mNormalScreens = getConstantBoolean(normalScreens); - } - - /** - * returns the value of the <code>largeScreens</code> attribute or null if not present. - */ - public Boolean getLargeScreens() { - return mLargeScreens; - } - - void setLargeScreens(Boolean largeScreens) { - mLargeScreens = getConstantBoolean(largeScreens); - } - - /** - * Returns either {@link Boolean#TRUE} or {@link Boolean#FALSE} based on the value of - * the given Boolean object. - */ - private Boolean getConstantBoolean(Boolean v) { - if (v != null) { - if (v.equals(Boolean.TRUE)) { - return Boolean.TRUE; - } else { - return Boolean.FALSE; - } - } - - return null; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof SupportsScreens) { - SupportsScreens support = (SupportsScreens) obj; - // since all the fields are guaranteed to be either Boolean.TRUE or Boolean.FALSE - // (or null), we can simply check they are identical and not bother with - // calling equals (which would require to check != null. - // see #getConstanntBoolean(Boolean) - return mResizeable == support.mResizeable && - mAnyDensity == support.mAnyDensity && - mSmallScreens == support.mSmallScreens && - mNormalScreens == support.mNormalScreens && - mLargeScreens == support.mLargeScreens; - } - - return false; - } - - /* Override hashCode, mostly to make Eclipse happy and not warn about it. - * And if you ever put this in a Map or Set, it will avoid surprises. */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mAnyDensity == null) ? 0 : mAnyDensity.hashCode()); - result = prime * result + ((mLargeScreens == null) ? 0 : mLargeScreens.hashCode()); - result = prime * result + ((mNormalScreens == null) ? 0 : mNormalScreens.hashCode()); - result = prime * result + ((mResizeable == null) ? 0 : mResizeable.hashCode()); - result = prime * result + ((mSmallScreens == null) ? 0 : mSmallScreens.hashCode()); - return result; - } - - /** - * Returns true if the two instances support the same screen sizes. - * This is similar to {@link #equals(Object)} except that it ignores the values of - * {@link #getAnyDensity()} and {@link #getResizeable()}. - * @param support the other instance to compare to. - * @return true if the two instances support the same screen sizes. - */ - public boolean hasSameScreenSupportAs(SupportsScreens support) { - // since all the fields are guaranteed to be either Boolean.TRUE or Boolean.FALSE - // (or null), we can simply check they are identical and not bother with - // calling equals (which would require to check != null. - // see #getConstanntBoolean(Boolean) - - // This only checks that matter here are the screen sizes. resizeable and anyDensity - // are not checked. - return mSmallScreens == support.mSmallScreens && - mNormalScreens == support.mNormalScreens && - mLargeScreens == support.mLargeScreens; - } - - /** - * Returns true if the two instances have strictly different screen size support. - * This means that there is no screen size that they both support. - * @param support the other instance to compare to. - * @return true if they are stricly different. - */ - public boolean hasStrictlyDifferentScreenSupportAs(SupportsScreens support) { - // since all the fields are guaranteed to be either Boolean.TRUE or Boolean.FALSE - // (or null), we can simply check they are identical and not bother with - // calling equals (which would require to check != null. - // see #getConstanntBoolean(Boolean) - - // This only checks that matter here are the screen sizes. resizeable and anyDensity - // are not checked. - return (mSmallScreens != Boolean.TRUE || support.mSmallScreens != Boolean.TRUE) && - (mNormalScreens != Boolean.TRUE || support.mNormalScreens != Boolean.TRUE) && - (mLargeScreens != Boolean.TRUE || support.mLargeScreens != Boolean.TRUE); - } - - /** - * Comparison of 2 Supports-screens. This only uses screen sizes (ignores resizeable and - * anyDensity), and considers that - * {@link #hasStrictlyDifferentScreenSupportAs(SupportsScreens)} returns true and - * {@link #overlapWith(SupportsScreens)} returns false. - * @throws IllegalArgumentException if the two instanced are not strictly different or - * overlap each other - * @see #hasStrictlyDifferentScreenSupportAs(SupportsScreens) - * @see #overlapWith(SupportsScreens) - */ - public int compareScreenSizesWith(SupportsScreens o) { - if (hasStrictlyDifferentScreenSupportAs(o) == false) { - throw new IllegalArgumentException("The two instances are not strictly different."); - } - if (overlapWith(o)) { - throw new IllegalArgumentException("The two instances overlap each other."); - } - - int comp = mLargeScreens.compareTo(o.mLargeScreens); - if (comp != 0) return comp; - - comp = mNormalScreens.compareTo(o.mNormalScreens); - if (comp != 0) return comp; - - comp = mSmallScreens.compareTo(o.mSmallScreens); - if (comp != 0) return comp; - - return 0; - } - - /** - * Returns a string encoding of the content of the instance. This string can be used to - * instantiate a {@link SupportsScreens} object through - * {@link #SupportsScreens(String)}. - */ - public String getEncodedValues() { - return String.format("%1$s|%2$s|%3$s|%4$s|%5$s", - mAnyDensity, mResizeable, mSmallScreens, mNormalScreens, mLargeScreens); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - boolean alreadyOutputSomething = false; - - if (Boolean.TRUE.equals(mSmallScreens)) { - alreadyOutputSomething = true; - sb.append("small"); - } - - if (Boolean.TRUE.equals(mNormalScreens)) { - if (alreadyOutputSomething) { - sb.append(", "); - } - alreadyOutputSomething = true; - sb.append("normal"); - } - - if (Boolean.TRUE.equals(mLargeScreens)) { - if (alreadyOutputSomething) { - sb.append(", "); - } - alreadyOutputSomething = true; - sb.append("large"); - } - - if (alreadyOutputSomething == false) { - sb.append("<none>"); - } - - return sb.toString(); - } - - /** - * Returns true if the two instance overlap with each other. - * This can happen if one instances supports a size, when the other instance doesn't while - * supporting a size above and a size below. - * @param otherSS the other supports-screens to compare to. - */ - public boolean overlapWith(SupportsScreens otherSS) { - if (mSmallScreens == null || mNormalScreens == null || mLargeScreens == null || - otherSS.mSmallScreens == null || otherSS.mNormalScreens == null || - otherSS.mLargeScreens == null) { - throw new IllegalArgumentException("Some screen sizes Boolean are not initialized"); - } - - if (mSmallScreens == Boolean.TRUE && mNormalScreens == Boolean.FALSE && - mLargeScreens == Boolean.TRUE) { - return otherSS.mNormalScreens == Boolean.TRUE; - } - - if (otherSS.mSmallScreens == Boolean.TRUE && otherSS.mNormalScreens == Boolean.FALSE && - otherSS.mLargeScreens == Boolean.TRUE) { - return mNormalScreens == Boolean.TRUE; - } - - return false; - } - } - - /** - * Class representing a <code>uses-library</code> node in the manifest. - */ - public final static class UsesLibrary { - String mName; - Boolean mRequired = Boolean.TRUE; // default is true even if missing - - public String getName() { - return mName; - } - - public Boolean getRequired() { - return mRequired; - } - } - - /** - * Class representing a <code>uses-feature</code> node in the manifest. - */ - public final static class UsesFeature { - String mName; - int mGlEsVersion = 0; - Boolean mRequired = Boolean.TRUE; // default is true even if missing - - public String getName() { - return mName; - } - - /** - * Returns the value of the glEsVersion attribute, or 0 if the attribute was not present. - */ - public int getGlEsVersion() { - return mGlEsVersion; - } - - public Boolean getRequired() { - return mRequired; - } - } - - /** - * Class representing the <code>uses-configuration</code> node in the manifest. - */ - public final static class UsesConfiguration { - Boolean mReqFiveWayNav; - Boolean mReqHardKeyboard; - Keyboard mReqKeyboardType; - TouchScreen mReqTouchScreen; - Navigation mReqNavigation; - - /** - * returns the value of the <code>reqFiveWayNav</code> attribute or null if not present. - */ - public Boolean getReqFiveWayNav() { - return mReqFiveWayNav; - } - - /** - * returns the value of the <code>reqNavigation</code> attribute or null if not present. - */ - public Navigation getReqNavigation() { - return mReqNavigation; - } - - /** - * returns the value of the <code>reqHardKeyboard</code> attribute or null if not present. - */ - public Boolean getReqHardKeyboard() { - return mReqHardKeyboard; - } - - /** - * returns the value of the <code>reqKeyboardType</code> attribute or null if not present. - */ - public Keyboard getReqKeyboardType() { - return mReqKeyboardType; - } - - /** - * returns the value of the <code>reqTouchScreen</code> attribute or null if not present. - */ - public TouchScreen getReqTouchScreen() { - return mReqTouchScreen; - } - } - - /** - * Returns the package defined in the manifest, if found. - * @return The package name or null if not found. - */ - public String getPackage() { - return mPackage; - } - - /** - * Returns the versionCode value defined in the manifest, if found, null otherwise. - * @return the versionCode or null if not found. - */ - public Integer getVersionCode() { - return mVersionCode; - } - - /** - * Returns the list of activities found in the manifest. - * @return An array of fully qualified class names, or empty if no activity were found. - */ - public Activity[] getActivities() { - return mActivities.toArray(new Activity[mActivities.size()]); - } - - /** - * Returns the name of one activity found in the manifest, that is configured to show - * up in the HOME screen. - * @return the fully qualified name of a HOME activity or null if none were found. - */ - public Activity getLauncherActivity() { - return mLauncherActivity; - } - - /** - * Returns the list of process names declared by the manifest. - */ - public String[] getProcesses() { - if (mProcesses != null) { - return mProcesses.toArray(new String[mProcesses.size()]); - } - - return new String[0]; - } - - /** - * Returns the <code>debuggable</code> attribute value or null if it is not set. - */ - public Boolean getDebuggable() { - return mDebuggable; - } - - /** - * Returns the <code>minSdkVersion</code> attribute, or null if it's not set. - */ - public String getMinSdkVersionString() { - return mMinSdkVersionString; - } - - /** - * Sets the value of the <code>minSdkVersion</code> attribute. - * @param minSdkVersion the string value of the attribute in the manifest. - */ - public void setMinSdkVersionString(String minSdkVersion) { - mMinSdkVersionString = minSdkVersion; - if (mMinSdkVersionString != null) { - try { - mMinSdkVersion = Integer.parseInt(mMinSdkVersionString); - } catch (NumberFormatException e) { - mMinSdkVersion = MIN_SDK_CODENAME; - } - } - } - - /** - * Returns the <code>minSdkVersion</code> attribute, or 0 if it's not set or is a codename. - * @see #getMinSdkVersionString() - */ - public int getMinSdkVersion() { - return mMinSdkVersion; - } - - - /** - * Sets the value of the <code>minSdkVersion</code> attribute. - * @param targetSdkVersion the string value of the attribute in the manifest. - */ - public void setTargetSdkVersionString(String targetSdkVersion) { - if (targetSdkVersion != null) { - try { - mTargetSdkVersion = Integer.parseInt(targetSdkVersion); - } catch (NumberFormatException e) { - // keep the value at 0. - } - } - } - - /** - * Returns the <code>targetSdkVersion</code> attribute, or the same value as - * {@link #getMinSdkVersion()} if it was not set in the manifest. - */ - public int getTargetSdkVersion() { - if (mTargetSdkVersion == 0) { - return getMinSdkVersion(); - } - - return mTargetSdkVersion; - } - - /** - * Returns the list of instrumentations found in the manifest. - * @return An array of {@link Instrumentation}, or empty if no instrumentations were - * found. - */ - public Instrumentation[] getInstrumentations() { - return mInstrumentations.toArray(new Instrumentation[mInstrumentations.size()]); - } - - /** - * Returns the list of libraries in use found in the manifest. - * @return An array of {@link UsesLibrary} objects, or empty if no libraries were found. - */ - public UsesLibrary[] getUsesLibraries() { - return mLibraries.toArray(new UsesLibrary[mLibraries.size()]); - } - - /** - * Returns the list of features in use found in the manifest. - * @return An array of {@link UsesFeature} objects, or empty if no libraries were found. - */ - public UsesFeature[] getUsesFeatures() { - return mFeatures.toArray(new UsesFeature[mFeatures.size()]); - } - - /** - * Returns the glEsVersion from a <uses-feature> or {@link #GL_ES_VERSION_NOT_SET} if not set. - */ - public int getGlEsVersion() { - for (UsesFeature feature : mFeatures) { - if (feature.mGlEsVersion > 0) { - return feature.mGlEsVersion; - } - } - return GL_ES_VERSION_NOT_SET; - } - - /** - * Returns the {@link SupportsScreens} object representing the <code>supports-screens</code> - * node, or null if the node doesn't exist at all. - * Some values in the {@link SupportsScreens} instance maybe null, indicating that they - * were not present in the manifest. To get an instance that contains the values, as seen - * by the Android platform when the app is running, use {@link #getSupportsScreensValues()}. - */ - public SupportsScreens getSupportsScreensFromManifest() { - return mSupportsScreensFromManifest; - } - - /** - * Returns an always non-null instance of {@link SupportsScreens} that's been initialized with - * the default values, and the values from the manifest. - * The default values depends on the manifest values for minSdkVersion and targetSdkVersion. - */ - public synchronized SupportsScreens getSupportsScreensValues() { - if (mSupportsScreensValues == null) { - if (mSupportsScreensFromManifest == null) { - mSupportsScreensValues = SupportsScreens.getDefaultValues(getTargetSdkVersion()); - } else { - // get a SupportsScreen that replace the missing values with default values. - mSupportsScreensValues = mSupportsScreensFromManifest.resolveSupportsScreensValues( - getTargetSdkVersion()); - } - } - - return mSupportsScreensValues; - } - - /** - * Returns the {@link UsesConfiguration} object representing the <code>uses-configuration</code> - * node, or null if the node doesn't exist at all. - */ - public UsesConfiguration getUsesConfiguration() { - return mUsesConfiguration; - } - - void addProcessName(String processName) { - if (mProcesses == null) { - mProcesses = new TreeSet<String>(); - } - - if (processName.startsWith(":")) { - mProcesses.add(mPackage + processName); - } else { - mProcesses.add(processName); - } - } - -} |