All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robolectric.res.XpathResourceXmlLoader Maven / Gradle / Ivy

package org.robolectric.res;

import com.ximpleware.AutoPilot;
import com.ximpleware.NavException;
import com.ximpleware.VTDNav;
import com.ximpleware.XPathEvalException;
import com.ximpleware.XPathParseException;
import org.jetbrains.annotations.NotNull;

import javax.xml.xpath.XPathExpressionException;

public abstract class XpathResourceXmlLoader extends XmlLoader {
  private final String expression;

  public XpathResourceXmlLoader(String expression) {
    this.expression = expression;
  }

  @Override protected void processResourceXml(FsFile xmlFile, XmlNode xmlNode, XmlContext xmlContext) throws Exception {
    for (XmlNode node : xmlNode.selectByXpath(expression)) {
      String name = node.getAttrValue("name");
      processNode(name, node, xmlContext);
    }
  }

  protected abstract void processNode(String name, XmlNode xmlNode, XmlContext xmlContext) throws XPathExpressionException;

  public static class XmlNode {
    private final VTDNav vtdNav;

    public XmlNode(VTDNav vtdNav) {
      this.vtdNav = vtdNav;
    }

    public String getElementName() {
      try {
        return vtdNav.toString(vtdNav.getCurrentIndex());
      } catch (NavException e) {
        throw new RuntimeException(e);
      }
    }

    public XmlNode getFirstChild() {
      try {
        VTDNav cloneVtdNav = vtdNav.cloneNav();
        if (!cloneVtdNav.toElement(VTDNav.FIRST_CHILD)) return null;
        return new XmlNode(cloneVtdNav);
      } catch (NavException e) {
        throw new RuntimeException(e);
      }
    }

    public String getTextContent() {
      try {
        return vtdNav.getXPathStringVal();
      } catch (NavException e) {
        throw new RuntimeException(e);
      }
    }

    public Iterable selectByXpath(String expr) throws XPathParseException {
      VTDNav cloneVtdNav = vtdNav.cloneNav();
      final AutoPilot ap = new AutoPilot(cloneVtdNav);
      ap.selectXPath(expr);
      return returnIterable(new Iterator(ap, cloneVtdNav) {
        @Override boolean doHasNext() throws XPathEvalException, NavException {
          int result = ap.evalXPath();
          if (result == -1) {
            ap.resetXPath();
          }
          return result != -1;
        }
      });
    }

    public Iterable selectElements(String name) {
      VTDNav cloneVtdNav = vtdNav.cloneNav();
      final AutoPilot ap = new AutoPilot(cloneVtdNav);
      ap.selectElement(name);
      return returnIterable(new Iterator(ap, cloneVtdNav) {
        @Override boolean doHasNext() throws XPathEvalException, NavException {
          return ap.iterate();
        }
      });
    }

    private Iterable returnIterable(final Iterator iterator) {
      return new Iterable() {
        @NotNull @Override public java.util.Iterator iterator() {
          return iterator;
        }
      };
    }

    public String getAttrValue(String attrName) {
      try {
        int nameIndex = vtdNav.getAttrVal(attrName);
        return nameIndex == -1 ? null : vtdNav.toNormalizedString(nameIndex);
      } catch (NavException e) {
        throw new RuntimeException(e);
      }
    }

    public void pushLocation() {
      vtdNav.push();
    }

    public void popLocation() {
      vtdNav.pop();
    }

    public boolean moveToParent() {
      try {
        return vtdNav.toElement(VTDNav.PARENT);
      } catch (NavException e) {
        throw new RuntimeException(e);
      }
    }

    private abstract class Iterator implements java.util.Iterator {
      private final AutoPilot ap;
      private final VTDNav vtdNav;

      public Iterator(AutoPilot ap, VTDNav vtdNav) {
        this.ap = ap;
        this.vtdNav = vtdNav;
      }

      @Override public boolean hasNext() {
        try {
          return doHasNext();
        } catch (XPathEvalException e) {
          throw new RuntimeException(e);
        } catch (NavException e) {
          throw new RuntimeException(e);
        }
      }

      abstract boolean doHasNext() throws XPathEvalException, NavException;

      @Override public XmlNode next() {
        return new XmlNode(vtdNav);
      }

      @Override public void remove() {
        throw new UnsupportedOperationException();
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy