1#!/usr/bin/python2.4
2#
3#
4# Copyright 2008, The Android Open Source Project
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17import xml.dom.minidom
18import xml.parsers
19import os
20
21
22import coverage_target
23import logger
24import errors
25
26class CoverageTargets:
27  """Accessor for the code coverage target xml file
28  Expects the following format:
29  <targets>
30    <target
31      name=""
32      type="JAVA_LIBRARIES|APPS"
33      build_path=""
34
35      [<src path=""/>] (0..*)  - These are relative to build_path. If missing,
36                                 assumes 'src'
37    >/target>
38
39    TODO: add more format checking
40  """
41
42  _TARGET_TAG_NAME = 'coverage_target'
43  _NAME_ATTR = 'name'
44  _TYPE_ATTR = 'type'
45  _BUILD_ATTR = 'build_path'
46  _SRC_TAG = 'src'
47  _PATH_ATTR = 'path'
48
49  def __init__(self, ):
50    self._target_map= {}
51
52  def __iter__(self):
53    return iter(self._target_map.values())
54
55  def Parse(self, file_path):
56    """Parse the coverage target data from from given file path, and add it to
57       the current object
58       Args:
59         file_path: absolute file path to parse
60       Raises:
61         errors.ParseError if file_path cannot be parsed
62    """
63    try:
64      doc = xml.dom.minidom.parse(file_path)
65    except IOError:
66      # Error: The results file does not exist
67      logger.Log('Results file %s does not exist' % file_path)
68      raise errors.ParseError
69    except xml.parsers.expat.ExpatError:
70      logger.Log('Error Parsing xml file: %s ' %  file_path)
71      raise errors.ParseError
72
73    target_elements = doc.getElementsByTagName(self._TARGET_TAG_NAME)
74
75    for target_element in target_elements:
76      target = coverage_target.CoverageTarget()
77      self._ParseCoverageTarget(target, target_element)
78      self._AddTarget(target)
79
80  def _AddTarget(self, target):
81    self._target_map[target.GetName()] = target
82
83  def GetBuildTargets(self):
84    """ returns list of target names """
85    build_targets = []
86    for target in self:
87      build_targets.append(target.GetName())
88    return build_targets
89
90  def GetTargets(self):
91    """ returns list of CoverageTarget"""
92    return self._target_map.values()
93
94  def GetTarget(self, name):
95    """ returns CoverageTarget for given name. None if not found """
96    try:
97      return self._target_map[name]
98    except KeyError:
99      return None
100
101  def _ParseCoverageTarget(self, target, target_element):
102    """Parse coverage data from XML.
103
104    Args:
105      target: the Coverage object to populate
106      target_element: the XML element to get data from
107    """
108    target.SetName(target_element.getAttribute(self._NAME_ATTR))
109    target.SetType(target_element.getAttribute(self._TYPE_ATTR))
110    target.SetBuildPath(target_element.getAttribute(self._BUILD_ATTR))
111    self._paths = []
112    self._ParsePaths(target, target_element)
113
114  def _ParsePaths(self, target, target_element):
115    src_elements = target_element.getElementsByTagName(self._SRC_TAG)
116    if len(src_elements) <= 0:
117      # no src tags specified. Assume build_path + src
118      target.AddPath(os.path.join(target.GetBuildPath(), "src"))
119    for src_element in src_elements:
120      rel_path = src_element.getAttribute(self._PATH_ATTR)
121      target.AddPath(os.path.join(target.GetBuildPath(), rel_path))
122
123
124def Parse(xml_file_path):
125  """parses out a file_path class from given path to xml"""
126  targets = CoverageTargets()
127  targets.Parse(xml_file_path)
128  return targets
129