blob: f2339d14f2b74f665bf742ade723521b6573d1a5 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.uiautomator.tree;
import org.eclipse.swt.graphics.Rectangle;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class UiHierarchyXmlLoader {
private BasicTreeNode mRootNode;
private List<Rectangle> mNafNodes;
public UiHierarchyXmlLoader() {
}
/**
* Uses a SAX parser to process XML dump
* @param xmlPath
* @return
*/
public BasicTreeNode parseXml(String xmlPath) {
mRootNode = null;
mNafNodes = new ArrayList<Rectangle>();
// standard boilerplate to get a SAX parser
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = null;
try {
parser = factory.newSAXParser();
} catch (ParserConfigurationException e) {
e.printStackTrace();
return null;
} catch (SAXException e) {
e.printStackTrace();
return null;
}
// handler class for SAX parser to receiver standard parsing events:
// e.g. on reading "<foo>", startElement is called, on reading "</foo>",
// endElement is called
DefaultHandler handler = new DefaultHandler(){
BasicTreeNode mParentNode;
BasicTreeNode mWorkingNode;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
boolean nodeCreated = false;
// starting an element implies that the element that has not yet been closed
// will be the parent of the element that is being started here
mParentNode = mWorkingNode;
if ("hierarchy".equals(qName)) {
mWorkingNode = new RootWindowNode(attributes.getValue("windowName"));
nodeCreated = true;
} else if ("node".equals(qName)) {
UiNode tmpNode = new UiNode();
for (int i = 0; i < attributes.getLength(); i++) {
tmpNode.addAtrribute(attributes.getQName(i), attributes.getValue(i));
}
mWorkingNode = tmpNode;
nodeCreated = true;
// check if current node is NAF
String naf = tmpNode.getAttribute("NAF");
if ("true".equals(naf)) {
mNafNodes.add(new Rectangle(tmpNode.x, tmpNode.y,
tmpNode.width, tmpNode.height));
}
}
// nodeCreated will be false if the element started is neither
// "hierarchy" nor "node"
if (nodeCreated) {
if (mRootNode == null) {
// this will only happen once
mRootNode = mWorkingNode;
}
if (mParentNode != null) {
mParentNode.addChild(mWorkingNode);
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
//mParentNode should never be null here in a well formed XML
if (mParentNode != null) {
// closing an element implies that we are back to working on
// the parent node of the element just closed, i.e. continue to
// parse more child nodes
mWorkingNode = mParentNode;
mParentNode = mParentNode.getParent();
}
}
};
try {
parser.parse(new File(xmlPath), handler);
} catch (SAXException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
return mRootNode;
}
/**
* Returns the list of "Not Accessibility Friendly" nodes found during parsing.
*
* Call this function after parsing
*
* @return
*/
public List<Rectangle> getNafNodes() {
return Collections.unmodifiableList(mNafNodes);
}
}