LayoutXmlProcessor.java revision 9784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3
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 169784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport org.apache.commons.io.FileUtils; 179784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport org.apache.commons.io.filefilter.FileFilterUtils; 1897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyarimport org.apache.commons.lang3.StringEscapeUtils; 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; 249784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport android.databinding.tool.util.Preconditions; 25fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.writer.JavaFileWriter; 26a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 278e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.io.File; 288e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.io.FilenameFilter; 298e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.io.IOException; 308e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.io.StringWriter; 319784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyarimport java.net.URI; 32a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport java.util.ArrayList; 338e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.util.List; 348e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport java.util.UUID; 358e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 368e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.bind.JAXBContext; 378e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.bind.JAXBException; 388e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.bind.Marshaller; 398e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.parsers.ParserConfigurationException; 408e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.xpath.XPathExpressionException; 418e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 428e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount/** 438e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * Processes the layout XML, stripping the binding attributes and elements 448e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * and writes the information into an annotated class file for the annotation 458e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount * processor to work with. 468e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount */ 478e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountpublic class LayoutXmlProcessor { 48a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar // hardcoded in baseAdapters 49fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount public static final String RESOURCE_BUNDLE_PACKAGE = "android.databinding.layouts"; 50a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public static final String CLASS_NAME = "DataBindingInfo"; 518e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount private final JavaFileWriter mFileWriter; 528e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount private final ResourceBundle mResourceBundle; 5397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar private final int mMinSdk; 5497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar 558e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount private boolean mProcessingComplete; 568e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount private boolean mWritten; 57a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private final boolean mIsLibrary; 588e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount private final String mBuildId = UUID.randomUUID().toString(); 599784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private final OriginalFileLookup mOriginalFileLookup; 608e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 619784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public LayoutXmlProcessor(String applicationPackage, 629784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar JavaFileWriter fileWriter, int minSdk, boolean isLibrary, 639784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar OriginalFileLookup originalFileLookup) { 648e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount mFileWriter = fileWriter; 658e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount mResourceBundle = new ResourceBundle(applicationPackage); 6697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar mMinSdk = minSdk; 67a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar mIsLibrary = isLibrary; 689784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mOriginalFileLookup = originalFileLookup; 69a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 70a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 719784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static void processIncrementalInputFiles(ResourceInput input, 729784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ProcessFileCallback callback) 739784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws IOException, ParserConfigurationException, XPathExpressionException, 749784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar SAXException { 759784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar processExistingIncrementalFiles(input.getRootInputFolder(), input.getAdded(), callback); 769784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar processExistingIncrementalFiles(input.getRootInputFolder(), input.getChanged(), callback); 779784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar processRemovedIncrementalFiles(input.getRootInputFolder(), input.getRemoved(), callback); 78890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar } 79890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar 809784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static void processExistingIncrementalFiles(File inputRoot, List<File> files, 819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ProcessFileCallback callback) 829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws IOException, XPathExpressionException, SAXException, 839784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ParserConfigurationException { 849784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File file : files) { 859784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File parent = file.getParentFile(); 869784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (inputRoot.equals(parent)) { 879784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processOtherRootFile(file); 889784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else if (layoutFolderFilter.accept(parent, parent.getName())) { 899784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processLayoutFile(file); 909784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 919784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processOtherFile(parent, file); 920c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar } 939784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 949784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 959784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 969784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static void processRemovedIncrementalFiles(File inputRoot, List<File> files, 979784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ProcessFileCallback callback) 989784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws IOException { 999784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File file : files) { 1009784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File parent = file.getParentFile(); 1019784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (inputRoot.equals(parent)) { 1029784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processRemovedOtherRootFile(file); 1039784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else if (layoutFolderFilter.accept(parent, parent.getName())) { 1049784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processRemovedLayoutFile(file); 1059784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 1069784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processRemovedOtherFile(parent, file); 1079784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1089784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1099784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 110a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 1119784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static void processAllInputFiles(ResourceInput input, ProcessFileCallback callback) 1129784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws IOException, XPathExpressionException, SAXException, 1139784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ParserConfigurationException { 1149784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.deleteDirectory(input.getRootOutputFolder()); 1159784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Preconditions.check(input.getRootOutputFolder().mkdirs(), "out dir should be re-created"); 1169784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar Preconditions.check(input.getRootInputFolder().isDirectory(), "it must be a directory"); 1179784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File firstLevel : input.getRootInputFolder().listFiles()) { 1189784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (firstLevel.isDirectory()) { 1199784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (layoutFolderFilter.accept(firstLevel, firstLevel.getName())) { 1209784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processLayoutFolder(firstLevel); 1219784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File xmlFile : firstLevel.listFiles(xmlFileFilter)) { 1229784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processLayoutFile(xmlFile); 1239784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1249784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 1259784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processOtherFolder(firstLevel); 1269784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File file : firstLevel.listFiles()) { 1279784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processOtherFile(firstLevel, file); 1289784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 129a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 1309784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 1319784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar callback.processOtherRootFile(firstLevel); 132a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 1339784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 134a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 135a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 136a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 137a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar /** 138a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * used by the studio plugin 139a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 140a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public ResourceBundle getResourceBundle() { 141a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return mResourceBundle; 1428e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 1438e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 1449784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public boolean processResources(final ResourceInput input) 1458e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount throws ParserConfigurationException, SAXException, XPathExpressionException, 1468e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount IOException { 1478e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount if (mProcessingComplete) { 1488e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount return false; 1498e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 1509784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final LayoutFileParser layoutFileParser = new LayoutFileParser(); 1519784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final URI inputRootUri = input.getRootInputFolder().toURI(); 1529784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar ProcessFileCallback callback = new ProcessFileCallback() { 1539784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private File convertToOutFile(File file) { 1549784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final String subPath = toSystemDependentPath(inputRootUri 1559784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar .relativize(file.toURI()).getPath()); 1569784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return new File(input.getRootOutputFolder(), subPath); 1579784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1589784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1599784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processLayoutFile(File file) 1609784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws ParserConfigurationException, SAXException, XPathExpressionException, 1619784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar IOException { 1629784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File output = convertToOutFile(file); 1639784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final ResourceBundle.LayoutFileBundle bindingLayout = layoutFileParser 1649784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar .parseXml(file, output, mResourceBundle.getAppPackage(), mOriginalFileLookup); 1659784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (bindingLayout != null && !bindingLayout.isEmpty()) { 1669784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mResourceBundle.addLayoutBundle(bindingLayout); 1679784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1689784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1699784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1709784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1719784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processOtherFile(File parentFolder, File file) throws IOException { 1729784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File outParent = convertToOutFile(parentFolder); 1739784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.copyFile(file, new File(outParent, file.getName())); 1749784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1759784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1769784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1779784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processRemovedLayoutFile(File file) { 1789784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mResourceBundle.addRemovedFile(file); 1798e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 1809784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processRemovedOtherFile(File parentFolder, File file) throws IOException { 1839784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File outParent = convertToOutFile(parentFolder); 1849784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.forceDelete(new File(outParent, file.getName())); 1859784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1869784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1879784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1889784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processOtherFolder(File folder) { 1899784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar //noinspection ResultOfMethodCallIgnored 1909784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar convertToOutFile(folder).mkdirs(); 1919784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1929784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1939784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 1949784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processLayoutFolder(File folder) { 1959784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar //noinspection ResultOfMethodCallIgnored 1969784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar convertToOutFile(folder).mkdirs(); 1979784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 1989784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 1999784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 2009784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processOtherRootFile(File file) throws IOException { 2019784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File outFile = convertToOutFile(file); 2029784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (file.isDirectory()) { 2039784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.copyDirectory(file, outFile); 2049784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 2059784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.copyFile(file, outFile); 2069784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2079784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2089784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 2099784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 2109784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void processRemovedOtherRootFile(File file) throws IOException { 2119784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final File outFile = convertToOutFile(file); 2129784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (file.isDirectory()) { 2139784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.deleteDirectory(outFile); 2149784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 2159784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.deleteQuietly(outFile); 2169784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2179784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2189784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar }; 2199784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (input.isIncremental()) { 2209784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar processIncrementalInputFiles(input, callback); 2219784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } else { 2229784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar processAllInputFiles(input, callback); 2238e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2248e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount mProcessingComplete = true; 2258e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount return true; 2268e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2278e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 2289784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public static String toSystemDependentPath(String path) { 2299784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar if (File.separatorChar != '/') { 2309784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar path = path.replace('/', File.separatorChar); 2319784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2329784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return path; 2339784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2349784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 235be83770af82294c1841eef414513653646b88dc6Yigit Boyar public void writeLayoutInfoFiles(File xmlOutDir) throws JAXBException { 2368e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount if (mWritten) { 2378e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount return; 2388e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2398e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount JAXBContext context = JAXBContext.newInstance(ResourceBundle.LayoutFileBundle.class); 2408e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount Marshaller marshaller = context.createMarshaller(); 241be83770af82294c1841eef414513653646b88dc6Yigit Boyar 2428e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount for (List<ResourceBundle.LayoutFileBundle> layouts : mResourceBundle.getLayoutBundles() 2438e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount .values()) { 2448e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount for (ResourceBundle.LayoutFileBundle layout : layouts) { 245a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar writeXmlFile(xmlOutDir, layout, marshaller); 2468e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2478e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2489784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar for (File file : mResourceBundle.getRemovedFiles()) { 2499784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar String exportFileName = generateExportFileName(file); 2509784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar FileUtils.deleteQuietly(new File(xmlOutDir, exportFileName)); 2519784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2528e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount mWritten = true; 2538e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2548e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 255a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private void writeXmlFile(File xmlOutDir, ResourceBundle.LayoutFileBundle layout, 256a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar Marshaller marshaller) throws JAXBException { 2579784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar String filename = generateExportFileName(layout); 258a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar String xml = toXML(layout, marshaller); 259a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar mFileWriter.writeToFile(new File(xmlOutDir, filename), xml); 260a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 261a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 262a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public String getInfoClassFullName() { 263a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return RESOURCE_BUNDLE_PACKAGE + "." + CLASS_NAME; 264a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 265a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 266a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private String toXML(ResourceBundle.LayoutFileBundle layout, Marshaller marshaller) 2678e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount throws JAXBException { 268a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar StringWriter writer = new StringWriter(); 269a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar marshaller.marshal(layout, writer); 270a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return writer.getBuffer().toString(); 271a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 272a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 273a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar /** 274a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Generates a string identifier that can uniquely identify the given layout bundle. 275a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * This identifier can be used when we need to export data about this layout bundle. 276a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 2779784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static String generateExportFileName(ResourceBundle.LayoutFileBundle layout) { 2789784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return generateExportFileName(layout.getFileName(), layout.getDirectory()); 2799784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2809784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 2819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private static String generateExportFileName(File file) { 2829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar final String fileName = file.getName(); 2839784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return generateExportFileName(fileName.substring(0, fileName.lastIndexOf('.')), 2849784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar file.getParentFile().getName()); 2859784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 2869784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 2879784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public static String generateExportFileName(String fileName, String dirName) { 2889784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar StringBuilder name = new StringBuilder(fileName); 2899784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar name.append('-').append(dirName); 290a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar for (int i = name.length() - 1; i >= 0; i--) { 291a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar char c = name.charAt(i); 2928e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount if (c == '-') { 293a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar name.deleteCharAt(i); 294a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar c = Character.toUpperCase(name.charAt(i)); 295a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar name.setCharAt(i, c); 2968e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2978e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 2989784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar name.append(".xml"); 299a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return name.toString(); 3008e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 3018e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 302b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar public void writeInfoClass(/*Nullable*/ File sdkDir, File xmlOutDir, 303b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar /*Nullable*/ File exportClassListTo) { 30408119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar writeInfoClass(sdkDir, xmlOutDir, exportClassListTo, false, false); 305b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar } 306b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar 3079784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public String getPackage() { 3089784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mResourceBundle.getAppPackage(); 3099784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3109784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 311b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar public void writeInfoClass(/*Nullable*/ File sdkDir, File xmlOutDir, File exportClassListTo, 31208119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar boolean enableDebugLogs, boolean printEncodedErrorLogs) { 313ee7586713d68806b556a425cbebf007a56261ff3Yigit Boyar final String sdkPath = sdkDir == null ? null : StringEscapeUtils.escapeJava(sdkDir.getAbsolutePath()); 314a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar final Class annotation = BindingBuildInfo.class; 315a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar final String layoutInfoPath = StringEscapeUtils.escapeJava(xmlOutDir.getAbsolutePath()); 316b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar final String exportClassListToPath = exportClassListTo == null ? "" : 317b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar StringEscapeUtils.escapeJava(exportClassListTo.getAbsolutePath()); 318a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar String classString = "package " + RESOURCE_BUNDLE_PACKAGE + ";\n\n" + 319a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "import " + annotation.getCanonicalName() + ";\n\n" + 320a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "@" + annotation.getSimpleName() + "(buildId=\"" + mBuildId + "\", " + 321a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "modulePackage=\"" + mResourceBundle.getAppPackage() + "\", " + 322ae161289a90f6ac69ffe6411ac8c09653c81d04dYigit Boyar "sdkRoot=" + "\"" + (sdkPath == null ? "" : sdkPath) + "\"," + 323a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "layoutInfoDir=\"" + layoutInfoPath + "\"," + 324b6887f1479c3ecec38a7989748ef33de1fbcd973Yigit Boyar "exportClassListTo=\"" + exportClassListToPath + "\"," + 325a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "isLibrary=" + mIsLibrary + "," + 326b1356339eaa6c8e967e4fc1dc283b82909a1208dYigit Boyar "minSdk=" + mMinSdk + "," + 32708119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar "enableDebugLogs=" + enableDebugLogs + "," + 32808119ea342cb47910ca80ff646d746f00e4663ceYigit Boyar "printEncodedError=" + printEncodedErrorLogs + ")\n" + 329a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar "public class " + CLASS_NAME + " {}\n"; 330fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount mFileWriter.writeToFile(RESOURCE_BUNDLE_PACKAGE + "." + CLASS_NAME, classString); 3318e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 3328e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 333a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private static final FilenameFilter layoutFolderFilter = new FilenameFilter() { 3348e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount @Override 3358e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount public boolean accept(File dir, String name) { 3368e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount return name.startsWith("layout"); 3378e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 3388e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount }; 3398e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount 340a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private static final FilenameFilter xmlFileFilter = new FilenameFilter() { 3418e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount @Override 3428e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount public boolean accept(File dir, String name) { 3438e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount return name.toLowerCase().endsWith(".xml"); 3448e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount } 3458e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount }; 346890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar 347890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar /** 348890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar * Helper interface that can find the original copy of a resource XML. 349890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar */ 350890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar public interface OriginalFileLookup { 351890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar 352890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar /** 353890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar * @param file The intermediate build file 354890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar * @return The original file or null if original File cannot be found. 355890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar */ 356890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar File getOriginalFileFor(File file); 357890b4850c628f04eb75397e427ba7074e4f9c386Yigit Boyar } 3589784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3599784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar /** 3609784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar * API agnostic class to get resource changes incrementally. 3619784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar */ 3629784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public static class ResourceInput { 3639784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private final boolean mIncremental; 3649784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private final File mRootInputFolder; 3659784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private final File mRootOutputFolder; 3669784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3679784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private List<File> mAdded = new ArrayList<File>(); 3689784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private List<File> mRemoved = new ArrayList<File>(); 3699784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private List<File> mChanged = new ArrayList<File>(); 3709784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3719784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public ResourceInput(boolean incremental, File rootInputFolder, File rootOutputFolder) { 3729784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mIncremental = incremental; 3739784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mRootInputFolder = rootInputFolder; 3749784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mRootOutputFolder = rootOutputFolder; 3759784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3769784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3779784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void added(File file) { 3789784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mAdded.add(file); 3799784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3809784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void removed(File file) { 3819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mRemoved.add(file); 3829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3839784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public void changed(File file) { 3849784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mChanged.add(file); 3859784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3869784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3879784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public boolean shouldCopy() { 3889784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return !mRootInputFolder.equals(mRootOutputFolder); 3899784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3909784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3919784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<File> getAdded() { 3929784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mAdded; 3939784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3949784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3959784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<File> getRemoved() { 3969784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mRemoved; 3979784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 3989784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 3999784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<File> getChanged() { 4009784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mChanged; 4019784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 4029784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4039784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File getRootInputFolder() { 4049784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mRootInputFolder; 4059784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 4069784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4079784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar File getRootOutputFolder() { 4089784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mRootOutputFolder; 4099784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 4109784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4119784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public boolean isIncremental() { 4129784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return mIncremental; 4139784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 4149784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 4159784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4169784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private interface ProcessFileCallback { 4179784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processLayoutFile(File file) 4189784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar throws ParserConfigurationException, SAXException, XPathExpressionException, 4199784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar IOException; 4209784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processOtherFile(File parentFolder, File file) throws IOException; 4219784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processRemovedLayoutFile(File file); 4229784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processRemovedOtherFile(File parentFolder, File file) throws IOException; 4239784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4249784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processOtherFolder(File folder); 4259784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4269784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processLayoutFolder(File folder); 4279784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4289784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processOtherRootFile(File file) throws IOException; 4299784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 4309784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar void processRemovedOtherRootFile(File file) throws IOException; 4319784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 4328e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount} 433