1953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll/* 2953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * Copyright (C) 2008 The Android Open Source Project 3953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * 4953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * you may not use this file except in compliance with the License. 6953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * You may obtain a copy of the License at 7953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * 8953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * http://www.eclipse.org/org/documents/epl-v10.php 9953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * 10953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * Unless required by applicable law or agreed to in writing, software 11953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * distributed under the License is distributed on an "AS IS" BASIS, 12953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * See the License for the specific language governing permissions and 14953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * limitations under the License. 15953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll */ 16953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 17f85ad3e3e3f3686d0bdaa3177ed10348cf72375eRaphael Mollpackage com.android.ide.common.resources.platform; 18953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 19f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.SdkConstants.ANDROID_PREFIX; 20f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.SdkConstants.ANDROID_THEME_PREFIX; 21f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.SdkConstants.ID_PREFIX; 22f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.SdkConstants.NEW_ID_PREFIX; 235a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbyeimport static com.android.SdkConstants.PREFIX_THEME_REF; 24f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.SdkConstants.VALUE_FALSE; 25f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.SdkConstants.VALUE_TRUE; 26f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.BOOLEAN; 27f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.COLOR; 28f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.DIMENSION; 29f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.ENUM; 30f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.FLAG; 31f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.FLOAT; 32f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.FRACTION; 33f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.INTEGER; 34f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport static com.android.ide.common.api.IAttributeInfo.Format.STRING; 35f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 3661684adfd7345f1a0df24bcf9176e6f528295bbbTor Norbyeimport com.android.annotations.NonNull; 37f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.android.annotations.Nullable; 382be70bde5a6dcd6447c32ef55866020be372f96cTor Norbyeimport com.android.ide.common.api.IAttributeInfo; 39f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.android.ide.common.resources.ResourceRepository; 40f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.android.resources.ResourceType; 41f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport com.google.common.base.Splitter; 42953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 4361684adfd7345f1a0df24bcf9176e6f528295bbbTor Norbyeimport java.util.EnumSet; 44f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbyeimport java.util.regex.Pattern; 4561684adfd7345f1a0df24bcf9176e6f528295bbbTor Norbye 46953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 47953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll/** 48953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * Information about an attribute as gathered from the attrs.xml file where 49953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * the attribute was declared. This must include a format (string, reference, float, etc.), 50953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * possible flag or enum values, whether it's deprecated and its javadoc. 51953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll */ 52953aeea61efb31402198b969478d1bda5dcbe613Raphael Mollpublic class AttributeInfo implements IAttributeInfo { 53953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** XML Name of the attribute */ 54953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll private String mName; 55953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 56953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Formats of the attribute. Cannot be null. Should have at least one format. */ 5761684adfd7345f1a0df24bcf9176e6f528295bbbTor Norbye private EnumSet<Format> mFormats; 58953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Values for enum. null for other types. */ 59953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll private String[] mEnumValues; 60953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Values for flag. null for other types. */ 61953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll private String[] mFlagValues; 62953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Short javadoc (i.e. the first sentence). */ 63953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll private String mJavaDoc; 64953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Documentation for deprecated attributes. Null if not deprecated. */ 65953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll private String mDeprecatedDoc; 66e287bc8580e19d72a911615475b353790cf000ebTor Norbye /** The source class defining this attribute */ 67e287bc8580e19d72a911615475b353790cf000ebTor Norbye private String mDefinedBy; 68953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 69953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** 70953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * @param name The XML Name of the attribute 71953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * @param formats The formats of the attribute. Cannot be null. 72953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * Should have at least one format. 73953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll */ 7461684adfd7345f1a0df24bcf9176e6f528295bbbTor Norbye public AttributeInfo(@NonNull String name, @NonNull EnumSet<Format> formats) { 75953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mName = name; 76953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mFormats = formats; 77953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 78953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 79953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** 80953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * @param name The XML Name of the attribute 81953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * @param formats The formats of the attribute. Cannot be null. 82953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * Should have at least one format. 83953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * @param javadoc Short javadoc (i.e. the first sentence). 84953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll */ 8561684adfd7345f1a0df24bcf9176e6f528295bbbTor Norbye public AttributeInfo(@NonNull String name, @NonNull EnumSet<Format> formats, String javadoc) { 86953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mName = name; 87953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mFormats = formats; 88953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mJavaDoc = javadoc; 89953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 90953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 91953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll public AttributeInfo(AttributeInfo info) { 92953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mName = info.mName; 93953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mFormats = info.mFormats; 94953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mEnumValues = info.mEnumValues; 95953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mFlagValues = info.mFlagValues; 96953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mJavaDoc = info.mJavaDoc; 97953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mDeprecatedDoc = info.mDeprecatedDoc; 98953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 99953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 10057f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye /** 10157f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye * Sets the XML Name of the attribute 10257f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye * 10357f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye * @param name the new name to assign 10457f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye */ 10557f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye public void setName(String name) { 10657f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye mName = name; 10757f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye } 10857f1244facb6c3de1fe8011ab66cdc3dd9ce0b61Tor Norbye 109953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Returns the XML Name of the attribute */ 110ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1117e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull String getName() { 112953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll return mName; 113953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 114953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Returns the formats of the attribute. Cannot be null. 115953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll * Should have at least one format. */ 116ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1177e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull EnumSet<Format> getFormats() { 118953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll return mFormats; 119953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 120953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Returns the values for enums. null for other types. */ 121ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 122953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll public String[] getEnumValues() { 123953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll return mEnumValues; 124953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 125953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Returns the values for flags. null for other types. */ 126ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 127953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll public String[] getFlagValues() { 128953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll return mFlagValues; 129953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 130953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Returns a short javadoc, .i.e. the first sentence. */ 131ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1327e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull String getJavaDoc() { 133953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll return mJavaDoc; 134953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 135953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Returns the documentation for deprecated attributes. Null if not deprecated. */ 136ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 137953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll public String getDeprecatedDoc() { 138953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll return mDeprecatedDoc; 139953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 140953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 141953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Sets the values for enums. null for other types. */ 142953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll public AttributeInfo setEnumValues(String[] values) { 143953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mEnumValues = values; 144953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll return this; 145953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 146953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 147953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Sets the values for flags. null for other types. */ 148953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll public AttributeInfo setFlagValues(String[] values) { 149953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mFlagValues = values; 150953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll return this; 151953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 152953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 153953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Sets a short javadoc, .i.e. the first sentence. */ 154953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll public void setJavaDoc(String javaDoc) { 155953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mJavaDoc = javaDoc; 156953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 157953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll 158953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll /** Sets the documentation for deprecated attributes. Null if not deprecated. */ 159953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll public void setDeprecatedDoc(String deprecatedDoc) { 160953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll mDeprecatedDoc = deprecatedDoc; 161953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll } 162e287bc8580e19d72a911615475b353790cf000ebTor Norbye 163e287bc8580e19d72a911615475b353790cf000ebTor Norbye /** 164e287bc8580e19d72a911615475b353790cf000ebTor Norbye * Sets the name of the class (fully qualified class name) which defined 165e287bc8580e19d72a911615475b353790cf000ebTor Norbye * this attribute 166e287bc8580e19d72a911615475b353790cf000ebTor Norbye * 167e287bc8580e19d72a911615475b353790cf000ebTor Norbye * @param definedBy the name of the class (fully qualified class name) which 168e287bc8580e19d72a911615475b353790cf000ebTor Norbye * defined this attribute 169e287bc8580e19d72a911615475b353790cf000ebTor Norbye */ 170e287bc8580e19d72a911615475b353790cf000ebTor Norbye public void setDefinedBy(String definedBy) { 171e287bc8580e19d72a911615475b353790cf000ebTor Norbye mDefinedBy = definedBy; 172e287bc8580e19d72a911615475b353790cf000ebTor Norbye } 173e287bc8580e19d72a911615475b353790cf000ebTor Norbye 174e287bc8580e19d72a911615475b353790cf000ebTor Norbye /** 175e287bc8580e19d72a911615475b353790cf000ebTor Norbye * Returns the name of the class (fully qualified class name) which defined 176e287bc8580e19d72a911615475b353790cf000ebTor Norbye * this attribute 177e287bc8580e19d72a911615475b353790cf000ebTor Norbye * 178e287bc8580e19d72a911615475b353790cf000ebTor Norbye * @return the name of the class (fully qualified class name) which defined 179e287bc8580e19d72a911615475b353790cf000ebTor Norbye * this attribute 180e287bc8580e19d72a911615475b353790cf000ebTor Norbye */ 181ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1827e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull String getDefinedBy() { 183e287bc8580e19d72a911615475b353790cf000ebTor Norbye return mDefinedBy; 184e287bc8580e19d72a911615475b353790cf000ebTor Norbye } 185f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 186f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye private final static Pattern INTEGER_PATTERN = Pattern.compile("-?[0-9]+"); //$NON-NLS-1$ 187f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye private final static Pattern FLOAT_PATTERN = 188f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye Pattern.compile("-?[0-9]?(\\.[0-9]+)?"); //$NON-NLS-1$ 189f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye private final static Pattern DIMENSION_PATTERN = 190f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye Pattern.compile("-?[0-9]+(\\.[0-9]+)?(dp|dip|sp|px|pt|in|mm)"); //$NON-NLS-1$ 191f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 192f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye /** 193f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * Checks the given value and returns true only if it is a valid XML value 194f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * for this attribute. 195f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * 196f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * @param value the XML value to check 197f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * @param projectResources project resources to validate resource URLs with, 198f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * if any 199f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * @param frameworkResources framework resources to validate resource URLs 200f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * with, if any 201f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye * @return true if the value is valid, false otherwise 202f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye */ 203f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye public boolean isValid( 204f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye @NonNull String value, 205f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye @Nullable ResourceRepository projectResources, 206f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye @Nullable ResourceRepository frameworkResources) { 207f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 208f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (mFormats.contains(STRING) || mFormats.isEmpty()) { 209f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // Anything is allowed 210f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 211f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 212f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 213f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // All other formats require a nonempty string 214f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (value.isEmpty()) { 2155a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye // Except for flags 2165a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye if (mFormats.contains(FLAG)) { 2175a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye return true; 2185a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye } 2195a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye 220f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return false; 221f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 222f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye char first = value.charAt(0); 223f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 224f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // There are many attributes which are incorrectly marked in the attrs.xml 225f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // file, such as "duration", "minHeight", etc. These are marked as only 226f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // accepting "integer", but also appear to accept "reference". Therefore, 227f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // in these cases, be more lenient. (This happens for theme references too, 228f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // such as ?android:attr/listPreferredItemHeight) 229f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if ((first == '@' || first == '?') /* && mFormats.contains(REFERENCE)*/) { 230f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (value.equals("@null")) { 231f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 232f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 233f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 234f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (value.startsWith(NEW_ID_PREFIX) || value.startsWith(ID_PREFIX)) { 235f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // These are handled in the IdGeneratingResourceFile; we shouldn't 236f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // complain about not finding ids in the repository yet since they may 237f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // not yet have been defined (@+id's can be defined in the same layout, 238f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // later on.) 239f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 240f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 241f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 242f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (value.startsWith(ANDROID_PREFIX) || value.startsWith(ANDROID_THEME_PREFIX)) { 243f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (frameworkResources != null) { 244f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return frameworkResources.hasResourceItem(value); 245f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 246f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } else if (projectResources != null) { 247f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return projectResources.hasResourceItem(value); 248f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 249f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 250f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // Validate resource string 251f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye String url = value; 252f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye int typeEnd = url.indexOf('/', 1); 253f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (typeEnd != -1) { 254f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye int typeBegin = url.startsWith("@+") ? 2 : 1; //$NON-NLS-1$ 255f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye int colon = url.lastIndexOf(':', typeEnd); 256f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (colon != -1) { 257f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye typeBegin = colon + 1; 258f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 259f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye String typeName = url.substring(typeBegin, typeEnd); 260f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye ResourceType type = ResourceType.getEnum(typeName); 261f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (type != null) { 262f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // TODO: Validate that the name portion conforms to the rules 263f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // (is an identifier but not a keyword, etc.) 264f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // Also validate that the prefix before the colon is either 265f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // not there or is "android" 266f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 267f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye //int nameBegin = typeEnd + 1; 268f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye //String name = url.substring(nameBegin); 269f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 270f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 2715a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye } else if (value.startsWith(PREFIX_THEME_REF)) { 2725a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye if (projectResources != null) { 2735a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye return projectResources.hasResourceItem(ResourceType.ATTR, 2745a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye value.substring(PREFIX_THEME_REF.length())); 2755a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye } else { 2765a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye // Until proven otherwise 2775a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye return true; 2785a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye } 279f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 280f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 281f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 282f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (mFormats.contains(ENUM) && mEnumValues != null) { 283f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye for (String e : mEnumValues) { 284f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (value.equals(e)) { 285f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 286f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 287f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 288f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 289f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 290f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (mFormats.contains(FLAG) && mFlagValues != null) { 291f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye for (String v : Splitter.on('|').split(value)) { 292f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye for (String e : mFlagValues) { 293f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (v.equals(e)) { 294f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 295f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 296f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 297f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 298f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 299f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 300f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (mFormats.contains(DIMENSION)) { 301f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (DIMENSION_PATTERN.matcher(value).matches()) { 302f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 303f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 304f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 305f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 306f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (mFormats.contains(BOOLEAN)) { 3075a56f60c78b0cff7867d9708fb0033f9f4f53211Tor Norbye if (value.equalsIgnoreCase(VALUE_TRUE) || value.equalsIgnoreCase(VALUE_FALSE)) { 308f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 309f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 310f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 311f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 312f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (mFormats.contains(FLOAT)) { 313f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (Character.isDigit(first) || first == '-' || first == '.') { 314f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (FLOAT_PATTERN.matcher(value).matches()) { 315f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 316f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 317f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // AAPT accepts more general floats, such as ".1", 318f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye try { 319f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye Float.parseFloat(value); 320f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 321f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } catch (NumberFormatException nufe) { 322f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // Not a float 323f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 324f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 325f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 326f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 327f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (mFormats.contains(INTEGER)) { 328f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (Character.isDigit(first) || first == '-') { 329f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (INTEGER_PATTERN.matcher(value).matches()) { 330f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 331f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 332f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 333f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 334f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 335f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (mFormats.contains(COLOR)) { 336f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (first == '#' && value.length() <= 9) { // Only allowed 32 bit ARGB 337f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye try { 338f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // Use Long.parseLong rather than Integer.parseInt to not overflow on 339f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // 32 big hex values like "ff191919" 340f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye Long.parseLong(value.substring(1), 16); 341f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 342f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } catch (NumberFormatException nufe) { 343f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // Not a valid color number 344f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 345f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 346f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 347f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 348f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye if (mFormats.contains(FRACTION)) { 349f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye // should end with % or %p 350f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return true; 351f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 352f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye 353f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye return false; 354f48bde52e60fefec0763cad1b45bc1dcd1bf0841Tor Norbye } 355953aeea61efb31402198b969478d1bda5dcbe613Raphael Moll} 356