aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com/google/devtools/build/android/xml
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2016-04-05 17:52:42 +0000
committerGravatar Lukacs Berki <lberki@google.com>2016-04-07 11:40:01 +0000
commit0f86dc815c46f5bde00e42fc875ed0502a1fac44 (patch)
tree54661f592792a5c35f6e7b5ec0134f995dcaebf4 /src/tools/android/java/com/google/devtools/build/android/xml
parentc0b4e2c5cc15c749afba7a238d6337c7c4d66004 (diff)
4.25 of 5: Writing of UnwrittenMergedAndroidData
Introduces the AndroidDataWriter and AndroidDataWritingVisitor to abstract the io operations from the data classes. Necessary refactoring to the stubbed write method on DataValue in DataAsset.writeAsset and DataResource.writeResource. New interface for the AttributeValues to reflect the simplifications of writing Resource Attributes. Of special note is the fact all xml is written into a single file, values.xml. This is following the Gradle convention and aapt has demonstrated a preference of only reading a values.xml and ignoring all other xml files in the values directory. Unless profiling demonstrates an advantage to writing multiple files (which I doubt), this merger carries on this convention. -- MOS_MIGRATED_REVID=119066611
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/xml')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/ArrayXmlResourceValue.java49
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/AttrXmlResourceValue.java258
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/IdXmlResourceValue.java17
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/PluralXmlResourceValue.java42
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/SimpleXmlResourceValue.java25
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/StyleXmlResourceValue.java41
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/StyleableXmlResourceValue.java40
7 files changed, 316 insertions, 156 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/xml/ArrayXmlResourceValue.java b/src/tools/android/java/com/google/devtools/build/android/xml/ArrayXmlResourceValue.java
index 752e803c3e..329ae85405 100644
--- a/src/tools/android/java/com/google/devtools/build/android/xml/ArrayXmlResourceValue.java
+++ b/src/tools/android/java/com/google/devtools/build/android/xml/ArrayXmlResourceValue.java
@@ -14,17 +14,23 @@
package com.google.devtools.build.android.xml;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.android.AndroidDataWritingVisitor;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
import com.google.devtools.build.android.XmlResourceValues;
-import java.io.Writer;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
@@ -40,20 +46,33 @@ import javax.xml.stream.events.XMLEvent;
* .html#TypedArray) which which are indicated by a &lt;array&gt; tag.</li>
* <li>Integer array (http://developer.android.com/guide/topics/resources/more-resources
* .html#IntegerArray) which are indicated by &lt;integer-array&gt; tag.</li>
+ * <li>String array (http://developer.android.com/guide/topics/resources/string-resource
+ * .html#StringArray) which are indicated by &lt;string-array&gt; tag.</li>
* </ul>
*
* Both of these are accessed by R.array.&lt;name&gt; in java.
*/
+@Immutable
public class ArrayXmlResourceValue implements XmlResourceValue {
private static final QName TAG_INTEGER_ARRAY = QName.valueOf("integer-array");
private static final QName TAG_ARRAY = QName.valueOf("array");
+ private static final QName TAG_STRING_ARRAY = QName.valueOf("string-array");
+ private static final Function<String, String> ITEM_TO_XML =
+ new Function<String, String>() {
+ @Nullable
+ @Override
+ public String apply(@Nullable String item) {
+ return String.format("<item>%s</item>", item);
+ }
+ };
/**
* Enumerates the different types of array tags.
*/
public enum ArrayType {
INTEGER_ARRAY(TAG_INTEGER_ARRAY),
- ARRAY(TAG_ARRAY);
+ ARRAY(TAG_ARRAY),
+ STRING_ARRAY(TAG_STRING_ARRAY);
public QName tagName;
@@ -71,12 +90,20 @@ public class ArrayXmlResourceValue implements XmlResourceValue {
throw new IllegalArgumentException(
String.format("%s not found in %s", tagQName, Arrays.toString(values())));
}
+
+ String openTag(FullyQualifiedName key) {
+ return String.format("<%s name='%s'>", tagName.getLocalPart(), key.name());
+ }
+
+ String closeTag() {
+ return String.format("</%s>", tagName.getLocalPart());
+ }
}
- private final List<String> values;
- private ArrayType arrayType;
+ private final ImmutableList<String> values;
+ private final ArrayType arrayType;
- private ArrayXmlResourceValue(ArrayType arrayType, List<String> values) {
+ private ArrayXmlResourceValue(ArrayType arrayType, ImmutableList<String> values) {
this.arrayType = arrayType;
this.values = values;
}
@@ -87,13 +114,17 @@ public class ArrayXmlResourceValue implements XmlResourceValue {
}
public static XmlResourceValue of(ArrayType arrayType, List<String> values) {
- return new ArrayXmlResourceValue(arrayType, values);
+ return new ArrayXmlResourceValue(arrayType, ImmutableList.copyOf(values));
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement writing xml.
- throw new UnsupportedOperationException();
+ public void write(
+ FullyQualifiedName key, Path source, AndroidDataWritingVisitor mergedDataWriter) {
+ mergedDataWriter.writeToValuesXml(
+ key,
+ FluentIterable.of(String.format("<!-- %s -->", source), arrayType.openTag(key))
+ .append(FluentIterable.from(values).transform(ITEM_TO_XML))
+ .append(arrayType.closeTag()));
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/xml/AttrXmlResourceValue.java b/src/tools/android/java/com/google/devtools/build/android/xml/AttrXmlResourceValue.java
index 52f44dbc6e..61dfdefd6a 100644
--- a/src/tools/android/java/com/google/devtools/build/android/xml/AttrXmlResourceValue.java
+++ b/src/tools/android/java/com/google/devtools/build/android/xml/AttrXmlResourceValue.java
@@ -14,24 +14,32 @@
package com.google.devtools.build.android.xml;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.Ordering;
+import com.google.devtools.build.android.AndroidDataWritingVisitor;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
import com.google.devtools.build.android.XmlResourceValues;
-import java.io.Writer;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
+import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
@@ -55,9 +63,10 @@ import javax.xml.stream.events.XMLEvent;
* each layout attribute *must* have a corresponding attribute which will be used to validate the
* value/resource reference defined in it.
*
- * <p>AttrXmlValue, due to the mutiple types of attributes is actually a composite class that
- * contains multiple XmlValue instances for each resource.
+ * <p>AttrXmlValue, due to the multiple types of attributes is actually a composite class that
+ * contains multiple {@link XmlResourceValue} instances for each resource.
*/
+@Immutable
public class AttrXmlResourceValue implements XmlResourceValue {
private static final String FRACTION = "fraction";
@@ -72,19 +81,19 @@ public class AttrXmlResourceValue implements XmlResourceValue {
private static final String FLAG = "flag";
private static final QName TAG_ENUM = QName.valueOf(ENUM);
private static final QName TAG_FLAG = QName.valueOf(FLAG);
- private final Map<String, XmlResourceValue> formats;
+ private final ImmutableMap<String, ResourceXmlAttrValue> formats;
- private AttrXmlResourceValue(Map<String, XmlResourceValue> formats) {
+ private AttrXmlResourceValue(ImmutableMap<String, ResourceXmlAttrValue> formats) {
this.formats = formats;
}
private static Map<String, String> readSubValues(XMLEventReader reader, QName subTagType)
throws XMLStreamException {
- Map<String, String> enumValue = new HashMap<>();
+ Builder<String, String> builder = ImmutableMap.builder();
while (reader.hasNext()
&& XmlResourceValues.isTag(XmlResourceValues.peekNextTag(reader), subTagType)) {
StartElement element = reader.nextEvent().asStartElement();
- enumValue.put(
+ builder.put(
XmlResourceValues.getElementName(element), XmlResourceValues.getElementValue(element));
XMLEvent endTag = reader.nextEvent();
if (!XmlResourceValues.isEndTag(endTag, subTagType)) {
@@ -92,7 +101,7 @@ public class AttrXmlResourceValue implements XmlResourceValue {
String.format("Unexpected [%s]; Expected %s", endTag, "</enum>"), endTag.getLocation());
}
}
- return enumValue;
+ return builder.build();
}
private static void endAttrElement(XMLEventReader reader) throws XMLStreamException {
@@ -103,11 +112,11 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@VisibleForTesting
- private static final class BuilderEntry implements Map.Entry<String, XmlResourceValue> {
+ private static final class BuilderEntry implements Entry<String, ResourceXmlAttrValue> {
private final String name;
- private final XmlResourceValue value;
+ private final ResourceXmlAttrValue value;
- public BuilderEntry(String name, XmlResourceValue value) {
+ BuilderEntry(String name, ResourceXmlAttrValue value) {
this.name = name;
this.value = value;
}
@@ -118,19 +127,19 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@Override
- public XmlResourceValue getValue() {
+ public ResourceXmlAttrValue getValue() {
return value;
}
@Override
- public XmlResourceValue setValue(XmlResourceValue value) {
+ public ResourceXmlAttrValue setValue(ResourceXmlAttrValue value) {
throw new UnsupportedOperationException();
}
}
@SafeVarargs
@VisibleForTesting
- public static XmlResourceValue fromFormatEntries(Map.Entry<String, XmlResourceValue>... entries) {
+ public static XmlResourceValue fromFormatEntries(Entry<String, ResourceXmlAttrValue>... entries) {
return of(ImmutableMap.copyOf(Arrays.asList(entries)));
}
@@ -146,52 +155,52 @@ public class AttrXmlResourceValue implements XmlResourceValue {
formatNames.add(nextTag.asStartElement().getName().getLocalPart().toLowerCase());
}
- Map<String, XmlResourceValue> formats = new HashMap<>();
+ Builder<String, ResourceXmlAttrValue> formats = ImmutableMap.builder();
for (String formatName : formatNames) {
switch (formatName) {
case FLAG:
Map<String, String> flags = readSubValues(eventReader, TAG_FLAG);
endAttrElement(eventReader);
- formats.put(formatName, AttrFlagXmlValue.of(flags));
+ formats.put(formatName, FlagResourceXmlAttrValue.of(flags));
break;
case ENUM:
Map<String, String> enums = readSubValues(eventReader, TAG_ENUM);
endAttrElement(eventReader);
- formats.put(formatName, AttrEnumXmlValue.of(enums));
+ formats.put(formatName, EnumResourceXmlAttrValue.of(enums));
break;
case REFERENCE:
- formats.put(formatName, AttrReferenceXmlValue.of());
+ formats.put(formatName, ReferenceResourceXmlAttrValue.of());
break;
case COLOR:
- formats.put(formatName, AttrColorXmlValue.of());
+ formats.put(formatName, ColorResourceXmlAttrValue.of());
break;
case BOOLEAN:
- formats.put(formatName, AttrBooleanXmlValue.of());
+ formats.put(formatName, BooleanResourceXmlAttrValue.of());
break;
case DIMENSION:
- formats.put(formatName, AttrDimensionXmlValue.of());
+ formats.put(formatName, DimensionResourceXmlAttrValue.of());
break;
case FLOAT:
- formats.put(formatName, AttrFloatXmlValue.of());
+ formats.put(formatName, FloatResourceXmlAttrValue.of());
break;
case INTEGER:
- formats.put(formatName, AttrIntegerXmlValue.of());
+ formats.put(formatName, IntegerResourceXmlAttrValue.of());
break;
case STRING:
- formats.put(formatName, AttrStringXmlValue.of());
+ formats.put(formatName, StringResourceXmlAttrValue.of());
break;
case FRACTION:
- formats.put(formatName, AttrFractionXmlValue.of());
+ formats.put(formatName, FractionResourceXmlAttrValue.of());
break;
default:
throw new XMLStreamException(
String.format("Unexpected attr format: %S", formatName), attr.getLocation());
}
}
- return of(formats);
+ return of(formats.build());
}
- public static XmlResourceValue of(Map<String, XmlResourceValue> formats) {
+ public static XmlResourceValue of(ImmutableMap<String, ResourceXmlAttrValue> formats) {
return new AttrXmlResourceValue(formats);
}
@@ -218,40 +227,58 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public void write(
+ FullyQualifiedName key, Path source, AndroidDataWritingVisitor mergedDataWriter) {
+ ImmutableList<String> formatKeys = Ordering.natural().immutableSortedCopy(formats.keySet());
+ FluentIterable<String> iterable =
+ FluentIterable.of(
+ String.format("<!-- %s -->", source),
+ String.format(
+ "<attr name='%s' format='%s'>", key.name(), Joiner.on('|').join(formatKeys)));
+ for (String formatKey : formatKeys) {
+ iterable = formats.get(formatKey).appendTo(iterable);
+ }
+ mergedDataWriter.writeToValuesXml(key, iterable.append("</attr>"));
}
+ @CheckReturnValue
+ interface ResourceXmlAttrValue {
+ FluentIterable<String> appendTo(FluentIterable<String> iterable);
+ }
+
+ // TODO(corysmith): The ResourceXmlAttrValue implementors, other than enum and flag, share a
+ // lot of boilerplate. Determine how to reduce it.
/** Represents an Android Enum Attribute resource. */
@VisibleForTesting
- public static class AttrEnumXmlValue implements XmlResourceValue {
-
+ public static class EnumResourceXmlAttrValue implements ResourceXmlAttrValue {
+
+ private static final Function<Entry<String, String>, String> MAP_TO_ENUM =
+ new Function<Entry<String, String>, String>() {
+ @Nullable
+ @Override
+ public String apply(Entry<String, String> entry) {
+ return String.format("<enum name='%s' value='%s'/>", entry.getKey(), entry.getValue());
+ }
+ };
private Map<String, String> values;
- private AttrEnumXmlValue(Map<String, String> values) {
+ private EnumResourceXmlAttrValue(Map<String, String> values) {
this.values = values;
}
@VisibleForTesting
- public static Map.Entry<String, XmlResourceValue> asEntryOf(String... keyThenValue) {
+ public static Entry<String, ResourceXmlAttrValue> asEntryOf(String... keyThenValue) {
Preconditions.checkArgument(keyThenValue.length > 0);
Preconditions.checkArgument(keyThenValue.length % 2 == 0);
- Builder<String, String> builder = ImmutableMap.<String, String>builder();
+ Builder<String, String> builder = ImmutableMap.builder();
for (int i = 0; i < keyThenValue.length; i += 2) {
builder.put(keyThenValue[i], keyThenValue[i + 1]);
}
return new BuilderEntry(ENUM, of(builder.build()));
}
- public static XmlResourceValue of(Map<String, String> values) {
- return new AttrEnumXmlValue(values);
- }
-
- @Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public static ResourceXmlAttrValue of(Map<String, String> values) {
+ return new EnumResourceXmlAttrValue(values);
}
@Override
@@ -261,10 +288,10 @@ public class AttrXmlResourceValue implements XmlResourceValue {
@Override
public boolean equals(Object obj) {
- if (!(obj instanceof AttrEnumXmlValue)) {
+ if (!(obj instanceof EnumResourceXmlAttrValue)) {
return false;
}
- AttrEnumXmlValue other = (AttrEnumXmlValue) obj;
+ EnumResourceXmlAttrValue other = (EnumResourceXmlAttrValue) obj;
return Objects.equals(values, other.values);
}
@@ -272,25 +299,31 @@ public class AttrXmlResourceValue implements XmlResourceValue {
public String toString() {
return MoreObjects.toStringHelper(getClass()).add("values", values).toString();
}
+
+ @Override
+ public FluentIterable<String> appendTo(FluentIterable<String> iterable) {
+ return iterable.append(FluentIterable.from(values.entrySet()).transform(MAP_TO_ENUM));
+ }
}
/** Represents an Android Flag Attribute resource. */
@VisibleForTesting
- public static class AttrFlagXmlValue implements XmlResourceValue {
+ public static class FlagResourceXmlAttrValue implements ResourceXmlAttrValue {
private Map<String, String> values;
- private AttrFlagXmlValue(Map<String, String> values) {
+ private FlagResourceXmlAttrValue(Map<String, String> values) {
this.values = values;
}
- public static XmlResourceValue of(Map<String, String> values) {
- return new AttrFlagXmlValue(values);
+ public static ResourceXmlAttrValue of(Map<String, String> values) {
+ // ImmutableMap guarantees a stable order.
+ return new FlagResourceXmlAttrValue(ImmutableMap.copyOf(values));
}
@VisibleForTesting
- public static Map.Entry<String, XmlResourceValue> asEntryOf(String... keyThenValue) {
- Builder<String, String> builder = ImmutableMap.<String, String>builder();
+ public static Entry<String, ResourceXmlAttrValue> asEntryOf(String... keyThenValue) {
+ Builder<String, String> builder = ImmutableMap.builder();
Preconditions.checkArgument(keyThenValue.length > 0);
Preconditions.checkArgument(keyThenValue.length % 2 == 0);
for (int i = 0; i < keyThenValue.length; i += 2) {
@@ -300,22 +333,16 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
- }
-
- @Override
public int hashCode() {
return values.hashCode();
}
@Override
public boolean equals(Object obj) {
- if (!(obj instanceof AttrFlagXmlValue)) {
+ if (!(obj instanceof FlagResourceXmlAttrValue)) {
return false;
}
- AttrFlagXmlValue other = (AttrFlagXmlValue) obj;
+ FlagResourceXmlAttrValue other = (FlagResourceXmlAttrValue) obj;
return Objects.equals(values, other.values);
}
@@ -323,14 +350,30 @@ public class AttrXmlResourceValue implements XmlResourceValue {
public String toString() {
return MoreObjects.toStringHelper(getClass()).add("values", values).toString();
}
+
+ @Override
+ public FluentIterable<String> appendTo(FluentIterable<String> iterable) {
+ return iterable.append(
+ FluentIterable.from(values.entrySet())
+ .transform(
+ new Function<Entry<String, String>, String>() {
+ @Nullable
+ @Override
+ public String apply(Entry<String, String> input) {
+ return String.format(
+ "<flag name='%s' value='%s'/>", input.getKey(), input.getValue());
+ }
+ }));
+ }
}
/** Represents an Android Reference Attribute resource. */
@VisibleForTesting
- public static class AttrReferenceXmlValue implements XmlResourceValue {
- private static final AttrReferenceXmlValue INSTANCE = new AttrReferenceXmlValue();
+ public static class ReferenceResourceXmlAttrValue implements ResourceXmlAttrValue {
+ private static final ReferenceResourceXmlAttrValue INSTANCE =
+ new ReferenceResourceXmlAttrValue();
- public static XmlResourceValue of() {
+ public static ResourceXmlAttrValue of() {
return INSTANCE;
}
@@ -340,18 +383,17 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public FluentIterable<String> appendTo(FluentIterable<String> iterable) {
+ return iterable;
}
}
/** Represents an Android Color Attribute resource. */
@VisibleForTesting
- public static class AttrColorXmlValue implements XmlResourceValue {
- private static final AttrColorXmlValue INSTANCE = new AttrColorXmlValue();
+ public static class ColorResourceXmlAttrValue implements ResourceXmlAttrValue {
+ private static final ColorResourceXmlAttrValue INSTANCE = new ColorResourceXmlAttrValue();
- public static XmlResourceValue of() {
+ public static ResourceXmlAttrValue of() {
return INSTANCE;
}
@@ -361,18 +403,17 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public FluentIterable<String> appendTo(FluentIterable<String> iterable) {
+ return iterable;
}
}
/** Represents an Android Boolean Attribute resource. */
@VisibleForTesting
- public static class AttrBooleanXmlValue implements XmlResourceValue {
- private static final AttrBooleanXmlValue INSTANCE = new AttrBooleanXmlValue();
+ public static class BooleanResourceXmlAttrValue implements ResourceXmlAttrValue {
+ private static final BooleanResourceXmlAttrValue INSTANCE = new BooleanResourceXmlAttrValue();
- public static XmlResourceValue of() {
+ public static ResourceXmlAttrValue of() {
return INSTANCE;
}
@@ -382,18 +423,17 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public FluentIterable<String> appendTo(FluentIterable<String> iterable) {
+ return iterable;
}
}
/** Represents an Android Float Attribute resource. */
@VisibleForTesting
- public static class AttrFloatXmlValue implements XmlResourceValue {
- private static final AttrFloatXmlValue INSTANCE = new AttrFloatXmlValue();
+ public static class FloatResourceXmlAttrValue implements ResourceXmlAttrValue {
+ private static final FloatResourceXmlAttrValue INSTANCE = new FloatResourceXmlAttrValue();
- public static XmlResourceValue of() {
+ public static ResourceXmlAttrValue of() {
return INSTANCE;
}
@@ -403,39 +443,38 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public FluentIterable<String> appendTo(FluentIterable<String> iterable) {
+ return iterable;
}
}
/** Represents an Android Dimension Attribute resource. */
@VisibleForTesting
- public static class AttrDimensionXmlValue implements XmlResourceValue {
- private static final AttrDimensionXmlValue INSTANCE = new AttrDimensionXmlValue();
+ public static class DimensionResourceXmlAttrValue implements ResourceXmlAttrValue {
+ private static final DimensionResourceXmlAttrValue INSTANCE =
+ new DimensionResourceXmlAttrValue();
+
+ public static ResourceXmlAttrValue of() {
+ return INSTANCE;
+ }
@VisibleForTesting
public static BuilderEntry asEntry() {
return new BuilderEntry(DIMENSION, of());
}
- public static XmlResourceValue of() {
- return INSTANCE;
- }
-
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public FluentIterable<String> appendTo(FluentIterable<String> iterable) {
+ return iterable;
}
}
/** Represents an Android Integer Attribute resource. */
@VisibleForTesting
- public static class AttrIntegerXmlValue implements XmlResourceValue {
- private static final AttrIntegerXmlValue INSTANCE = new AttrIntegerXmlValue();
+ public static class IntegerResourceXmlAttrValue implements ResourceXmlAttrValue {
+ private static final IntegerResourceXmlAttrValue INSTANCE = new IntegerResourceXmlAttrValue();
- public static XmlResourceValue of() {
+ public static ResourceXmlAttrValue of() {
return INSTANCE;
}
@@ -445,18 +484,17 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public FluentIterable<String> appendTo(FluentIterable<String> iterable) {
+ return iterable;
}
}
/** Represents an Android String Attribute resource. */
@VisibleForTesting
- public static class AttrStringXmlValue implements XmlResourceValue {
- private static final AttrStringXmlValue INSTANCE = new AttrStringXmlValue();
+ public static class StringResourceXmlAttrValue implements ResourceXmlAttrValue {
+ private static final StringResourceXmlAttrValue INSTANCE = new StringResourceXmlAttrValue();
- public static XmlResourceValue of() {
+ public static ResourceXmlAttrValue of() {
return INSTANCE;
}
@@ -466,18 +504,17 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public FluentIterable<String> appendTo(FluentIterable<String> iterable) {
+ return iterable;
}
}
/** Represents an Android Fraction Attribute resource. */
@VisibleForTesting
- public static class AttrFractionXmlValue implements XmlResourceValue {
- private static final AttrFractionXmlValue INSTANCE = new AttrFractionXmlValue();
+ public static class FractionResourceXmlAttrValue implements ResourceXmlAttrValue {
+ private static final FractionResourceXmlAttrValue INSTANCE = new FractionResourceXmlAttrValue();
- public static XmlResourceValue of() {
+ public static ResourceXmlAttrValue of() {
return INSTANCE;
}
@@ -487,9 +524,8 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public FluentIterable<String> appendTo(FluentIterable<String> iterable) {
+ return iterable;
}
}
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/xml/IdXmlResourceValue.java b/src/tools/android/java/com/google/devtools/build/android/xml/IdXmlResourceValue.java
index f8221ed332..309971005f 100644
--- a/src/tools/android/java/com/google/devtools/build/android/xml/IdXmlResourceValue.java
+++ b/src/tools/android/java/com/google/devtools/build/android/xml/IdXmlResourceValue.java
@@ -14,10 +14,14 @@
package com.google.devtools.build.android.xml;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.FluentIterable;
+import com.google.devtools.build.android.AndroidDataWritingVisitor;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import java.io.Writer;
+import java.nio.file.Path;
+
+import javax.annotation.concurrent.Immutable;
/**
* Represents an Android Resource id.
@@ -28,6 +32,7 @@ import java.io.Writer;
* that they have no intrinsic defined value. They exist to reference parts of other resources.
* Ids can also be declared on the fly in components with the syntax @[+][package:]id/resource_name.
*/
+@Immutable
public class IdXmlResourceValue implements XmlResourceValue {
static final IdXmlResourceValue SINGLETON = new IdXmlResourceValue();
@@ -37,9 +42,13 @@ public class IdXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public void write(
+ FullyQualifiedName key, Path source, AndroidDataWritingVisitor mergedDataWriter) {
+ mergedDataWriter.writeToValuesXml(
+ key,
+ FluentIterable.of(
+ String.format("<!-- %s -->", source),
+ String.format("<item type='id' name='%s'/>", key.name())));
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/xml/PluralXmlResourceValue.java b/src/tools/android/java/com/google/devtools/build/android/xml/PluralXmlResourceValue.java
index 36c18c0a9e..8df051797a 100644
--- a/src/tools/android/java/com/google/devtools/build/android/xml/PluralXmlResourceValue.java
+++ b/src/tools/android/java/com/google/devtools/build/android/xml/PluralXmlResourceValue.java
@@ -13,20 +13,27 @@
// limitations under the License.
package com.google.devtools.build.android.xml;
+import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.android.AndroidDataWritingVisitor;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import java.io.Writer;
-import java.util.Map;
+import java.nio.file.Path;
+import java.util.Map.Entry;
import java.util.Objects;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
/**
* Represents an Android Plural Resource.
*
* <p>Plurals are a localization construct (http://developer.android.com/guide/topics/resources/
- * string-resource.html#Plurals) that are basically a map of key to value. They are defined in
- * xml as:
+ * string-resource.html#Plurals) that are basically a map of key to
+ * value. They are defined in xml as:
* <code>
* &lt;plurals name="plural_name"&gt;
* &lt;item quantity=["zero" | "one" | "two" | "few" | "many" | "other"]&gt;
@@ -35,22 +42,37 @@ import java.util.Objects;
* &lt;/plurals&gt;
* </code>
*/
+@Immutable
public class PluralXmlResourceValue implements XmlResourceValue {
- private Map<String, String> values;
+ public static final Function<Entry<String, String>, String> ENTRY_TO_PLURAL =
+ new Function<Entry<String, String>, String>() {
+ @Nullable
+ @Override
+ public String apply(Entry<String, String> input) {
+ return String.format("<item quantity='%s'>%s</item>", input.getKey(), input.getValue());
+ }
+ };
+ private final ImmutableMap<String, String> values;
- private PluralXmlResourceValue(Map<String, String> values) {
+ private PluralXmlResourceValue(ImmutableMap<String, String> values) {
this.values = values;
}
- public static XmlResourceValue of(Map<String, String> values) {
+ public static XmlResourceValue of(ImmutableMap<String, String> values) {
return new PluralXmlResourceValue(values);
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public void write(
+ FullyQualifiedName key, Path source, AndroidDataWritingVisitor mergedDataWriter) {
+ mergedDataWriter.writeToValuesXml(
+ key,
+ FluentIterable.of(
+ String.format("<!-- %s -->", source),
+ String.format("<plurals name='%s'>", key.name()))
+ .append(FluentIterable.from(values.entrySet()).transform(ENTRY_TO_PLURAL))
+ .append("</plurals>"));
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/xml/SimpleXmlResourceValue.java b/src/tools/android/java/com/google/devtools/build/android/xml/SimpleXmlResourceValue.java
index ce7684b764..4df442f35f 100644
--- a/src/tools/android/java/com/google/devtools/build/android/xml/SimpleXmlResourceValue.java
+++ b/src/tools/android/java/com/google/devtools/build/android/xml/SimpleXmlResourceValue.java
@@ -14,15 +14,18 @@
package com.google.devtools.build.android.xml;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.FluentIterable;
+import com.google.devtools.build.android.AndroidDataWritingVisitor;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
import com.android.resources.ResourceType;
-import java.io.Writer;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.Objects;
+import javax.annotation.concurrent.Immutable;
import javax.xml.namespace.QName;
/**
@@ -37,6 +40,7 @@ import javax.xml.namespace.QName;
* value="<em>value</em>"&gt;. In the interest of keeping the parsing svelte, these are
* represented by a single class.
*/
+@Immutable
public class SimpleXmlResourceValue implements XmlResourceValue {
static final QName TAG_STRING = QName.valueOf("string");
static final QName TAG_BOOL = QName.valueOf("bool");
@@ -94,8 +98,8 @@ public class SimpleXmlResourceValue implements XmlResourceValue {
}
}
- private String value;
- private Type valueType;
+ private final String value;
+ private final Type valueType;
public static XmlResourceValue of(Type valueType, String value) {
return new SimpleXmlResourceValue(valueType, value);
@@ -107,9 +111,18 @@ public class SimpleXmlResourceValue implements XmlResourceValue {
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public void write(
+ FullyQualifiedName key, Path source, AndroidDataWritingVisitor mergedDataWriter) {
+ mergedDataWriter.writeToValuesXml(
+ key,
+ FluentIterable.of(
+ String.format("<!-- %s -->", source),
+ String.format(
+ "<%s name='%s'>%s</%s>",
+ valueType.tagName.getLocalPart(),
+ key.name(),
+ value,
+ valueType.tagName.getLocalPart())));
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/xml/StyleXmlResourceValue.java b/src/tools/android/java/com/google/devtools/build/android/xml/StyleXmlResourceValue.java
index 3055089ea0..2067a01f77 100644
--- a/src/tools/android/java/com/google/devtools/build/android/xml/StyleXmlResourceValue.java
+++ b/src/tools/android/java/com/google/devtools/build/android/xml/StyleXmlResourceValue.java
@@ -13,14 +13,22 @@
// limitations under the License.
package com.google.devtools.build.android.xml;
+import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.android.AndroidDataWritingVisitor;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import java.io.Writer;
+import java.nio.file.Path;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Objects;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
/**
* Represents an Android Style Resource.
*
@@ -38,23 +46,40 @@ import java.util.Objects;
* &lt;/resources&gt;
* </code>
*/
+@Immutable
public class StyleXmlResourceValue implements XmlResourceValue {
- private String parent;
- private Map<String, String> values;
+ public static final Function<Entry<String, String>, String> ENTRY_TO_ITEM =
+ new Function<Entry<String, String>, String>() {
+ @Nullable
+ @Override
+ public String apply(Entry<String, String> input) {
+ return String.format("<item name='%s'>%s</item>", input.getKey(), input.getValue());
+ }
+ };
+ private final String parent;
+ private final ImmutableMap<String, String> values;
public static StyleXmlResourceValue of(String parent, Map<String, String> values) {
- return new StyleXmlResourceValue(parent, values);
+ return new StyleXmlResourceValue(parent, ImmutableMap.copyOf(values));
}
- private StyleXmlResourceValue(String parent, Map<String, String> values) {
+ private StyleXmlResourceValue(String parent, ImmutableMap<String, String> values) {
this.parent = parent;
this.values = values;
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public void write(
+ FullyQualifiedName key, Path source, AndroidDataWritingVisitor mergedDataWriter) {
+ mergedDataWriter.writeToValuesXml(
+ key,
+ FluentIterable.of(
+ String.format("<!-- %s -->", source),
+ parent == null || parent.isEmpty()
+ ? String.format("<style name='%s'>", key.name())
+ : String.format("<style name='%s' parent='%s'>", key.name(), parent))
+ .append(FluentIterable.from(values.entrySet()).transform(ENTRY_TO_ITEM))
+ .append("</style>"));
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/xml/StyleableXmlResourceValue.java b/src/tools/android/java/com/google/devtools/build/android/xml/StyleableXmlResourceValue.java
index f1a0486307..76011237f7 100644
--- a/src/tools/android/java/com/google/devtools/build/android/xml/StyleableXmlResourceValue.java
+++ b/src/tools/android/java/com/google/devtools/build/android/xml/StyleableXmlResourceValue.java
@@ -14,15 +14,23 @@
package com.google.devtools.build.android.xml;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Ordering;
+import com.google.devtools.build.android.AndroidDataWritingVisitor;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import java.io.Writer;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
/**
* Represent an Android styleable resource.
*
@@ -46,26 +54,42 @@ import java.util.Objects;
*
* <p>The StyleableXmlValue only contains names of the attributes it holds, not definitions.
*/
+@Immutable
public class StyleableXmlResourceValue implements XmlResourceValue {
- private final List<String> attrs;
+ public static final Function<String, String> ITEM_TO_ATTR =
+ new Function<String, String>() {
+ @Nullable
+ @Override
+ public String apply(@Nullable String input) {
+ return String.format("<attr name='%s'/>", input);
+ }
+ };
+ private final ImmutableList<String> attrs;
- private StyleableXmlResourceValue(List<String> attrs) {
+ private StyleableXmlResourceValue(ImmutableList<String> attrs) {
this.attrs = attrs;
}
public static XmlResourceValue of(List<String> attrs) {
- return new StyleableXmlResourceValue(attrs);
+ return new StyleableXmlResourceValue(ImmutableList.copyOf(attrs));
}
@VisibleForTesting
public static XmlResourceValue of(String... attrs) {
- return new StyleableXmlResourceValue(Arrays.asList(attrs));
+ return new StyleableXmlResourceValue(
+ Ordering.natural().immutableSortedCopy(Arrays.asList(attrs)));
}
@Override
- public void write(Writer buffer, FullyQualifiedName name) {
- // TODO(corysmith): Implement write.
- throw new UnsupportedOperationException();
+ public void write(
+ FullyQualifiedName key, Path source, AndroidDataWritingVisitor mergedDataWriter) {
+ mergedDataWriter.writeToValuesXml(
+ key,
+ FluentIterable.of(
+ String.format("<!-- %s -->", source),
+ String.format("<declare-styleable name='%s'>", key.name()))
+ .append(FluentIterable.from(attrs).transform(ITEM_TO_ATTR))
+ .append("</declare-styleable>"));
}
@Override