You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
8.8 KiB
183 lines
8.8 KiB
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright 2012-2016 Mir Calculate. 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
|
|
from calculate.lib.cl_xml import xpath
|
|
from calculate.lib.format.xml_gconf import xml_gconf
|
|
from calculate.lib.cl_lang import setLocalTranslate
|
|
from collections import Iterable
|
|
|
|
_ = lambda x: x
|
|
setLocalTranslate('cl_lib3', sys.modules[__name__])
|
|
|
|
|
|
class xml_gconf_tree(xml_gconf):
|
|
"""Класс для объединения gconf_tree-xml файлов"""
|
|
|
|
def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True, **kw):
|
|
"""Объединение корневой ноды шаблона и корневой ноды файла"""
|
|
xmlNode = xmlNewNode
|
|
childNodes = xmlNode.childNodes
|
|
nextOldNode = xmlOldNode
|
|
if xmlNode.nodeType == xmlNode.ELEMENT_NODE:
|
|
n = xmlNode
|
|
tagName = n.tagName
|
|
tagNameStr = tagName.encode("UTF-8")
|
|
nAction = u''
|
|
attrName = ''
|
|
if flagRootNode:
|
|
if not tagName == "gconf":
|
|
self.setError(_("The text is not a valid gconf-XML format \
|
|
(not found '<gconf>...</gconf>')"))
|
|
return False
|
|
else:
|
|
if not tagName in ("dir", "entry"):
|
|
self.setError(_("The text is not a valid gconf-XML format \
|
|
(found '<%(tag)s>..</%(tag)s>')") % {'tag': tagNameStr})
|
|
return False
|
|
if not n.hasAttribute("name"):
|
|
self.setError(
|
|
_('Not found attribute "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 nAction not in ("join", "replace", "drop"):
|
|
textError = _("In the text of the XML template, "
|
|
"reserved attribute 'action' comes with an "
|
|
"incorrect value.\n"
|
|
"Valid values of the 'action' attribute are: "
|
|
'(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 the '
|
|
'root node')
|
|
self.setError(textError)
|
|
return False
|
|
if oldNodes:
|
|
if len(oldNodes) > 1:
|
|
textError = _("Ambiguity in this template: the "
|
|
"same nodes are on a same 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: x[0] not 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 isinstance(childNodes, Iterable):
|
|
for node in childNodes:
|
|
if not self._join(node, nextOldNode, False):
|
|
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 Exception:
|
|
self.setError(_("Failed to join the template"))
|
|
return False
|
|
return True
|