blob: 76430e715009e495948f4f639a7743fa924ad596 [file] [log] [blame]
# Copyright 2016 The Vanadium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
"""Convert data to format used by RICO.
This script converts the XML view hierarchy data to the JSON format used by
RICO.
"""
import argparse
import json
import os
import re
import shutil
import xml.etree.ElementTree as ET
TRUTHY_VALUES = ['true']
def make_json_node(xml_node):
"""Converts a node in the view hierarchy to JSON."""
def to_bool(string):
return string in TRUTHY_VALUES
node = {}
node['class'] = xml_node.attrib.get('class')
node['visibility'] = xml_node.attrib.get('visibility')
node['visible-to-user'] = to_bool(xml_node.attrib.get('visible-to-user'))
node['adapter-view'] = to_bool(xml_node.attrib.get('adapter-view'))
node['focusable'] = to_bool(xml_node.attrib.get('focusable'))
node['enabled'] = to_bool(xml_node.attrib.get('enabled'))
node['draw'] = to_bool(xml_node.attrib.get('draw'))
node['scrollable-horizontal'] = to_bool(xml_node.attrib.get(
'scrollable-horizontal'))
node['scrollable-vertical'] = to_bool(xml_node.attrib.get(
'scrollable-vertical'))
node['clickable'] = to_bool(xml_node.attrib.get('clickable'))
node['pointer'] = xml_node.attrib.get('pointer')
node['long-clickable'] = to_bool(xml_node.attrib.get('long-clickable'))
node['focused'] = to_bool(xml_node.attrib.get('focused'))
node['selected'] = to_bool(xml_node.attrib.get('selected'))
node['pressed'] = to_bool(xml_node.attrib.get('pressed'))
node['abs-pos'] = to_bool(xml_node.attrib.get('abs-pos'))
node['text'] = xml_node.attrib.get('text')
bounds = xml_node.attrib.get('bounds')
if bounds:
p = re.compile('\[(-?\d*),(-?\d*)\]\[(-?\d*),(-?\d*)\]')
m = p.match(bounds)
node['bounds'] = [int(m.group(1)), int(m.group(2)), int(m.group(3)),
int(m.group(4))]
else:
node['bounds'] = None
node['resource-id'] = xml_node.attrib.get('resource-id')
node['package'] = xml_node.attrib.get('package')
node['content-desc'] = xml_node.attrib.get('content-desc')
children = []
for child in xml_node:
children.append(make_json_node(child))
node['children'] = children
return node
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('data_folder_path',
help=('Full path to the data folder. It could contain '
'multiple folders for different sessions inside it.'
))
args = parser.parse_args()
data_folder_path = args.data_folder_path
out_view = {}
session_ids = [f for f in os.listdir(data_folder_path) if os.path.isdir(
os.path.join(data_folder_path, f))]
for session_id in session_ids:
try:
view_nums = [f.split('.')[0] for f in os.listdir(
os.path.join(data_folder_path, session_id, 'xml'))
if '.xml' in f]
except OSError:
shutil.rmtree(os.path.join('processed_data', session_id))
print session_id
for view_num in view_nums:
print view_num
# If the input XML or JSON file cannot be parsed we skip that view.
try:
tree = ET.parse(os.path.join('processed_data', session_id, 'xml',
view_num + '.xml'))
except ET.ParseError:
print 'Error parsing XML file.'
continue
xml_root = tree.getroot()
try:
with open(os.path.join('processed_data', session_id, 'xml',
view_num + '.json')) as data_file:
data = json.load(data_file)
except IOError:
print 'Error loading JSON file.'
continue
out_view['activity_name'] = data['DDDG_Current_Activity']
activity = {'root': make_json_node(xml_root)}
activity['added_fragments'] = data['DDDG_Added_Fragments']
activity['active_fragments'] = data['DDDG_Active_Fragments']
activity['is_keyboard_deployed'] = data['DDDG_Keyboard_Deployed']
out_view['activity'] = activity
outfolder = os.path.join('processed_data', session_id, 'rico_views')
if not os.path.exists(outfolder):
os.makedirs(outfolder)
outfile_name = os.path.join(outfolder, view_num + '.json')
with open(outfile_name, 'w') as outfile:
json.dump(out_view, outfile, indent=2)