aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java242
1 files changed, 242 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
new file mode 100644
index 000000000..5ea1edc0e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2010 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.eclipse.adt.internal.resources;
+
+import static com.android.SdkConstants.DOT_XML;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.common.resources.ResourceItem;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils;
+import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+import com.android.resources.ResourceFolderType;
+import com.android.resources.ResourceType;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jface.dialogs.IInputValidator;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Validator which ensures that new Android resource names are valid.
+ */
+public class ResourceNameValidator implements IInputValidator {
+ /** Set of existing names to check for conflicts with */
+ private Set<String> mExisting;
+
+ /** If true, the validated name must be unique */
+ private boolean mUnique = true;
+
+ /** If true, the validated name must exist */
+ private boolean mExist;
+
+ /**
+ * True if the resource name being considered is a "file" based resource (where the
+ * resource name is the actual file name, rather than just a value attribute inside an
+ * XML file name of arbitrary name
+ */
+ private boolean mIsFileType;
+
+ /**
+ * True if the resource type can point to image resources
+ */
+ private boolean mIsImageType;
+
+ /** If true, allow .xml as a name suffix */
+ private boolean mAllowXmlExtension;
+
+ private ResourceNameValidator(boolean allowXmlExtension, Set<String> existing,
+ boolean isFileType, boolean isImageType) {
+ mAllowXmlExtension = allowXmlExtension;
+ mExisting = existing;
+ mIsFileType = isFileType;
+ mIsImageType = isImageType;
+ }
+
+ /**
+ * Makes the resource name validator require that names are unique.
+ *
+ * @return this, for construction chaining
+ */
+ public ResourceNameValidator unique() {
+ mUnique = true;
+ mExist = false;
+
+ return this;
+ }
+
+ /**
+ * Makes the resource name validator require that names already exist
+ *
+ * @return this, for construction chaining
+ */
+ public ResourceNameValidator exist() {
+ mExist = true;
+ mUnique = false;
+
+ return this;
+ }
+
+ @Override
+ public String isValid(String newText) {
+ // IValidator has the same interface as SWT's IInputValidator
+ try {
+ if (newText == null || newText.trim().length() == 0) {
+ return "Enter a new name";
+ }
+
+ if (mAllowXmlExtension && newText.endsWith(DOT_XML)) {
+ newText = newText.substring(0, newText.length() - DOT_XML.length());
+ }
+
+ if (mAllowXmlExtension && mIsImageType
+ && ImageUtils.hasImageExtension(newText)) {
+ newText = newText.substring(0, newText.lastIndexOf('.'));
+ }
+
+ if (!mIsFileType) {
+ newText = newText.replace('.', '_');
+ }
+
+ if (newText.indexOf('.') != -1 && !newText.endsWith(DOT_XML)) {
+ if (mIsImageType) {
+ return "The filename must end with .xml or .png";
+ } else {
+ return "The filename must end with .xml";
+ }
+ }
+
+ // Resource names must be valid Java identifiers, since they will
+ // be represented as Java identifiers in the R file:
+ if (!Character.isJavaIdentifierStart(newText.charAt(0))) {
+ return "The resource name must begin with a character";
+ }
+ for (int i = 1, n = newText.length(); i < n; i++) {
+ char c = newText.charAt(i);
+ if (!Character.isJavaIdentifierPart(c)) {
+ return String.format("'%1$c' is not a valid resource name character", c);
+ }
+ }
+
+ if (mIsFileType) {
+ char first = newText.charAt(0);
+ if (!(first >= 'a' && first <= 'z')) {
+ return String.format(
+ "File-based resource names must start with a lowercase letter.");
+ }
+
+ // AAPT only allows lowercase+digits+_:
+ // "%s: Invalid file name: must contain only [a-z0-9_.]","
+ for (int i = 0, n = newText.length(); i < n; i++) {
+ char c = newText.charAt(i);
+ if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_')) {
+ return String.format(
+ "File-based resource names must contain only lowercase a-z, 0-9, or _.");
+ }
+ }
+ }
+
+ String level = "1.5"; //$NON-NLS-1$
+ IStatus validIdentifier = JavaConventions.validateIdentifier(newText, level, level);
+ if (!validIdentifier.isOK()) {
+ return String.format("%1$s is not a valid name (reserved Java keyword)", newText);
+ }
+
+
+ if (mExisting != null && (mUnique || mExist)) {
+ boolean exists = mExisting.contains(newText);
+ if (mUnique && exists) {
+ return String.format("%1$s already exists", newText);
+ } else if (mExist && !exists) {
+ return String.format("%1$s does not exist", newText);
+ }
+ }
+
+ return null;
+ } catch (Exception e) {
+ AdtPlugin.log(e, "Validation failed: %s", e.toString());
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Creates a new {@link ResourceNameValidator}
+ *
+ * @param allowXmlExtension if true, allow .xml to be entered as a suffix for the
+ * resource name
+ * @param type the resource type of the resource name being validated
+ * @return a new {@link ResourceNameValidator}
+ */
+ public static ResourceNameValidator create(boolean allowXmlExtension,
+ ResourceFolderType type) {
+ boolean isFileType = type != ResourceFolderType.VALUES;
+ return new ResourceNameValidator(allowXmlExtension, null, isFileType,
+ type == ResourceFolderType.DRAWABLE);
+ }
+
+ /**
+ * Creates a new {@link ResourceNameValidator}
+ *
+ * @param allowXmlExtension if true, allow .xml to be entered as a suffix for the
+ * resource name
+ * @param existing An optional set of names that already exist (and therefore will not
+ * be considered valid if entered as the new name)
+ * @param type the resource type of the resource name being validated
+ * @return a new {@link ResourceNameValidator}
+ */
+ public static ResourceNameValidator create(boolean allowXmlExtension, Set<String> existing,
+ ResourceType type) {
+ boolean isFileType = ResourceHelper.isFileBasedResourceType(type);
+ return new ResourceNameValidator(allowXmlExtension, existing, isFileType,
+ type == ResourceType.DRAWABLE).unique();
+ }
+
+ /**
+ * Creates a new {@link ResourceNameValidator}. By default, the name will need to be
+ * unique in the project.
+ *
+ * @param allowXmlExtension if true, allow .xml to be entered as a suffix for the
+ * resource name
+ * @param project the project to validate new resource names for
+ * @param type the resource type of the resource name being validated
+ * @return a new {@link ResourceNameValidator}
+ */
+ public static ResourceNameValidator create(boolean allowXmlExtension,
+ @Nullable IProject project,
+ @NonNull ResourceType type) {
+ Set<String> existing = null;
+ if (project != null) {
+ existing = new HashSet<String>();
+ ResourceManager manager = ResourceManager.getInstance();
+ ProjectResources projectResources = manager.getProjectResources(project);
+ Collection<ResourceItem> items = projectResources.getResourceItemsOfType(type);
+ for (ResourceItem item : items) {
+ existing.add(item.getName());
+ }
+ }
+
+ boolean isFileType = ResourceHelper.isFileBasedResourceType(type);
+ return new ResourceNameValidator(allowXmlExtension, existing, isFileType,
+ type == ResourceType.DRAWABLE);
+ }
+}