blob: 5b6aed6298ee9d28a9eff0c70b9374a84248710a [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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.android.builder.compiling;
import static com.android.SdkConstants.ATTR_NAME;
import static com.android.SdkConstants.ATTR_TRANSLATABLE;
import static com.android.SdkConstants.ATTR_TYPE;
import static com.android.SdkConstants.TAG_ITEM;
import static com.android.SdkConstants.TAG_RESOURCES;
import static com.android.SdkConstants.VALUE_FALSE;
import static com.google.common.base.Preconditions.checkNotNull;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.builder.core.AndroidBuilder;
import com.android.builder.model.ClassField;
import com.android.ide.common.xml.XmlPrettyPrinter;
import com.android.resources.ResourceType;
import com.android.utils.XmlUtils;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
/**
* Class able to generate a res value file in an Android project.
*/
public class ResValueGenerator {
public static final String RES_VALUE_FILENAME_XML = "generated.xml";
private static final List<ResourceType> RESOURCES_WITH_TAGS = ImmutableList.of(
ResourceType.ARRAY,
ResourceType.ATTR,
ResourceType.BOOL,
ResourceType.COLOR,
ResourceType.DECLARE_STYLEABLE,
ResourceType.DIMEN,
ResourceType.FRACTION,
ResourceType.INTEGER,
ResourceType.PLURALS,
ResourceType.STRING,
ResourceType.STYLE);
private final File mGenFolder;
private final List<ClassField> mFields = Lists.newArrayList();
private List<Object> mItems = Lists.newArrayList();
/**
* Creates a generator
* @param genFolder the gen folder of the project
*/
public ResValueGenerator(@NonNull File genFolder) {
mGenFolder = checkNotNull(genFolder);
}
public ResValueGenerator addResource(
@NonNull String type, @NonNull String name, @NonNull String value) {
mFields.add(AndroidBuilder.createClassField(type, name, value));
return this;
}
public ResValueGenerator addItems(@Nullable Collection<Object> items) {
if (items != null) {
mItems.addAll(items);
}
return this;
}
/**
* Returns a File representing where the BuildConfig class will be.
*/
public File getFolderPath() {
return new File(mGenFolder, "values");
}
/**
* Generates the resource files
*/
public void generate() throws IOException, ParserConfigurationException {
File pkgFolder = getFolderPath();
if (!pkgFolder.isDirectory()) {
if (!pkgFolder.mkdirs()) {
throw new RuntimeException("Failed to create " + pkgFolder.getAbsolutePath());
}
}
File resFile = new File(pkgFolder, RES_VALUE_FILENAME_XML);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
factory.setIgnoringComments(true);
DocumentBuilder builder;
builder = factory.newDocumentBuilder();
Document document = builder.newDocument();
Node rootNode = document.createElement(TAG_RESOURCES);
document.appendChild(rootNode);
rootNode.appendChild(document.createTextNode("\n"));
rootNode.appendChild(document.createComment("Automatically generated file. DO NOT MODIFY"));
rootNode.appendChild(document.createTextNode("\n\n"));
for (Object item : mItems) {
if (item instanceof ClassField) {
ClassField field = (ClassField)item;
ResourceType type = ResourceType.getEnum(field.getType());
boolean hasResourceTag = (type != null && RESOURCES_WITH_TAGS.contains(type));
Node itemNode = document.createElement(hasResourceTag ? field.getType() : TAG_ITEM);
Attr nameAttr = document.createAttribute(ATTR_NAME);
nameAttr.setValue(field.getName());
itemNode.getAttributes().setNamedItem(nameAttr);
if (!hasResourceTag) {
Attr typeAttr = document.createAttribute(ATTR_TYPE);
typeAttr.setValue(field.getType());
itemNode.getAttributes().setNamedItem(typeAttr);
}
if (type == ResourceType.STRING) {
Attr translatable = document.createAttribute(ATTR_TRANSLATABLE);
translatable.setValue(VALUE_FALSE);
itemNode.getAttributes().setNamedItem(translatable);
}
if (!field.getValue().isEmpty()) {
itemNode.appendChild(document.createTextNode(field.getValue()));
}
rootNode.appendChild(itemNode);
} else if (item instanceof String) {
rootNode.appendChild(document.createTextNode("\n"));
rootNode.appendChild(document.createComment((String) item));
rootNode.appendChild(document.createTextNode("\n"));
}
}
String content;
try {
content = XmlPrettyPrinter.prettyPrint(document, true);
} catch (Throwable t) {
content = XmlUtils.toXml(document);
}
Files.write(content, resFile, Charsets.UTF_8);
}
}