MenuLoader.java revision 29610b43047065c5dc66452d33f0113ac7e65fe8
1package com.xtremelabs.robolectric.res;
2
3import android.content.Context;
4import android.view.Menu;
5import android.view.MenuItem;
6import org.w3c.dom.Document;
7import org.w3c.dom.NamedNodeMap;
8import org.w3c.dom.Node;
9import org.w3c.dom.NodeList;
10
11import java.io.File;
12import java.util.ArrayList;
13import java.util.HashMap;
14import java.util.List;
15import java.util.Map;
16
17public class MenuLoader extends XmlLoader {
18    private Map<String, MenuNode> menuNodesByMenuName = new HashMap<String, MenuNode>();
19
20    public MenuLoader(ResourceExtractor resourceExtractor) {
21        super(resourceExtractor);
22    }
23
24    @Override
25    protected void processResourceXml(File xmlFile, Document document, boolean ignored) throws Exception {
26        MenuNode topLevelNode = new MenuNode("top-level", new HashMap<String, String>());
27
28        NodeList items = document.getChildNodes();
29        if (items.getLength() != 1)
30            throw new RuntimeException("Expected only one top-level item in menu file " + xmlFile.getName());
31        if (items.item(0).getNodeName().compareTo("menu") != 0)
32            throw new RuntimeException("Expected a top-level item called 'menu' in menu file " + xmlFile.getName());
33
34        processChildren(items.item(0).getChildNodes(), topLevelNode);
35        menuNodesByMenuName.put(
36                "menu/" + xmlFile.getName().replace(".xml", ""),
37                topLevelNode);
38    }
39
40    private void processChildren(NodeList childNodes, MenuNode parent) {
41        for (int i = 0; i < childNodes.getLength(); i++) {
42            Node node = childNodes.item(i);
43            processNode(node, parent);
44        }
45    }
46
47    private void processNode(Node node, MenuNode parent) {
48        String name = node.getNodeName();
49        NamedNodeMap attributes = node.getAttributes();
50        Map<String, String> attrMap = new HashMap<String, String>();
51        if (attributes != null) {
52            int length = attributes.getLength();
53            for (int i = 0; i < length; i++) {
54                Node attr = attributes.item(i);
55                attrMap.put(attr.getNodeName(), attr.getNodeValue());
56            }
57        }
58
59        if (!name.startsWith("#")) {
60            MenuNode menuNode = new MenuNode(name, attrMap);
61            parent.addChild(menuNode);
62            if (node.getChildNodes().getLength() != 0)
63                throw new RuntimeException(node.getChildNodes().toString());
64        }
65    }
66
67    public void inflateMenu(Context context, String key, Menu root) {
68        inflateMenu(context, key, null, root);
69    }
70
71    public void inflateMenu(Context context, int resourceId, Menu root) {
72        inflateMenu(context, resourceExtractor.getResourceName(resourceId), root);
73    }
74
75    private void inflateMenu(Context context, String key, Map<String, String> attributes, Menu root) {
76        MenuNode menuNode = menuNodesByMenuName.get(key);
77        if (menuNode == null) {
78            throw new RuntimeException("Could not find menu " + key);
79        }
80        try {
81            if (attributes != null) {
82                for (Map.Entry<String, String> entry : attributes.entrySet()) {
83                    if (!entry.getKey().equals("menu")) {
84                        menuNode.attributes.put(entry.getKey(), entry.getValue());
85                    }
86                }
87            }
88            menuNode.inflate(context, root);
89        } catch (Exception e) {
90            throw new RuntimeException("error inflating " + key, e);
91        }
92    }
93
94    public class MenuNode {
95        private String name;
96        private final Map<String, String> attributes;
97
98        private List<MenuNode> children = new ArrayList<MenuNode>();
99
100        public MenuNode(String name, Map<String, String> attributes) {
101            this.name = name;
102            this.attributes = attributes;
103        }
104
105        public List<MenuNode> getChildren() {
106            return children;
107        }
108
109        public void addChild(MenuNode MenuNode) {
110            children.add(MenuNode);
111        }
112
113        public void inflate(Context context, Menu root) throws Exception {
114            for (MenuNode child : children) {
115                assert (child.getChildren().size() == 0);
116                MenuItem menuItem = root.add(child.attributes.get("android:id"));
117                assert (menuItem != null);
118                menuItem.setTitle(child.attributes.get("android:title"));
119            }
120        }
121    }
122}
123
124