#-*- coding: utf-8 -*- # Copyright 2010 Calculate Ltd. http://www.calculate-linux.org # # 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. import sys import time import re from xml import xpath import xml.dom.minidom from format.xml_gconf import xml_gconf # Перевод cообщений модуля from cl_lang import lang tr = lang() tr.setLocalDomain('cl_lib') tr.setLanguage(sys.modules[__name__]) class xml_gconf_tree(xml_gconf): """Класс для объединения gconf_tree-xml файлов""" def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True): """Объединение корневой ноды шаблона и корневой ноды файла""" xmlNode = xmlNewNode childNodes = xmlNode.childNodes nextOldNode = xmlOldNode flagError = False if xmlNode.nodeType == xmlNode.ELEMENT_NODE: n = xmlNode tagName = n.tagName tagNameStr = tagName.encode("UTF-8") nAction = u'' nName = u'' nType = u'' nValue = u'' nSchema = u'' attrName = '' if flagRootNode: if not tagName == "gconf": self.setError(_("The text is not a valid gconf-XML format \ (not found '...')")) return False else: if not tagName in ("dir", "entry"): self.setError(_("The text is not a valid gconf-XML format \ (found '<%(tag)s>..'")%{'tag':tagNameStr}) return False if not n.hasAttribute("name"): self.setError(\ _('Not found arrtibute "name" in %(tag)s')\ %{'tag':tagNameStr}) return False nName = n.getAttribute("name") attrName = u"attribute::name='%s'"%nName if n.hasAttribute("action"): nAction = n.getAttribute("action") if not nAction in ("join","replace","drop"): textError = _('''In the text, XML template, look \ for a reserved attribute 'action' with the incorrect value.\n\ Valid values attribute 'action': \ (action="join", action="replace", action="drop")''') self.setError(textError) return False if xmlOldNode.parentNode: findAttrStr = "" if attrName: findAttrStr = "[%s]"%attrName findPath = u"child::%s%s"%(tagName,findAttrStr) # Рабочая нода if flagRootNode: workNode = xmlOldNode.parentNode else: workNode = xmlOldNode oldNodes = xpath.Evaluate(findPath, workNode) # По умолчанию - объединение аттрибутов flagJoin = True flagReplace = False flagDrop = False if nAction=="replace": flagReplace = True flagJoin = False # Удаляем ноду if nAction == "drop": flagDrop = True flagJoin = False if flagRootNode: textError = _('Incorrect action="drop" in root node') self.setError(textError) return False if oldNodes: if len(oldNodes)>1: textError = _("The uncertainty in this template are \ the same nodes at one level") self.setError(textError) return False nextOldNode = oldNodes[0] # Объединение аттрибутов нод if flagJoin: listOldAttributes = nextOldNode.attributes.items() if listOldAttributes: listOldAttributes = filter(lambda x:\ x[0] != "mtime", listOldAttributes) # Замена содержимого if xmlNode.tagName == "entry": replaceXmlNode = xmlNode.cloneNode(True) # Сравнение содержимого нод if not self.cmpListsNodesEntry([replaceXmlNode], [nextOldNode]): replaceXmlNode.setAttribute("mtime", self.currentTime) if not\ self._removeDropNodesAndAttrAction(\ replaceXmlNode): return False workNode.replaceChild(replaceXmlNode, nextOldNode) childNodes = False listNewAttributes = xmlNode.attributes.items() if listNewAttributes: listNewAttributes = filter(lambda x:\ not x[0] in ("action", "mtime"), listNewAttributes) if set(listNewAttributes)!= set(listOldAttributes): # Объединение аттрибутов for attrName, attrValue in listNewAttributes: nextOldNode.setAttribute(attrName, attrValue) if nextOldNode.tagName == "entry": nextOldNode.setAttribute("mtime", self.currentTime) # Замещение ноды elif flagReplace: replaceXmlNode = xmlNode.cloneNode(True) # Сравнение содержимого нод if not self.cmpListsNodesEntry([replaceXmlNode], [nextOldNode]): if replaceXmlNode.tagName == "entry": replaceXmlNode.setAttribute("mtime", self.currentTime) if not\ self._removeDropNodesAndAttrAction(\ replaceXmlNode): return False workNode.replaceChild(replaceXmlNode, nextOldNode) childNodes = False # Удаление ноды elif flagDrop: workNode.removeChild(nextOldNode) childNodes = False else: # Добавление ноды childNodes = False if not flagDrop: appendXmlNode = xmlNode.cloneNode(True) if appendXmlNode.tagName == "entry": appendXmlNode.setAttribute("mtime", self.currentTime) if not\ self._removeDropNodesAndAttrAction(appendXmlNode): return False workNode.appendChild(appendXmlNode) if childNodes: for node in childNodes: if not self._join(node, nextOldNode, False): flagError = True break if flagError: return False return True def join(self, xml_gconfObj): """Объединяем конфигурации""" # Получаем текущее время self.currentTime = self.getCurrentTime() if isinstance(xml_gconfObj, xml_gconf_tree): try: self.joinDoc(xml_gconfObj.doc) except: self.setError(_("Failed to join the template")) return False return True