1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.adt.internal.editors.layout; 18 19 import com.android.ide.common.api.IAttributeInfo.Format; 20 import com.android.ide.common.resources.platform.AttributeInfo; 21 import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor; 22 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor; 23 import com.android.ide.eclipse.adt.internal.editors.descriptors.TextAttributeDescriptor; 24 import com.android.ide.eclipse.adt.internal.editors.mock.MockXmlNode; 25 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; 26 import com.android.resources.Density; 27 import com.android.sdklib.SdkConstants; 28 29 import org.w3c.dom.Node; 30 import org.xmlpull.v1.XmlPullParser; 31 import org.xmlpull.v1.XmlPullParserException; 32 33 import java.util.HashMap; 34 35 import junit.framework.TestCase; 36 37 public class UiElementPullParserTest extends TestCase { 38 39 private UiElementNode ui; 40 private HashMap<String, String> button1Map; 41 private HashMap<String, String> button2Map; 42 private HashMap<String, String> textMap; 43 createTextAttrDesc(String xmlName)44 private TextAttributeDescriptor createTextAttrDesc(String xmlName) { 45 return new TextAttributeDescriptor( 46 xmlName, // xmlLocalName 47 xmlName, // uiName 48 SdkConstants.NS_RESOURCES, // ns uri 49 "", // tooltip 50 new AttributeInfo(xmlName, new Format[] { Format.STRING }) 51 ); 52 } 53 54 @Override setUp()55 protected void setUp() throws Exception { 56 // set up some basic descriptors. 57 // We have button, textview, linear layout, relative layout. 58 // only the layouts have children (all 4 descriptors possible) 59 // Also add some dummy attributes. 60 ElementDescriptor buttonDescriptor = new ElementDescriptor("Button", "Button", "", "", 61 new AttributeDescriptor[] { 62 createTextAttrDesc("name"), 63 createTextAttrDesc("text"), 64 }, 65 new ElementDescriptor[] {}, false); 66 67 ElementDescriptor textDescriptor = new ElementDescriptor("TextView", "TextView", "", "", 68 new AttributeDescriptor[] { 69 createTextAttrDesc("name"), 70 createTextAttrDesc("text"), 71 }, 72 new ElementDescriptor[] {}, false); 73 74 ElementDescriptor linearDescriptor = new ElementDescriptor("LinearLayout", "Linear Layout", 75 "", "", 76 new AttributeDescriptor[] { 77 createTextAttrDesc("orientation"), 78 }, 79 new ElementDescriptor[] { }, false); 80 81 ElementDescriptor relativeDescriptor = new ElementDescriptor("RelativeLayout", 82 "Relative Layout", "", "", 83 new AttributeDescriptor[] { 84 createTextAttrDesc("orientation"), 85 }, 86 new ElementDescriptor[] { }, false); 87 88 ElementDescriptor[] a = new ElementDescriptor[] { 89 buttonDescriptor, textDescriptor, linearDescriptor, relativeDescriptor 90 }; 91 92 linearDescriptor.setChildren(a); 93 relativeDescriptor.setChildren(a); 94 95 // document descriptor 96 ElementDescriptor rootDescriptor = new ElementDescriptor("root", "", "", "", 97 new AttributeDescriptor[] { }, a, false); 98 99 100 ui = new UiElementNode(rootDescriptor); 101 102 /* create a dummy XML file. 103 * <LinearLayout android:orientation="vertical"> 104 * <Button android:name="button1" android:text="button1text"/> 105 * <RelativeLayout android:orientation="toto"> 106 * <Button android:name="button2" android:text="button2text"/> 107 * <TextView android:name="text1" android:text="text1text"/> 108 * </RelativeLayout> 109 * </LinearLayout> 110 */ 111 MockXmlNode button1 = new MockXmlNode(null /* namespace */, "Button", Node.ELEMENT_NODE, 112 null); 113 button1.addAttributes(SdkConstants.NS_RESOURCES, "name", "button1"); 114 button1.addAttributes(SdkConstants.NS_RESOURCES, "text", "button1text"); 115 116 // create a map of the attributes we add to the multi-attribute nodes so that 117 // we can more easily test the values when we parse the XML. 118 // This is due to some attributes showing in a certain order for a node and in a different 119 // order in another node. Since the order doesn't matter, we just simplify the test. 120 button1Map = new HashMap<String, String>(); 121 button1Map.put("name", "button1"); 122 button1Map.put("text", "button1text"); 123 124 MockXmlNode button2 = new MockXmlNode(null /* namespace */, "Button", Node.ELEMENT_NODE, 125 null); 126 button2.addAttributes(SdkConstants.NS_RESOURCES, "name", "button2"); 127 button2.addAttributes(SdkConstants.NS_RESOURCES, "text", "button2text"); 128 129 button2Map = new HashMap<String, String>(); 130 button2Map.put("name", "button2"); 131 button2Map.put("text", "button2text"); 132 133 MockXmlNode text = new MockXmlNode(null /* namespace */, "TextView", Node.ELEMENT_NODE, 134 null); 135 text.addAttributes(SdkConstants.NS_RESOURCES, "name", "text1"); 136 text.addAttributes(SdkConstants.NS_RESOURCES, "text", "text1text"); 137 138 textMap = new HashMap<String, String>(); 139 textMap.put("name", "text1"); 140 textMap.put("text", "text1text"); 141 142 MockXmlNode relative = new MockXmlNode(null /* namespace */, "RelativeLayout", 143 Node.ELEMENT_NODE, new MockXmlNode[] { button2, text }); 144 relative.addAttributes(SdkConstants.NS_RESOURCES, "orientation", "toto"); 145 146 MockXmlNode linear = new MockXmlNode(null /* namespace */, "LinearLayout", 147 Node.ELEMENT_NODE, new MockXmlNode[] { button1, relative }); 148 linear.addAttributes(SdkConstants.NS_RESOURCES, "orientation", "vertical"); 149 150 MockXmlNode root = new MockXmlNode(null /* namespace */, "root", Node.ELEMENT_NODE, 151 new MockXmlNode[] { linear }); 152 153 // put the namespace/prefix in place 154 root.setPrefix(SdkConstants.NS_RESOURCES, "android"); 155 156 // load the xml into the UiElementNode 157 ui.loadFromXmlNode(root); 158 159 super.setUp(); 160 } 161 162 @Override tearDown()163 protected void tearDown() throws Exception { 164 super.tearDown(); 165 } 166 testParser()167 public void testParser() { 168 try { 169 // wrap the parser around the ui element node, and start parsing 170 UiElementPullParser parser = new UiElementPullParser( 171 ui, // model 172 false, // explodedView 173 null, // explodeNodes 174 Density.MEDIUM, // density (default from ConfigurationComposite) 175 Density.MEDIUM.getDpiValue(), // xdpi (default from ConfigurationComposite) 176 null // iProject 177 ); 178 179 assertEquals(XmlPullParser.START_DOCUMENT, parser.getEventType()); 180 181 // top level Linear layout 182 assertEquals(XmlPullParser.START_TAG, parser.next()); 183 assertEquals("LinearLayout", parser.getName()); 184 assertEquals(1, parser.getAttributeCount()); 185 assertEquals("orientation", parser.getAttributeName(0)); 186 assertEquals(SdkConstants.NS_RESOURCES, parser.getAttributeNamespace(0)); 187 assertEquals("android", parser.getAttributePrefix(0)); 188 assertEquals("vertical", parser.getAttributeValue(0)); 189 190 // Button 191 assertEquals(XmlPullParser.START_TAG, parser.next()); 192 assertEquals("Button", parser.getName()); 193 assertEquals(2, parser.getAttributeCount()); 194 check(parser, 0, button1Map); 195 check(parser, 1, button1Map); 196 // end of button 197 assertEquals(XmlPullParser.END_TAG, parser.next()); 198 199 // Relative Layout 200 assertEquals(XmlPullParser.START_TAG, parser.next()); 201 assertEquals("RelativeLayout", parser.getName()); 202 assertEquals(1, parser.getAttributeCount()); 203 assertEquals("orientation", parser.getAttributeName(0)); 204 assertEquals(SdkConstants.NS_RESOURCES, parser.getAttributeNamespace(0)); 205 assertEquals("android", parser.getAttributePrefix(0)); 206 assertEquals("toto", parser.getAttributeValue(0)); 207 208 // Button 209 assertEquals(XmlPullParser.START_TAG, parser.next()); 210 assertEquals("Button", parser.getName()); 211 assertEquals(2, parser.getAttributeCount()); 212 check(parser, 0, button2Map); 213 check(parser, 1, button2Map); 214 // end of button 215 assertEquals(XmlPullParser.END_TAG, parser.next()); 216 217 // TextView 218 assertEquals(XmlPullParser.START_TAG, parser.next()); 219 assertEquals("TextView", parser.getName()); 220 assertEquals(2, parser.getAttributeCount()); 221 check(parser, 0, textMap); 222 check(parser, 1, textMap); 223 // end of TextView 224 assertEquals(XmlPullParser.END_TAG, parser.next()); 225 226 // end of RelativeLayout 227 assertEquals(XmlPullParser.END_TAG, parser.next()); 228 229 230 // end of top level linear layout 231 assertEquals(XmlPullParser.END_TAG, parser.next()); 232 233 assertEquals(XmlPullParser.END_DOCUMENT, parser.next()); 234 } catch (XmlPullParserException e) { 235 e.printStackTrace(); 236 assertTrue(false); 237 } 238 } 239 240 /** 241 * Receives a {@link XmlPullParser} at the START_TAG level, and checks the i-th attribute 242 * to be present in the {@link HashMap} with the proper (name, value) 243 * @param parser 244 * @param i 245 * @param map 246 */ check(UiElementPullParser parser, int i, HashMap<String, String> map)247 private void check(UiElementPullParser parser, int i, HashMap<String, String> map) { 248 String name = parser.getAttributeName(i); 249 String value = parser.getAttributeValue(i); 250 251 String referenceValue = map.get(name); 252 assertNotNull(referenceValue); 253 assertEquals(referenceValue, value); 254 255 assertEquals(SdkConstants.NS_RESOURCES, parser.getAttributeNamespace(i)); 256 assertEquals("android", parser.getAttributePrefix(i)); 257 } 258 259 } 260