#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# 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.
#
"""Directly processes text of backends.xml.

BackendsXmlParser is called with an XML string to produce a BackendsXml object
containing the data from the XML.

BackendsXmlParser: converts XML to BackendsXml objct
Backend: describes a single backend specified in backends.xml

"""

from xml.etree import ElementTree

from google.appengine.tools import xml_parser_utils
from google.appengine.tools.app_engine_config_exception import AppEngineConfigException
from google.appengine.tools.value_mixin import ValueMixin


class BackendsXmlParser(object):
  """Provides logic for walking down XML tree and pulling data."""

  def ProcessXml(self, xml_str):
    """Parses XML string and returns object representation of relevant info.

    Args:
      xml_str: The XML string.
    Returns:
      A list of Backend object containg information about backends from the XML.
    Raises:
      AppEngineConfigException: In case of malformed XML or illegal inputs.
    """
    try:
      self.backends = []
      self.errors = []
      xml_root = ElementTree.fromstring(xml_str)

      for child in xml_root.getchildren():
        self.ProcessBackendNode(child)

      if self.errors:
        raise AppEngineConfigException('\n'.join(self.errors))

      return self.backends
    except ElementTree.ParseError:
      raise AppEngineConfigException('Bad input -- not valid XML')

  def ProcessBackendNode(self, node):
    """Processes XML nodes labeled 'backend' into a BackendsXml object."""
    tag = xml_parser_utils.GetTag(node)
    if tag != 'backend':
      self.errors.append('Unrecognized node: <%s>' % tag)
      return

    backend = Backend()
    name = xml_parser_utils.GetAttribute(node, 'name')
    if not name:
      self.errors.append('All backends must have names')
      backend.name = '-'
    else:
      backend.name = name
    instance_class = xml_parser_utils.GetChildNodeText(node, 'class')
    if instance_class:
      backend.instance_class = instance_class
    instances = xml_parser_utils.GetChildNodeText(node, 'instances')
    if instances:
      try:
        backend.instances = int(instances)
      except ValueError:
        self.errors.append(
            '<instances> must be an integer (bad value %s) in backend %s' %
            (instances, backend.name))
    max_concurrent_requests = xml_parser_utils.GetChildNodeText(
        node, 'max-concurrent-requests')
    if max_concurrent_requests:
      try:
        backend.max_concurrent_requests = int(max_concurrent_requests)
      except ValueError:
        self.errors.append('<max-concurrent-requests> must be an integer '
                           '(bad value %s) in backend %s' %
                           (max_concurrent_requests, backend.name))

    options_node = xml_parser_utils.GetChild(node, 'options')
    if options_node is not None:
      for sub_node in options_node.getchildren():
        tag = xml_parser_utils.GetTag(sub_node)
        if tag not in ('fail-fast', 'dynamic', 'public'):
          self.errors.append('<options> only supports values fail-fast, '
                             'dynamic, and public (bad value %s) in backend %s'
                             % (tag, backend.name))
          continue
        tag = tag.replace('-', '')
        if xml_parser_utils.BooleanValue(sub_node.text):
          backend.options.add(tag)
        else:
          if tag in backend.options:
            backend.options.remove(tag)

    self.backends.append(backend)


class Backend(ValueMixin):
  """Instances contain information about individual backend specifications."""

  def __init__(self):
    self.name = None
    self.instances = None
    self.instance_class = None
    self.max_concurrent_requests = None
    self.options = set()


