package org.robolectric.res;

import com.ximpleware.VTDGen;
import com.ximpleware.VTDNav;
import org.jetbrains.annotations.NotNull;

public class DocumentLoader {
  private static final FsFile.Filter ENDS_WITH_XML = new FsFile.Filter() {
    @Override public boolean accept(@NotNull FsFile fsFile) {
      return fsFile.getName().endsWith(".xml");
    }
  };

  private final FsFile resourceBase;
  private final String packageName;
  private final VTDGen vtdGen;

  public DocumentLoader(String packageName, ResourcePath resourcePath) {
    this.resourceBase = resourcePath.getResourceBase();
    this.packageName = packageName;
    vtdGen = new VTDGen();
  }

  public void load(String folderBaseName, XmlLoader... xmlLoaders) {
    FsFile[] files = resourceBase.listFiles(new StartsWithFilter(folderBaseName));
    if (files == null) {
      throw new RuntimeException(resourceBase.join(folderBaseName) + " is not a directory");
    }
    for (FsFile dir : files) {
      loadFile(dir, xmlLoaders);
    }
  }

  private void loadFile(FsFile dir, XmlLoader[] xmlLoaders) {
    if (!dir.exists()) {
      throw new RuntimeException("no such directory " + dir);
    }

    for (FsFile file : dir.listFiles(ENDS_WITH_XML)) {
      loadResourceXmlFile(file, xmlLoaders);
    }
  }

  private void loadResourceXmlFile(FsFile fsFile, XmlLoader... xmlLoaders) {
    VTDNav vtdNav = parse(fsFile);
    for (XmlLoader xmlLoader : xmlLoaders) {
      xmlLoader.processResourceXml(new XpathResourceXmlLoader.XmlNode(vtdNav), new XmlContext(packageName, fsFile));
    }
  }

  private VTDNav parse(FsFile xmlFile) {
    try {
      byte[] bytes = xmlFile.getBytes();
      vtdGen.setDoc(bytes);
      vtdGen.parse(true);

      return vtdGen.getNav();
    } catch (Exception e) {
      throw new RuntimeException("Error parsing " + xmlFile, e);
    }
  }
}

@@ -1393,84 +1393,49 @@
     
-for (XmlLoader xmlLoader : xmlLoaders) %7B%0A      xmlLoader.processResourceXml(
+XpathResourceXmlLoader.XmlNode xmlNode = 
 new 
@@ -1472,17 +1472,45 @@
 (vtdNav)
-,
+;%0A    XmlContext xmlContext =
  new Xml
@@ -1537,16 +1537,117 @@
  fsFile)
+;%0A    for (XmlLoader xmlLoader : xmlLoaders) %7B%0A      xmlLoader.processResourceXml(xmlNode, xmlContext
 );%0A    %7D

Address code review comments.