loops/external/element.py

274 lines
9 KiB
Python

#
# Copyright (c) 2012 Helmut Merz helmutm@cy55.de
#
# 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
#
"""
Basic implementation of the elements used for the intermediate format for export
and import of loops objects.
"""
import os
from zope import component
from zope.cachedescriptors.property import Lazy
from zope.dottedname.resolve import resolve
from zope.interface import Interface, implements
from zope.traversing.api import getName, traverse
from cybertools.composer.interfaces import IInstance
from cybertools.composer.schema.interfaces import ISchemaFactory
from cybertools.typology.interfaces import IType
from loops.common import adapted
from loops.interfaces import IConceptSchema
from loops.external.interfaces import IElement
from loops.i18n.common import I18NValue
from loops.layout.base import LayoutNode
from loops.predicate import adaptedRelation
from loops.view import Node
class Element(dict):
implements(IElement)
elementType = ''
posArgs = ()
object = None
parent = None
subElements = None
def __init__(self, name, title, type=None, *args, **kw):
self['name'] = name
self['title'] = title
if type:
self['type'] = type
for k, v in kw.items():
self[k] = v
def __getitem__(self, key):
if isinstance(key, Element):
key = (key,)
if isinstance(key, tuple):
for item in key:
item.parent = self
self.add(item)
return key
return super(Element, self).__getitem__(key)
def processExport(self, extractor):
pass
def add(self, element):
if self.subElements is None:
self.subElements = []
self.subElements.append(element)
def execute(self, loader):
pass
class ConceptElement(Element):
elementType = 'concept'
posArgs = ('name', 'title', 'type')
def execute(self, loader):
type = loader.concepts[self['type']]
kw = dict((k, v) for k, v in self.items()
if k not in self.posArgs)
self.object = loader.addConcept(self['name'], self['title'], type)
formState = self.getInstance().applyTemplate(data=kw, ignoreValidation=True)
# simple hack for resolving interface definition:
pi = self.get('predicateInterface')
if pi is not None:
adapted(self.object).predicateInterface = resolve(pi)
def getInstance(self, omit=['title']):
adObject = adapted(self.object)
schemaFactory = ISchemaFactory(adObject)
ti = IType(self.object).typeInterface or IConceptSchema
instance = component.getAdapter(adObject, IInstance, name='editor')
instance.template = schemaFactory(ti, manager=self, omit=omit)
return instance
class TypeElement(ConceptElement):
elementType = 'type'
posArgs = ('name', 'title')
def __init__(self, name, title, *args, **kw):
super(TypeElement, self).__init__(name, title, *args, **kw)
ti = self.get('typeInterface')
if ti:
if not isinstance(ti, basestring):
self['typeInterface'] = '.'.join((ti.__module__, ti.__name__))
def execute(self, loader):
kw = dict((k, v) for k, v in self.items()
if k not in ('name', 'title', 'type', 'typeInterface'))
ti = self.get('typeInterface')
if ti:
kw['typeInterface'] = resolve(ti)
self.object = loader.addConcept(self['name'], self['title'],
loader.typeConcept, **kw)
instance = self.getInstance(omit=['title', 'typeInterface'])
formState = instance.applyTemplate(data=kw, ignoreValidation=True)
if ti:
# overwrite type interface, might have been ignored in addConcept
adapted(self.object).typeInterface = kw['typeInterface']
class ChildElement(Element):
elementType = 'child'
posArgs = ('first', 'second', 'predicate', 'order', 'relevance')
def __init__(self, *args, **kw):
for idx, arg in enumerate(args):
self[self.posArgs[idx]] = arg
for k, v in kw.items():
self[k] = v
def execute(self, loader):
loader.assignChild(self['first'], self['second'], self['predicate'],
order = self.get('order') or 0,
relevance = self.get('relevance') or 1.0)
additionalParams = [(k, v) for k, v in self.items()
if k not in self.posArgs]
if additionalParams:
pred = loader.getPredicate(self['predicate'])
first = loader.concepts[self['first']]
second = loader.concepts[self['second']]
relation = first.getChildRelations([pred], child=second)[0]
adaptedRel = adaptedRelation(relation)
for attr, value in additionalParams:
setattr(adaptedRel, attr, value)
class ResourceElement(Element):
elementType = 'resource'
posArgs = ('name', 'title', 'type')
def processExport(self, extractor):
content = self.pop('data', '')
fileFlags = 'wb'
if (self.get('contentType', '').startswith('text/')
and isinstance(content, unicode)):
content = content.encode('UTF-8')
fileFlags = 'wt'
directory = extractor.resourceDirectory
if not os.path.exists(directory):
os.makedirs(directory)
dataPath = os.path.join(directory, self['name'])
f = open(dataPath, fileFlags)
f.write(content)
f.close()
def execute(self, loader):
type = loader.concepts[self['type']]
kw = dict((k, v) for k, v in self.items()
if k not in self.posArgs)
dataPath = os.path.join(loader.resourceDirectory, self['name'])
if os.path.exists(dataPath):
ct = self.get('contentType', '')
flag = ct.startswith('text/') and 'r' or 'rb'
f = open(dataPath, flag)
content = f.read()
if ct.startswith('text/'):
content = content.decode('UTF-8')
kw['data'] = content
f.close()
self.object = loader.addResource(self['name'], self['title'], type, **kw)
class ResourceRelationElement(ChildElement):
elementType = 'resourceRelation'
def execute(self, loader):
loader.assignResource(self['first'], self['second'], self['predicate'],
order = self.get('order') or 0,
relevance = self.get('relevance') or 1.0)
class DeassignmentElement(Element):
elementType = 'deassign'
posArgs = ('first', 'second', 'predicate')
def __init__(self, *args, **kw):
for idx, arg in enumerate(args):
self[self.posArgs[idx]] = arg
for k, v in kw.items():
self[k] = v
def execute(self, loader):
if self.get('type') in ('child', 'concept'):
loader.deassignChild(self['first'], self['second'], self['predicate'])
else:
loader.deassignResource(self['first'], self['second'], self['predicate'])
class NodeElement(Element):
elementType = 'node'
posArgs = ('name', 'title', 'path', 'type')
factory = Node
def __init__(self, *args, **kw):
for idx, arg in enumerate(args):
self[self.posArgs[idx]] = arg
for k, v in kw.items():
self[k] = v
def execute(self, loader):
type = self['type']
cont = traverse(loader.views, self['path'])
#target = self.pop('target', None)
kw = dict((k, v) for k, v in self.items()
if k not in self.posArgs)
node = loader.addNode(self['name'], self['title'], cont, type,
factory=self.factory, **kw)
#if target is not None:
# targetObject = traverse(loader.context, target, None)
# node.target = targetObject
#self.object = node
class LayoutNodeElement(NodeElement):
elementType = 'layoutNode'
factory = LayoutNode
# element registry
elementTypes = dict(
type=TypeElement,
concept=ConceptElement,
child=ChildElement,
resource=ResourceElement,
resourceRelation=ResourceRelationElement,
deassign=DeassignmentElement,
node=NodeElement,
layoutNode=LayoutNodeElement,
I18NValue=I18NValue,
)
toplevelElements = ('type', 'concept', 'resource',
'child', 'resourceRelation', 'node', 'deassign')