aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com/google/devtools/build/android
diff options
context:
space:
mode:
authorGravatar corysmith <corysmith@google.com>2018-02-16 13:14:29 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-02-16 13:18:21 -0800
commitf672a31b8b19baab95373e4f2f6d110aa8b8f0fb (patch)
tree58cef0309a67e62e3fe0ef024916d9d5c53bae8c /src/tools/android/java/com/google/devtools/build/android
parent950bcf79c47484832bb4c84fbb23f6b56800e0b3 (diff)
Normalized the serialization proto to save space and allow greater versatility in storage.
RELNOTES: None PiperOrigin-RevId: 186036607
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java153
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java2
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java67
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidDataSerializer.java211
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java2
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidParsedDataDeserializer.java157
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceParsingAction.java2
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java2
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/Converters.java4
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/DataKey.java14
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/DataResourceXml.java48
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/DataSource.java25
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/DataSourceTable.java131
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/DataValue.java7
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/DataValueFile.java12
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/DependencyAndroidData.java2
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/DeserializationException.java3
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java32
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/ManifestMergerAction.java5
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/PlaceholderIdFieldInitializerBuilder.java2
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/RelativeAssetPath.java6
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/ResourceProcessorBusyBox.java2
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java2
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/UnvalidatedAndroidDirectories.java4
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/Writeable.java23
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/XmlResourceValue.java9
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java34
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/proto/serialize_format.proto64
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/ArrayXmlResourceValue.java68
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/AttrXmlResourceValue.java15
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/IdXmlResourceValue.java19
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/Namespaces.java19
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/PluralXmlResourceValue.java26
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/PublicXmlResourceValue.java35
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/ResourcesAttribute.java42
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/SimpleXmlResourceValue.java153
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/StyleXmlResourceValue.java14
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/xml/StyleableXmlResourceValue.java49
38 files changed, 682 insertions, 783 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java b/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java
index 83b628cd9e..4ef23e76e2 100644
--- a/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java
@@ -125,83 +125,82 @@ public class Aapt2ResourcePackagingAction {
profiler.recordEndOf("merging");
-
- profiler.startTask("compile");
- final ResourceCompiler compiler =
- ResourceCompiler.create(
- executorService,
- compiledResources,
- aaptConfigOptions.aapt2,
- aaptConfigOptions.buildToolsVersion);
-
- CompiledResources compiled =
- options
- .primaryData
- .processDataBindings(
- options.dataBindingInfoOut, options.packageForR, databindingResourcesRoot)
- .compile(compiler, compiledResources)
- .processManifest(
- manifest ->
- AndroidManifestProcessor.with(STD_LOGGER)
- .processManifest(
- options.applicationId,
- options.versionCode,
- options.versionName,
- manifest,
- processedManifest))
- .processManifest(
- manifest ->
- new DensitySpecificManifestProcessor(densities, densityManifest)
- .process(manifest));
- profiler.recordEndOf("compile").startTask("link");
- // Write manifestOutput now before the dummy manifest is created.
- if (options.manifestOutput != null) {
- AndroidResourceOutputs.copyManifestToOutput(compiled, options.manifestOutput);
- }
-
- List<CompiledResources> compiledResourceDeps =
- // Last defined dependencies will overwrite previous one, so always place direct
- // after transitive.
- concat(options.transitiveData.stream(), options.directData.stream())
- .map(DependencyAndroidData::getCompiledSymbols)
- .collect(toList());
-
- List<Path> assetDirs =
- concat(options.transitiveData.stream(), options.directData.stream())
- .flatMap(dep -> dep.assetDirs.stream())
- .collect(toList());
- assetDirs.addAll(options.primaryData.assetDirs);
-
- final PackagedResources packagedResources =
- ResourceLinker.create(aaptConfigOptions.aapt2, linkedOut)
- .profileUsing(profiler)
- .customPackage(options.packageForR)
- .outputAsProto(aaptConfigOptions.resourceTableAsProto)
- .dependencies(ImmutableList.of(StaticLibrary.from(aaptConfigOptions.androidJar)))
- .include(compiledResourceDeps)
- .withAssets(assetDirs)
- .buildVersion(aaptConfigOptions.buildToolsVersion)
- .conditionalKeepRules(aaptConfigOptions.conditionalKeepRules == TriState.YES)
- .filterToDensity(densities)
- .includeOnlyConfigs(aaptConfigOptions.resourceConfigs)
- .link(compiled)
- .copyPackageTo(options.packagePath)
- .copyProguardTo(options.proguardOutput)
- .copyMainDexProguardTo(options.mainDexProguardOutput)
- .createSourceJar(options.srcJarOutput)
- .copyRTxtTo(options.rOutput);
- profiler.recordEndOf("link");
- if (options.resourcesOutput != null) {
- profiler.startTask("package");
- // The compiled resources and the merged resources should be the same.
- // TODO(corysmith): Decompile or otherwise provide the exact resources in the apk.
- ResourcesZip.fromApk(
- mergedAndroidData.getResourceDir(),
- packagedResources.getApk(),
- packagedResources.getResourceIds())
- .writeTo(options.resourcesOutput, false /* compress */);
- profiler.recordEndOf("package");
- }
+ profiler.startTask("compile");
+ final ResourceCompiler compiler =
+ ResourceCompiler.create(
+ executorService,
+ compiledResources,
+ aaptConfigOptions.aapt2,
+ aaptConfigOptions.buildToolsVersion);
+
+ CompiledResources compiled =
+ options
+ .primaryData
+ .processDataBindings(
+ options.dataBindingInfoOut, options.packageForR, databindingResourcesRoot)
+ .compile(compiler, compiledResources)
+ .processManifest(
+ manifest ->
+ AndroidManifestProcessor.with(STD_LOGGER)
+ .processManifest(
+ options.applicationId,
+ options.versionCode,
+ options.versionName,
+ manifest,
+ processedManifest))
+ .processManifest(
+ manifest ->
+ new DensitySpecificManifestProcessor(densities, densityManifest)
+ .process(manifest));
+ profiler.recordEndOf("compile").startTask("link");
+ // Write manifestOutput now before the dummy manifest is created.
+ if (options.manifestOutput != null) {
+ AndroidResourceOutputs.copyManifestToOutput(compiled, options.manifestOutput);
+ }
+
+ List<CompiledResources> compiledResourceDeps =
+ // Last defined dependencies will overwrite previous one, so always place direct
+ // after transitive.
+ concat(options.transitiveData.stream(), options.directData.stream())
+ .map(DependencyAndroidData::getCompiledSymbols)
+ .collect(toList());
+
+ List<Path> assetDirs =
+ concat(options.transitiveData.stream(), options.directData.stream())
+ .flatMap(dep -> dep.assetDirs.stream())
+ .collect(toList());
+ assetDirs.addAll(options.primaryData.assetDirs);
+
+ final PackagedResources packagedResources =
+ ResourceLinker.create(aaptConfigOptions.aapt2, linkedOut)
+ .profileUsing(profiler)
+ .customPackage(options.packageForR)
+ .outputAsProto(aaptConfigOptions.resourceTableAsProto)
+ .dependencies(ImmutableList.of(StaticLibrary.from(aaptConfigOptions.androidJar)))
+ .include(compiledResourceDeps)
+ .withAssets(assetDirs)
+ .buildVersion(aaptConfigOptions.buildToolsVersion)
+ .conditionalKeepRules(aaptConfigOptions.conditionalKeepRules == TriState.YES)
+ .filterToDensity(densities)
+ .includeOnlyConfigs(aaptConfigOptions.resourceConfigs)
+ .link(compiled)
+ .copyPackageTo(options.packagePath)
+ .copyProguardTo(options.proguardOutput)
+ .copyMainDexProguardTo(options.mainDexProguardOutput)
+ .createSourceJar(options.srcJarOutput)
+ .copyRTxtTo(options.rOutput);
+ profiler.recordEndOf("link");
+ if (options.resourcesOutput != null) {
+ profiler.startTask("package");
+ // The compiled resources and the merged resources should be the same.
+ // TODO(corysmith): Decompile or otherwise provide the exact resources in the apk.
+ ResourcesZip.fromApk(
+ mergedAndroidData.getResourceDir(),
+ packagedResources.getApk(),
+ packagedResources.getResourceIds())
+ .writeTo(options.resourcesOutput, false /* compress */);
+ profiler.recordEndOf("package");
}
}
}
+}
diff --git a/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java b/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java
index 20e9e6c9d7..3f3c35c029 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AarGeneratorAction.java
@@ -169,7 +169,7 @@ public class AarGeneratorAction {
null,
VariantType.LIBRARY,
null,
- /* filteredResources= */ ImmutableList.<String>of(),
+ /* filteredResources= */ ImmutableList.of(),
options.throwOnResourceConflict);
logger.fine(String.format("Merging finished at %dms", timer.elapsed(TimeUnit.MILLISECONDS)));
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java b/src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java
index fb4d93dcc6..0e6209b2c9 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidCompiledDataDeserializer.java
@@ -28,9 +28,6 @@ import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.LittleEndianDataInputStream;
import com.google.devtools.build.android.FullyQualifiedName.Factory;
-import com.google.devtools.build.android.proto.SerializeFormat;
-import com.google.devtools.build.android.proto.SerializeFormat.Header;
-import com.google.devtools.build.android.xml.ResourcesAttribute.AttributeType;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
@@ -80,7 +77,8 @@ public class AndroidCompiledDataDeserializer implements AndroidDataDeserializer
private void readResourceTable(
LittleEndianDataInputStream resourceTableStream,
KeyValueConsumers consumers,
- Factory fqnFactory) throws IOException {
+ Factory fqnFactory)
+ throws IOException {
long alignedSize = resourceTableStream.readLong();
Preconditions.checkArgument(alignedSize <= Integer.MAX_VALUE);
@@ -113,34 +111,27 @@ public class AndroidCompiledDataDeserializer implements AndroidDataDeserializer
new SimpleEntry<FullyQualifiedName, Boolean>(fqn, packageName.isEmpty()));
List<ConfigValue> configValues = resource.getConfigValueList();
- if (configValues.isEmpty()
- && resource.getVisibility().getLevel() == Level.PUBLIC) {
+ if (configValues.isEmpty() && resource.getVisibility().getLevel() == Level.PUBLIC) {
int sourceIndex = resource.getVisibility().getSource().getPathIdx();
String source = sourcePool.get(sourceIndex);
DataSource dataSource = DataSource.of(Paths.get(source));
- DataResourceXml dataResourceXml = DataResourceXml
- .fromPublic(dataSource, resourceType, resource.getEntryId().getId());
+ DataResourceXml dataResourceXml =
+ DataResourceXml.fromPublic(dataSource, resourceType, resource.getEntryId().getId());
consumers.combiningConsumer.accept(fqn, dataResourceXml);
- } else if (packageName.isEmpty()) {// This means this resource is not in the android sdk
+ } else if (packageName.isEmpty()) { // This means this resource is not in the android sdk
Preconditions.checkArgument(configValues.size() == 1);
- int sourceIndex =
- configValues.get(0)
- .getValue()
- .getSource()
- .getPathIdx();
+ int sourceIndex = configValues.get(0).getValue().getSource().getPathIdx();
String source = sourcePool.get(sourceIndex);
DataSource dataSource = DataSource.of(Paths.get(source));
Value resourceValue = resource.getConfigValue(0).getValue();
DataResourceXml dataResourceXml =
- DataResourceXml
- .from(resourceValue, dataSource, resourceType, fullyQualifiedNames);
+ DataResourceXml.from(resourceValue, dataSource, resourceType, fullyQualifiedNames);
- if (resourceType == ResourceType.ID
- || resourceType == ResourceType.STYLEABLE) {
+ if (resourceType == ResourceType.ID || resourceType == ResourceType.STYLEABLE) {
consumers.combiningConsumer.accept(fqn, dataResourceXml);
} else {
consumers.overwritingConsumer.accept(fqn, dataResourceXml);
@@ -165,13 +156,14 @@ public class AndroidCompiledDataDeserializer implements AndroidDataDeserializer
private void readCompiledFile(
LittleEndianDataInputStream compiledFileStream,
KeyValueConsumers consumers,
- Factory fqnFactory) throws IOException {
- //Skip aligned size. We don't need it here.
+ Factory fqnFactory)
+ throws IOException {
+ // Skip aligned size. We don't need it here.
Preconditions.checkArgument(compiledFileStream.skipBytes(8) == 8);
int resFileHeaderSize = compiledFileStream.readInt();
- //Skip data payload size. We don't need it here.
+ // Skip data payload size. We don't need it here.
Preconditions.checkArgument(compiledFileStream.skipBytes(8) == 8);
byte[] file = new byte[resFileHeaderSize];
@@ -201,35 +193,10 @@ public class AndroidCompiledDataDeserializer implements AndroidDataDeserializer
}
private void readAttributesFile(
- InputStream resourceFileStream,
- FileSystem fileSystem,
- KeyValueConsumers consumers) throws IOException {
-
- Header header = Header.parseDelimitedFrom(resourceFileStream);
- List<DataKey> fullyQualifiedNames = new ArrayList<>();
- for (int i = 0; i < header.getEntryCount(); i++) {
- SerializeFormat.DataKey protoKey =
- SerializeFormat.DataKey.parseDelimitedFrom(resourceFileStream);
- fullyQualifiedNames.add(FullyQualifiedName.fromProto(protoKey));
- }
-
- DataSourceTable sourceTable = DataSourceTable.read(resourceFileStream, fileSystem, header);
-
- for (DataKey fullyQualifiedName : fullyQualifiedNames) {
- SerializeFormat.DataValue protoValue =
- SerializeFormat.DataValue.parseDelimitedFrom(resourceFileStream);
- DataSource source = sourceTable.sourceFromId(protoValue.getSourceId());
- DataResourceXml dataResourceXml =
- (DataResourceXml) DataResourceXml.from(protoValue, source);
- AttributeType attributeType =
- AttributeType.valueOf(protoValue.getXmlValue().getValueType());
-
- if (attributeType.isCombining()) {
- consumers.combiningConsumer.accept(fullyQualifiedName, dataResourceXml);
- } else {
- consumers.overwritingConsumer.accept(fullyQualifiedName, dataResourceXml);
- }
- }
+ InputStream resourceFileStream, FileSystem fileSystem, KeyValueConsumers consumers)
+ throws IOException {
+ AndroidParsedDataDeserializer.deserializeEntries(
+ consumers, resourceFileStream, fileSystem, ImmutableSet.of());
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidDataSerializer.java b/src/tools/android/java/com/google/devtools/build/android/AndroidDataSerializer.java
index 2304f3cb67..9a1c3a07ac 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidDataSerializer.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidDataSerializer.java
@@ -13,17 +13,23 @@
// limitations under the License.
package com.google.devtools.build.android;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
import com.google.devtools.build.android.proto.SerializeFormat;
+import com.google.devtools.build.android.proto.SerializeFormat.DataValue.Builder;
import com.google.devtools.build.android.proto.SerializeFormat.Header;
+import com.google.devtools.build.android.xml.Namespaces;
import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Set;
@@ -33,6 +39,128 @@ import java.util.logging.Logger;
/** Serializes {@link DataKey},{@link DataValue} entries to a binary file. */
public class AndroidDataSerializer {
+
+ /** A visitor to accumulate the necessary state to write a resource entry. */
+ public interface SerializeEntryVisitor extends Writeable {
+ SerializeEntryVisitor setSource(DataSource dataSource);
+
+ SerializeEntryVisitor setKey(DataKey key);
+
+ SerializeEntryVisitor overwrite(Set<DataSource> dataSource);
+
+ SerializeEntryVisitor setXml(XmlResourceValue value);
+
+ SerializeEntryVisitor setNamespaces(Namespaces namespaces);
+ }
+
+ private static class DataValueBuilder implements SerializeEntryVisitor {
+
+ private final Builder builder;
+ private final WritablePool<DataKey> keys;
+ private final WritablePool<DataSource> sources;
+ private final WritablePool<XmlResourceValue> xml;
+ private final WritablePool<Namespaces> namespaces;
+
+ public DataValueBuilder(
+ Builder builder,
+ WritablePool<DataKey> keys,
+ WritablePool<DataSource> sources,
+ WritablePool<XmlResourceValue> xml,
+ WritablePool<Namespaces> namespaces) {
+ this.builder = Preconditions.checkNotNull(builder);
+ this.keys = Preconditions.checkNotNull(keys);
+ this.sources = sources;
+ this.xml = xml;
+ this.namespaces = namespaces;
+ }
+
+ static DataValueBuilder create(
+ WritablePool<DataKey> keys,
+ WritablePool<DataSource> sources,
+ WritablePool<XmlResourceValue> xml,
+ WritablePool<Namespaces> namespaces) {
+ return new DataValueBuilder(
+ SerializeFormat.DataValue.newBuilder(), keys, sources, xml, namespaces);
+ }
+
+ @Override
+ public SerializeEntryVisitor setSource(DataSource dataSource) {
+ builder.setSourceId(sources.queue(dataSource));
+ overwrite(dataSource.overrides());
+ return this;
+ }
+
+ @Override
+ public SerializeEntryVisitor setKey(DataKey key) {
+ builder.setKeyId(keys.queue(key));
+ return this;
+ }
+
+ @Override
+ public SerializeEntryVisitor overwrite(Set<DataSource> dataSource) {
+ for (DataSource source : dataSource) {
+ builder.addOverwrittenSourceId(sources.queue(source));
+ }
+ return this;
+ }
+
+ @Override
+ public SerializeEntryVisitor setXml(XmlResourceValue value) {
+ builder.setXmlId(xml.queue(value));
+ return this;
+ }
+
+ @Override
+ public SerializeEntryVisitor setNamespaces(Namespaces namespaces) {
+ builder.setNamespaceId(this.namespaces.queue(namespaces));
+ return this;
+ }
+
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ builder.build().writeDelimitedTo(out);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("builder", builder.build())
+ .add("keys", keys)
+ .add("sources", sources)
+ .add("xml", xml)
+ .add("namespaces", namespaces)
+ .toString();
+ }
+ }
+
+ private static class WritablePool<T extends Writeable> implements Writeable {
+ BiMap<T, Integer> lookup = HashBiMap.create();
+ Integer lastIndex = 0;
+
+ Integer queue(T value) {
+ if (!lookup.containsKey(value)) {
+ lookup.put(value, lastIndex++);
+ }
+ return lookup.get(value);
+ }
+
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ final BiMap<Integer, T> indexed = lookup.inverse();
+ for (int idx = 0; idx < lastIndex; idx++) {
+ indexed.get(idx).writeTo(out);
+ }
+ }
+
+ public int size() {
+ return lookup.size();
+ }
+
+ public static <T extends Writeable> WritablePool<T> create() {
+ return new WritablePool<>();
+ }
+ }
+
private static final Logger logger = Logger.getLogger(AndroidDataSerializer.class.getName());
private final NavigableMap<DataKey, DataValue> entries = new TreeMap<>();
@@ -63,52 +191,59 @@ public class AndroidDataSerializer {
if (out.getParent() != null) {
Files.createDirectories(out.getParent());
}
+ WritablePool<DataKey> keys = WritablePool.create();
+ WritablePool<DataSource> sources = WritablePool.create();
+ WritablePool<XmlResourceValue> xml = WritablePool.create();
+ WritablePool<Namespaces> namespaces = WritablePool.create();
+
try (OutputStream outStream =
new BufferedOutputStream(
Files.newOutputStream(out, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE))) {
// Set the header for the deserialization process.
- SerializeFormat.Header.Builder headerBuilder =
- Header.newBuilder().setEntryCount(entries.size());
- // Create table of source paths to allow references in the serialization format via an index.
- ByteArrayOutputStream sourceTableOutputStream = new ByteArrayOutputStream(2048);
- DataSourceTable sourceTable =
- DataSourceTable.createAndWrite(entries, sourceTableOutputStream, headerBuilder);
+ List<SerializeEntryVisitor> values = new ArrayList<>(entries.size());
+ for (Entry<DataKey, DataValue> entry : entries.entrySet()) {
+ values.add(
+ entry
+ .getValue()
+ .serializeTo(
+ DataValueBuilder.create(keys, sources, xml, namespaces)
+ .setKey(entry.getKey())));
+ }
- headerBuilder.build().writeDelimitedTo(outStream);
+ Header.newBuilder()
+ .setKeyCount(keys.size())
+ .setSourceCount(sources.size())
+ .setValueCount(values.size())
+ .setXmlCount(xml.size())
+ .setNamespacesCount(namespaces.size())
+ .build()
+ .writeDelimitedTo(outStream);
- writeKeyValuesTo(entries, outStream, sourceTable, sourceTableOutputStream.toByteArray());
- }
- logger.fine(String.format("Serialized merged in %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
- }
+ /*
+ Serialization order:
+ keys
+ sources
+ values
+ xml
+ namespaces
- private void writeKeyValuesTo(
- NavigableMap<DataKey, DataValue> map,
- OutputStream outStream,
- DataSourceTable sourceTable,
- byte[] sourceTableBytes)
- throws IOException {
- Set<Entry<DataKey, DataValue>> entries = map.entrySet();
- int[] orderedValueSizes = new int[entries.size()];
- int valueSizeIndex = 0;
- // Serialize all the values in sorted order to a intermediate buffer, so that the keys
- // can be associated with a value size.
- // TODO(corysmith): Tune the size of the byte array.
- ByteArrayOutputStream valuesOutputStream = new ByteArrayOutputStream(2048);
- for (Map.Entry<DataKey, DataValue> entry : entries) {
- orderedValueSizes[valueSizeIndex++] =
- entry.getValue().serializeTo(sourceTable, valuesOutputStream);
- }
- // Serialize all the keys in sorted order
- valueSizeIndex = 0;
- for (Map.Entry<DataKey, DataValue> entry : entries) {
- entry.getKey().serializeTo(outStream, orderedValueSizes[valueSizeIndex++]);
+ This allows deserializing keys for R generation, as well as sources and entries for
+ lightweight merging.
+ */
+
+ keys.writeTo(outStream);
+ sources.writeTo(outStream);
+ for (SerializeEntryVisitor value : values) {
+ value.writeTo(outStream);
+ }
+ xml.writeTo(outStream);
+ namespaces.writeTo(outStream);
+
+ outStream.flush();
}
- // write the source table
- outStream.write(sourceTableBytes);
- // write the values to the output stream.
- outStream.write(valuesOutputStream.toByteArray());
+ logger.fine(String.format("Serialized merged in %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
}
/** Queues the key and value for serialization as a entries entry. */
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java b/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java
index 38d38f3aa0..a9770f76cd 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidDataWriter.java
@@ -654,7 +654,7 @@ public class AndroidDataWriter implements AndroidDataWritingVisitor {
}
/** Base interface for writing information to a {@link Writer}. */
- private static interface Segment {
+ private interface Segment {
/**
* Writes the segment contents to a Writer
*
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidParsedDataDeserializer.java b/src/tools/android/java/com/google/devtools/build/android/AndroidParsedDataDeserializer.java
index e704c06552..3ded0da24f 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidParsedDataDeserializer.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidParsedDataDeserializer.java
@@ -15,7 +15,6 @@ package com.google.devtools.build.android;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
@@ -24,6 +23,9 @@ import com.google.devtools.build.android.ParsedAndroidData.Builder;
import com.google.devtools.build.android.ParsedAndroidData.KeyValueConsumer;
import com.google.devtools.build.android.proto.SerializeFormat;
import com.google.devtools.build.android.proto.SerializeFormat.Header;
+import com.google.devtools.build.android.proto.SerializeFormat.ProtoSource;
+import com.google.devtools.build.android.proto.SerializeFormat.XmlNamespaces;
+import com.google.devtools.build.android.xml.Namespaces;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
@@ -34,12 +36,11 @@ import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
/** Deserializes {@link DataKey}, {@link DataValue} entries from a binary file. */
public class AndroidParsedDataDeserializer implements AndroidDataDeserializer {
@@ -87,7 +88,7 @@ public class AndroidParsedDataDeserializer implements AndroidDataDeserializer {
}
public static AndroidParsedDataDeserializer create() {
- return new AndroidParsedDataDeserializer(ImmutableSet.<String>of());
+ return new AndroidParsedDataDeserializer(ImmutableSet.of());
}
private AndroidParsedDataDeserializer(ImmutableSet<String> filteredResources) {
@@ -108,12 +109,8 @@ public class AndroidParsedDataDeserializer implements AndroidDataDeserializer {
Stopwatch timer = Stopwatch.createStarted();
try (InputStream in = Files.newInputStream(inPath, StandardOpenOption.READ)) {
FileSystem currentFileSystem = inPath.getFileSystem();
- Header header = Header.parseDelimitedFrom(in);
- if (header == null) {
- throw new DeserializationException("No Header found in " + inPath);
- }
- readEntriesSegment(consumers, in, currentFileSystem, header);
- } catch (IOException e) {
+ deserializeEntries(consumers, in, currentFileSystem, filteredResources);
+ } catch (Throwable e) {
throw new DeserializationException("Error deserializing " + inPath, e);
} finally {
logger.fine(
@@ -121,59 +118,103 @@ public class AndroidParsedDataDeserializer implements AndroidDataDeserializer {
}
}
- private void readEntriesSegment(
- KeyValueConsumers consumers, InputStream in, FileSystem currentFileSystem, Header header)
+ public static void deserializeEntries(
+ KeyValueConsumers consumers,
+ InputStream in,
+ FileSystem currentFileSystem,
+ ImmutableSet<String> filteredResources)
throws IOException {
- int numberOfEntries = header.getEntryCount();
- Map<DataKey, KeyValueConsumer<DataKey, ? extends DataValue>> keys =
- Maps.newLinkedHashMapWithExpectedSize(numberOfEntries);
- for (int i = 0; i < numberOfEntries; i++) {
- SerializeFormat.DataKey protoKey = SerializeFormat.DataKey.parseDelimitedFrom(in);
- if (protoKey.hasResourceType()) {
- FullyQualifiedName resourceName = FullyQualifiedName.fromProto(protoKey);
- keys.put(
- resourceName,
- resourceName.isOverwritable()
- ? consumers.overwritingConsumer
- : consumers.combiningConsumer);
- } else {
- keys.put(RelativeAssetPath.fromProto(protoKey, currentFileSystem), consumers.assetConsumer);
- }
+
+ /*
+ Serialization order:
+ header
+ keys
+ sources
+ values
+ xml
+ namespaces
+ */
+
+ Header header = Header.parseDelimitedFrom(in);
+ if (header == null) {
+ throw new DeserializationException("Invalid Format: no header");
+ }
+
+ DataKey[] keys = new DataKey[header.getKeyCount()];
+ for (int i = 0; i < header.getKeyCount(); i++) {
+ final SerializeFormat.DataKey proto = SerializeFormat.DataKey.parseDelimitedFrom(in);
+ keys[i] =
+ proto.hasResourceType()
+ ? FullyQualifiedName.fromProto(proto)
+ : RelativeAssetPath.fromProto(proto, currentFileSystem);
+ }
+
+ DataSource[] sources = new DataSource[header.getSourceCount()];
+ for (int i = 0; i < header.getSourceCount(); i++) {
+ sources[i] = DataSource.from(ProtoSource.parseDelimitedFrom(in), currentFileSystem);
}
- // Read back the sources table.
- DataSourceTable sourceTable = DataSourceTable.read(in, currentFileSystem, header);
-
- // TODO(corysmith): Make this a lazy read of the values.
- for (Entry<DataKey, KeyValueConsumer<DataKey, ?>> entry : keys.entrySet()) {
- SerializeFormat.DataValue protoValue = SerializeFormat.DataValue.parseDelimitedFrom(in);
- DataSource source = sourceTable.sourceFromId(protoValue.getSourceId());
- // Compose the `shortPath` manually to ensure it uses a forward slash.
- // Using Path.subpath would return a backslash-using path on Windows.
- String shortPath =
- source.getPath().getParent().getFileName() + "/" + source.getPath().getFileName();
- if (filteredResources.contains(shortPath) && !Files.exists(source.getPath())) {
- // Skip files that were filtered out during analysis.
- // TODO(asteinb): Properly filter out these files from android_library symbol files during
- // analysis instead, and remove this list.
+ List<SerializeFormat.DataValue> values = new ArrayList<>(header.getValueCount());
+ for (int i = 0; i < header.getValueCount(); i++) {
+ final SerializeFormat.DataValue protoValue = SerializeFormat.DataValue.parseDelimitedFrom(in);
+ if (sources[protoValue.getSourceId()].shouldFilter(filteredResources)) {
continue;
}
- if (protoValue.hasXmlValue()) {
- // TODO(corysmith): Figure out why the generics are wrong.
- // If I use Map<DataKey, KeyValueConsumer<DataKey, ? extends DataValue>>, I can put
- // consumers into the map, but I can't call accept.
- // If I use Map<DataKey, KeyValueConsumer<DataKey, ? super DataValue>>, I can consume
- // but I can't put.
- // Same for below.
- @SuppressWarnings("unchecked")
- KeyValueConsumer<DataKey, DataValue> value =
- (KeyValueConsumer<DataKey, DataValue>) entry.getValue();
- value.accept(entry.getKey(), DataResourceXml.from(protoValue, source));
- } else {
- @SuppressWarnings("unchecked")
- KeyValueConsumer<DataKey, DataValue> value =
- (KeyValueConsumer<DataKey, DataValue>) entry.getValue();
- value.accept(entry.getKey(), DataValueFile.of(source));
+ values.add(protoValue);
+ }
+
+ XmlResourceValue[] xml = new XmlResourceValue[header.getXmlCount()];
+ for (int i = 0; i < header.getXmlCount(); i++) {
+ xml[i] =
+ XmlResourceValues.valueFromProto(SerializeFormat.DataValueXml.parseDelimitedFrom(in));
+ }
+
+ Namespaces[] namespaces = new Namespaces[header.getNamespacesCount()];
+ for (int i = 0; i < header.getNamespacesCount(); i++) {
+ final XmlNamespaces proto = XmlNamespaces.parseDelimitedFrom(in);
+ namespaces[i] = Namespaces.fromProto(proto);
+ }
+
+ for (SerializeFormat.DataValue protoValue : values) {
+ final DataSource dataSource =
+ sources[protoValue.getSourceId()].overwrite(
+ protoValue
+ .getOverwrittenSourceIdList()
+ .stream()
+ .map(sourceId -> sources[sourceId])
+ .collect(Collectors.toList())
+ .toArray(new DataSource[0]));
+
+ final DataKey dataKey = keys[protoValue.getKeyId()];
+
+ switch (dataKey.getKeyType()) {
+ case ASSET_PATH:
+ consumers.assetConsumer.accept(dataKey, DataValueFile.of(dataSource));
+ break;
+ case FULL_QUALIFIED_NAME:
+ final FullyQualifiedName fullyQualifiedName = (FullyQualifiedName) dataKey;
+
+ KeyValueConsumer<DataKey, DataResource> consumer =
+ fullyQualifiedName.isOverwritable()
+ ? consumers.overwritingConsumer
+ : consumers.combiningConsumer;
+
+ if (!protoValue.hasXmlId()) {
+ consumer.accept(dataKey, DataValueFile.of(dataSource));
+ } else {
+ consumer.accept(
+ fullyQualifiedName,
+ protoValue.hasNamespaceId()
+ ? DataResourceXml.createWithNamespaces(
+ dataSource,
+ xml[protoValue.getXmlId()],
+ namespaces[protoValue.getNamespaceId()])
+ : DataResourceXml.createWithNoNamespace(
+ dataSource, xml[protoValue.getXmlId()]));
+ }
+ break;
+ default:
+ throw new DeserializationException("Unknown key type " + dataKey);
}
}
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceParsingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceParsingAction.java
index e2a98e4f13..ce5cb77147 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceParsingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceParsingAction.java
@@ -83,7 +83,7 @@ public class AndroidResourceParsingAction {
logger.fine(String.format("Walked XML tree at %dms", timer.elapsed(TimeUnit.MILLISECONDS)));
UnwrittenMergedAndroidData unwrittenData =
UnwrittenMergedAndroidData.of(
- null, parsedPrimary, ParsedAndroidData.from(ImmutableList.<DependencyAndroidData>of()));
+ null, parsedPrimary, ParsedAndroidData.from(ImmutableList.of()));
AndroidDataSerializer serializer = AndroidDataSerializer.create();
unwrittenData.serializeTo(serializer);
serializer.flushTo(options.output);
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java
index 23f1671a07..970c7bc512 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java
@@ -162,7 +162,7 @@ public class AndroidResourceValidatorAction {
options.packageForR,
new FlagAaptOptions(aaptConfigOptions),
aaptConfigOptions.resourceConfigs,
- ImmutableList.<String>of(),
+ ImmutableList.of(),
dummyManifest,
resources,
assets,
diff --git a/src/tools/android/java/com/google/devtools/build/android/Converters.java b/src/tools/android/java/com/google/devtools/build/android/Converters.java
index e58dd2d29b..75c5ead21e 100644
--- a/src/tools/android/java/com/google/devtools/build/android/Converters.java
+++ b/src/tools/android/java/com/google/devtools/build/android/Converters.java
@@ -218,7 +218,7 @@ public final class Converters {
@Override
public List<DependencySymbolFileProvider> convert(String input) throws OptionsParsingException {
if (input.isEmpty()) {
- return ImmutableList.<DependencySymbolFileProvider>of();
+ return ImmutableList.of();
}
try {
ImmutableList.Builder<DependencySymbolFileProvider> builder = ImmutableList.builder();
@@ -473,7 +473,7 @@ public final class Converters {
@Override
public List<StaticLibrary> convert(String input) throws OptionsParsingException {
- final Builder<StaticLibrary> builder = ImmutableList.<StaticLibrary>builder();
+ final Builder<StaticLibrary> builder = ImmutableList.builder();
for (String path : SPLITTER.splitToList(input)) {
builder.add(libraryConverter.convert(path));
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/DataKey.java b/src/tools/android/java/com/google/devtools/build/android/DataKey.java
index 02f193c0f7..f8a76a5768 100644
--- a/src/tools/android/java/com/google/devtools/build/android/DataKey.java
+++ b/src/tools/android/java/com/google/devtools/build/android/DataKey.java
@@ -13,9 +13,6 @@
// limitations under the License.
package com.google.devtools.build.android;
-import java.io.IOException;
-import java.io.OutputStream;
-
/**
* A general interface for resource and asset keys.
*
@@ -26,16 +23,7 @@ import java.io.OutputStream;
*
* <p>For Assets, it is the asset path from the assets directory.
*/
-public interface DataKey extends Comparable<DataKey> {
-
- /**
- * Writes the Key and the value size to a stream.
- *
- * @param output The destination stream to serialize the key.
- * @param valueSize The size, in bytes, of the serialized output for this key. The value size can
- * be used for calculating offsets of the value in the stream.
- */
- void serializeTo(OutputStream output, int valueSize) throws IOException;
+public interface DataKey extends Comparable<DataKey>, Writeable {
/** Returns a human readable string representation of the key. */
String toPrettyString();
diff --git a/src/tools/android/java/com/google/devtools/build/android/DataResourceXml.java b/src/tools/android/java/com/google/devtools/build/android/DataResourceXml.java
index 2b39c449e6..eade76072a 100644
--- a/src/tools/android/java/com/google/devtools/build/android/DataResourceXml.java
+++ b/src/tools/android/java/com/google/devtools/build/android/DataResourceXml.java
@@ -20,13 +20,11 @@ import static com.android.resources.ResourceType.PUBLIC;
import com.android.aapt.Resources.Value;
import com.android.resources.ResourceType;
import com.google.common.base.MoreObjects;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.android.AndroidDataSerializer.SerializeEntryVisitor;
import com.google.devtools.build.android.FullyQualifiedName.Factory;
import com.google.devtools.build.android.FullyQualifiedName.VirtualType;
import com.google.devtools.build.android.ParsedAndroidData.KeyValueConsumer;
-import com.google.devtools.build.android.proto.SerializeFormat;
-import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml;
import com.google.devtools.build.android.xml.ArrayXmlResourceValue;
import com.google.devtools.build.android.xml.AttrXmlResourceValue;
import com.google.devtools.build.android.xml.IdXmlResourceValue;
@@ -40,7 +38,6 @@ import com.google.devtools.build.android.xml.StyleableXmlResourceValue;
import com.google.protobuf.InvalidProtocolBufferException;
import java.io.BufferedInputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -161,15 +158,6 @@ public class DataResourceXml implements DataResource {
}
}
- @SuppressWarnings("deprecation")
- // TODO(corysmith): Update proto to use get<>Map
- public static DataValue from(SerializeFormat.DataValue protoValue, DataSource source)
- throws InvalidProtocolBufferException {
- DataValueXml xmlValue = protoValue.getXmlValue();
- return createWithNamespaces(
- source, valueFromProto(xmlValue), Namespaces.from(xmlValue.getNamespace()));
- }
-
public static DataResourceXml from(
Value protoValue,
DataSource source,
@@ -184,33 +172,6 @@ public class DataResourceXml implements DataResource {
return dataResourceXml;
}
- private static XmlResourceValue valueFromProto(SerializeFormat.DataValueXml proto)
- throws InvalidProtocolBufferException {
- Preconditions.checkArgument(proto.hasType());
- switch (proto.getType()) {
- case ARRAY:
- return ArrayXmlResourceValue.from(proto);
- case SIMPLE:
- return SimpleXmlResourceValue.from(proto);
- case ATTR:
- return AttrXmlResourceValue.from(proto);
- case ID:
- return IdXmlResourceValue.of();
- case PLURAL:
- return PluralXmlResourceValue.from(proto);
- case PUBLIC:
- return PublicXmlResourceValue.from(proto);
- case STYLE:
- return StyleXmlResourceValue.from(proto);
- case STYLEABLE:
- return StyleableXmlResourceValue.from(proto);
- case RESOURCES_ATTRIBUTE:
- return ResourcesAttribute.from(proto);
- default:
- throw new IllegalArgumentException();
- }
- }
-
private static XmlResourceValue valueFromProto(
Value proto,
ResourceType resourceType,
@@ -327,7 +288,7 @@ public class DataResourceXml implements DataResource {
}
public static DataResourceXml createWithNoNamespace(Path sourcePath, XmlResourceValue xml) {
- return createWithNamespaces(sourcePath, xml, ImmutableMap.<String, String>of());
+ return createWithNamespaces(sourcePath, xml, ImmutableMap.of());
}
public static DataResourceXml createWithNoNamespace(DataSource source, XmlResourceValue xml) {
@@ -391,9 +352,8 @@ public class DataResourceXml implements DataResource {
}
@Override
- public int serializeTo(DataSourceTable sourceTable, OutputStream outStream)
- throws IOException {
- return xml.serializeTo(sourceTable.getSourceId(source), namespaces, outStream);
+ public SerializeEntryVisitor serializeTo(SerializeEntryVisitor visitor) {
+ return visitor.setXml(xml).setSource(source).setNamespaces(namespaces);
}
// TODO(corysmith): Clean up all the casting. The type structure is unclean.
diff --git a/src/tools/android/java/com/google/devtools/build/android/DataSource.java b/src/tools/android/java/com/google/devtools/build/android/DataSource.java
index 16c79d7f81..994935484a 100644
--- a/src/tools/android/java/com/google/devtools/build/android/DataSource.java
+++ b/src/tools/android/java/com/google/devtools/build/android/DataSource.java
@@ -17,17 +17,20 @@ import com.android.SdkConstants;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.android.proto.SerializeFormat;
import com.google.devtools.build.android.proto.SerializeFormat.ProtoSource;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributeView;
+import java.util.Set;
/** Represents where the DataValue was derived from. */
-public class DataSource implements Comparable<DataSource> {
+public class DataSource implements Comparable<DataSource>, Writeable {
public static DataSource from(ProtoSource protoSource, FileSystem currentFileSystem) {
Path path = currentFileSystem.getPath(protoSource.getFilename());
@@ -35,7 +38,7 @@ public class DataSource implements Comparable<DataSource> {
}
public static DataSource of(Path sourcePath) {
- return new DataSource(sourcePath, ImmutableSet.<DataSource>of());
+ return new DataSource(sourcePath, ImmutableSet.of());
}
private final Path path;
@@ -98,6 +101,9 @@ public class DataSource implements Comparable<DataSource> {
}
public DataSource overwrite(DataSource... sources) {
+ if (sources.length == 0) {
+ return this;
+ }
ImmutableSet.Builder<DataSource> overridesBuilder =
ImmutableSet.<DataSource>builder().addAll(this.overrides);
for (DataSource dataSource : sources) {
@@ -137,4 +143,19 @@ public class DataSource implements Comparable<DataSource> {
public String asConflictString() {
return path.toString();
}
+
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ SerializeFormat.ProtoSource.newBuilder()
+ .setFilename(path.toString())
+ .build()
+ .writeDelimitedTo(out);
+ }
+
+ public boolean shouldFilter(Set<String> filteredResources) {
+ return filteredResources.contains(path.getParent().getFileName() + "/" + path.getFileName())
+ // Since the filtered resources short path could match multiple sources, check to make sure
+ // the source doesn't exist.
+ && !Files.exists(path);
+ }
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/DataSourceTable.java b/src/tools/android/java/com/google/devtools/build/android/DataSourceTable.java
deleted file mode 100644
index ac953da711..0000000000
--- a/src/tools/android/java/com/google/devtools/build/android/DataSourceTable.java
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2016 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
-//
-// 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.google.devtools.build.android;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.devtools.build.android.proto.SerializeFormat;
-import com.google.devtools.build.android.proto.SerializeFormat.Header;
-import com.google.devtools.build.android.proto.SerializeFormat.ProtoSource;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.FileSystem;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.NavigableMap;
-import java.util.stream.Collectors;
-
-/**
- * Tracks mappings from resource source paths (/foo/bar/res/values/colors.xml) to an ID for a more
- * compact serialization format.
- */
-class DataSourceTable {
-
- private static final Function<DataValue, DataSource> VALUE_TO_SOURCE = DataValue::source;
- private final Map<DataSource, Integer> sourceTable = new LinkedHashMap<>();
- private DataSource[] idToSource;
-
- /**
- * Creates a DataSourceTable and serialize to the given outstream. Assigns each resource source
- * path a number to enable {@link #getSourceId(DataSource)} queries.
- *
- * @param map the final map of resources
- * @param outStream stream to serialize the source table
- * @param headerBuilder the header to serialize
- * @throws IOException if this fails to serialize the table to the outStream
- */
- public static DataSourceTable createAndWrite(
- NavigableMap<DataKey, DataValue> map, OutputStream outStream, Header.Builder headerBuilder)
- throws IOException {
- DataSourceTable sourceTable = new DataSourceTable();
- sourceTable.writeSourceInfo(map, outStream);
- sourceTable.setHeader(headerBuilder);
- return sourceTable;
- }
-
- /** Convert the absolute source path to the source table index */
- public int getSourceId(DataSource source) {
- return sourceTable.get(source);
- }
-
- private void writeSourceInfo(NavigableMap<DataKey, DataValue> map, OutputStream outStream)
- throws IOException {
- int sourceNumber = 0;
- LinkedList<DataSource> sourceQueue =
- map.values()
- .stream()
- .map(VALUE_TO_SOURCE)
- .collect(Collectors.toCollection(LinkedList::new));
- while (!sourceQueue.isEmpty()) {
- DataSource source = sourceQueue.pop();
- if (!sourceTable.containsKey(source)) {
- sourceTable.put(source, sourceNumber);
- ++sourceNumber;
- sourceQueue.addAll(source.overrides());
- }
- }
- for (DataSource dataSource : sourceTable.keySet()) {
- ProtoSource.newBuilder()
- .setFilename(dataSource.getPath().toString())
- .addAllOverwritten(sourcesToIds(dataSource.overrides()))
- .build()
- .writeDelimitedTo(outStream);
- }
- }
-
- private List<Integer> sourcesToIds(ImmutableSet<DataSource> overrides) {
- ImmutableList.Builder<Integer> idsBuilder = ImmutableList.builder();
- for (DataSource dataSource : overrides) {
- if (!sourceTable.containsKey(dataSource)) {
- throw new IllegalArgumentException(
- "Cannot find data source: " + dataSource.toString() + " in " + sourceTable.keySet());
- }
- idsBuilder.add(sourceTable.get(dataSource));
- }
- return idsBuilder.build();
- }
-
- /** Fill in the serialize format header information required to deserialize */
- private Header.Builder setHeader(Header.Builder headerBuilder) {
- return headerBuilder.setSourceCount(sourceTable.size());
- }
-
- /** Deserialize the source table and allow {@link #sourceFromId(int)} queries. */
- public static DataSourceTable read(InputStream in, FileSystem currentFileSystem, Header header)
- throws IOException {
- DataSourceTable sourceTable = new DataSourceTable();
- sourceTable.readSourceInfo(in, currentFileSystem, header);
- return sourceTable;
- }
-
- /** Convert the source ID to full Path */
- public DataSource sourceFromId(int sourceId) {
- return idToSource[sourceId];
- }
-
- private void readSourceInfo(InputStream in, FileSystem currentFileSystem, Header header)
- throws IOException {
- int numberOfSources = header.getSourceCount();
- // Read back the sources.
- idToSource = new DataSource[numberOfSources];
- for (int i = 0; i < numberOfSources; i++) {
- ProtoSource protoSource = SerializeFormat.ProtoSource.parseDelimitedFrom(in);
- idToSource[i] = DataSource.from(protoSource, currentFileSystem);
- }
- }
-}
diff --git a/src/tools/android/java/com/google/devtools/build/android/DataValue.java b/src/tools/android/java/com/google/devtools/build/android/DataValue.java
index de9574508b..2a2bc51826 100644
--- a/src/tools/android/java/com/google/devtools/build/android/DataValue.java
+++ b/src/tools/android/java/com/google/devtools/build/android/DataValue.java
@@ -13,8 +13,8 @@
// limitations under the License.
package com.google.devtools.build.android;
+import com.google.devtools.build.android.AndroidDataSerializer.SerializeEntryVisitor;
import java.io.IOException;
-import java.io.OutputStream;
/**
* Represents the value associated with DataKey interface for resource and asset values.
@@ -28,9 +28,8 @@ public interface DataValue {
*/
DataSource source();
- /** Serializes to a supplied stream and returns the number of bytes written. */
- int serializeTo(
- DataSourceTable sourceTable, OutputStream output) throws IOException;
+ /** Serializes the value to the entry visitor. */
+ SerializeEntryVisitor serializeTo(SerializeEntryVisitor visitor) throws IOException;
DataValue update(DataSource source);
diff --git a/src/tools/android/java/com/google/devtools/build/android/DataValueFile.java b/src/tools/android/java/com/google/devtools/build/android/DataValueFile.java
index 3270e3ced0..9a1792f447 100644
--- a/src/tools/android/java/com/google/devtools/build/android/DataValueFile.java
+++ b/src/tools/android/java/com/google/devtools/build/android/DataValueFile.java
@@ -14,11 +14,10 @@
package com.google.devtools.build.android;
import com.google.common.base.MoreObjects;
+import com.google.devtools.build.android.AndroidDataSerializer.SerializeEntryVisitor;
import com.google.devtools.build.android.AndroidResourceMerger.MergingException;
import com.google.devtools.build.android.proto.SerializeFormat;
-import com.google.protobuf.CodedOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.nio.file.Path;
import java.util.Objects;
@@ -85,13 +84,8 @@ public class DataValueFile implements DataResource, DataAsset {
}
@Override
- public int serializeTo(DataSourceTable sourceTable, OutputStream output)
- throws IOException {
- SerializeFormat.DataValue.Builder builder = SerializeFormat.DataValue.newBuilder();
- SerializeFormat.DataValue value = builder.setSourceId(sourceTable.getSourceId(source)).build();
- value.writeDelimitedTo(output);
- return CodedOutputStream.computeUInt32SizeNoTag(value.getSerializedSize())
- + value.getSerializedSize();
+ public SerializeEntryVisitor serializeTo(SerializeEntryVisitor visitor) {
+ return visitor.setSource(source);
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/DependencyAndroidData.java b/src/tools/android/java/com/google/devtools/build/android/DependencyAndroidData.java
index b4d4b99b3f..2a770464be 100644
--- a/src/tools/android/java/com/google/devtools/build/android/DependencyAndroidData.java
+++ b/src/tools/android/java/com/google/devtools/build/android/DependencyAndroidData.java
@@ -54,7 +54,7 @@ class DependencyAndroidData extends SerializedAndroidData {
// The local symbols.bin is optional -- if it is missing, we'll use the full R.txt
Path rTxt = exists(fileSystem.getPath(parts[3]));
ImmutableList<Path> assetDirs =
- parts[1].length() == 0 ? ImmutableList.<Path>of() : splitPaths(parts[1], fileSystem);
+ parts[1].length() == 0 ? ImmutableList.of() : splitPaths(parts[1], fileSystem);
CompiledResources compiledSymbols = null;
Path symbolsBin = null;
diff --git a/src/tools/android/java/com/google/devtools/build/android/DeserializationException.java b/src/tools/android/java/com/google/devtools/build/android/DeserializationException.java
index 8c6e5990c9..098f4f5316 100644
--- a/src/tools/android/java/com/google/devtools/build/android/DeserializationException.java
+++ b/src/tools/android/java/com/google/devtools/build/android/DeserializationException.java
@@ -13,7 +13,6 @@
// limitations under the License.
package com.google.devtools.build.android;
-import java.io.IOException;
/** Thrown when there is an error during deserialization. */
public class DeserializationException extends RuntimeException {
@@ -30,7 +29,7 @@ public class DeserializationException extends RuntimeException {
this.isLegacy = false;
}
- public DeserializationException(IOException e) {
+ public DeserializationException(Throwable e) {
super(e);
this.isLegacy = false;
}
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 9344412390..d0a5545b4f 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
@@ -264,11 +264,6 @@ public class FullyQualifiedName implements DataKey {
return KeyType.FULL_QUALIFIED_NAME;
}
- @Override
- public void serializeTo(OutputStream out, int valueSize) throws IOException {
- toSerializedBuilder().setValueSize(valueSize).build().writeDelimitedTo(out);
- }
-
public SerializeFormat.DataKey.Builder toSerializedBuilder() {
return SerializeFormat.DataKey.newBuilder()
.setKeyPackage(pkg)
@@ -277,6 +272,11 @@ public class FullyQualifiedName implements DataKey {
.setKeyValue(name);
}
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ toSerializedBuilder().build().writeDelimitedTo(out);
+ }
+
/** The non-resource {@link Type}s of a {@link FullyQualifiedName}. */
public enum VirtualType implements Type {
RESOURCES_ATTRIBUTE("<resources>", "Resources Attribute");
@@ -284,7 +284,7 @@ public class FullyQualifiedName implements DataKey {
private final String name;
private final String displayName;
- private VirtualType(String name, String displayName) {
+ VirtualType(String name, String displayName) {
this.name = name;
this.displayName = displayName;
}
@@ -349,31 +349,31 @@ public class FullyQualifiedName implements DataKey {
/** Represents the type of a {@link FullyQualifiedName}. */
public interface Type {
- public String getName();
+ String getName();
- public ConcreteType getType();
+ ConcreteType getType();
- public boolean isOverwritable(FullyQualifiedName fqn);
+ boolean isOverwritable(FullyQualifiedName fqn);
- public int compareTo(Type other);
+ int compareTo(Type other);
@Override
- public boolean equals(Object obj);
+ boolean equals(Object obj);
@Override
- public int hashCode();
+ int hashCode();
@Override
- public String toString();
+ String toString();
/**
* 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 {
+ enum ConcreteType {
RESOURCE_TYPE,
- VIRTUAL_TYPE;
+ VIRTUAL_TYPE
}
}
@@ -511,7 +511,7 @@ public class FullyQualifiedName implements DataKey {
// This is fragile but better than the Gradle scheme of just dropping
// entire subtrees.
- Builder<String> builder = ImmutableList.<String>builder();
+ Builder<String> builder = ImmutableList.builder();
addIfNotNull(config.getCountryCodeQualifier(), builder);
addIfNotNull(config.getNetworkCodeQualifier(), builder);
if (transformedLocaleQualifiers.isEmpty()) {
diff --git a/src/tools/android/java/com/google/devtools/build/android/ManifestMergerAction.java b/src/tools/android/java/com/google/devtools/build/android/ManifestMergerAction.java
index a7301f1030..b8249dcda6 100644
--- a/src/tools/android/java/com/google/devtools/build/android/ManifestMergerAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/ManifestMergerAction.java
@@ -41,7 +41,6 @@ import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
@@ -162,8 +161,8 @@ public class ManifestMergerAction {
private static Options options;
private static Path removePermissions(Path manifest, Path outputDir)
- throws IOException, ParserConfigurationException, TransformerConfigurationException,
- TransformerException, TransformerFactoryConfigurationError, SAXException {
+ throws IOException, ParserConfigurationException, TransformerException,
+ TransformerFactoryConfigurationError, SAXException {
DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = docBuilder.parse(manifest.toFile());
for (String tag : PERMISSION_TAGS) {
diff --git a/src/tools/android/java/com/google/devtools/build/android/PlaceholderIdFieldInitializerBuilder.java b/src/tools/android/java/com/google/devtools/build/android/PlaceholderIdFieldInitializerBuilder.java
index 12b7abe4ae..ee1663356d 100644
--- a/src/tools/android/java/com/google/devtools/build/android/PlaceholderIdFieldInitializerBuilder.java
+++ b/src/tools/android/java/com/google/devtools/build/android/PlaceholderIdFieldInitializerBuilder.java
@@ -453,7 +453,7 @@ class PlaceholderIdFieldInitializerBuilder {
// The styleable array should be sorted by ID value.
// Make sure that if we have android: framework attributes, their IDs are listed first.
ImmutableMap<String, Integer> arrayInitMap =
- arrayInitValues.orderEntriesByValue(Ordering.<Integer>natural()).build();
+ arrayInitValues.orderEntriesByValue(Ordering.natural()).build();
initList.put(field, IntArrayFieldInitializer.of(arrayInitMap.values()));
int index = 0;
for (String attr : arrayInitMap.keySet()) {
diff --git a/src/tools/android/java/com/google/devtools/build/android/RelativeAssetPath.java b/src/tools/android/java/com/google/devtools/build/android/RelativeAssetPath.java
index 1801026c96..fa5174222d 100644
--- a/src/tools/android/java/com/google/devtools/build/android/RelativeAssetPath.java
+++ b/src/tools/android/java/com/google/devtools/build/android/RelativeAssetPath.java
@@ -32,6 +32,7 @@ import java.util.Objects;
* <p>Note: Assets have no qualifiers or packages.
*/
public class RelativeAssetPath implements DataKey {
+
/** A Factory that creates RelativeAssetsPath objects whose paths are relative to a given path. */
public static class Factory {
private final Path assetRoot;
@@ -110,12 +111,11 @@ public class RelativeAssetPath implements DataKey {
}
@Override
- public void serializeTo(OutputStream output, int valueSize) throws IOException {
+ public void writeTo(OutputStream out) throws IOException {
SerializeFormat.DataKey.newBuilder()
.setKeyValue(relativeAssetPath.toString())
- .setValueSize(valueSize)
.build()
- .writeDelimitedTo(output);
+ .writeDelimitedTo(out);
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/ResourceProcessorBusyBox.java b/src/tools/android/java/com/google/devtools/build/android/ResourceProcessorBusyBox.java
index a99da9b931..cb1f43c320 100644
--- a/src/tools/android/java/com/google/devtools/build/android/ResourceProcessorBusyBox.java
+++ b/src/tools/android/java/com/google/devtools/build/android/ResourceProcessorBusyBox.java
@@ -54,7 +54,7 @@ import java.util.logging.Logger;
* </pre>
*/
public class ResourceProcessorBusyBox {
- static enum Tool {
+ enum Tool {
PACKAGE() {
@Override
void call(String[] args) throws Exception {
diff --git a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
index 7d9f59fb0d..bb68ef7e65 100644
--- a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
@@ -325,7 +325,7 @@ public class ResourceShrinkerAction {
aaptConfigOptions.splits,
new MergedAndroidData(
shrunkResources, resourceFiles.resolve("assets"), options.primaryManifest),
- ImmutableList.<DependencyAndroidData>of() /* libraries */,
+ ImmutableList.of() /* libraries */,
generatedSources,
options.shrunkApk,
null /* proguardOutput */,
diff --git a/src/tools/android/java/com/google/devtools/build/android/UnvalidatedAndroidDirectories.java b/src/tools/android/java/com/google/devtools/build/android/UnvalidatedAndroidDirectories.java
index 49fdb18296..7aa3164c7c 100644
--- a/src/tools/android/java/com/google/devtools/build/android/UnvalidatedAndroidDirectories.java
+++ b/src/tools/android/java/com/google/devtools/build/android/UnvalidatedAndroidDirectories.java
@@ -41,8 +41,8 @@ public class UnvalidatedAndroidDirectories {
}
String[] parts = text.split(":");
return new UnvalidatedAndroidDirectories(
- parts.length > 0 ? splitPaths(parts[0], fileSystem) : ImmutableList.<Path>of(),
- parts.length > 1 ? splitPaths(parts[1], fileSystem) : ImmutableList.<Path>of());
+ parts.length > 0 ? splitPaths(parts[0], fileSystem) : ImmutableList.of(),
+ parts.length > 1 ? splitPaths(parts[1], fileSystem) : ImmutableList.of());
}
protected static ImmutableList<Path> splitPaths(String pathsString, FileSystem fileSystem) {
diff --git a/src/tools/android/java/com/google/devtools/build/android/Writeable.java b/src/tools/android/java/com/google/devtools/build/android/Writeable.java
new file mode 100644
index 0000000000..d1ef46dc0d
--- /dev/null
+++ b/src/tools/android/java/com/google/devtools/build/android/Writeable.java
@@ -0,0 +1,23 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+//
+// 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.google.devtools.build.android;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/** Common interface for serialization using the {@link AndroidDataSerializer}. */
+public interface Writeable {
+ /** Writes the current state to the {@link OutputStream}. */
+ void writeTo(OutputStream out) throws IOException;
+}
diff --git a/src/tools/android/java/com/google/devtools/build/android/XmlResourceValue.java b/src/tools/android/java/com/google/devtools/build/android/XmlResourceValue.java
index f24d6b271a..e8cab89c19 100644
--- a/src/tools/android/java/com/google/devtools/build/android/XmlResourceValue.java
+++ b/src/tools/android/java/com/google/devtools/build/android/XmlResourceValue.java
@@ -13,12 +13,8 @@
// limitations under the License.
package com.google.devtools.build.android;
-import com.google.devtools.build.android.xml.Namespaces;
-import java.io.IOException;
-import java.io.OutputStream;
-
/** An {@link XmlResourceValue} is extracted from xml files in the resource 'values' directory. */
-public interface XmlResourceValue {
+public interface XmlResourceValue extends Writeable {
/**
* Each XmlValue is expected to write a valid representation in xml to the writer.
*
@@ -28,9 +24,6 @@ public interface XmlResourceValue {
*/
void write(FullyQualifiedName key, DataSource source, AndroidDataWritingVisitor mergedDataWriter);
- /** Serializes the resource value to the OutputStream and returns the bytes written. */
- int serializeTo(int sourceId, Namespaces namespaces, OutputStream out) throws IOException;
-
/**
* Combines these xml values together and returns a single value.
*
diff --git a/src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java b/src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java
index 1ea38826bf..20df22251b 100644
--- a/src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java
+++ b/src/tools/android/java/com/google/devtools/build/android/XmlResourceValues.java
@@ -20,15 +20,18 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.android.ParsedAndroidData.KeyValueConsumer;
import com.google.devtools.build.android.proto.SerializeFormat;
+import com.google.devtools.build.android.xml.ArrayXmlResourceValue;
import com.google.devtools.build.android.xml.AttrXmlResourceValue;
import com.google.devtools.build.android.xml.IdXmlResourceValue;
import com.google.devtools.build.android.xml.Namespaces;
import com.google.devtools.build.android.xml.PluralXmlResourceValue;
import com.google.devtools.build.android.xml.PublicXmlResourceValue;
+import com.google.devtools.build.android.xml.ResourcesAttribute;
import com.google.devtools.build.android.xml.SimpleXmlResourceValue;
import com.google.devtools.build.android.xml.StyleXmlResourceValue;
import com.google.devtools.build.android.xml.StyleableXmlResourceValue;
import com.google.protobuf.CodedOutputStream;
+import com.google.protobuf.InvalidProtocolBufferException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
@@ -443,4 +446,35 @@ public class XmlResourceValues {
public static boolean isSkip(StartElement start) {
return isTag(start, TAG_SKIP);
}
+
+ /** Creates the value from a proto. */
+ public static XmlResourceValue valueFromProto(SerializeFormat.DataValueXml proto) {
+ try {
+ Preconditions.checkArgument(proto.hasType());
+ switch (proto.getType()) {
+ case ARRAY:
+ return ArrayXmlResourceValue.from(proto);
+ case SIMPLE:
+ return SimpleXmlResourceValue.from(proto);
+ case ATTR:
+ return AttrXmlResourceValue.from(proto);
+ case ID:
+ return IdXmlResourceValue.of();
+ case PLURAL:
+ return PluralXmlResourceValue.from(proto);
+ case PUBLIC:
+ return PublicXmlResourceValue.from(proto);
+ case STYLE:
+ return StyleXmlResourceValue.from(proto);
+ case STYLEABLE:
+ return StyleableXmlResourceValue.from(proto);
+ case RESOURCES_ATTRIBUTE:
+ return ResourcesAttribute.from(proto);
+ default:
+ throw new IllegalArgumentException();
+ }
+ } catch (InvalidProtocolBufferException e) {
+ throw new DeserializationException(e);
+ }
+ }
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/proto/serialize_format.proto b/src/tools/android/java/com/google/devtools/build/android/proto/serialize_format.proto
index b87d5fee83..9412cea29f 100644
--- a/src/tools/android/java/com/google/devtools/build/android/proto/serialize_format.proto
+++ b/src/tools/android/java/com/google/devtools/build/android/proto/serialize_format.proto
@@ -24,25 +24,29 @@ option java_package = "com.google.devtools.build.android.proto";
// See com.google.devtools.build.android.AndroidDataSerializer for details on
// how these messages are used.
message Header {
- // The number of entries stored in a serialized buffer.
- optional uint32 entry_count = 1;
// The number of ProtoSource entries.
- optional uint32 source_count = 2;
+ optional uint32 source_count = 1;
+ // The number of keys in the serialized buffer.
+ optional uint32 key_count = 2;
+ // The number of values in the serialized buffer.
+ optional uint32 value_count = 3;
+ // The number of xml definitions in the serialized buffer.
+ optional uint32 xml_count = 4;
+ // The number of xml namespace definitions in the serialized buffer.
+ optional uint32 namespaces_count = 5;
}
// The serialized format for a DataKey.
message DataKey {
// Used for both the FullyQualifiedName name and RelativeAssetPath path
- optional string key_value = 2;
- // The resource type for FullyQualifiedNames
- optional string resource_type = 3;
- optional string key_package = 4;
- repeated string qualifiers = 5;
- // The size of the associated value. Useful for calculating an offset.
// Required
- optional int32 value_size = 6;
+ optional string key_value = 1;
+ // The resource type for FullyQualifiedNames
+ optional string resource_type = 2;
+ optional string key_package = 3;
+ repeated string qualifiers = 4;
// Whether this DataKey is a reference to another DataKey.
- optional bool reference = 7;
+ optional bool reference = 5;
}
// The serialized format for a DataValue.
@@ -51,30 +55,41 @@ message DataValue {
// Required
optional uint32 source_id = 1;
- // If xml_value is defined it's an xml value, otherwise, it's a file value.
- optional DataValueXml xml_value= 2;
+ // Index of stored xml value
+ optional uint32 xml_id = 2;
+
+ // Index of stored key.
+ // Required
+ optional uint32 key_id = 3;
+
+ // Sources that have been overwritten.
+ repeated uint32 overwritten_source_id = 4;
+
+ optional uint32 namespace_id = 5;
}
// A container for all the source information to be persisted.
message ProtoSource {
// Required
optional string filename = 1;
- // The indexes of sources this source replaces.
- repeated uint32 overwritten = 2;
+}
+
+message XmlNamespaces {
+ map<string, string> namespace = 1;
}
// The container for a serialized xml value.
message DataValueXml {
enum XmlType {
- ARRAY = 0;
- ATTR = 1;
- ID = 2;
- PLURAL = 3;
- PUBLIC = 4;
- SIMPLE = 5;
- STYLEABLE = 6;
- STYLE = 7;
- RESOURCES_ATTRIBUTE = 8;
+ ARRAY = 1;
+ ATTR = 2;
+ ID = 3;
+ PLURAL = 4;
+ PUBLIC = 5;
+ SIMPLE = 6;
+ STYLEABLE = 7;
+ STYLE = 8;
+ RESOURCES_ATTRIBUTE = 9;
}
optional XmlType type = 1;
@@ -85,5 +100,4 @@ message DataValueXml {
optional string value_type = 6;
repeated DataKey references = 7;
map<string, string> attribute = 8;
- map<string, string> namespace = 9;
}
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 fb74fd2208..f977c7b315 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
@@ -29,6 +29,8 @@ import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
import com.google.devtools.build.android.XmlResourceValues;
import com.google.devtools.build.android.proto.SerializeFormat;
+import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml;
+import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.XmlType;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
@@ -45,14 +47,15 @@ import javax.xml.stream.events.XMLEvent;
/**
* Represents an Android resource array.
*
- * There are two flavors of Android Resource arrays:
+ * <p>There are two flavors of Android Resource arrays:
+ *
* <ul>
- * <li>Typed arrays (http://developer.android.com/guide/topics/resources/more-resources
- * .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>
+ * <li>Typed arrays (http://developer.android.com/guide/topics/resources/more-resources
+ * .html#TypedArray) which which are indicated by a &lt;array&gt; tag.
+ * <li>Integer array (http://developer.android.com/guide/topics/resources/more-resources
+ * .html#IntegerArray) which are indicated by &lt;integer-array&gt; tag.
+ * <li>String array (http://developer.android.com/guide/topics/resources/string-resource
+ * .html#StringArray) which are indicated by &lt;string-array&gt; tag.
* </ul>
*
* Both of these are accessed by R.array.&lt;name&gt; in java.
@@ -62,9 +65,19 @@ 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");
- /**
- * Enumerates the different types of array parentTags.
- */
+
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ DataValueXml.newBuilder()
+ .addAllListValue(values)
+ .setType(XmlType.ARRAY)
+ .putAllAttribute(attributes)
+ .setValueType(arrayType.toString())
+ .build()
+ .writeDelimitedTo(out);
+ }
+
+ /** Enumerates the different types of array parentTags. */
public enum ArrayType {
INTEGER_ARRAY(TAG_INTEGER_ARRAY),
ARRAY(TAG_ARRAY),
@@ -105,7 +118,7 @@ public class ArrayXmlResourceValue implements XmlResourceValue {
}
public static XmlResourceValue of(ArrayType arrayType, List<String> values) {
- return of(arrayType, values, ImmutableMap.<String, String>of());
+ return of(arrayType, values, ImmutableMap.of());
}
public static XmlResourceValue of(
@@ -138,20 +151,20 @@ public class ArrayXmlResourceValue implements XmlResourceValue {
}
}
- return of(
- ArrayType.ARRAY,
- items,
- ImmutableMap.of());
+ return of(ArrayType.ARRAY, items, ImmutableMap.of());
}
@Override
public void write(
FullyQualifiedName key, DataSource source, AndroidDataWritingVisitor mergedDataWriter) {
- ValuesResourceDefinition definition = mergedDataWriter.define(key).derivedFrom(source)
- .startTag(arrayType.tagName)
- .named(key)
- .addAttributesFrom(attributes.entrySet())
- .closeTag();
+ ValuesResourceDefinition definition =
+ mergedDataWriter
+ .define(key)
+ .derivedFrom(source)
+ .startTag(arrayType.tagName)
+ .named(key)
+ .addAttributesFrom(attributes.entrySet())
+ .closeTag();
for (String value : values) {
definition =
definition
@@ -165,21 +178,6 @@ public class ArrayXmlResourceValue implements XmlResourceValue {
}
@Override
- public int serializeTo(int sourceId, Namespaces namespaces, OutputStream output)
- throws IOException {
- return XmlResourceValues.serializeProtoDataValue(
- output,
- XmlResourceValues.newSerializableDataValueBuilder(sourceId)
- .setXmlValue(
- SerializeFormat.DataValueXml.newBuilder()
- .addAllListValue(values)
- .setType(SerializeFormat.DataValueXml.XmlType.ARRAY)
- .putAllNamespace(namespaces.asMap())
- .putAllAttribute(attributes)
- .setValueType(arrayType.toString())));
- }
-
- @Override
public int hashCode() {
return Objects.hash(arrayType, values, attributes);
}
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 f2645ac0a3..96ac31c947 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
@@ -404,23 +404,16 @@ public class AttrXmlResourceValue implements XmlResourceValue {
}
}
- @SuppressWarnings("deprecation")
@Override
- public int serializeTo(int sourceId, Namespaces namespaces, OutputStream output)
- throws IOException {
- SerializeFormat.DataValue.Builder builder =
- XmlResourceValues.newSerializableDataValueBuilder(sourceId);
+ public void writeTo(OutputStream out) throws IOException {
SerializeFormat.DataValueXml.Builder xmlValueBuilder =
SerializeFormat.DataValueXml.newBuilder();
- xmlValueBuilder
- .setType(SerializeFormat.DataValueXml.XmlType.ATTR)
- .putAllNamespace(namespaces.asMap());
+ xmlValueBuilder.setType(SerializeFormat.DataValueXml.XmlType.ATTR);
for (Entry<String, ResourceXmlAttrValue> entry : formats.entrySet()) {
xmlValueBuilder.putMappedXmlValue(
- entry.getKey(), entry.getValue().appendTo(builder.getXmlValueBuilder()));
+ entry.getKey(), entry.getValue().appendTo(SerializeFormat.DataValueXml.newBuilder()));
}
- builder.setXmlValue(xmlValueBuilder);
- return XmlResourceValues.serializeProtoDataValue(output, builder);
+ xmlValueBuilder.build().writeDelimitedTo(out);
}
@Override
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 c3fb2faefa..e3fe65aa02 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
@@ -20,11 +20,8 @@ import com.google.devtools.build.android.AndroidResourceSymbolSink;
import com.google.devtools.build.android.DataSource;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import com.google.devtools.build.android.XmlResourceValues;
import com.google.devtools.build.android.proto.SerializeFormat;
-import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.Builder;
import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.XmlType;
-import com.google.protobuf.CodedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Objects;
@@ -94,20 +91,8 @@ public class IdXmlResourceValue implements XmlResourceValue {
}
@Override
- public int serializeTo(int sourceId, Namespaces namespaces, OutputStream output)
- throws IOException {
- Builder xmlValue =
- SerializeFormat.DataValueXml.newBuilder()
- .setType(XmlType.ID)
- .putAllNamespace(namespaces.asMap());
- if (value != null) {
- xmlValue.setValue(value);
- }
- SerializeFormat.DataValue dataValue =
- XmlResourceValues.newSerializableDataValueBuilder(sourceId).setXmlValue(xmlValue).build();
- dataValue.writeDelimitedTo(output);
- return CodedOutputStream.computeUInt32SizeNoTag(dataValue.getSerializedSize())
- + dataValue.getSerializedSize();
+ public void writeTo(OutputStream out) throws IOException {
+ SerializeFormat.DataValueXml.newBuilder().setType(XmlType.ID).build().writeDelimitedTo(out);
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/xml/Namespaces.java b/src/tools/android/java/com/google/devtools/build/android/xml/Namespaces.java
index 82e8810139..10da5ff225 100644
--- a/src/tools/android/java/com/google/devtools/build/android/xml/Namespaces.java
+++ b/src/tools/android/java/com/google/devtools/build/android/xml/Namespaces.java
@@ -16,8 +16,13 @@ package com.google.devtools.build.android.xml;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.android.DataResourceXml;
+import com.google.devtools.build.android.Writeable;
import com.google.devtools.build.android.XmlResourceValue;
import com.google.devtools.build.android.XmlResourceValues;
+import com.google.devtools.build.android.proto.SerializeFormat;
+import com.google.devtools.build.android.proto.SerializeFormat.XmlNamespaces;
+import java.io.IOException;
+import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -39,11 +44,23 @@ import javax.xml.stream.events.StartElement;
* resources tag to combining multiple {@link DataResourceXml}s, the Namespaces must be tracked and
* kept with each value.
*/
-public class Namespaces implements Iterable<Entry<String, String>> {
+public class Namespaces implements Iterable<Entry<String, String>>, Writeable {
private static final Logger logger = Logger.getLogger(Namespaces.class.getCanonicalName());
private static final Namespaces EMPTY_INSTANCE =
new Namespaces(ImmutableMap.<String, String>of());
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ SerializeFormat.XmlNamespaces.newBuilder()
+ .putAllNamespace(prefixToUri)
+ .build()
+ .writeDelimitedTo(out);
+ }
+
+ public static Namespaces fromProto(XmlNamespaces xmlNamespaces) {
+ return from(xmlNamespaces.getNamespaceMap());
+ }
+
/** Collects prefix and uri pairs from elements. */
public static class Collector {
private Map<String, String> prefixToUri = new HashMap<>();
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 b912cc141e..7c1b6532e3 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
@@ -24,10 +24,8 @@ import com.google.devtools.build.android.AndroidResourceSymbolSink;
import com.google.devtools.build.android.DataSource;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import com.google.devtools.build.android.XmlResourceValues;
import com.google.devtools.build.android.proto.SerializeFormat;
import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.XmlType;
-import com.google.protobuf.CodedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
@@ -157,23 +155,13 @@ public class PluralXmlResourceValue implements XmlResourceValue {
}
@Override
- public int serializeTo(int sourceId, Namespaces namespaces, OutputStream output)
- throws IOException {
- SerializeFormat.DataValue.Builder builder =
- XmlResourceValues.newSerializableDataValueBuilder(sourceId);
- SerializeFormat.DataValue value =
- builder
- .setXmlValue(
- builder
- .getXmlValueBuilder()
- .setType(XmlType.PLURAL)
- .putAllNamespace(namespaces.asMap())
- .putAllAttribute(attributes)
- .putAllMappedStringValue(values))
- .build();
- value.writeDelimitedTo(output);
- return CodedOutputStream.computeUInt32SizeNoTag(value.getSerializedSize())
- + value.getSerializedSize();
+ public void writeTo(OutputStream out) throws IOException {
+ SerializeFormat.DataValueXml.newBuilder()
+ .setType(XmlType.PLURAL)
+ .putAllAttribute(attributes)
+ .putAllMappedStringValue(values)
+ .build()
+ .writeDelimitedTo(out);
}
@Override
diff --git a/src/tools/android/java/com/google/devtools/build/android/xml/PublicXmlResourceValue.java b/src/tools/android/java/com/google/devtools/build/android/xml/PublicXmlResourceValue.java
index af4184d88a..c1e3eb40a0 100644
--- a/src/tools/android/java/com/google/devtools/build/android/xml/PublicXmlResourceValue.java
+++ b/src/tools/android/java/com/google/devtools/build/android/xml/PublicXmlResourceValue.java
@@ -19,13 +19,11 @@ import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
import com.google.devtools.build.android.AndroidDataWritingVisitor;
import com.google.devtools.build.android.AndroidResourceSymbolSink;
import com.google.devtools.build.android.DataSource;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import com.google.devtools.build.android.XmlResourceValues;
import com.google.devtools.build.android.proto.SerializeFormat;
import java.io.IOException;
import java.io.OutputStream;
@@ -33,6 +31,7 @@ import java.util.EnumMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
+import java.util.stream.Collectors;
/**
* Represents an Android resource &lt;public&gt; xml tag.
@@ -139,23 +138,19 @@ public class PublicXmlResourceValue implements XmlResourceValue {
}
@Override
- public int serializeTo(int sourceId, Namespaces namespaces, OutputStream output)
- throws IOException {
- Map<String, String> assignments = Maps.newLinkedHashMapWithExpectedSize(typeToId.size());
- for (Entry<ResourceType, Optional<Integer>> entry : typeToId.entrySet()) {
- Optional<Integer> value = entry.getValue();
- String stringValue = value.isPresent() ? value.get().toString() : MISSING_ID_VALUE;
- assignments.put(entry.getKey().toString(), stringValue);
- }
- SerializeFormat.DataValue.Builder builder =
- XmlResourceValues.newSerializableDataValueBuilder(sourceId);
- builder.setXmlValue(
- builder
- .getXmlValueBuilder()
- .setType(SerializeFormat.DataValueXml.XmlType.PUBLIC)
- .putAllNamespace(namespaces.asMap())
- .putAllMappedStringValue(assignments));
- return XmlResourceValues.serializeProtoDataValue(output, builder);
+ public void writeTo(OutputStream out) throws IOException {
+ SerializeFormat.DataValueXml.newBuilder()
+ .setType(SerializeFormat.DataValueXml.XmlType.PUBLIC)
+ .putAllMappedStringValue(
+ typeToId
+ .entrySet()
+ .stream()
+ .collect(
+ Collectors.toMap(
+ e -> e.getKey().toString(),
+ e -> e.getValue().transform(Object::toString).or(MISSING_ID_VALUE))))
+ .build()
+ .writeDelimitedTo(out);
}
@Override
@@ -178,7 +173,7 @@ public class PublicXmlResourceValue implements XmlResourceValue {
}
return of(combined);
}
-
+
@Override
public String asConflictStringWith(DataSource source) {
return source.asConflictString();
diff --git a/src/tools/android/java/com/google/devtools/build/android/xml/ResourcesAttribute.java b/src/tools/android/java/com/google/devtools/build/android/xml/ResourcesAttribute.java
index a54667ecdb..75a6c0207e 100644
--- a/src/tools/android/java/com/google/devtools/build/android/xml/ResourcesAttribute.java
+++ b/src/tools/android/java/com/google/devtools/build/android/xml/ResourcesAttribute.java
@@ -21,9 +21,7 @@ import com.google.devtools.build.android.AndroidResourceSymbolSink;
import com.google.devtools.build.android.DataSource;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import com.google.devtools.build.android.XmlResourceValues;
import com.google.devtools.build.android.proto.SerializeFormat;
-import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.Builder;
import com.google.errorprone.annotations.Immutable;
import java.io.IOException;
import java.io.OutputStream;
@@ -40,13 +38,15 @@ public class ResourcesAttribute implements XmlResourceValue {
public String combine(String first, String second);
}
- private static final Combiner COMMA_SEPARATED_COMBINER = new Combiner() {
- private final Joiner joiner = Joiner.on(',');
- @Override
- public String combine(String first, String second) {
- return joiner.join(first, second);
- }
- };
+ private static final Combiner COMMA_SEPARATED_COMBINER =
+ new Combiner() {
+ private final Joiner joiner = Joiner.on(',');
+
+ @Override
+ public String combine(String first, String second) {
+ return joiner.join(first, second);
+ }
+ };
/**
* Represents the semantic meaning of an xml attribute and how it is combined with other
@@ -92,9 +92,7 @@ public class ResourcesAttribute implements XmlResourceValue {
Map.Entry<String, String> attribute =
Iterables.getOnlyElement(proto.getAttributeMap().entrySet());
return new ResourcesAttribute(
- AttributeType.valueOf(proto.getValueType()),
- attribute.getKey(),
- attribute.getValue());
+ AttributeType.valueOf(proto.getValueType()), attribute.getKey(), attribute.getValue());
}
private final AttributeType type;
@@ -114,19 +112,13 @@ public class ResourcesAttribute implements XmlResourceValue {
}
@Override
- public int serializeTo(int sourceId, Namespaces namespaces, OutputStream output)
- throws IOException {
- SerializeFormat.DataValue.Builder builder =
- XmlResourceValues.newSerializableDataValueBuilder(sourceId);
- Builder xmlValueBuilder =
- builder
- .getXmlValueBuilder()
- .putAllNamespace(namespaces.asMap())
- .setType(SerializeFormat.DataValueXml.XmlType.RESOURCES_ATTRIBUTE)
- .setValueType(type.name())
- .putAttribute(name, value);
- builder.setXmlValue(xmlValueBuilder);
- return XmlResourceValues.serializeProtoDataValue(output, builder);
+ public void writeTo(OutputStream out) throws IOException {
+ SerializeFormat.DataValueXml.newBuilder()
+ .setType(SerializeFormat.DataValueXml.XmlType.RESOURCES_ATTRIBUTE)
+ .setValueType(type.name())
+ .putAttribute(name, value)
+ .build()
+ .writeDelimitedTo(out);
}
@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 32147cd49c..55bef85bc1 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
@@ -27,9 +27,10 @@ import com.google.devtools.build.android.AndroidResourceSymbolSink;
import com.google.devtools.build.android.DataSource;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import com.google.devtools.build.android.XmlResourceValues;
import com.google.devtools.build.android.proto.SerializeFormat;
+import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml;
import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.Builder;
+import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.XmlType;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
@@ -41,8 +42,7 @@ import javax.xml.namespace.QName;
/**
* Represents a simple Android resource xml value.
*
- * <p>
- * There is a class of resources that are simple name/value pairs: string
+ * <p>There is a class of resources that are simple name/value pairs: string
* (http://developer.android.com/guide/topics/resources/string-resource.html), bool
* (http://developer.android.com/guide/topics/resources/more-resources.html#Bool), color
* (http://developer.android.com/guide/topics/resources/more-resources.html#Color), and dimen
@@ -66,106 +66,27 @@ public class SimpleXmlResourceValue implements XmlResourceValue {
static final QName TAG_RAW = QName.valueOf("raw");
static final QName TAG_STRING = QName.valueOf("string");
- /** Provides an enumeration resource type and simple value validation. */
+ /** Provides an enumeration resource type. */
public enum Type {
- BOOL(TAG_BOOL) {
- @Override
- public boolean validate(String value) {
- final String cleanValue = value.toLowerCase().trim();
- return "true".equals(cleanValue) || "false".equals(cleanValue);
- }
- },
- COLOR(TAG_COLOR) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the hex color.
- return true;
- }
- },
- DIMEN(TAG_DIMEN) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the dimension type.
- return true;
- }
- },
- DRAWABLE(TAG_DRAWABLE) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the drawable type.
- return true;
- }
- },
- FRACTION(TAG_FRACTION) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the fraction type.
- return true;
- }
- },
- INTEGER(TAG_INTEGER) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the integer type.
- return true;
- }
- },
- ITEM(TAG_ITEM) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the item type.
- return true;
- }
- },
- LAYOUT(TAG_LAYOUT) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the layout type.
- return true;
- }
- },
- MENU(TAG_MENU) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the menu type.
- return true;
- }
- },
- MIPMAP(TAG_MIPMAP) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the mipmap type.
- return true;
- }
- },
- PUBLIC(TAG_PUBLIC) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the public type.
- return true;
- }
- },
- RAW(TAG_RAW) {
- @Override
- public boolean validate(String value) {
- // TODO(corysmith): Validate the raw type.
- return true;
- }
- },
- STRING(TAG_STRING) {
- @Override
- public boolean validate(String value) {
- return true;
- }
- };
+ BOOL(TAG_BOOL),
+ COLOR(TAG_COLOR),
+ DIMEN(TAG_DIMEN),
+ DRAWABLE(TAG_DRAWABLE),
+ FRACTION(TAG_FRACTION),
+ INTEGER(TAG_INTEGER),
+ ITEM(TAG_ITEM),
+ LAYOUT(TAG_LAYOUT),
+ MENU(TAG_MENU),
+ MIPMAP(TAG_MIPMAP),
+ PUBLIC(TAG_PUBLIC),
+ RAW(TAG_RAW),
+ STRING(TAG_STRING);
private final QName tagName;
Type(QName tagName) {
this.tagName = tagName;
}
- abstract boolean validate(String value);
-
public static Type from(ResourceType resourceType) {
for (Type valueType : values()) {
if (valueType.tagName.getLocalPart().equals(resourceType.getName())) {
@@ -177,8 +98,7 @@ public class SimpleXmlResourceValue implements XmlResourceValue {
throw new IllegalArgumentException(
String.format(
"%s resource type not found in available types: %s",
- resourceType,
- Arrays.toString(values())));
+ resourceType, Arrays.toString(values())));
}
}
@@ -200,8 +120,7 @@ public class SimpleXmlResourceValue implements XmlResourceValue {
return of(Type.ITEM, ImmutableMap.of("type", resourceType.getName(), "format", format), value);
}
- public static XmlResourceValue itemWithValue(
- ResourceType resourceType, String value) {
+ public static XmlResourceValue itemWithValue(ResourceType resourceType, String value) {
return of(Type.ITEM, ImmutableMap.of("type", resourceType.getName()), value);
}
@@ -265,11 +184,11 @@ public class SimpleXmlResourceValue implements XmlResourceValue {
String.format(";%s,%d,%d", span.getTag(), span.getFirstChar(), span.getLastChar()));
}
stringValue = stringBuilder.toString();
- } else if ((resourceType == ResourceType.COLOR
- || resourceType == ResourceType.DRAWABLE) && item.hasPrim()) {
+ } 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()){
+ } 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";
@@ -282,10 +201,7 @@ public class SimpleXmlResourceValue implements XmlResourceValue {
String.format("'%s' is not a valid resource type.", resourceType));
}
- return of(
- Type.valueOf(resourceType.toString().toUpperCase()),
- ImmutableMap.of(),
- stringValue);
+ return of(Type.valueOf(resourceType.toString().toUpperCase()), ImmutableMap.of(), stringValue);
}
@Override
@@ -294,23 +210,20 @@ public class SimpleXmlResourceValue implements XmlResourceValue {
}
@Override
- public int serializeTo(int sourceId, Namespaces namespaces, OutputStream output)
- throws IOException {
- SerializeFormat.DataValue.Builder builder =
- XmlResourceValues.newSerializableDataValueBuilder(sourceId);
- Builder xmlValueBuilder =
- builder
- .getXmlValueBuilder()
- .putAllNamespace(namespaces.asMap())
- .setType(SerializeFormat.DataValueXml.XmlType.SIMPLE)
+ public void writeTo(OutputStream out) throws IOException {
+ final Builder builder =
+ DataValueXml.newBuilder()
+ .setType(XmlType.SIMPLE)
+ .setValueType(valueType.name())
// TODO(corysmith): Find a way to avoid writing strings to the serialized format
// it's inefficient use of space and costs more when deserializing.
.putAllAttribute(attributes);
+
if (value != null) {
- xmlValueBuilder.setValue(value);
+ builder.setValue(value);
}
- builder.setXmlValue(xmlValueBuilder.setValueType(valueType.name()));
- return XmlResourceValues.serializeProtoDataValue(output, builder);
+
+ builder.build().writeDelimitedTo(out);
}
@Override
@@ -342,7 +255,7 @@ public class SimpleXmlResourceValue implements XmlResourceValue {
public XmlResourceValue combineWith(XmlResourceValue value) {
throw new IllegalArgumentException(this + " is not a combinable resource.");
}
-
+
@Override
public String asConflictStringWith(DataSource source) {
if (value != null) {
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 5cd0f6e0a5..6929c9d588 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
@@ -24,7 +24,6 @@ import com.google.devtools.build.android.AndroidResourceSymbolSink;
import com.google.devtools.build.android.DataSource;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import com.google.devtools.build.android.XmlResourceValues;
import com.google.devtools.build.android.proto.SerializeFormat;
import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.XmlType;
import java.io.IOException;
@@ -39,8 +38,7 @@ import javax.annotation.concurrent.Immutable;
/**
* Represents an Android Style Resource.
*
- * <p>
- * Styles (http://developer.android.com/guide/topics/resources/style-resource.html) define a look
+ * <p>Styles (http://developer.android.com/guide/topics/resources/style-resource.html) define a look
* and feel for a layout or other ui construct. They are effectively a s set of values that
* correspond to &lt;attr&gt; resources defined either in the base android framework or in other
* resources. They also allow inheritance on other styles. For a style to valid in a given resource
@@ -154,19 +152,15 @@ public class StyleXmlResourceValue implements XmlResourceValue {
}
@Override
- public int serializeTo(int sourceId, Namespaces namespaces, OutputStream output)
- throws IOException {
+ public void writeTo(OutputStream out) throws IOException {
SerializeFormat.DataValueXml.Builder xmlValueBuilder =
SerializeFormat.DataValueXml.newBuilder()
.setType(XmlType.STYLE)
- .putAllNamespace(namespaces.asMap())
.putAllMappedStringValue(values);
if (parent != null) {
xmlValueBuilder.setValue(parent);
}
- return XmlResourceValues.serializeProtoDataValue(
- output,
- XmlResourceValues.newSerializableDataValueBuilder(sourceId).setXmlValue(xmlValueBuilder));
+ xmlValueBuilder.build().writeDelimitedTo(out);
}
@Override
@@ -195,7 +189,7 @@ public class StyleXmlResourceValue implements XmlResourceValue {
public XmlResourceValue combineWith(XmlResourceValue value) {
throw new IllegalArgumentException(this + " is not a combinable resource.");
}
-
+
@Override
public String asConflictStringWith(DataSource source) {
return source.asConflictString();
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 c9661690cf..5006600a48 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
@@ -27,7 +27,6 @@ import com.google.devtools.build.android.AndroidResourceSymbolSink;
import com.google.devtools.build.android.DataSource;
import com.google.devtools.build.android.FullyQualifiedName;
import com.google.devtools.build.android.XmlResourceValue;
-import com.google.devtools.build.android.XmlResourceValues;
import com.google.devtools.build.android.proto.SerializeFormat;
import com.google.devtools.build.android.proto.SerializeFormat.DataValueXml.XmlType;
import java.io.IOException;
@@ -38,6 +37,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
+import java.util.stream.Collectors;
import javax.annotation.concurrent.Immutable;
/**
@@ -65,22 +65,11 @@ public class StyleableXmlResourceValue implements XmlResourceValue {
static final Function<Entry<FullyQualifiedName, Boolean>, SerializeFormat.DataKey>
FULLY_QUALIFIED_NAME_TO_DATA_KEY =
- new Function<Entry<FullyQualifiedName, Boolean>, SerializeFormat.DataKey>() {
- @Override
- public SerializeFormat.DataKey apply(Entry<FullyQualifiedName, Boolean> input) {
- return input.getKey().toSerializedBuilder().setReference(input.getValue()).build();
- }
- };
+ input -> input.getKey().toSerializedBuilder().setReference(input.getValue()).build();
static final Function<SerializeFormat.DataKey, Entry<FullyQualifiedName, Boolean>>
DATA_KEY_TO_FULLY_QUALIFIED_NAME =
- new Function<SerializeFormat.DataKey, Entry<FullyQualifiedName, Boolean>>() {
- @Override
- public Entry<FullyQualifiedName, Boolean> apply(SerializeFormat.DataKey input) {
- FullyQualifiedName key = FullyQualifiedName.fromProto(input);
- return new SimpleEntry<FullyQualifiedName, Boolean>(key, input.getReference());
- }
- };
+ input -> new SimpleEntry<>(FullyQualifiedName.fromProto(input), input.getReference());
private final ImmutableMap<FullyQualifiedName, Boolean> attrs;
@@ -145,17 +134,17 @@ public class StyleableXmlResourceValue implements XmlResourceValue {
}
@Override
- public int serializeTo(int sourceId, Namespaces namespaces, OutputStream output)
- throws IOException {
- return XmlResourceValues.serializeProtoDataValue(
- output,
- XmlResourceValues.newSerializableDataValueBuilder(sourceId)
- .setXmlValue(
- SerializeFormat.DataValueXml.newBuilder()
- .setType(XmlType.STYLEABLE)
- .putAllNamespace(namespaces.asMap())
- .addAllReferences(
- Iterables.transform(attrs.entrySet(), FULLY_QUALIFIED_NAME_TO_DATA_KEY))));
+ public void writeTo(OutputStream out) throws IOException {
+ SerializeFormat.DataValueXml.newBuilder()
+ .setType(XmlType.STYLEABLE)
+ .addAllReferences(
+ attrs
+ .entrySet()
+ .stream()
+ .map(FULLY_QUALIFIED_NAME_TO_DATA_KEY)
+ .collect(Collectors.toSet()))
+ .build()
+ .writeDelimitedTo(out);
}
public static XmlResourceValue from(SerializeFormat.DataValueXml proto) {
@@ -202,12 +191,12 @@ public class StyleableXmlResourceValue implements XmlResourceValue {
/**
* Combines this instance with another {@link StyleableXmlResourceValue}.
*
- * Defining two Styleables (undocumented in the official Android Docs) with the same
- * {@link FullyQualifiedName} results in a single Styleable containing a union of all the
- * attribute references.
+ * <p>Defining two Styleables (undocumented in the official Android Docs) with the same {@link
+ * FullyQualifiedName} results in a single Styleable containing a union of all the attribute
+ * references.
*
- * @param value Another {@link StyleableXmlResourceValue} with the same
- * {@link FullyQualifiedName}.
+ * @param value Another {@link StyleableXmlResourceValue} with the same {@link
+ * FullyQualifiedName}.
* @return {@link StyleableXmlResourceValue} containing a sorted union of the attribute
* references.
* @throws IllegalArgumentException if value is not an {@link StyleableXmlResourceValue}.