/*
* Copyright (C) 2013 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.ide.common.res2;
import static com.android.SdkConstants.FD_RES;
import static com.android.SdkConstants.FD_RES_DRAWABLE;
import static com.android.SdkConstants.FD_RES_LAYOUT;
import static com.android.SdkConstants.FD_RES_VALUES;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.resources.TestResourceRepository;
import com.android.ide.common.resources.configuration.FolderConfiguration;
import com.android.ide.common.resources.configuration.LocaleQualifier;
import com.android.ide.common.resources.configuration.ScreenOrientationQualifier;
import com.android.resources.ResourceType;
import com.android.resources.ScreenOrientation;
import com.android.utils.ILogger;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import junit.framework.TestCase;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
@SuppressWarnings("javadoc")
public class ResourceRepositoryTest2 extends TestCase {
private File mTempDir;
private File mRes;
private ResourceMerger mResourceMerger;
private ResourceRepository mRepository;
private ILogger mLogger;
@SuppressWarnings("ResultOfMethodCallIgnored")
@Override
protected void setUp() throws Exception {
super.setUp();
mTempDir = Files.createTempDir();
mRes = new File(mTempDir, FD_RES);
mRes.mkdirs();
File layout = new File(mRes, FD_RES_LAYOUT);
File layoutLand = new File(mRes, FD_RES_LAYOUT + "-land");
File values = new File(mRes, FD_RES_VALUES);
File valuesEs = new File(mRes, FD_RES_VALUES + "-es");
File valuesEsUs = new File(mRes, FD_RES_VALUES + "-es-rUS");
File valuesKok = new File(mRes, FD_RES_VALUES + "-b+kok");
File valuesKokIn = new File(mRes, FD_RES_VALUES + "-b+kok+IN");
File drawable = new File(mRes, FD_RES_DRAWABLE);
layout.mkdirs();
layoutLand.mkdirs();
values.mkdirs();
valuesEs.mkdirs();
valuesEsUs.mkdirs();
valuesKok.mkdirs();
valuesKokIn.mkdirs();
drawable.mkdirs();
new File(layout, "layout1.xml").createNewFile();
new File(layoutLand, "layout1.xml").createNewFile();
new File(layoutLand, "only_land.xml").createNewFile();
new File(layout, "layout2.xml").createNewFile();
new File(drawable, "graphic.9.png").createNewFile();
File strings = new File(values, "strings.xml");
Files.write(""
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<resources>\n"
+ " <item type=\"id\" name=\"action_bar_refresh\" />\n"
+ " <item type=\"dimen\" name=\"dialog_min_width_major\">45%</item>\n"
+ " <string name=\"home_title\">Home Sample</string>\n"
+ " <string name=\"show_all_apps\">All</string>\n"
+ " <string name=\"menu_wallpaper\">Wallpaper</string>\n"
+ " <string name=\"menu_search\">Search</string>\n"
+ " <string name=\"menu_settings\">Settings</string>\n"
+ " <string name=\"dummy\" translatable=\"false\">Ignore Me</string>\n"
+ " <string name=\"wallpaper_instructions\">Tap picture to set portrait wallpaper</string>\n"
+ "</resources>\n", strings, Charsets.UTF_8);
Files.write(""
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<resources>\n"
+ " <string name=\"show_all_apps\">Todo</string>\n"
+ "</resources>\n", new File(valuesEs, "strings.xml"), Charsets.UTF_8);
Files.write(""
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<resources>\n"
+ " <string name=\"show_all_apps\">Todo</string>\n"
+ "</resources>\n", new File(valuesEsUs, "strings.xml"), Charsets.UTF_8);
Files.write(""
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<resources>\n"
+ " <string name=\"show_all_apps\">Todo</string>\n"
+ "</resources>\n", new File(valuesKok, "strings.xml"), Charsets.UTF_8);
Files.write(""
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<resources>\n"
+ " <string name=\"show_all_apps\">Todo</string>\n"
+ "</resources>\n", new File(valuesKokIn, "strings.xml"), Charsets.UTF_8);
if ("testGetMatchingFileAliases".equals(getName())) {
Files.write(""
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<resources>\n"
+ " <item name=\"layout2\" type=\"layout\">@layout/indirect3</item>\n"
+ " <item name=\"indirect3\" type=\"layout\">@layout/indirect2</item>\n"
+ " <item name=\"indirect2\" type=\"layout\">@layout/indirect1</item>\n"
+ " <item name=\"indirect1\" type=\"layout\">@layout/layout1</item>\n"
+ "</resources>", new File(valuesEsUs, "refs.xml"), Charsets.UTF_8);
}
mResourceMerger = new ResourceMerger();
ResourceSet resourceSet = new ResourceSet("main");
resourceSet.addSource(mRes);
resourceSet.loadFromFiles(mLogger = new RecordingLogger());
mResourceMerger.addDataSet(resourceSet);
mRepository = new ResourceRepository(false);
mResourceMerger.mergeData(mRepository.createMergeConsumer(), true /*doCleanUp*/);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
deleteFile(mTempDir);
}
private static void deleteFile(File dir) {
if (dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
deleteFile(f);
}
}
} else if (dir.isFile()) {
assertTrue(dir.getPath(), dir.delete());
}
}
public void testBasic() throws Exception {
assertFalse(mRepository.hasResourceItem("@layout/layout0"));
assertTrue(mRepository.hasResourceItem("@layout/layout1"));
assertFalse(mRepository.hasResourceItem(ResourceType.LAYOUT, "layout0"));
assertTrue(mRepository.hasResourceItem(ResourceType.LAYOUT, "layout1"));
assertFalse(mRepository.hasResourceItem(ResourceType.STRING, "layout1"));
assertTrue(mRepository.hasResourceItem(ResourceType.STRING, "home_title"));
assertFalse(mRepository.hasResourceItem(ResourceType.STRING, "home_title2"));
assertFalse(mRepository.hasResourceItem(ResourceType.DRAWABLE, "graph"));
assertTrue(mRepository.hasResourceItem(ResourceType.DRAWABLE, "graphic"));
assertTrue(mRepository.hasResourceItem("@id/action_bar_refresh"));
assertTrue(mRepository.hasResourceItem("@drawable/graphic"));
assertTrue(mRepository.hasResourcesOfType(ResourceType.DRAWABLE));
assertFalse(mRepository.hasResourcesOfType(ResourceType.ANIM));
List<ResourceType> availableResourceTypes = mRepository.getAvailableResourceTypes();
assertEquals(5, availableResourceTypes.size()); // layout, string, drawable, id, dimen
Collection<String> allStrings = mRepository.getItemsOfType(ResourceType.STRING);
assertEquals(7, allStrings.size());
List<ResourceItem> itemList = mRepository.getResourceItem(ResourceType.STRING, "menu_settings");
assertNotNull(itemList);
assertEquals(1, itemList.size());
for (ResourceItem item : itemList) {
assertEquals("menu_settings", item.getName());
assertEquals("@string/menu_settings", item.getXmlString(ResourceType.STRING, false));
}
//assertTrue(item.hasDefault());
itemList = mRepository.getResourceItem(ResourceType.STRING, "show_all_apps");
assertNotNull(itemList);
assertTrue(itemList.size() > 1);
for (ResourceItem item : itemList) {
assertEquals("show_all_apps", item.getName());
assertEquals("@string/show_all_apps", item.getXmlString(ResourceType.STRING, false));
}
//assertTrue(item.hasDefault());
FolderConfiguration folderConfig = new FolderConfiguration();
folderConfig.setLocaleQualifier(LocaleQualifier.getQualifier("en"));
Map<ResourceType, Map<String, ResourceValue>> configuredItems = mRepository
.getConfiguredResources(folderConfig);
ResourceValue value = configuredItems.get(ResourceType.STRING).get("show_all_apps");
assertNotNull(value);
assertEquals("All", value.getValue());
assertSame(ResourceType.STRING, value.getResourceType());
folderConfig = new FolderConfiguration();
folderConfig.setLocaleQualifier(LocaleQualifier.getQualifier("es"));
configuredItems = mRepository.getConfiguredResources(folderConfig);
value = configuredItems.get(ResourceType.STRING).get("show_all_apps");
assertNotNull(value);
assertEquals("Todo", value.getValue());
assertSame(ResourceType.STRING, value.getResourceType());
itemList = mRepository.getResourceItem(ResourceType.LAYOUT, "only_land");
assertNotNull(itemList);
//assertFalse(item.hasDefault());
assertEquals(1, itemList.size());
ResourceFile resourceFile = itemList.get(0).getSource();
assertEquals("only_land.xml", resourceFile.getFile().getName());
assertEquals(ScreenOrientation.LANDSCAPE.getResourceValue(), resourceFile.getQualifiers());
itemList = mRepository.getResourceItem(ResourceType.LAYOUT, "layout1");
assertNotNull(itemList);
//assertTrue(item.hasDefault());
assertEquals(2, itemList.size());
SortedSet<String> languages = mRepository.getLanguages();
assertEquals(2, languages.size());
assertTrue(languages.contains("es"));
assertTrue(languages.contains("kok"));
assertEquals(Collections.singleton("US"), mRepository.getRegions("es"));
assertEquals(Collections.singleton("IN"), mRepository.getRegions("kok"));
// List<ResourceFile> layouts = mRepository.getSourceFiles(ResourceType.LAYOUT, "layout1",
// folderConfig);
// assertNotNull(layouts);
// assertEquals(1, layouts.size());
// com.android.ide.common.resources.ResourceFile file1 = layouts.get(0);
// assertEquals("layout1.xml", file1.getFile().getName());
// assertSame(mRepository, file1.getRepository());
}
public void testGetConfiguredResources() throws Exception {
FolderConfiguration folderConfig = new FolderConfiguration();
folderConfig.setLocaleQualifier(LocaleQualifier.getQualifier("es"));
folderConfig.setScreenOrientationQualifier(
new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
Map<ResourceType, Map<String, ResourceValue>> configuredResources =
mRepository.getConfiguredResources(folderConfig);
Map<String, ResourceValue> strings = configuredResources.get(ResourceType.STRING);
Map<String, ResourceValue> layouts = configuredResources.get(ResourceType.LAYOUT);
Map<String, ResourceValue> ids = configuredResources.get(ResourceType.ID);
Map<String, ResourceValue> dimens = configuredResources.get(ResourceType.DIMEN);
assertEquals(1, ids.size());
assertEquals(1, dimens.size());
assertEquals("dialog_min_width_major", dimens.get("dialog_min_width_major").getName());
assertEquals("45%", dimens.get("dialog_min_width_major").getValue());
assertEquals("Todo", strings.get("show_all_apps").getValue());
assertEquals(3, layouts.size());
assertNotNull(layouts.get("layout1"));
ResourceFile file = mRepository.getMatchingFile("dialog_min_width_major",
ResourceType.DIMEN, folderConfig);
assertNotNull(file);
// file = mRepository.getMatchingFile("dialog_min_width_major", ResourceFolderType.VALUES,
// folderConfig);
// assertNotNull(file);
// file = mRepository.getMatchingFile("layout1", ResourceFolderType.LAYOUT, folderConfig);
// assertNotNull(file);
file = mRepository.getMatchingFile("layout1", ResourceType.LAYOUT, folderConfig);
assertNotNull(file);
}
public void testGetMatchingFileAliases() throws Exception {
FolderConfiguration folderConfig = new FolderConfiguration();
folderConfig.setLocaleQualifier(LocaleQualifier.getQualifier("es"));
folderConfig.setScreenOrientationQualifier(
new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
Map<ResourceType, Map<String, ResourceValue>> configuredResources =
mRepository.getConfiguredResources(folderConfig);
Map<String, ResourceValue> layouts = configuredResources.get(ResourceType.LAYOUT);
assertEquals(6, layouts.size());
assertNotNull(layouts.get("layout1"));
folderConfig.setLocaleQualifier(LocaleQualifier.getQualifier("es-rES"));
ResourceFile file = mRepository.getMatchingFile("dialog_min_width_major",
ResourceType.DIMEN, folderConfig);
assertNotNull(file);
file = mRepository.getMatchingFile("layout2", ResourceType.LAYOUT, folderConfig);
assertNotNull(file);
assertEquals("layout2.xml", file.getFile().getName());
assertEquals("", file.getQualifiers());
folderConfig.setLocaleQualifier(LocaleQualifier.getQualifier("es-rUS"));
file = mRepository.getMatchingFile("layout2", ResourceType.LAYOUT, folderConfig);
assertNotNull(file);
assertEquals("layout1.xml", file.getFile().getName());
assertEquals("land", file.getQualifiers());
}
public void testUpdates() throws Exception {
assertFalse(mRepository.hasResourcesOfType(ResourceType.ANIM));
assertFalse(mRepository.hasResourcesOfType(ResourceType.MENU));
assertFalse(mRepository.hasResourcesOfType(ResourceType.BOOL));
assertTrue(mRepository.hasResourcesOfType(ResourceType.DRAWABLE));
assertTrue(mRepository.hasResourceItem("@drawable/graphic"));
// Delete the drawable graphic
ResourceSet resourceSet = mResourceMerger.getDataSets().get(0);
File drawableFolder = new File(mRes, FD_RES_DRAWABLE);
File graphicFile = new File(drawableFolder, "graphic.9.png");
resourceSet.updateWith(mRes, graphicFile, FileStatus.REMOVED, mLogger);
mResourceMerger.mergeData(mRepository.createMergeConsumer(), true /*doCleanUp*/);
assertFalse(mRepository.hasResourceItem("@drawable/graphic"));
assertFalse(mRepository.hasResourcesOfType(ResourceType.DRAWABLE));
// Delete one of the overridden layouts
List<ResourceItem> itemList = mRepository.getResourceItem(ResourceType.LAYOUT, "layout1");
assertNotNull(itemList);
assertTrue(itemList.size() > 1);
assertTrue(mRepository.hasResourcesOfType(ResourceType.LAYOUT));
assertTrue(mRepository.hasResourceItem("@layout/layout1"));
File layoutFolder = new File(mRes, FD_RES_LAYOUT + "-land");
File layoutFile = new File(layoutFolder, "layout1.xml");
resourceSet.updateWith(mRes, layoutFile, FileStatus.REMOVED, mLogger);
mResourceMerger.mergeData(mRepository.createMergeConsumer(), true /*doCleanUp*/);
// We still have a layout1: only default now
assertTrue(mRepository.hasResourceItem("@layout/layout1"));
itemList = mRepository.getResourceItem(ResourceType.LAYOUT, "layout1");
assertNotNull(itemList);
assertEquals(1, itemList.size());
// change strings
assertTrue(mRepository.hasResourceItem("@string/dummy"));
assertFalse(mRepository.hasResourceItem("@string/myDummy"));
itemList = mRepository.getResourceItem(ResourceType.STRING, "dummy");
assertNotNull(itemList);
assertNotNull(itemList.get(0));
ResourceFile stringResFile = itemList.get(0).getSource();
File stringFile = stringResFile.getFile();
assertTrue(stringFile.exists());
String strings = Files.toString(stringFile, Charsets.UTF_8);
assertNotNull(strings);
strings = strings.replace("name=\"dummy\"", "name=\"myDummy\"");
Files.write(strings, stringFile, Charsets.UTF_8);
resourceSet.updateWith(mRes, stringFile, FileStatus.CHANGED, mLogger);
mResourceMerger.mergeData(mRepository.createMergeConsumer(), true /*doCleanUp*/);
assertTrue(mRepository.hasResourceItem("@string/myDummy"));
assertFalse(mRepository.hasResourceItem("@string/dummy"));
// add files
assertFalse(mRepository.hasResourceItem("@layout/layout5"));
File layout = new File(mRes, FD_RES_LAYOUT);
File newFile = new File(layout, "layout5.xml");
boolean created = newFile.createNewFile();
assertTrue(created);
resourceSet.updateWith(mRes, newFile, FileStatus.NEW, mLogger);
mResourceMerger.mergeData(mRepository.createMergeConsumer(), true /*doCleanUp*/);
assertTrue(mRepository.hasResourceItem("@layout/layout5"));
}
@SuppressWarnings("ConstantConditions")
public void testXliff() throws Exception {
ResourceRepository resources = TestResourceRepository.createRes2(false, new Object[]{
"values/strings.xml", ""
+ "<resources xmlns:xliff=\"urn:oasis:names:tc:xliff:document:1.2\" >\n"
+ " <string name=\"share_with_application\">\n"
+ " Share your score of <xliff:g id=\"score\" example=\"1337\">%1$s</xliff:g>\n"
+ " with <xliff:g id=\"application_name\" example=\"Bluetooth\">%2$s</xliff:g>!\n"
+ " </string>\n"
+ " <string name=\"callDetailsDurationFormat\"><xliff:g id=\"minutes\" example=\"42\">%s</xliff:g> mins <xliff:g id=\"seconds\" example=\"28\">%s</xliff:g> secs</string>\n"
+ " <string name=\"description_call\">Call <xliff:g id=\"name\">%1$s</xliff:g></string>\n"
+ " <string name=\"other\"><xliff:g id=\"number_of_sessions\">%1$s</xliff:g> sessions removed from your schedule</string>\n"
+ " <!-- Format string used to add a suffix like \"KB\" or \"MB\" to a number\n"
+ " to display a size in kilobytes, megabytes, or other size units.\n"
+ " Some languages (like French) will want to add a space between\n"
+ " the placeholders. -->\n"
+ " <string name=\"fileSizeSuffix\"><xliff:g id=\"number\" example=\"123\">%1$s</xliff:g><xliff:g id=\"unit\" example=\"KB\">%2$s</xliff:g></string>"
+ "</resources>\n"
});
assertFalse(resources.isFramework());
assertNotNull(resources);
assertNotNull(resources);
assertEquals("Share your score of (1337) with (Bluetooth)!",
resources.getResourceItem(ResourceType.STRING, "share_with_application").get(0).getResourceValue(false).getValue());
assertEquals("Call ${name}",
resources.getResourceItem(ResourceType.STRING, "description_call").get(0).getResourceValue(false).getValue());
assertEquals("(42) mins (28) secs",
resources.getResourceItem(ResourceType.STRING, "callDetailsDurationFormat").get(0).getResourceValue(false).getValue());
assertEquals("${number_of_sessions} sessions removed from your schedule",
resources.getResourceItem(ResourceType.STRING, "other").get(0).getResourceValue(false).getValue());
assertEquals("(123)(KB)",
resources.getResourceItem(ResourceType.STRING, "fileSizeSuffix").get(0).getResourceValue(false).getValue());
}
}