163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye/* 263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * Copyright (C) 2010 The Android Open Source Project 363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * 463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * you may not use this file except in compliance with the License. 663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * You may obtain a copy of the License at 763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * 863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * http://www.eclipse.org/org/documents/epl-v10.php 963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * 1063a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * Unless required by applicable law or agreed to in writing, software 1163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * distributed under the License is distributed on an "AS IS" BASIS, 1263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * See the License for the specific language governing permissions and 1463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye * limitations under the License. 1563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye */ 1663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbyepackage com.android.ide.common.layout; 1763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 1813a9256cbb601228887eea910ce1dbd68a776b17Tor Norbyeimport static com.android.SdkConstants.ANDROID_URI; 1912d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ANDROID_WIDGET_PREFIX; 2012d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ATTR_ID; 21fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbyeimport static junit.framework.Assert.assertEquals; 2213a9256cbb601228887eea910ce1dbd68a776b17Tor Norbyeimport static junit.framework.Assert.assertNotNull; 2313a9256cbb601228887eea910ce1dbd68a776b17Tor Norbyeimport static junit.framework.Assert.assertTrue; 2413a9256cbb601228887eea910ce1dbd68a776b17Tor Norbyeimport static junit.framework.Assert.fail; 25bfcbad18934be1f51ae03d4b6255cfe2d7239aafTor Norbye 267e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbyeimport com.android.annotations.NonNull; 277e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbyeimport com.android.annotations.Nullable; 2863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbyeimport com.android.ide.common.api.IAttributeInfo; 2963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbyeimport com.android.ide.common.api.INode; 3063a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbyeimport com.android.ide.common.api.INodeHandler; 3180d9301c2e874b29889c41adb0623666cf534fa0Tor Norbyeimport com.android.ide.common.api.Margins; 3263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbyeimport com.android.ide.common.api.Rect; 3313a9256cbb601228887eea910ce1dbd68a776b17Tor Norbyeimport com.android.ide.common.xml.XmlFormatStyle; 3413a9256cbb601228887eea910ce1dbd68a776b17Tor Norbyeimport com.android.ide.common.xml.XmlPrettyPrinter; 3513a9256cbb601228887eea910ce1dbd68a776b17Tor Norbyeimport com.android.ide.eclipse.adt.internal.editors.formatting.EclipseXmlFormatPreferences; 3613a9256cbb601228887eea910ce1dbd68a776b17Tor Norbyeimport com.android.ide.eclipse.adt.internal.editors.formatting.EclipseXmlPrettyPrinter; 37fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbyeimport com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities; 38fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbyeimport com.google.common.base.Splitter; 3963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 400cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbyeimport org.w3c.dom.Attr; 41fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbyeimport org.w3c.dom.Document; 42fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbyeimport org.w3c.dom.Element; 430cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbyeimport org.w3c.dom.NamedNodeMap; 44fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 45fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbyeimport java.io.IOException; 46fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbyeimport java.io.StringWriter; 4763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbyeimport java.util.ArrayList; 48e287bc8580e19d72a911615475b353790cf000ebTor Norbyeimport java.util.Collections; 4963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbyeimport java.util.HashMap; 50fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbyeimport java.util.Iterator; 5163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbyeimport java.util.List; 5263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbyeimport java.util.Map; 53fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbyeimport java.util.regex.Matcher; 54fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbyeimport java.util.regex.Pattern; 55fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 5663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye/** Test/mock implementation of {@link INode} */ 57fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye@SuppressWarnings("javadoc") 5863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbyepublic class TestNode implements INode { 5963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye private TestNode mParent; 6063a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 6163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye private final List<TestNode> mChildren = new ArrayList<TestNode>(); 6263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 6363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye private final String mFqcn; 6463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 6563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye private Rect mBounds = new Rect(); // Invalid bounds initially 6663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 6763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye private Map<String, IAttribute> mAttributes = new HashMap<String, IAttribute>(); 6863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 6963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye private Map<String, IAttributeInfo> mAttributeInfos = new HashMap<String, IAttributeInfo>(); 7063a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 71e287bc8580e19d72a911615475b353790cf000ebTor Norbye private List<String> mAttributeSources; 72e287bc8580e19d72a911615475b353790cf000ebTor Norbye 7363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public TestNode(String fqcn) { 7463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye this.mFqcn = fqcn; 7563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 7663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 7763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public TestNode bounds(Rect bounds) { 7863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye this.mBounds = bounds; 7963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 8063a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return this; 8163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 8263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 8363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public TestNode id(String id) { 84bfcbad18934be1f51ae03d4b6255cfe2d7239aafTor Norbye return set(ANDROID_URI, ATTR_ID, id); 8563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 8663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 8763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public TestNode set(String uri, String name, String value) { 8863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye setAttribute(uri, name, value); 8963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 9063a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return this; 9163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 9263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 9363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public TestNode add(TestNode child) { 9463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye mChildren.add(child); 9563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye child.mParent = this; 9663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 9763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return this; 9863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 9963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 10063a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public TestNode add(TestNode... children) { 10163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye for (TestNode child : children) { 10263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye mChildren.add(child); 10363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye child.mParent = this; 10463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 10563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 10663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return this; 10763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 10863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 10963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public static TestNode create(String fcqn) { 11063a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return new TestNode(fcqn); 11163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 11263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 11363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public void removeChild(int index) { 11463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye TestNode removed = mChildren.remove(index); 11563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye removed.mParent = null; 11663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 11763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 11863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye // ==== INODE ==== 11963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 120ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1217e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull INode appendChild(@NonNull String viewFqcn) { 12263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return insertChildAt(viewFqcn, mChildren.size()); 12363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 12463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 125ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1267e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public void editXml(@NonNull String undoName, @NonNull INodeHandler callback) { 12763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye callback.handle(this); 12863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 12963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 130e287bc8580e19d72a911615475b353790cf000ebTor Norbye public void putAttributeInfo(String uri, String attrName, IAttributeInfo info) { 131e287bc8580e19d72a911615475b353790cf000ebTor Norbye mAttributeInfos.put(uri + attrName, info); 132e287bc8580e19d72a911615475b353790cf000ebTor Norbye } 133e287bc8580e19d72a911615475b353790cf000ebTor Norbye 134ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1357e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public IAttributeInfo getAttributeInfo(@Nullable String uri, @NonNull String attrName) { 13663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return mAttributeInfos.get(uri + attrName); 13763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 13863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 139ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1407e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull Rect getBounds() { 14163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return mBounds; 14263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 14363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 144ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1457e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull INode[] getChildren() { 14663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return mChildren.toArray(new INode[mChildren.size()]); 14763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 14863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 149ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1507e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull IAttributeInfo[] getDeclaredAttributes() { 15163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return mAttributeInfos.values().toArray(new IAttributeInfo[mAttributeInfos.size()]); 15263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 15363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 154ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1557e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull String getFqcn() { 15663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return mFqcn; 15763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 15863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 159ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1607e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull IAttribute[] getLiveAttributes() { 16163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return mAttributes.values().toArray(new IAttribute[mAttributes.size()]); 16263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 16363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 164ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 16563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public INode getParent() { 16663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return mParent; 16763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 16863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 169ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 17063a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public INode getRoot() { 17163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye TestNode curr = this; 17263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye while (curr.mParent != null) { 17363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye curr = curr.mParent; 17463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 17563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 17663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return curr; 17763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 17863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 179ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1807e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public String getStringAttr(@Nullable String uri, @NonNull String attrName) { 18163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye IAttribute attr = mAttributes.get(uri + attrName); 18263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye if (attr == null) { 18363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return null; 18463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 18563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 18663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return attr.getValue(); 18763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 18863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 189ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 1907e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull INode insertChildAt(@NonNull String viewFqcn, int index) { 19163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye TestNode child = new TestNode(viewFqcn); 19263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye if (index == -1) { 19363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye mChildren.add(child); 19463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } else { 19563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye mChildren.add(index, child); 19663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 19763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye child.mParent = this; 19863a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return child; 19963a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 20063a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 201ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 2027e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public void removeChild(@NonNull INode node) { 203adee9788a5ac646a39b516abe4cdd1022911a3f5Tor Norbye int index = mChildren.indexOf(node); 204adee9788a5ac646a39b516abe4cdd1022911a3f5Tor Norbye if (index != -1) { 205adee9788a5ac646a39b516abe4cdd1022911a3f5Tor Norbye removeChild(index); 206adee9788a5ac646a39b516abe4cdd1022911a3f5Tor Norbye } 207adee9788a5ac646a39b516abe4cdd1022911a3f5Tor Norbye } 208adee9788a5ac646a39b516abe4cdd1022911a3f5Tor Norbye 209ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 2107e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public boolean setAttribute(@Nullable String uri, @NonNull String localName, 2117e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye @Nullable String value) { 21263a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye mAttributes.put(uri + localName, new TestAttribute(uri, localName, value)); 21363a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye return true; 21463a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 21563a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye 21663a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye @Override 21763a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye public String toString() { 218fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye String id = getStringAttr(ANDROID_URI, ATTR_ID); 219fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return "TestNode [id=" + (id != null ? id : "?") + ", fqn=" + mFqcn + ", infos=" 220fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye + mAttributeInfos + ", attributes=" + mAttributes + ", bounds=" + mBounds + "]"; 22163a966c7d8a08f175d1a8aee688c74d0090af888Tor Norbye } 222adee9788a5ac646a39b516abe4cdd1022911a3f5Tor Norbye 223ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 22480d9301c2e874b29889c41adb0623666cf534fa0Tor Norbye public int getBaseline() { 22580d9301c2e874b29889c41adb0623666cf534fa0Tor Norbye return -1; 22680d9301c2e874b29889c41adb0623666cf534fa0Tor Norbye } 22780d9301c2e874b29889c41adb0623666cf534fa0Tor Norbye 228ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 2297e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull Margins getMargins() { 23080d9301c2e874b29889c41adb0623666cf534fa0Tor Norbye return null; 23180d9301c2e874b29889c41adb0623666cf534fa0Tor Norbye } 232e287bc8580e19d72a911615475b353790cf000ebTor Norbye 233ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 2347e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull List<String> getAttributeSources() { 235e287bc8580e19d72a911615475b353790cf000ebTor Norbye return mAttributeSources != null ? mAttributeSources : Collections.<String>emptyList(); 236e287bc8580e19d72a911615475b353790cf000ebTor Norbye } 237e287bc8580e19d72a911615475b353790cf000ebTor Norbye 238e287bc8580e19d72a911615475b353790cf000ebTor Norbye public void setAttributeSources(List<String> attributeSources) { 239e287bc8580e19d72a911615475b353790cf000ebTor Norbye mAttributeSources = attributeSources; 240e287bc8580e19d72a911615475b353790cf000ebTor Norbye } 241fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 242fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye /** Create a test node from the given XML */ 243fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public static TestNode createFromXml(String xml) { 244fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye Document document = DomUtilities.parseDocument(xml, false); 245fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assertNotNull(document); 246fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assertNotNull(document.getDocumentElement()); 247fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 248fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return createFromNode(document.getDocumentElement()); 249fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 250fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 251fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public static String toXml(TestNode node) { 252fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assertTrue("This method only works with nodes constructed from XML", 253fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye node instanceof TestXmlNode); 254fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye Document document = ((TestXmlNode) node).mElement.getOwnerDocument(); 255fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye // Insert new whitespace nodes etc 256fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye String xml = dumpDocument(document); 257fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye document = DomUtilities.parseDocument(xml, false); 258fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 25913a9256cbb601228887eea910ce1dbd68a776b17Tor Norbye XmlPrettyPrinter printer = new EclipseXmlPrettyPrinter(EclipseXmlFormatPreferences.create(), 260fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye XmlFormatStyle.LAYOUT, "\n"); 261fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye StringBuilder sb = new StringBuilder(1000); 262fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); 263fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye printer.prettyPrint(-1, document, null, null, sb, false); 264fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return sb.toString(); 265fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 266fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 267fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye @SuppressWarnings("deprecation") 268fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye private static String dumpDocument(Document document) { 269fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye // Diagnostics: print out the XML that we're about to render 270fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye org.apache.xml.serialize.OutputFormat outputFormat = 271fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye new org.apache.xml.serialize.OutputFormat( 272fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye "XML", "ISO-8859-1", true); //$NON-NLS-1$ //$NON-NLS-2$ 273fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye outputFormat.setIndent(2); 274fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye outputFormat.setLineWidth(100); 275fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye outputFormat.setIndenting(true); 276fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye outputFormat.setOmitXMLDeclaration(true); 277fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye outputFormat.setOmitDocumentType(true); 278fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye StringWriter stringWriter = new StringWriter(); 279fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye // Using FQN here to avoid having an import above, which will result 280fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye // in a deprecation warning, and there isn't a way to annotate a single 281fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye // import element with a SuppressWarnings. 282fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye org.apache.xml.serialize.XMLSerializer serializer = 283fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye new org.apache.xml.serialize.XMLSerializer(stringWriter, outputFormat); 284fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye serializer.setNamespaces(true); 285fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye try { 286fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye serializer.serialize(document.getDocumentElement()); 287fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return stringWriter.toString(); 288fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } catch (IOException e) { 289fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye e.printStackTrace(); 290fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 291fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return null; 292fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 293fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 294fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye private static TestNode createFromNode(Element element) { 295fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye String fqcn = ANDROID_WIDGET_PREFIX + element.getTagName(); 296fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye TestNode node = new TestXmlNode(fqcn, element); 297fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 298fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye for (Element child : DomUtilities.getChildren(element)) { 299fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye node.add(createFromNode(child)); 300fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 301fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 302fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return node; 303fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 304fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 305fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye @Nullable 306fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public static TestNode findById(TestNode node, String id) { 307fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye id = BaseLayoutRule.stripIdPrefix(id); 308fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return node.findById(id); 309fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 310fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 311fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye private TestNode findById(String targetId) { 312fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye String id = getStringAttr(ANDROID_URI, ATTR_ID); 313fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye if (id != null && targetId.equals(BaseLayoutRule.stripIdPrefix(id))) { 314fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return this; 315fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 316fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 317fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye for (TestNode child : mChildren) { 318fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye TestNode result = child.findById(targetId); 319fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye if (result != null) { 320fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return result; 321fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 322fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 323fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 324fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return null; 325fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 326fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 327fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye private static String getTagName(String fqcn) { 328fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return fqcn.substring(fqcn.lastIndexOf('.') + 1); 329fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 330fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 331fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye private static class TestXmlNode extends TestNode { 332fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye private final Element mElement; 333fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 334fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public TestXmlNode(String fqcn, Element element) { 335fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye super(fqcn); 336fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye mElement = element; 337fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 338fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 339fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye @Override 3400cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye public @NonNull IAttribute[] getLiveAttributes() { 3410cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye List<IAttribute> result = new ArrayList<IAttribute>(); 3420cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye 3430cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye NamedNodeMap attributes = mElement.getAttributes(); 3440cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye for (int i = 0, n = attributes.getLength(); i < n; i++) { 3450cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye Attr attribute = (Attr) attributes.item(i); 3460cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye result.add(new TestXmlAttribute(attribute)); 3470cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye } 3480cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye return result.toArray(new IAttribute[result.size()]); 3490cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye } 3500cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye 3510cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye @Override 352fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public boolean setAttribute(String uri, String localName, String value) { 3530cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye if (value == null) { 3540cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye mElement.removeAttributeNS(uri, localName); 3550cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye } else { 3560cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye mElement.setAttributeNS(uri, localName, value); 3570cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye } 358fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return super.setAttribute(uri, localName, value); 359fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 360fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 361fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye @Override 362fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public INode appendChild(String viewFqcn) { 363fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye Element child = mElement.getOwnerDocument().createElement(getTagName(viewFqcn)); 364fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye mElement.appendChild(child); 365fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return new TestXmlNode(viewFqcn, child); 366fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 367fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 368fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye @Override 369fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public INode insertChildAt(String viewFqcn, int index) { 370fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye if (index == -1) { 371fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return appendChild(viewFqcn); 372fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 373fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye Element child = mElement.getOwnerDocument().createElement(getTagName(viewFqcn)); 374fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye List<Element> children = DomUtilities.getChildren(mElement); 375fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye if (children.size() >= index) { 376fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye Element before = children.get(index); 377fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye mElement.insertBefore(child, before); 378fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } else { 379fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye fail("Unexpected index"); 380fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye mElement.appendChild(child); 381fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 382fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return new TestXmlNode(viewFqcn, child); 383fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 384fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 385fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye @Override 386fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public String getStringAttr(String uri, String name) { 387fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye String value; 388fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye if (uri == null) { 389fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye value = mElement.getAttribute(name); 390fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } else { 391fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye value = mElement.getAttributeNS(uri, name); 392fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 393fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye if (value.isEmpty()) { 394fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye value = null; 395fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 396fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 397fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye return value; 398fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 399fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 400fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye @Override 401fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public void removeChild(INode node) { 402fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assert node instanceof TestXmlNode; 403fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye mElement.removeChild(((TestXmlNode) node).mElement); 404fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 405fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 406fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye @Override 407fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public void removeChild(int index) { 408fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye List<Element> children = DomUtilities.getChildren(mElement); 409fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assertTrue(index < children.size()); 410fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye Element oldChild = children.get(index); 411fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye mElement.removeChild(oldChild); 412fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 413fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 414fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 4150cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye public static class TestXmlAttribute implements IAttribute { 4160cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye private Attr mAttribute; 4170cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye 4180cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye public TestXmlAttribute(Attr attribute) { 4190cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye this.mAttribute = attribute; 4200cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye } 4210cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye 4220cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye @Override 4230cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye public String getUri() { 4240cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye return mAttribute.getNamespaceURI(); 4250cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye } 4260cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye 4270cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye @Override 4280cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye public String getName() { 4290cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye String name = mAttribute.getLocalName(); 4300cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye if (name == null) { 4310cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye name = mAttribute.getName(); 4320cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye } 4330cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye return name; 4340cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye } 4350cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye 4360cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye @Override 4370cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye public String getValue() { 4380cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye return mAttribute.getValue(); 4390cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye } 4400cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye } 4410cb8e647ef345f5c2a6b7eb08b517421131bca4eTor Norbye 442fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye // Recursively initialize this node with the bounds specified in the given hierarchy 443fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye // dump (from ViewHierarchy's DUMP_INFO flag 444fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye public void assignBounds(String bounds) { 445fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye Iterable<String> split = Splitter.on('\n').trimResults().split(bounds); 446fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assignBounds(split.iterator()); 447fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 448fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 449fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye private void assignBounds(Iterator<String> iterator) { 450fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assertTrue(iterator.hasNext()); 451fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye String desc = iterator.next(); 452fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 453fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye Pattern pattern = Pattern.compile("^\\s*(.+)\\s+\\[(.+)\\]\\s*(<.+>)?\\s*(\\S+)?\\s*$"); 454fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye Matcher matcher = pattern.matcher(desc); 455fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assertTrue(matcher.matches()); 456fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye String fqn = matcher.group(1); 457fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assertEquals(getFqcn(), fqn); 458fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye String boundsString = matcher.group(2); 459fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye String[] bounds = boundsString.split(","); 460fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assertEquals(boundsString, 4, bounds.length); 461fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye try { 462fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye int left = Integer.parseInt(bounds[0]); 463fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye int top = Integer.parseInt(bounds[1]); 464fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye int right = Integer.parseInt(bounds[2]); 465fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye int bottom = Integer.parseInt(bounds[3]); 466fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye mBounds = new Rect(left, top, right - left, bottom - top); 467fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } catch (NumberFormatException nufe) { 46813a9256cbb601228887eea910ce1dbd68a776b17Tor Norbye fail(nufe.getLocalizedMessage()); 469fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 470fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye String tag = matcher.group(3); 471fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye 472fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye for (INode child : getChildren()) { 473fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye assertTrue(iterator.hasNext()); 474fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye ((TestNode) child).assignBounds(iterator); 475fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 476fb6d52d71a7461cb1ac4149f4f71d6a63e7436daTor Norbye } 477a881b0b34678ad76c9f5eba62fac7a00a22ac606Tor Norbye} 478