# # 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: 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')