SoftwareInstance.py 3.73 KB
Newer Older
Łukasz Nowak's avatar
Łukasz Nowak committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
from Products.ERP5.Document.Item import Item
Łukasz Nowak's avatar
Łukasz Nowak committed
31
from lxml import etree
32 33 34 35
import collections

class DisconnectedSoftwareTree(Exception):
  pass
Łukasz Nowak's avatar
Łukasz Nowak committed
36

37 38 39
class CyclicSoftwareTree(Exception):
  pass

Łukasz Nowak's avatar
Łukasz Nowak committed
40 41 42 43 44 45 46 47 48 49 50 51 52
class SoftwareInstance(Item):
  """
  """

  meta_type = 'ERP5 Software Instance'
  portal_type = 'Software Instance'
  add_permission = Permissions.AddPortalContent

  # Declarative security
  security = ClassSecurityInfo()
  security.declareObjectProtected(Permissions.AccessContentsInformation)


Łukasz Nowak's avatar
Łukasz Nowak committed
53 54 55
  security.declareProtected(Permissions.AccessContentsInformation,
    'getSlaXmlAsDict')
  def getSlaXmlAsDict(self):
56
    """Returns SLA XML as python dictionary"""
Łukasz Nowak's avatar
Łukasz Nowak committed
57 58 59 60
    result_dict = {}
    xml = self.getSlaXml()
    if xml is not None and xml != '':
      tree = etree.fromstring(xml.encode('utf-8'))
61 62 63 64 65 66 67 68
      for element in tree.findall('parameter'):
        key = element.get('id')
        value = result_dict.get(key, None)
        if value is not None:
          value = value + ' ' + element.text
        else:
          value = element.text
        result_dict[key] = value
Łukasz Nowak's avatar
Łukasz Nowak committed
69
    return result_dict
70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
  security.declareProtected(Permissions.AccessContentsInformation,
    'checkNotCyclic')
  def checkNotCyclic(self, graph):
    # see http://neopythonic.blogspot.com/2009/01/detecting-cycles-in-directed-graph.html
    todo = set(graph.keys())
    while todo:
      node = todo.pop()
      stack = [node]
      while stack:
        top = stack[-1]
        for node in graph[top]:
          if node in stack:
            raise CyclicSoftwareTree
          if node in todo:
            stack.append(node)
            todo.remove(node)
            break
        else:
          node = stack.pop()
    return True

92
  security.declareProtected(Permissions.AccessContentsInformation,
Łukasz Nowak's avatar
Łukasz Nowak committed
93
    'checkConnected')
Łukasz Nowak's avatar
Łukasz Nowak committed
94
  def checkConnected(self, graph, root):
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
    size = len(graph)
    visited = set()
    to_crawl = collections.deque(graph[root])
    while to_crawl:
      current = to_crawl.popleft()
      if current in visited:
        continue
      visited.add(current)
      node_children = set(graph[current])
      to_crawl.extend(node_children - visited)
    # add one to visited, as root won't be visited, only children
    # this is false positive in case of cyclic graphs, but they are
    # anyway wrong in Software Instance trees
    if size != len(visited) + 1:
      raise DisconnectedSoftwareTree
Łukasz Nowak's avatar
Łukasz Nowak committed
110
    return True