// FIXME: we assume that every node has attributes, may be wrong
private void readPreference(String file, AndroidView root, Integer preferenceId) {
    Document doc;
    try {
      DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
      doc = dBuilder.parse(file);
    } catch (Exception ex) {
      throw new RuntimeException(ex);
    }
    Element rootElement = doc.getDocumentElement();
    String rootTagName = rootElement.getTagName();
    if (!(rootTagName.equals("PreferenceScreen")
            || rootTagName.equals("preference-headers")
            || rootTagName.equals("android.support.v7.preference.PreferenceScreen")
            || rootTagName.equals("android.support.v7.preference.preference-headers"))) {
      return;
    }
    LinkedList<Pair<Node, AndroidView>> work = Lists.newLinkedList();
    work.add(new Pair<>(rootElement, root));
    while (!work.isEmpty()) {
      Pair<Node, AndroidView> p = work.removeFirst();
      Node node = p.getO1();
      AndroidView view = p.getO2();
      view.setOrigin(file);
      NamedNodeMap attrMap = node.getAttributes();
      if (attrMap == null) {
        System.out.println(file + "!!!" + node.getClass() + "!!!"
                + node.toString() + "!!!" + node.getTextContent());
      }
      Node keyNode = attrMap.getNamedItem(KEY_ATTR);
      if (keyNode != null) {
        String key = keyNode.getTextContent();
        view.addAttr(KEY_ATTR, key);
        HashMap<Integer, String> maps = preferencesMap.get("preference-screen");
        if (maps == null) {
          maps = Maps.newHashMap();
        }
        maps.put(preferenceId, FilenameUtils.removeExtension(new File(file).getName()));
        preferencesMap.put("preference-screen", maps);
        Set<String> preferenceKeys = preferenceKeyMaps.get(preferenceId);
        if (preferenceKeys == null) {
          preferenceKeys = new HashSet<>();
          preferenceKeyMaps.put(preferenceId, preferenceKeys);
        }
        preferenceKeys.add(key);
      }
      Node fragmentNode = attrMap.getNamedItem(FRAGMENT_ATTR);
      if (fragmentNode != null) {
        view.addAttr(FRAGMENT_ATTR, fragmentNode.getTextContent());
        HashMap<Integer, String> maps = preferencesMap.get("preference-header");
        if (maps == null) {
          maps = Maps.newHashMap();
        }
        maps.put(preferenceId, FilenameUtils.removeExtension(new File(file).getName()));
        preferencesMap.put("preference-header", maps);
      }
      int guiId = -1;
      // Retrieve view type
      String guiName = node.getNodeName();
      String title = readAndroidTextOrTitle(attrMap, "title");
      String summary = readAndroidTextOrTitle(attrMap, "summary");
      String tooltip = readAndroidTextOrTitle(attrMap, "tooltipText");
      String contentDescription = readAndroidTextOrTitle(attrMap, "contentDescription");
      String images = readAndroidImageResource(attrMap);
      view.save(guiId, title, summary, tooltip, contentDescription, images, guiName);
      //view.save(guiId, title, "", guiName);
      NodeList children = node.getChildNodes();
      for (int i = 0; i < children.getLength(); i++) {
        Node newNode = children.item(i);
        String nodeName = newNode.getNodeName();
        if ("#comment".equals(nodeName)) {
          continue;
        }
        if ("#text".equals(nodeName)) {
          // possible for XML files created on a different operating system
          // than the one our analysis is run on
          continue;
        }
        AndroidView newView = new AndroidView();
        // FIXME: we assume that every node has attributes, may be wrong
        if (!newNode.hasAttributes()) {
          Logger.verb("WARNING", "xml node " + newNode + " has no attributes");
          // Fixed: this is wrong for the case group item -> menu -> item
          //continue;
        } else {
          NamedNodeMap attrs = newNode.getAttributes();
          for (int idx = 0; idx < attrs.getLength(); idx += 1) {
            Node attr = attrs.item(idx);
            String name = attr.getNodeName();
            String value = attr.getNodeValue();
            newView.addAttr(name, value);
          }
        }
        newView.setParent(view);
        work.add(new Pair<>(newNode, newView));
      }
    }
  }
}
AndroidView newView = new AndroidView();
// FIXME: we assume that every node has attributes, may be wrong
if (!newNode.hasAttributes()) {
Logger.verb("WARNING", "xml node " + newNode + " has no attributes");
String nodeName = newNode.getNodeName();
if ("#comment".equals(nodeName)) {
continue;
}
if ("#text".equals(nodeName)) {
// possible for XML files created on a different operating system
// than the one our analysis is run on
continue;
}
AndroidView newView = new AndroidView();
// FIXME: we assume that every node has attributes, may be wrong
if (!newNode.hasAttributes()) {
Logger.verb("WARNING", "xml node " + newNode + " has no attributes");
// Fixed: this is wrong for the case group item -> menu -> item
//continue;
} else {
NamedNodeMap attrs = newNode.getAttributes();
for (int idx = 0; idx < attrs.getLength(); idx += 1) {
Node attr = attrs.item(idx);
String name = attr.getNodeName();
String value = attr.getNodeValue();
String title = readAndroidTextOrTitle(attrMap, "title");
String summary = readAndroidTextOrTitle(attrMap, "summary");
String tooltip = readAndroidTextOrTitle(attrMap, "tooltipText");
String contentDescription = readAndroidTextOrTitle(attrMap, "contentDescription");
String images = readAndroidImageResource(attrMap);
view.save(guiId, title, summary, tooltip, contentDescription, images, guiName);
//view.save(guiId, title, "", guiName);
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node newNode = children.item(i);
String nodeName = newNode.getNodeName();
if ("#comment".equals(nodeName)) {
continue;
}
if ("#text".equals(nodeName)) {
// possible for XML files created on a different operating system
// than the one our analysis is run on
continue;
}
AndroidView newView = new AndroidView();
// FIXME: we assume that every node has attributes, may be wrong
if (!newNode.hasAttributes()) {
Logger.verb("WARNING", "xml node " + newNode + " has no attributes");
// Fixed: this is wrong for the case group item -> menu -> item
//continue;
} else {
NamedNodeMap attrs = newNode.getAttributes();
for (int idx = 0; idx < attrs.getLength(); idx += 1) {
Node attr = attrs.item(idx);
String name = attr.getNodeName();
String value = attr.getNodeValue();
newView.addAttr(name, value);
}
}
newView.setParent(view);
work.add(new Pair<>(newNode, newView));
}
}
}