#!/usr/bin/python

#
# 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.
#

"""
A parser for metadata_properties.xml can also render the resulting model
over a Mako template.

Usage:
  metadata_parser_xml.py <filename.xml> <template.mako> [<output_file>]
  - outputs the resulting template to output_file (stdout if none specified)

Module:
  The parser is also available as a module import (MetadataParserXml) to use
  in other modules.

Dependencies:
  BeautifulSoup - an HTML/XML parser available to download from
          http://www.crummy.com/software/BeautifulSoup/
  Mako - a template engine for Python, available to download from
     http://www.makotemplates.org/
"""

import sys
import os
import StringIO

from bs4 import BeautifulSoup
from bs4 import NavigableString

from mako.template import Template
from mako.lookup import TemplateLookup
from mako.runtime import Context

from metadata_model import *
import metadata_model
from metadata_validate import *
import metadata_helpers

class MetadataParserXml:
  """
  A class to parse any XML file that passes validation with metadata-validate.
  It builds a metadata_model.Metadata graph and then renders it over a
  Mako template.

  Attributes (Read-Only):
    soup: an instance of BeautifulSoup corresponding to the XML contents
    metadata: a constructed instance of metadata_model.Metadata
  """
  def __init__(self, file_name):
    """
    Construct a new MetadataParserXml, immediately try to parse it into a
    metadata model.

    Args:
      file_name: path to an XML file that passes metadata-validate

    Raises:
      ValueError: if the XML file failed to pass metadata_validate.py
    """
    self._soup = validate_xml(file_name)

    if self._soup is None:
      raise ValueError("%s has an invalid XML file" %(file_name))

    self._metadata = Metadata()
    self._parse()
    self._metadata.construct_graph()

  @property
  def soup(self):
    return self._soup

  @property
  def metadata(self):
    return self._metadata

  @staticmethod
  def _find_direct_strings(element):
    if element.string is not None:
      return [element.string]

    return [i for i in element.contents if isinstance(i, NavigableString)]

  @staticmethod
  def _strings_no_nl(element):
    return "".join([i.strip() for i in MetadataParserXml._find_direct_strings(element)])

  def _parse(self):

    tags = self.soup.tags
    if tags is not None:
      for tag in tags.find_all('tag'):
        self.metadata.insert_tag(tag['id'], tag.string)

    # add all entries, preserving the ordering of the XML file
    # this is important for future ABI compatibility when generating code
    entry_filter = lambda x: x.name == 'entry' or x.name == 'clone'
    for entry in self.soup.find_all(entry_filter):
      if entry.name == 'entry':
        d = {
              'name': fully_qualified_name(entry),
              'type': entry['type'],
              'kind': find_kind(entry),
              'type_notes': entry.attrs.get('type_notes')
            }

        d2 = self._parse_entry(entry)
        insert = self.metadata.insert_entry
      else:
        d = {
           'name': entry['entry'],
           'kind': find_kind(entry),
           'target_kind': entry['kind'],
          # no type since its the same
          # no type_notes since its the same
        }
        d2 = {}

        insert = self.metadata.insert_clone

      d3 = self._parse_entry_optional(entry)

      entry_dict = dict(d.items() + d2.items() + d3.items())
      insert(entry_dict)

    self.metadata.construct_graph()

  def _parse_entry(self, entry):
    d = {}

    #
    # Enum
    #
    if entry.get('enum', 'false') == 'true':

      enum_values = []
      enum_optionals = []
      enum_notes = {}
      enum_ids = {}
      for value in entry.enum.find_all('value'):

        value_body = self._strings_no_nl(value)
        enum_values.append(value_body)

        if value.attrs.get('optional', 'false') == 'true':
          enum_optionals.append(value_body)

        notes = value.find('notes')
        if notes is not None:
          enum_notes[value_body] = notes.string

        if value.attrs.get('id') is not None:
          enum_ids[value_body] = value['id']

      d['enum_values'] = enum_values
      d['enum_optionals'] = enum_optionals
      d['enum_notes'] = enum_notes
      d['enum_ids'] = enum_ids
      d['enum'] = True

    #
    # Container (Array/Tuple)
    #
    if entry.attrs.get('container') is not None:
      container_name = entry['container']

      array = entry.find('array')
      if array is not None:
        array_sizes = []
        for size in array.find_all('size'):
          array_sizes.append(size.string)
        d['container_sizes'] = array_sizes

      tupl = entry.find('tuple')
      if tupl is not None:
        tupl_values = []
        for val in tupl.find_all('value'):
          tupl_values.append(val.name)
        d['tuple_values'] = tupl_values
        d['container_sizes'] = len(tupl_values)

      d['container'] = container_name

    return d

  def _parse_entry_optional(self, entry):
    d = {}

    optional_elements = ['description', 'range', 'units', 'notes']
    for i in optional_elements:
      prop = find_child_tag(entry, i)

      if prop is not None:
        d[i] = prop.string

    tag_ids = []
    for tag in entry.find_all('tag'):
      tag_ids.append(tag['id'])

    d['tag_ids'] = tag_ids

    return d

  def render(self, template, output_name=None):
    """
    Render the metadata model using a Mako template as the view.

    The template gets the metadata as an argument, as well as all
    public attributes from the metadata_helpers module.

    Args:
      template: path to a Mako template file
      output_name: path to the output file, or None to use stdout
    """
    buf = StringIO.StringIO()
    metadata_helpers._context_buf = buf

    helpers = [(i, getattr(metadata_helpers, i))
                for i in dir(metadata_helpers) if not i.startswith('_')]
    helpers = dict(helpers)

    lookup = TemplateLookup(directories=[os.getcwd()])
    tpl = Template(filename=template, lookup=lookup)

    ctx = Context(buf, metadata=self.metadata, **helpers)
    tpl.render_context(ctx)

    tpl_data = buf.getvalue()
    metadata_helpers._context_buf = None
    buf.close()

    if output_name is None:
      print tpl_data
    else:
      file(output_name, "w").write(tpl_data)

#####################
#####################

if __name__ == "__main__":
  if len(sys.argv) <= 2:
    print >> sys.stderr,                                                       \
           "Usage: %s <filename.xml> <template.mako> [<output_file>]"          \
           % (sys.argv[0])
    sys.exit(0)

  file_name = sys.argv[1]
  template_name = sys.argv[2]
  output_name = sys.argv[3] if len(sys.argv) > 3 else None
  parser = MetadataParserXml(file_name)
  parser.render(template_name, output_name)

  sys.exit(0)
