aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java
diff options
context:
space:
mode:
authorGravatar Andrew Pellegrini <apell@google.com>2017-03-13 18:02:16 +0000
committerGravatar Yun Peng <pcloudy@google.com>2017-03-14 08:53:14 +0000
commit82122525effd106e551503f70050bac18d0f85cb (patch)
tree878a3e8f44945f292e450e19f075f61e70c737eb /src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java
parent3a26d6924bf3a6e35d3718eb498def3693155ac6 (diff)
Add <resources> attribute processing to the Android resource processing toolchain.
-- PiperOrigin-RevId: 149963021 MOS_MIGRATED_REVID=149963021
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java295
1 files changed, 239 insertions, 56 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java b/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java
index 5ae3e2cc07..836239d6be 100644
--- a/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java
+++ b/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java
@@ -13,6 +13,8 @@
// limitations under the License.
package com.google.devtools.build.android;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.android.ide.common.resources.configuration.FolderConfiguration;
import com.android.ide.common.resources.configuration.ResourceQualifier;
import com.android.resources.ResourceType;
@@ -46,6 +48,158 @@ import javax.annotation.concurrent.Immutable;
*/
@Immutable
public class FullyQualifiedName implements DataKey {
+ /** Represents the type of a {@link FullyQualifiedName}. */
+ public interface Type {
+ /**
+ * The category of type that a {@link Type} can be.
+ *
+ * <p>
+ * <em>Note:</em> used for strict ordering of {@link FullyQualifiedName}s.
+ */
+ public enum ConcreteType {
+ RESOURCE_TYPE,
+ VIRTUAL_TYPE;
+ }
+
+ public String getName();
+ public ConcreteType getType();
+ public boolean isOverwritable();
+ public int compareTo(Type other);
+ @Override public boolean equals(Object obj);
+ @Override public int hashCode();
+ @Override public String toString();
+ }
+
+ private static Type createTypeFrom(String rawType) {
+ ResourceType resourceType = ResourceType.getEnum(rawType);
+ VirtualType virtualType = VirtualType.getEnum(rawType);
+ if (resourceType != null) {
+ return new ResourceTypeWrapper(resourceType);
+ } else if (virtualType != null) {
+ return virtualType;
+ }
+ return null;
+ }
+
+ private static class ResourceTypeWrapper implements Type {
+ private final ResourceType resourceType;
+
+ public ResourceTypeWrapper(ResourceType resourceType) {
+ this.resourceType = resourceType;
+ }
+
+ @Override
+ public String getName() {
+ return resourceType.getName();
+ }
+
+ @Override
+ public ConcreteType getType() {
+ return ConcreteType.RESOURCE_TYPE;
+ }
+
+ @Override
+ public boolean isOverwritable() {
+ return !(resourceType == ResourceType.ID
+ || resourceType == ResourceType.PUBLIC
+ || resourceType == ResourceType.STYLEABLE);
+ }
+
+ @Override
+ public int compareTo(Type other) {
+ if (!(other instanceof ResourceTypeWrapper)) {
+ return getType().compareTo(other.getType());
+ }
+ return resourceType.compareTo(((ResourceTypeWrapper) other).resourceType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ResourceTypeWrapper)) {
+ return false;
+ }
+ ResourceTypeWrapper other = (ResourceTypeWrapper) obj;
+ return Objects.equals(resourceType, other.resourceType);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(resourceType);
+ }
+
+ @Override
+ public String toString() {
+ return resourceType.toString();
+ }
+ }
+
+ /** The non-resource {@link Type}s of a {@link FullyQualifiedName}. */
+ public enum VirtualType implements Type {
+ RESOURCES_ATTRIBUTE("<resources>", "Resources Attribute");
+
+ /** Returns the enum represented by the {@code name}. */
+ public static VirtualType getEnum(String name) {
+ for (VirtualType type : values()) {
+ if (type.name.equals(name)) {
+ return type;
+ }
+ }
+ return null;
+ }
+
+ /** Returns an array with all the names defined by this enum. */
+ public static String[] getNames() {
+ VirtualType[] values = values();
+ String[] names = new String[values.length];
+ for (int i = values.length - 1; i >= 0; --i) {
+ names[i] = values[i].getName();
+ }
+ return names;
+ }
+
+ private final String name;
+ private final String displayName;
+
+ private VirtualType(String name, String displayName) {
+ this.name = name;
+ this.displayName = displayName;
+ }
+
+ /** Returns the resource type name. */
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /** Returns a translated display name for the resource type. */
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ @Override
+ public ConcreteType getType() {
+ return ConcreteType.VIRTUAL_TYPE;
+ }
+
+ @Override
+ public boolean isOverwritable() {
+ return true;
+ }
+
+ @Override
+ public int compareTo(Type other) {
+ if (!(other instanceof VirtualType)) {
+ return getType().compareTo(other.getType());
+ }
+ return compareTo(((VirtualType) other));
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+ }
+
public static final String DEFAULT_PACKAGE = "res-auto";
private static final Joiner DASH_JOINER = Joiner.on('-');
@@ -65,13 +219,19 @@ public class FullyQualifiedName implements DataKey {
public static final String INVALID_QUALIFIED_NAME_MESSAGE_NO_MATCH =
String.format(
"%%s is not a valid qualified name. "
- + "It should be in the pattern [package:]{%s}/resourcename",
- Joiner.on(",").join(ResourceType.values()));
+ + "It should be in the pattern [package:]{%s}/name",
+ Joiner.on(",").join(ImmutableList.<String>builder()
+ .add(ResourceType.getNames())
+ .add(VirtualType.getNames())
+ .build()));
public static final String INVALID_QUALIFIED_NAME_MESSAGE_NO_TYPE_OR_NAME =
String.format(
"Could not find either resource type (%%s) or name (%%s) in %%s. "
- + "It should be in the pattern [package:]{%s}/resourcename",
- Joiner.on(",").join(ResourceType.values()));
+ + "It should be in the pattern [package:]{%s}/name",
+ Joiner.on(",").join(ImmutableList.<String>builder()
+ .add(ResourceType.getNames())
+ .add(VirtualType.getNames())
+ .build()));
public static final String INVALID_QUALIFIERS = "%s contains invalid qualifiers.";
private final ImmutableList<String> qualifiers;
private final String pkg;
@@ -157,12 +317,16 @@ public class FullyQualifiedName implements DataKey {
return from(ImmutableList.copyOf(qualifiers), DEFAULT_PACKAGE);
}
- public FullyQualifiedName create(ResourceType resourceType, String resourceName) {
- return create(resourceType, resourceName, pkg);
+ public FullyQualifiedName create(Type type, String name, String pkg) {
+ return FullyQualifiedName.of(pkg, qualifiers, type, name);
+ }
+
+ public FullyQualifiedName create(ResourceType type, String name) {
+ return create(new ResourceTypeWrapper(type), name, pkg);
}
- public FullyQualifiedName create(ResourceType resourceType, String resourceName, String pkg) {
- return FullyQualifiedName.of(pkg, qualifiers, resourceType, resourceName);
+ public FullyQualifiedName create(VirtualType type, String name) {
+ return create(type, name, pkg);
}
/**
@@ -179,16 +343,16 @@ public class FullyQualifiedName implements DataKey {
String.format(INVALID_QUALIFIED_NAME_MESSAGE_NO_MATCH, raw));
}
String parsedPackage = matcher.group("package");
- ResourceType resourceType = ResourceType.getEnum(matcher.group("type"));
- String resourceName = matcher.group("name");
+ Type type = createTypeFrom(matcher.group("type"));
+ String name = matcher.group("name");
- if (resourceType == null || resourceName == null) {
+ if (type == null || name == null) {
throw new IllegalArgumentException(
String.format(
- INVALID_QUALIFIED_NAME_MESSAGE_NO_TYPE_OR_NAME, resourceType, resourceName, raw));
+ INVALID_QUALIFIED_NAME_MESSAGE_NO_TYPE_OR_NAME, type, name, raw));
}
return FullyQualifiedName.of(
- parsedPackage == null ? pkg : parsedPackage, qualifiers, resourceType, resourceName);
+ parsedPackage == null ? pkg : parsedPackage, qualifiers, type, name);
}
/**
@@ -230,44 +394,56 @@ public class FullyQualifiedName implements DataKey {
}
}
- public static boolean isOverwritable(FullyQualifiedName name) {
- return !(name.resourceType == ResourceType.ID
- || name.resourceType == ResourceType.PUBLIC
- || name.resourceType == ResourceType.STYLEABLE);
- }
-
/**
* Creates a new FullyQualifiedName with normalized qualifiers.
*
* @param pkg The resource package of the name. If unknown the default should be "res-auto"
* @param qualifiers The resource qualifiers of the name, such as "en" or "xhdpi".
- * @param resourceType The resource type of the name.
- * @param resourceName The resource name of the name.
+ * @param type The type of the name.
+ * @param name The name of the name.
* @return A new FullyQualifiedName.
*/
public static FullyQualifiedName of(
- String pkg, List<String> qualifiers, ResourceType resourceType, String resourceName) {
+ String pkg, List<String> qualifiers, Type type, String name) {
+ checkNotNull(pkg);
+ checkNotNull(qualifiers);
+ checkNotNull(type);
+ checkNotNull(name);
ImmutableList<String> immutableQualifiers = ImmutableList.copyOf(qualifiers);
// TODO(corysmith): Address the GC thrash this creates by managing a simplified, mutable key to
// do the instance check.
- FullyQualifiedName name =
- new FullyQualifiedName(pkg, immutableQualifiers, resourceType, resourceName);
+ FullyQualifiedName fqn =
+ new FullyQualifiedName(pkg, immutableQualifiers, type, name);
// Use putIfAbsent to get the canonical instance, if there. If it isn't, putIfAbsent will
// return null, and we should return the current instance.
- FullyQualifiedName cached = instanceCache.putIfAbsent(name, name);
+ FullyQualifiedName cached = instanceCache.putIfAbsent(fqn, fqn);
if (cached == null) {
- return name;
+ return fqn;
} else {
cacheHit.incrementAndGet();
return cached;
}
}
+ /**
+ * Creates a new FullyQualifiedName with normalized qualifiers.
+ *
+ * @param pkg The resource package of the name. If unknown the default should be "res-auto"
+ * @param qualifiers The resource qualifiers of the name, such as "en" or "xhdpi".
+ * @param type The resource type of the name.
+ * @param name The name of the name.
+ * @return A new FullyQualifiedName.
+ */
+ static FullyQualifiedName of(
+ String pkg, List<String> qualifiers, ResourceType type, String name) {
+ return of(pkg, qualifiers, new ResourceTypeWrapper(type), name);
+ }
+
public static FullyQualifiedName fromProto(SerializeFormat.DataKey protoKey) {
return of(
protoKey.getKeyPackage(),
protoKey.getQualifiersList(),
- ResourceType.valueOf(protoKey.getResourceType()),
+ createTypeFrom(protoKey.getResourceType()),
protoKey.getKeyValue());
}
@@ -281,8 +457,19 @@ public class FullyQualifiedName implements DataKey {
private final String pkg;
private final ImmutableList<String> qualifiers;
- private final ResourceType resourceType;
- private final String resourceName;
+ private final Type type;
+ private final String name;
+
+ private FullyQualifiedName(
+ String pkg,
+ ImmutableList<String> qualifiers,
+ Type type,
+ String name) {
+ this.pkg = pkg;
+ this.qualifiers = qualifiers;
+ this.type = type;
+ this.name = name;
+ }
/**
* Returns a string path representation of the FullyQualifiedName.
@@ -298,10 +485,10 @@ public class FullyQualifiedName implements DataKey {
return Paths.get(
DASH_JOINER.join(
ImmutableList.<String>builder()
- .add(resourceType.getName())
+ .add(type.getName())
.addAll(qualifiers)
.build()),
- resourceName + sourceExtension)
+ name + sourceExtension)
.toString();
}
@@ -311,8 +498,8 @@ public class FullyQualifiedName implements DataKey {
return String.format(
"%s/%s",
DASH_JOINER.join(
- ImmutableList.<String>builder().add(resourceType.getName()).addAll(qualifiers).build()),
- resourceName);
+ ImmutableList.<String>builder().add(type.getName()).addAll(qualifiers).build()),
+ name);
}
/**
@@ -333,22 +520,18 @@ public class FullyQualifiedName implements DataKey {
}
public String name() {
- return resourceName;
+ return name;
}
public ResourceType type() {
- return resourceType;
+ if (type instanceof ResourceTypeWrapper) {
+ return ((ResourceTypeWrapper) type).resourceType;
+ }
+ return null;
}
- private FullyQualifiedName(
- String pkg,
- ImmutableList<String> qualifiers,
- ResourceType resourceType,
- String resourceName) {
- this.pkg = pkg;
- this.qualifiers = qualifiers;
- this.resourceType = resourceType;
- this.resourceName = resourceName;
+ public boolean isOverwritable() {
+ return type.isOverwritable();
}
/** Creates a FullyQualifiedName from this one with a different package. */
@@ -357,12 +540,12 @@ public class FullyQualifiedName implements DataKey {
if (pkg.equals(newPackage)) {
return this;
}
- return of(newPackage, qualifiers, resourceType, resourceName);
+ return of(newPackage, qualifiers, type, name);
}
@Override
public int hashCode() {
- return Objects.hash(pkg, qualifiers, resourceType, resourceName);
+ return Objects.hash(pkg, qualifiers, type, name);
}
@Override
@@ -372,8 +555,8 @@ public class FullyQualifiedName implements DataKey {
}
FullyQualifiedName other = getClass().cast(obj);
return Objects.equals(pkg, other.pkg)
- && Objects.equals(resourceType, other.resourceType)
- && Objects.equals(resourceName, other.resourceName)
+ && Objects.equals(type, other.type)
+ && Objects.equals(name, other.name)
&& Objects.equals(qualifiers, other.qualifiers);
}
@@ -382,8 +565,8 @@ public class FullyQualifiedName implements DataKey {
return MoreObjects.toStringHelper(getClass())
.add("pkg", pkg)
.add("qualifiers", qualifiers)
- .add("resourceType", resourceType)
- .add("resourceName", resourceName)
+ .add("type", type)
+ .add("name", name)
.toString();
}
@@ -396,11 +579,11 @@ public class FullyQualifiedName implements DataKey {
if (!pkg.equals(other.pkg)) {
return pkg.compareTo(other.pkg);
}
- if (!resourceType.equals(other.resourceType)) {
- return resourceType.compareTo(other.resourceType);
+ if (!type.equals(other.type)) {
+ return type.compareTo(other.type);
}
- if (!resourceName.equals(other.resourceName)) {
- return resourceName.compareTo(other.resourceName);
+ if (!name.equals(other.name)) {
+ return name.compareTo(other.name);
}
if (!qualifiers.equals(other.qualifiers)) {
if (qualifiers.size() != other.qualifiers.size()) {
@@ -425,8 +608,8 @@ public class FullyQualifiedName implements DataKey {
public SerializeFormat.DataKey.Builder toSerializedBuilder() {
return SerializeFormat.DataKey.newBuilder()
.setKeyPackage(pkg)
- .setResourceType(resourceType.getName().toUpperCase())
+ .setResourceType(type.getName())
.addAllQualifiers(qualifiers)
- .setKeyValue(resourceName);
+ .setKeyValue(name);
}
}