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