use of com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoAttributeBuilder in project bundletool by google.
the class ManifestEditor method setMetadataValue.
private ManifestEditor setMetadataValue(String name, XmlProtoAttributeBuilder valueAttr) {
XmlProtoElementBuilder applicationEl = manifestElement.getOrCreateChildElement(APPLICATION_ELEMENT_NAME);
Optional<XmlProtoElementBuilder> existingMetadataEl = applicationEl.getChildrenElements(META_DATA_ELEMENT_NAME).filter(metadataEl -> metadataEl.getAndroidAttribute(NAME_RESOURCE_ID).map(nameAttr -> name.equals(nameAttr.getValueAsString())).orElse(false)).collect(toOptional());
if (existingMetadataEl.isPresent()) {
existingMetadataEl.get().removeAndroidAttribute(VALUE_RESOURCE_ID).addAttribute(valueAttr);
} else {
applicationEl.addChildElement(XmlProtoElementBuilder.create(META_DATA_ELEMENT_NAME).addAttribute(createAndroidAttribute("name", NAME_RESOURCE_ID).setValueAsString(name)).addAttribute(valueAttr));
}
return this;
}
use of com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoAttributeBuilder in project bundletool by google.
the class FusingAndroidManifestMerger method mergeElements.
/**
* Merges element with the same name and type from different manifests. {@code elements} list in
* this method contains data from feature modules first and element from the base module is the
* last one in the list.
*
* <p>If element is presented in more than one feature module elements are sorted by name of
* feature module. Example: if service with name 'myService' is defined in base module and
* features 'a' and 'b', {@code elements} list will contain its declaration in the following
* order: 'a' feature, 'b' feature, base.
*/
private XmlProtoElement mergeElements(ApplicationElementId elementId, List<XmlProtoElement> elements) {
// we just take the first element from the list.
if (mode.equals(Mode.REPLACE) || elements.size() == 1) {
return elements.get(0);
}
// Remove source data from nested elements as this data is meaningless for functionality and
// just contains information about line/column where element appeared in the original xml.
List<XmlProtoElement> elementsNoSource = elements.stream().map(element -> element.toBuilder().removeSourceDataRecursive().build()).collect(toImmutableList());
// For intent filters we gather all distinct filters defined in all modules.
Set<XmlProtoElement> intentFilters = elementsNoSource.stream().flatMap(element -> element.getChildrenElements(AndroidManifest.INTENT_FILTER_ELEMENT_NAME)).collect(toImmutableSet());
// For meta-data we group them by name and take one per each name.
ImmutableMap<String, XmlProtoElement> metadataByName = elementsNoSource.stream().flatMap(element -> element.getChildrenElements(AndroidManifest.META_DATA_ELEMENT_NAME)).filter(meta -> meta.getAndroidAttribute(AndroidManifest.NAME_RESOURCE_ID).isPresent()).collect(toImmutableMap(meta -> meta.getAndroidAttribute(AndroidManifest.NAME_RESOURCE_ID).get().getValueAsString(), Function.identity(), (a, b) -> {
// different modules throw conflict exception.
if (!a.equals(b)) {
throw CommandExecutionException.builder().withInternalMessage("Multiple meta-data entries with the same name are found inside" + " %s:%s: %s, %s", elementId.getType(), elementId.getName(), a, b).build();
}
return a;
}));
// Take element declaration from feature module and add all intent filters and meta data to it.
XmlProtoElementBuilder builder = elementsNoSource.get(0).toBuilder();
builder.removeChildrenElementsIf(child -> {
if (!child.isElement()) {
return false;
}
XmlProtoElementBuilder childElement = child.getElement();
String tag = childElement.getName();
Optional<String> name = childElement.getAndroidAttribute(AndroidManifest.NAME_RESOURCE_ID).map(XmlProtoAttributeBuilder::getValueAsString);
return tag.equals(AndroidManifest.INTENT_FILTER_ELEMENT_NAME) || (tag.equals(AndroidManifest.META_DATA_ELEMENT_NAME) && name.map(metadataByName::containsKey).orElse(false));
});
intentFilters.forEach(e -> builder.addChildElement(e.toBuilder()));
metadataByName.values().forEach(e -> builder.addChildElement(e.toBuilder()));
return builder.build();
}
Aggregations