package jadx.core.xmlgen;
import jadx.core.codegen.CodeWriter;
import jadx.core.utils.StringUtils;
import jadx.core.xmlgen.entry.RawNamedValue;
import jadx.core.xmlgen.entry.ResourceEntry;
import jadx.core.xmlgen.entry.ValuesParser;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ResXmlGen {
private static final Logger LOG = LoggerFactory.getLogger(ResXmlGen.class);
private static final Set<String> SKIP_RES_TYPES = new HashSet<String>(Arrays.asList(
"layout",
"mipmap",
"id"
));
private final ResourceStorage resStorage;
private final ValuesParser vp;
public ResXmlGen(ResourceStorage resStorage, ValuesParser vp) {
this.resStorage = resStorage;
this.vp = vp;
}
public List<ResContainer> makeResourcesXml() {
Map<String, CodeWriter> contMap = new HashMap<String, CodeWriter>();
for (ResourceEntry ri : resStorage.getResources()) {
if (SKIP_RES_TYPES.contains(ri.getTypeName())) {
continue;
}
String fn = getFileName(ri);
CodeWriter cw = contMap.get(fn);
if (cw == null) {
cw = new CodeWriter();
cw.add("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
cw.startLine("<resources>");
cw.incIndent();
contMap.put(fn, cw);
}
addValue(cw, ri);
}
List<ResContainer> files = new ArrayList<ResContainer>(contMap.size());
for (Map.Entry<String, CodeWriter> entry : contMap.entrySet()) {
String fileName = entry.getKey();
CodeWriter content = entry.getValue();
content.decIndent();
content.startLine("</resources>");
content.finish();
files.add(ResContainer.singleFile(fileName, content));
}
Collections.sort(files);
return files;
}
private void addValue(CodeWriter cw, ResourceEntry ri) {
if (ri.getSimpleValue() != null) {
String valueStr = vp.decodeValue(ri.getSimpleValue());
addSimpleValue(cw, ri.getTypeName(), "name", ri.getKeyName(), valueStr);
} else {
cw.startLine();
cw.add('<').add(ri.getTypeName()).add(' ');
cw.add("name=\"").add(ri.getKeyName()).add("\">");
cw.incIndent();
for (RawNamedValue value : ri.getNamedValues()) {
addItem(cw, value);
}
cw.decIndent();
cw.startLine().add("</").add(ri.getTypeName()).add('>');
}
}
private void addItem(CodeWriter cw, RawNamedValue value) {
String keyName = null;
String keyValue = null;
int nameRef = value.getNameRef();
if (ParserConstants.isResInternalId(nameRef)) {
keyValue = ParserConstants.PLURALS_MAP.get(nameRef);
if (keyValue != null) {
keyName = "quantity";
}
}
String valueStr = vp.decodeValue(value.getRawValue());
addSimpleValue(cw, "item", keyName, keyValue, valueStr);
}
private void addSimpleValue(CodeWriter cw, String typeName, String attrName, String attrValue, String valueStr) {
cw.startLine();
cw.add('<').add(typeName);
if (attrName != null && attrValue != null) {
cw.add(' ').add(attrName).add("=\"").add(attrValue).add('"');
}
cw.add('>');
if (typeName.equals("string")) {
cw.add(StringUtils.escapeResStrValue(valueStr));
} else {
cw.add(StringUtils.escapeResValue(valueStr));
}
cw.add("</").add(typeName).add('>');
}
private String getFileName(ResourceEntry ri) {
StringBuilder sb = new StringBuilder();
String locale = ri.getConfig().getLocale();
sb.append("res/values");
if (!locale.isEmpty()) {
sb.append('-').append(locale);
}
sb.append('/');
sb.append(ri.getTypeName());
if (!ri.getTypeName().endsWith("s")) {
sb.append('s');
}
sb.append(".xml");
return sb.toString();
}
}