172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/*
272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2007 Esmertec AG.
372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * you may not use this file except in compliance with the License.
772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * You may obtain a copy of the License at
872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
1072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
1172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * See the License for the specific language governing permissions and
1572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * limitations under the License.
1672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
1772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpackage com.android.mms.dom;
1972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.ArrayList;
2172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.w3c.dom.Node;
2372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.w3c.dom.NodeList;
2472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class NodeListImpl implements NodeList {
2672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private ArrayList<Node> mSearchNodes;
2772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private ArrayList<Node> mStaticNodes;
2872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private Node mRootNode;
2972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private String mTagName;
3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private boolean mDeepSearch;
3172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /*
3372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Internal Interface
3472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
3572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
3672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
3772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Constructs a NodeList by searching for all descendants or the direct
3872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * children of a root node with a given tag name.
3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param rootNode The root <code>Node</code> of the search.
4072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param tagName The tag name to be searched for. If null, all descendants
4172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *              will be returned.
4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param deep Limit the search to the direct children of rootNode if false,
4372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *              to all descendants otherwise.
4472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
4572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public NodeListImpl(Node rootNode, String tagName, boolean deepSearch) {
4672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mRootNode = rootNode;
4772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mTagName  = tagName;
4872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mDeepSearch = deepSearch;
4972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
5172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * Constructs a NodeList for a given static node list.
5372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param nodes The static node list.
5472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
5572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public NodeListImpl(ArrayList<Node> nodes) {
5672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mStaticNodes = nodes;
5772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /*
6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * NodeListImpl Interface
6172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public int getLength() {
6472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mStaticNodes == null) {
6572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            fillList(mRootNode);
6672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return mSearchNodes.size();
6772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
6872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return mStaticNodes.size();
6972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
7072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public Node item(int index) {
7372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Node node = null;
7472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mStaticNodes == null) {
7572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            fillList(mRootNode);
7672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            try {
7772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                node = mSearchNodes.get(index);
7872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } catch (IndexOutOfBoundsException e) {
7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Do nothing and return null
8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
8172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
8272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            try {
8372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                node = mStaticNodes.get(index);
8472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } catch (IndexOutOfBoundsException e) {
8572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Do nothing and return null
8672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
8772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
8872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return node;
8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * A preorder traversal is done in the following order:
9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * <ul>
9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *   <li> Visit root.
9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     *   <li> Traverse children from left to right in preorder.
9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * </ul>
9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * This method fills the live node list.
9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @param The root of preorder traversal
9972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * @return The next match
10072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
10172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void fillList(Node node) {
10272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // (Re)-initialize the container if this is the start of the search.
10372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Visit the root of this iteration otherwise.
10472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (node == mRootNode) {
10572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mSearchNodes = new ArrayList<Node>();
10672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
10772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if ((mTagName == null) || node.getNodeName().equals(mTagName)) {
10872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mSearchNodes.add(node);
10972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
11272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Descend one generation...
11372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        node = node.getFirstChild();
11472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
11572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // ...and visit in preorder the children if we are in deep search
11672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // or directly add the children to the list otherwise.
11772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        while (node != null) {
11872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (mDeepSearch) {
11972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                fillList(node);
12072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } else {
12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if ((mTagName == null) || node.getNodeName().equals(mTagName)) {
12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    mSearchNodes.add(node);
12372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
12472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
12572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            node = node.getNextSibling();
12672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
12772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
12872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
129