18e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount/* 28e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * Copyright (C) 2015 The Android Open Source Project 38e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * Licensed under the Apache License, Version 2.0 (the "License"); 48e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * you may not use this file except in compliance with the License. 58e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * You may obtain a copy of the License at 68e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * http://www.apache.org/licenses/LICENSE-2.0 78e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * Unless required by applicable law or agreed to in writing, software 88e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * distributed under the License is distributed on an "AS IS" BASIS, 98e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 108e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * See the License for the specific language governing permissions and 118e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * limitations under the License. 128e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount */ 138e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 14fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool; 158e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 164ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Guptaimport com.google.common.escape.Escaper; 174ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta 189784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport org.apache.commons.io.FileUtils; 198e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport org.xml.sax.SAXException; 208e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.BindingBuildInfo; 22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.store.LayoutFileParser; 23fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.store.ResourceBundle; 2489e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyarimport android.databinding.tool.util.L; 259784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport android.databinding.tool.util.Preconditions; 264ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Guptaimport android.databinding.tool.util.SourceCodeEscapers; 27fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.writer.JavaFileWriter; 28a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 298e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.io.File; 308e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.io.FilenameFilter; 318e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.io.IOException; 329784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.net.URI; 33a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport java.util.ArrayList; 348e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.util.List; 358e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.util.UUID; 368e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 378e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.bind.JAXBException; 388e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.parsers.ParserConfigurationException; 398e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.xpath.XPathExpressionException; 408e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 418e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount/** 428e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * Processes the layout XML, stripping the binding attributes and elements 438e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * and writes the information into an annotated class file for the annotation 448e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * processor to work with. 458e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount */ 468e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountpublic class LayoutXmlProcessor { 47a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar // hardcoded in baseAdapters 48fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount public static final String RESOURCE_BUNDLE_PACKAGE = "android.databinding.layouts"; 49a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public static final String CLASS_NAME = "DataBindingInfo"; 508e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount private final JavaFileWriter mFileWriter; 518e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount private final ResourceBundle mResourceBundle; 5297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar private final int mMinSdk; 5397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar 548e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount private boolean mProcessingComplete; 558e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount private boolean mWritten; 56a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private final boolean mIsLibrary; 578e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount private final String mBuildId = UUID.randomUUID().toString(); 589784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private final OriginalFileLookup mOriginalFileLookup; 598e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 609784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public LayoutXmlProcessor(String applicationPackage, 619784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar JavaFileWriter fileWriter, int minSdk, boolean isLibrary, 629784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar OriginalFileLookup originalFileLookup) { 638e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount mFileWriter = fileWriter; 648e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount mResourceBundle = new ResourceBundle(applicationPackage); 6597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar mMinSdk = minSdk; 66a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar mIsLibrary = isLibrary; 679784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mOriginalFileLookup = originalFileLookup; 68a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 69a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 709784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static void processIncrementalInputFiles(ResourceInput input, 719784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ProcessFileCallback callback) 729784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws IOException, ParserConfigurationException, XPathExpressionException, 739784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar SAXException { 749784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar processExistingIncrementalFiles(input.getRootInputFolder(), input.getAdded(), callback); 759784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar processExistingIncrementalFiles(input.getRootInputFolder(), input.getChanged(), callback); 769784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar processRemovedIncrementalFiles(input.getRootInputFolder(), input.getRemoved(), callback); 77890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar } 78890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar 799784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static void processExistingIncrementalFiles(File inputRoot, List<File> files, 809784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ProcessFileCallback callback) 819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws IOException, XPathExpressionException, SAXException, 829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ParserConfigurationException { 839784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File file : files) { 849784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File parent = file.getParentFile(); 859784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (inputRoot.equals(parent)) { 869784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processOtherRootFile(file); 879784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else if (layoutFolderFilter.accept(parent, parent.getName())) { 889784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processLayoutFile(file); 899784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 909784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processOtherFile(parent, file); 910c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar } 929784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 939784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 949784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 959784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static void processRemovedIncrementalFiles(File inputRoot, List<File> files, 969784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ProcessFileCallback callback) 979784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws IOException { 989784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File file : files) { 999784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File parent = file.getParentFile(); 1009784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (inputRoot.equals(parent)) { 1019784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processRemovedOtherRootFile(file); 1029784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else if (layoutFolderFilter.accept(parent, parent.getName())) { 1039784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processRemovedLayoutFile(file); 1049784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 1059784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processRemovedOtherFile(parent, file); 1069784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1079784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1089784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 109a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 1109784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static void processAllInputFiles(ResourceInput input, ProcessFileCallback callback) 1119784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws IOException, XPathExpressionException, SAXException, 1129784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ParserConfigurationException { 1139784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.deleteDirectory(input.getRootOutputFolder()); 1149784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Preconditions.check(input.getRootOutputFolder().mkdirs(), "out dir should be re-created"); 1159784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Preconditions.check(input.getRootInputFolder().isDirectory(), "it must be a directory"); 1169784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File firstLevel : input.getRootInputFolder().listFiles()) { 1179784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (firstLevel.isDirectory()) { 1189784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (layoutFolderFilter.accept(firstLevel, firstLevel.getName())) { 1199784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processLayoutFolder(firstLevel); 1209784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File xmlFile : firstLevel.listFiles(xmlFileFilter)) { 1219784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processLayoutFile(xmlFile); 1229784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1239784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 1249784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processOtherFolder(firstLevel); 1259784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File file : firstLevel.listFiles()) { 1269784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processOtherFile(firstLevel, file); 1279784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 128a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 1299784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 1309784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processOtherRootFile(firstLevel); 131a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 1329784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 133a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 134a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 135a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 136a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar /** 137a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * used by the studio plugin 138a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 139a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public ResourceBundle getResourceBundle() { 140a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return mResourceBundle; 1418e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 1428e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 1439784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public boolean processResources(final ResourceInput input) 1448e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount throws ParserConfigurationException, SAXException, XPathExpressionException, 1458e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount IOException { 1468e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount if (mProcessingComplete) { 1478e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount return false; 1488e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 1499784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final LayoutFileParser layoutFileParser = new LayoutFileParser(); 1509784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final URI inputRootUri = input.getRootInputFolder().toURI(); 1519784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ProcessFileCallback callback = new ProcessFileCallback() { 1529784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private File convertToOutFile(File file) { 1539784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final String subPath = toSystemDependentPath(inputRootUri 1549784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar .relativize(file.toURI()).getPath()); 1559784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return new File(input.getRootOutputFolder(), subPath); 1569784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1579784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1589784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processLayoutFile(File file) 1599784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws ParserConfigurationException, SAXException, XPathExpressionException, 1609784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar IOException { 16189e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar final File output = convertToOutFile(file); 1629784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final ResourceBundle.LayoutFileBundle bindingLayout = layoutFileParser 1639784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar .parseXml(file, output, mResourceBundle.getAppPackage(), mOriginalFileLookup); 1649784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (bindingLayout != null && !bindingLayout.isEmpty()) { 1659784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mResourceBundle.addLayoutBundle(bindingLayout); 1669784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1679784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1689784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1699784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1709784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processOtherFile(File parentFolder, File file) throws IOException { 17189e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar final File outParent = convertToOutFile(parentFolder); 1729784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.copyFile(file, new File(outParent, file.getName())); 1739784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1749784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1759784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1769784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processRemovedLayoutFile(File file) { 1779784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mResourceBundle.addRemovedFile(file); 17889e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar final File out = convertToOutFile(file); 17989e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar FileUtils.deleteQuietly(out); 1808e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 1819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1839784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processRemovedOtherFile(File parentFolder, File file) throws IOException { 18489e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar final File outParent = convertToOutFile(parentFolder); 18589e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar FileUtils.deleteQuietly(new File(outParent, file.getName())); 1869784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1879784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1889784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1899784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processOtherFolder(File folder) { 1909784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar //noinspection ResultOfMethodCallIgnored 1919784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar convertToOutFile(folder).mkdirs(); 1929784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1939784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1949784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1959784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processLayoutFolder(File folder) { 1969784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar //noinspection ResultOfMethodCallIgnored 1979784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar convertToOutFile(folder).mkdirs(); 1989784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1999784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 2009784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 2019784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processOtherRootFile(File file) throws IOException { 20289e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar final File outFile = convertToOutFile(file); 2039784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (file.isDirectory()) { 2049784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.copyDirectory(file, outFile); 2059784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 2069784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.copyFile(file, outFile); 2079784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2089784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2099784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 2109784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 2119784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processRemovedOtherRootFile(File file) throws IOException { 2129784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final File outFile = convertToOutFile(file); 21389e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar FileUtils.deleteQuietly(outFile); 2149784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2159784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar }; 2169784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (input.isIncremental()) { 2179784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar processIncrementalInputFiles(input, callback); 2189784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 2199784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar processAllInputFiles(input, callback); 2208e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2218e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount mProcessingComplete = true; 2228e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount return true; 2238e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2248e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 2259784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public static String toSystemDependentPath(String path) { 2269784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (File.separatorChar != '/') { 2279784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar path = path.replace('/', File.separatorChar); 2289784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2299784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return path; 2309784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2319784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 232be83770af82294c1841eef414513653646b88dc6Yigit Boyar public void writeLayoutInfoFiles(File xmlOutDir) throws JAXBException { 2338e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount if (mWritten) { 2348e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount return; 2358e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2368e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount for (List<ResourceBundle.LayoutFileBundle> layouts : mResourceBundle.getLayoutBundles() 2378e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount .values()) { 2388e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount for (ResourceBundle.LayoutFileBundle layout : layouts) { 23928e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar writeXmlFile(xmlOutDir, layout); 2408e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2418e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2429784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File file : mResourceBundle.getRemovedFiles()) { 2439784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar String exportFileName = generateExportFileName(file); 2449784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.deleteQuietly(new File(xmlOutDir, exportFileName)); 2459784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2468e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount mWritten = true; 2478e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2488e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 24928e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar private void writeXmlFile(File xmlOutDir, ResourceBundle.LayoutFileBundle layout) 25028e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar throws JAXBException { 2519784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar String filename = generateExportFileName(layout); 25228e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar mFileWriter.writeToFile(new File(xmlOutDir, filename), layout.toXML()); 253a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 254a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 255a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public String getInfoClassFullName() { 256a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return RESOURCE_BUNDLE_PACKAGE + "." + CLASS_NAME; 257a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 258a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 259a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar /** 260a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Generates a string identifier that can uniquely identify the given layout bundle. 261a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * This identifier can be used when we need to export data about this layout bundle. 262a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 2639784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static String generateExportFileName(ResourceBundle.LayoutFileBundle layout) { 2649784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return generateExportFileName(layout.getFileName(), layout.getDirectory()); 2659784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2669784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 2679784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static String generateExportFileName(File file) { 2689784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final String fileName = file.getName(); 2699784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return generateExportFileName(fileName.substring(0, fileName.lastIndexOf('.')), 2709784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar file.getParentFile().getName()); 2719784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2729784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 2739784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public static String generateExportFileName(String fileName, String dirName) { 27428e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar return fileName + '-' + dirName + ".xml"; 27528e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar } 27628e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar 27728e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar public static String exportLayoutNameFromInfoFileName(String infoFileName) { 27828e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar return infoFileName.substring(0, infoFileName.indexOf('-')); 2798e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2808e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 281b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar public void writeInfoClass(/*Nullable*/ File sdkDir, File xmlOutDir, 282b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar /*Nullable*/ File exportClassListTo) { 28308119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar writeInfoClass(sdkDir, xmlOutDir, exportClassListTo, false, false); 284b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar } 285b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar 2869784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public String getPackage() { 2879784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mResourceBundle.getAppPackage(); 2889784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2899784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 290b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar public void writeInfoClass(/*Nullable*/ File sdkDir, File xmlOutDir, File exportClassListTo, 29108119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar boolean enableDebugLogs, boolean printEncodedErrorLogs) { 2924ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta Escaper javaEscaper = SourceCodeEscapers.javaCharEscaper(); 2934ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta final String sdkPath = sdkDir == null ? null : javaEscaper.escape(sdkDir.getAbsolutePath()); 294a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar final Class annotation = BindingBuildInfo.class; 2954ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta final String layoutInfoPath = javaEscaper.escape(xmlOutDir.getAbsolutePath()); 296b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar final String exportClassListToPath = exportClassListTo == null ? "" : 2974ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta javaEscaper.escape(exportClassListTo.getAbsolutePath()); 298a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar String classString = "package " + RESOURCE_BUNDLE_PACKAGE + ";\n\n" + 299a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "import " + annotation.getCanonicalName() + ";\n\n" + 300a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "@" + annotation.getSimpleName() + "(buildId=\"" + mBuildId + "\", " + 301a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "modulePackage=\"" + mResourceBundle.getAppPackage() + "\", " + 302ae161289a90f6ac69ffe6411ac8c09653c81d04dYigit Boyar "sdkRoot=" + "\"" + (sdkPath == null ? "" : sdkPath) + "\"," + 303a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "layoutInfoDir=\"" + layoutInfoPath + "\"," + 304b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar "exportClassListTo=\"" + exportClassListToPath + "\"," + 305a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "isLibrary=" + mIsLibrary + "," + 306b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar "minSdk=" + mMinSdk + "," + 30708119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar "enableDebugLogs=" + enableDebugLogs + "," + 30808119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar "printEncodedError=" + printEncodedErrorLogs + ")\n" + 309a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "public class " + CLASS_NAME + " {}\n"; 310fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount mFileWriter.writeToFile(RESOURCE_BUNDLE_PACKAGE + "." + CLASS_NAME, classString); 3118e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 3128e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 313a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private static final FilenameFilter layoutFolderFilter = new FilenameFilter() { 3148e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount @Override 3158e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount public boolean accept(File dir, String name) { 3168e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount return name.startsWith("layout"); 3178e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 3188e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount }; 3198e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 320a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private static final FilenameFilter xmlFileFilter = new FilenameFilter() { 3218e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount @Override 3228e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount public boolean accept(File dir, String name) { 3238e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount return name.toLowerCase().endsWith(".xml"); 3248e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 3258e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount }; 326890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar 327890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar /** 328890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar * Helper interface that can find the original copy of a resource XML. 329890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar */ 330890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar public interface OriginalFileLookup { 331890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar 332890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar /** 333890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar * @param file The intermediate build file 334890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar * @return The original file or null if original File cannot be found. 335890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar */ 336890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar File getOriginalFileFor(File file); 337890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar } 3389784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3399784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar /** 3409784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * API agnostic class to get resource changes incrementally. 3419784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar */ 3429784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public static class ResourceInput { 3439784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private final boolean mIncremental; 3449784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private final File mRootInputFolder; 3459784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private final File mRootOutputFolder; 3469784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3479784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private List<File> mAdded = new ArrayList<File>(); 3489784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private List<File> mRemoved = new ArrayList<File>(); 3499784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private List<File> mChanged = new ArrayList<File>(); 3509784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3519784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public ResourceInput(boolean incremental, File rootInputFolder, File rootOutputFolder) { 3529784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mIncremental = incremental; 3539784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mRootInputFolder = rootInputFolder; 3549784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mRootOutputFolder = rootOutputFolder; 3559784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3569784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3579784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void added(File file) { 3589784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mAdded.add(file); 3599784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3609784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void removed(File file) { 3619784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mRemoved.add(file); 3629784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3639784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void changed(File file) { 3649784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mChanged.add(file); 3659784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3669784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3679784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public boolean shouldCopy() { 3689784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return !mRootInputFolder.equals(mRootOutputFolder); 3699784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3709784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3719784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<File> getAdded() { 3729784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mAdded; 3739784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3749784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3759784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<File> getRemoved() { 3769784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mRemoved; 3779784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3789784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3799784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<File> getChanged() { 3809784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mChanged; 3819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3839784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File getRootInputFolder() { 3849784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mRootInputFolder; 3859784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3869784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3879784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File getRootOutputFolder() { 3889784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mRootOutputFolder; 3899784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3909784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3919784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public boolean isIncremental() { 3929784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mIncremental; 3939784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 39489e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar 39589e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar @Override 39689e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar public String toString() { 39789e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar StringBuilder out = new StringBuilder(); 39889e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar out.append("ResourceInput{") 39989e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar .append("mIncremental=").append(mIncremental) 40089e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar .append(", mRootInputFolder=").append(mRootInputFolder) 40189e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar .append(", mRootOutputFolder=").append(mRootOutputFolder); 40289e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar logFiles(out, "added", mAdded); 40389e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar logFiles(out, "removed", mRemoved); 40489e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar logFiles(out, "changed", mChanged); 40589e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar return out.toString(); 40689e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar 40789e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar } 40889e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar 40989e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar private static void logFiles(StringBuilder out, String name, List<File> files) { 41089e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar out.append("\n ").append(name); 41189e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar for (File file : files) { 41289e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar out.append("\n - ").append(file.getAbsolutePath()); 41389e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar } 41489e50f43810ee32d8fc8ea359cd8e0ca4e9c8de4Yigit Boyar } 4159784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 4169784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4179784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private interface ProcessFileCallback { 4189784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processLayoutFile(File file) 4199784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws ParserConfigurationException, SAXException, XPathExpressionException, 4209784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar IOException; 4219784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processOtherFile(File parentFolder, File file) throws IOException; 4229784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processRemovedLayoutFile(File file); 4239784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processRemovedOtherFile(File parentFolder, File file) throws IOException; 4249784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4259784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processOtherFolder(File folder); 4269784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4279784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processLayoutFolder(File folder); 4289784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4299784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processOtherRootFile(File file) throws IOException; 4309784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4319784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processRemovedOtherRootFile(File file) throws IOException; 4329784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 4338e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount} 434