diff options
author | Googler <noreply@google.com> | 2017-11-15 11:55:15 -0800 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2017-11-15 11:57:13 -0800 |
commit | 7925d5b265249466bff385602e94509a05de6870 (patch) | |
tree | 9543038c23171dd93261a792a6f0571591e3cb09 /src/tools/android/java/com/google/devtools/build/android/xml | |
parent | 1e0b7cb49b5d22f72d9e32018d15972a9f28878c (diff) |
Create merge action and data deserializer for aapt2 compiled resources.
RELNOTES: None
PiperOrigin-RevId: 175858467
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/xml')
6 files changed, 236 insertions, 1 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 e3f5571c7d..fb74fd2208 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 @@ -13,6 +13,10 @@ // limitations under the License. package com.google.devtools.build.android.xml; +import com.android.aapt.Resources.Array; +import com.android.aapt.Resources.Array.Element; +import com.android.aapt.Resources.Item; +import com.android.aapt.Resources.Value; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; @@ -117,6 +121,29 @@ public class ArrayXmlResourceValue implements XmlResourceValue { ImmutableMap.copyOf(proto.getAttribute())); } + public static XmlResourceValue from(Value proto) { + Array array = proto.getCompoundValue().getArray(); + List<String> items = new ArrayList<>(); + + for (Element entry : array.getElementList()) { + Item item = entry.getItem(); + + if (item.hasPrim()) { + String stringValue = "#" + Integer.toHexString(item.getPrim().getData()); + items.add(stringValue); + } else if (item.hasRef()) { + items.add("@" + item.getRef().getName()); + } else if (item.hasStr()) { + items.add(item.getStr().getValue()); + } + } + + return of( + ArrayType.ARRAY, + items, + ImmutableMap.of()); + } + @Override public void write( FullyQualifiedName key, DataSource source, AndroidDataWritingVisitor mergedDataWriter) { 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 661e5ddf98..f2645ac0a3 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 @@ -16,6 +16,9 @@ package com.google.devtools.build.android.xml; import static com.google.common.base.Predicates.equalTo; import static com.google.common.base.Predicates.not; +import com.android.aapt.Resources.Attribute; +import com.android.aapt.Resources.Attribute.Symbol; +import com.android.aapt.Resources.Value; import com.android.resources.ResourceType; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; @@ -39,6 +42,7 @@ import java.io.IOException; import java.io.OutputStream; 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; @@ -195,6 +199,66 @@ public class AttrXmlResourceValue implements XmlResourceValue { return of(formats.build()); } + public static XmlResourceValue from(Value proto) throws InvalidProtocolBufferException { + Builder<String, ResourceXmlAttrValue> formats = + ImmutableMap.builder(); + + Attribute attribute = proto.getCompoundValue().getAttr(); + int formatFlags = attribute.getFormatFlags(); + + if (formatFlags != 0xFFFF) { + //These flags are defined in AOSP in ResourceTypes.h:ResTable_map + if ((formatFlags & 1 << 0) != 0) { + formats.put("reference", ReferenceResourceXmlAttrValue.of()); + } + if ((formatFlags & 1 << 1) != 0) { + formats.put("string", StringResourceXmlAttrValue.of()); + } + if ((formatFlags & 1 << 2) != 0) { + formats.put("integer", IntegerResourceXmlAttrValue.of()); + } + if ((formatFlags & 1 << 3) != 0) { + formats.put("boolean", BooleanResourceXmlAttrValue.of()); + } + if ((formatFlags & 1 << 4) != 0) { + formats.put("color", ColorResourceXmlAttrValue.of()); + } + if ((formatFlags & 1 << 5) != 0) { + formats.put("float", FloatResourceXmlAttrValue.of()); + } + if ((formatFlags & 1 << 6) != 0) { + formats.put("dimension", DimensionResourceXmlAttrValue.of()); + } + if ((formatFlags & 1 << 7) != 0) { + formats.put("fraction", FractionResourceXmlAttrValue.of()); + } + if ((formatFlags & 1 << 16) != 0) { + Map<String, String> enums = new HashMap<>(); + + for (Symbol attrSymbol : attribute.getSymbolList()) { + String name = attrSymbol.getName().getName().replaceFirst("id/", ""); + enums.put(name, Integer.toString(attrSymbol.getValue())); + } + + formats.put("enum", EnumResourceXmlAttrValue.of(enums)); + } + if ((formatFlags & 1 << 17) != 0) { + Map<String, String> flags = new HashMap<>(); + for (Symbol attrSymbol : attribute.getSymbolList()) { + String name = attrSymbol.getName().getName().replaceFirst("id/", ""); + flags.put(name, Integer.toString(attrSymbol.getValue())); + } + + formats.put("flags", FlagResourceXmlAttrValue.of(flags)); + } + if ((formatFlags & 0xFFFCFF00) != 0) { + throw new InvalidProtocolBufferException( + "Unexpected format flags: " + formatFlags); + } + } + return of(formats.build()); + } + /** * Creates a new {@link AttrXmlResourceValue}. Returns null if there are no formats. */ 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 1ff1578eab..6e1fba18c7 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,6 +13,8 @@ // limitations under the License. package com.google.devtools.build.android.xml; +import com.android.aapt.Resources.Plural; +import com.android.aapt.Resources.Value; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableMap; import com.google.devtools.build.android.AndroidDataWritingVisitor; @@ -27,6 +29,8 @@ import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.XmlT import com.google.protobuf.CodedOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import javax.annotation.concurrent.Immutable; @@ -131,6 +135,29 @@ public class PluralXmlResourceValue implements XmlResourceValue { ImmutableMap.copyOf(proto.getMappedStringValue())); } + public static XmlResourceValue from(Value proto) { + Plural plural = proto.getCompoundValue().getPlural(); + + Map<String, String> items = new HashMap<>(); + + for (Plural.Entry entry : plural.getEntryList()) { + String name = entry.getArity().toString().toLowerCase(); + String value = + entry + .getItem() + .getStr() + .toString() + .replace("value: \"", "") + .replace("\"", "") + .replace('\n', ' '); + items.put(name, value); + } + + return createWithAttributesAndValues( + ImmutableMap.of(), + ImmutableMap.copyOf(items)); + } + @Override public int serializeTo(int sourceId, Namespaces namespaces, OutputStream output) throws IOException { 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 923c163ad3..4006d4d7a4 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 @@ -13,6 +13,10 @@ // limitations under the License. package com.google.devtools.build.android.xml; +import com.android.aapt.Resources.Item; +import com.android.aapt.Resources.StyledString; +import com.android.aapt.Resources.StyledString.Span; +import com.android.aapt.Resources.Value; import com.android.resources.ResourceType; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableMap; @@ -54,6 +58,8 @@ public class SimpleXmlResourceValue implements XmlResourceValue { static final QName TAG_FRACTION = QName.valueOf("fraction"); static final QName TAG_INTEGER = QName.valueOf("integer"); static final QName TAG_ITEM = QName.valueOf("item"); + static final QName TAG_LAYOUT = QName.valueOf("layout"); + static final QName TAG_MIPMAP = QName.valueOf("mipmap"); static final QName TAG_PUBLIC = QName.valueOf("public"); static final QName TAG_STRING = QName.valueOf("string"); @@ -108,6 +114,20 @@ public class SimpleXmlResourceValue implements XmlResourceValue { return true; } }, + LAYOUT(TAG_LAYOUT) { + @Override + public boolean validate(String value) { + // TODO(corysmith): Validate the item type. + return true; + } + }, + MIPMAP(TAG_MIPMAP) { + @Override + public boolean validate(String value) { + // TODO(corysmith): Validate the item type. + return true; + } + }, PUBLIC(TAG_PUBLIC) { @Override public boolean validate(String value) { @@ -121,7 +141,7 @@ public class SimpleXmlResourceValue implements XmlResourceValue { return true; } }; - private QName tagName; + private final QName tagName; Type(QName tagName) { this.tagName = tagName; @@ -211,6 +231,45 @@ public class SimpleXmlResourceValue implements XmlResourceValue { proto.hasValue() ? proto.getValue() : null); } + public static XmlResourceValue from(Value proto, ResourceType resourceType) { + Item item = proto.getItem(); + String stringValue = null; + + if (item.hasStr()) { + stringValue = item.getStr().toString(); + } else if (item.hasRef()) { + stringValue = "@" + item.getRef().getName(); + } else if (item.hasStyledStr()) { + StyledString styledString = item.getStyledStr(); + StringBuilder stringBuilder = new StringBuilder(styledString.getValue()); + + for (Span span : styledString.getSpanList()) { + stringBuilder.append( + String.format(";%s,%d,%d", span.getTag(), span.getFirstChar(), span.getLastChar())); + } + stringValue = stringBuilder.toString(); + } else if ((resourceType == ResourceType.COLOR + || resourceType == ResourceType.DRAWABLE) && item.hasPrim()) { + stringValue = + String.format("#%1$8s", Integer.toHexString(item.getPrim().getData())).replace(' ', '0'); + } else if (resourceType == ResourceType.INTEGER && item.hasPrim()){ + stringValue = Integer.toString(item.getPrim().getData()); + } else if (resourceType == ResourceType.BOOL && item.hasPrim()) { + stringValue = item.getPrim().getData() == 0 ? "false" : "true"; + } else if (resourceType == ResourceType.FRACTION + || resourceType == ResourceType.DIMEN) { + stringValue = Integer.toString(item.getPrim().getData()); + } else { + throw new IllegalArgumentException( + String.format("'%s' is not a valid resource type.", resourceType)); + } + + return of( + Type.valueOf(resourceType.toString().toUpperCase()), + ImmutableMap.of(), + stringValue); + } + @Override public void writeResourceToClass(FullyQualifiedName key, AndroidResourceSymbolSink sink) { sink.acceptSimpleResource(key.type(), key.name()); 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 ccf52b6480..55c3d00fdd 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,6 +13,8 @@ // limitations under the License. package com.google.devtools.build.android.xml; +import com.android.aapt.Resources.Style; +import com.android.aapt.Resources.Value; import com.google.common.base.Function; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableMap; @@ -27,6 +29,7 @@ import com.google.devtools.build.android.proto.SerializeFormat; import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.XmlType; import java.io.IOException; import java.io.OutputStream; +import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; @@ -77,6 +80,42 @@ public class StyleXmlResourceValue implements XmlResourceValue { this.values = values; } + public static XmlResourceValue from(Value proto) { + Style style = proto.getCompoundValue().getStyle(); + String parent = ""; + + if (style.hasParent()) { + parent = proto.getCompoundValue().getStyle().getParent().getName(); + } + + Map<String, String> items = itemMapFromProto(style); + + return of(parent, items); + } + + private static Map<String, String> itemMapFromProto(Style style) { + Map<String, String> result = new HashMap<>(); + + for (Style.Entry styleEntry : style.getEntryList()) { + String itemName = styleEntry.getKey().getName().replace("attr/", ""); + String itemValue; + + if (styleEntry.getItem().hasRawStr()) { + itemValue = styleEntry.getItem().getRawStr().getValue(); + } else if (styleEntry.getItem().hasRef()) { + itemValue = "@" + styleEntry.getItem().getRef().getName(); + if (itemValue.equals("@")) { + itemValue = "@null"; + } + } else { + throw new IllegalArgumentException("Could not parse item value from Style resource."); + } + result.put(itemName, itemValue); + } + + return result; + } + @Override public void write( FullyQualifiedName key, DataSource source, AndroidDataWritingVisitor mergedDataWriter) { 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 8e55e089d3..c9661690cf 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 @@ -13,6 +13,8 @@ // limitations under the License. package com.google.devtools.build.android.xml; +import com.android.aapt.Resources.Styleable; +import com.android.aapt.Resources.Value; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.MoreObjects; @@ -31,6 +33,7 @@ import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.XmlT import java.io.IOException; import java.io.OutputStream; import java.util.AbstractMap.SimpleEntry; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; @@ -161,6 +164,22 @@ public class StyleableXmlResourceValue implements XmlResourceValue { Iterables.transform(proto.getReferencesList(), DATA_KEY_TO_FULLY_QUALIFIED_NAME))); } + public static XmlResourceValue from( + Value proto, Map<String, Entry<FullyQualifiedName, Boolean>> fullyQualifiedNames) { + Map<FullyQualifiedName, Boolean> attributes = new HashMap<>(); + + Styleable styleable = proto.getCompoundValue().getStyleable(); + for (Styleable.Entry entry : styleable.getEntryList()) { + String attrName = entry.getAttr().getName(); + + Entry<FullyQualifiedName, Boolean> fqnEntry = fullyQualifiedNames.get(attrName); + attributes.put(fqnEntry.getKey(), fqnEntry.getValue()); + fqnEntry.setValue(false); + } + + return of(ImmutableMap.copyOf(attributes)); + } + @Override public int hashCode() { return attrs.hashCode(); |