1 /* 2 * Copyright (C) 2007 Esmertec AG. 3 * Copyright (C) 2007 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.mms.dom; 19 20 import java.util.ArrayList; 21 22 import org.w3c.dom.Node; 23 import org.w3c.dom.NodeList; 24 25 public class NodeListImpl implements NodeList { 26 private ArrayList<Node> mSearchNodes; 27 private ArrayList<Node> mStaticNodes; 28 private Node mRootNode; 29 private String mTagName; 30 private boolean mDeepSearch; 31 32 /* 33 * Internal Interface 34 */ 35 36 /** 37 * Constructs a NodeList by searching for all descendants or the direct 38 * children of a root node with a given tag name. 39 * @param rootNode The root <code>Node</code> of the search. 40 * @param tagName The tag name to be searched for. If null, all descendants 41 * will be returned. 42 * @param deep Limit the search to the direct children of rootNode if false, 43 * to all descendants otherwise. 44 */ NodeListImpl(Node rootNode, String tagName, boolean deepSearch)45 public NodeListImpl(Node rootNode, String tagName, boolean deepSearch) { 46 mRootNode = rootNode; 47 mTagName = tagName; 48 mDeepSearch = deepSearch; 49 } 50 51 /** 52 * Constructs a NodeList for a given static node list. 53 * @param nodes The static node list. 54 */ NodeListImpl(ArrayList<Node> nodes)55 public NodeListImpl(ArrayList<Node> nodes) { 56 mStaticNodes = nodes; 57 } 58 59 /* 60 * NodeListImpl Interface 61 */ 62 getLength()63 public int getLength() { 64 if (mStaticNodes == null) { 65 fillList(mRootNode); 66 return mSearchNodes.size(); 67 } else { 68 return mStaticNodes.size(); 69 } 70 } 71 item(int index)72 public Node item(int index) { 73 Node node = null; 74 if (mStaticNodes == null) { 75 fillList(mRootNode); 76 try { 77 node = mSearchNodes.get(index); 78 } catch (IndexOutOfBoundsException e) { 79 // Do nothing and return null 80 } 81 } else { 82 try { 83 node = mStaticNodes.get(index); 84 } catch (IndexOutOfBoundsException e) { 85 // Do nothing and return null 86 } 87 } 88 return node; 89 } 90 91 /** 92 * A preorder traversal is done in the following order: 93 * <ul> 94 * <li> Visit root. 95 * <li> Traverse children from left to right in preorder. 96 * </ul> 97 * This method fills the live node list. 98 * @param The root of preorder traversal 99 * @return The next match 100 */ fillList(Node node)101 private void fillList(Node node) { 102 // (Re)-initialize the container if this is the start of the search. 103 // Visit the root of this iteration otherwise. 104 if (node == mRootNode) { 105 mSearchNodes = new ArrayList<Node>(); 106 } else { 107 if ((mTagName == null) || node.getNodeName().equals(mTagName)) { 108 mSearchNodes.add(node); 109 } 110 } 111 112 // Descend one generation... 113 node = node.getFirstChild(); 114 115 // ...and visit in preorder the children if we are in deep search 116 // or directly add the children to the list otherwise. 117 while (node != null) { 118 if (mDeepSearch) { 119 fillList(node); 120 } else { 121 if ((mTagName == null) || node.getNodeName().equals(mTagName)) { 122 mSearchNodes.add(node); 123 } 124 } 125 node = node.getNextSibling(); 126 } 127 } 128 } 129