web/ldt/ldt_utils/fileimport.py
changeset 1 eb9188f2ee4f
equal deleted inserted replaced
0:85b071fb75b2 1:eb9188f2ee4f
       
     1 from copy import deepcopy
       
     2 from django.conf import settings
       
     3 from django.core.exceptions import ObjectDoesNotExist
       
     4 from ldt.utils import zipfileext
       
     5 from models import Content, Media
       
     6 import fnmatch
       
     7 import lxml.etree
       
     8 import os.path
       
     9 import shutil
       
    10 import tempfile
       
    11 import urllib
       
    12 import uuid
       
    13 
       
    14 class FileImportError(Exception):
       
    15     def __init__(self, value):
       
    16         self.value = value
       
    17     def __str__(self):
       
    18         return repr(self.value)
       
    19 
       
    20 
       
    21 def Property(func):
       
    22     return property(**func()) 
       
    23 
       
    24 class IriInfo(object):
       
    25 
       
    26     
       
    27     def __init__(self, id, order, titledesc, basepath="", videopath=settings.STREAM_URL, decoupage_blacklist = settings.DECOUPAGE_BLACKLIST, flatten = True):
       
    28         self.id = id
       
    29         self.basepath = basepath
       
    30         self.order = order
       
    31         self.src = ""
       
    32         self.annotations = None
       
    33         self.videopath = videopath
       
    34         self.videourl = ""
       
    35         self.title = None
       
    36         self.desc = None
       
    37         self.duration = None
       
    38         self.created = False
       
    39         self.content = None
       
    40         self.decoupage_blacklist = decoupage_blacklist
       
    41         if self.decoupage_blacklist is None:
       
    42             self.decoupage_blacklist = ()
       
    43         self.flatten = flatten
       
    44         
       
    45         
       
    46     
       
    47     def processIri(self):
       
    48         # for just import a file ldt and get the title for every media
       
    49         if 'http' in self.src:
       
    50             #url = urllib.urlopen(self.src)
       
    51             path = url
       
    52             #doc = xml.dom.minidom.parse(url)
       
    53         #for import a zip, get title and copy file .iri in the media directory
       
    54         else:
       
    55             path = os.path.join(self.basepath, self.src)
       
    56             #doc = xml.dom.minidom.parse(path)
       
    57             
       
    58         doc = lxml.etree.parse(path)
       
    59         
       
    60         
       
    61         #doc = Ft.Xml.Domlette.ConvertDocument(doc) 
       
    62         #con = xml.xpath.Context.Context(doc, 1, 1, None)
       
    63         
       
    64         res = doc.xpath("/iri/head/meta[@name='title']/@content")
       
    65         #res = xml.xpath.Evaluate("/iri/head/meta[@name='title']/@content", context=con)
       
    66         #self.title = res[0].value
       
    67         self.title = res[0]
       
    68 
       
    69             
       
    70         #res = xml.xpath.Evaluate("/iri/body/ensembles",context=con)
       
    71         res = doc.xpath("/iri/body/ensembles")
       
    72         ensemblesnode = res[0]
       
    73 
       
    74         ensembleids = []
       
    75 
       
    76         for node in ensemblesnode: #ensemblesnode.childNodes:
       
    77             #if node.nodeType == xml.dom.Node.ELEMENT_NODE and node.tagName == "ensemble":
       
    78             if node.tag == "ensemble":
       
    79                 #id = node.getAttributeNS(None,u"id")
       
    80                 id = node.attrib["id"]
       
    81                 if id not in ensembleids:
       
    82                     ensembleids.append(id)
       
    83 
       
    84         if self.annotations is not None:
       
    85             newEnsemble = None
       
    86             #for cnode in self.annotations.childNodes:
       
    87             for cnode in self.annotations:
       
    88                 #if cnode.nodeType == xml.dom.Node.ELEMENT_NODE and cnode.tagName == "decoupage":
       
    89                 if cnode.tag == "decoupage":
       
    90                     if newEnsemble is None:
       
    91                         #newensemble = doc.createElementNS(None,'ensemble')
       
    92                         ensembleid = self.id+"_"+str(uuid.uuid1())
       
    93                         newensemble = lxml.etree.SubElement(ensemblesnode,
       
    94                                                             'ensemble',
       
    95                                                             {'id' : ensembleid,
       
    96                                                              'title' : self.annotations.get('title') or "",
       
    97                                                              'author' : self.annotations.get('author') or "",
       
    98                                                              'date' : self.annotations.get('date') or "",
       
    99                                                              'abstract' : self.annotations.get('abstract') or ""
       
   100                                                              }
       
   101                                                             )                        
       
   102                         ensembleids.append(ensembleid)
       
   103                     newDecoupageNode = deepcopy(cnode)
       
   104                     newensemble.append(newDecoupageNode)
       
   105                 #elif cnode.nodeType == xml.dom.Node.ELEMENT_NODE and cnode.tagName == "ensemble":
       
   106                 elif cnode.tag == "ensemble":
       
   107                     #ensembleid = cnode.getAttribute(u"id")
       
   108                     ensembleid = cnode.attrib['id']
       
   109                     cloneNode = deepcopy(cnode)
       
   110                     if ensembleid in ensembleids:
       
   111                         ensembleid = self.id+"_"+str(uuid.uuid1())
       
   112                         cloneNode.set(u"id", ensembleid)
       
   113                     ensembleids.append(ensembleid)
       
   114                     ensemblesnode.append(cloneNode)
       
   115 
       
   116         res = doc.xpath("/iri/body/medias/media[@id='video']/video")
       
   117         if self.flatten:
       
   118             src_video = res[0].get('src')
       
   119             self.videourl = os.path.basename(src_video)
       
   120             res[0].set('src', self.videourl)
       
   121         self.duration = res[0].get(u'dur')
       
   122             
       
   123         f = open(path, "w")
       
   124         try:
       
   125             #etree = lxml.etree.ElementTree(doc)
       
   126             doc.write(f, encoding="UTF-8", pretty_print=True, xml_declaration=True)
       
   127 #            xml.dom.ext.Print(doc, stream=f)
       
   128         finally:
       
   129             f.close()
       
   130         
       
   131         
       
   132         destPath = os.path.join(os.path.join(os.path.join(settings.MEDIA_ROOT, "media"), "ldt"), self.id);
       
   133         if not os.path.exists(destPath):
       
   134             os.makedirs(destPath)
       
   135         shutil.move(os.path.join(self.basepath, self.src), os.path.join(destPath, os.path.basename(self.src)))
       
   136         self.src = self.id + u"/" + os.path.basename(self.src)
       
   137 
       
   138 
       
   139 
       
   140     def saveContent(self):
       
   141 
       
   142         defaults_media = {'src':unicode(self.videourl), 'title':unicode(self.title), 'description':unicode(self.desc), 'videopath': unicode(self.videopath.rstrip("/") + "/")}
       
   143         media, media_created = Media.objects.get_or_create(src=unicode(self.videourl), defaults = defaults_media)
       
   144         if not media_created:
       
   145             for key, value in defaults_media.items():
       
   146                 setattr(media, key, value)
       
   147 
       
   148         media.save()
       
   149 
       
   150         defaults_content = { 
       
   151             'iriurl': unicode(self.src), 
       
   152             'title':unicode(self.title),
       
   153             'description':unicode(self.desc),
       
   154             'media':media,
       
   155             'iri':unicode(self.id + u"/" + os.path.basename(self.src)),
       
   156             'duration':int(self.duration)
       
   157         }
       
   158         content, self.created = Content.objects.get_or_create(iri_id=self.id, defaults = defaults_content)
       
   159         if not self.created:
       
   160             for key, value in defaults_content.items():
       
   161                 setattr(content, key, value)
       
   162         
       
   163         content.save()
       
   164 
       
   165         self.content = content
       
   166             
       
   167     def process(self):
       
   168         self.processIri()
       
   169         self.saveContent()
       
   170         
       
   171 class BaseFileImport(object):
       
   172 
       
   173     def __init__(self, filepath, videopath):
       
   174         self.__filepath = filepath
       
   175         self.__tempdir = ""
       
   176         self.__videopath = videopath
       
   177         self.__author = None
       
   178 
       
   179         
       
   180     def filepath(): #@NoSelf
       
   181         doc = """Docstring""" #@UnusedVariable
       
   182        
       
   183         def fget(self):
       
   184             return self.__filepath
       
   185            
       
   186         def fset(self, value):
       
   187             self.__filepath = value
       
   188            
       
   189         def fdel(self):
       
   190             del self.__filepath
       
   191            
       
   192         return locals()
       
   193        
       
   194     filepath = property(**filepath())
       
   195     
       
   196     def videopath(): #@NoSelf
       
   197         doc = """Docstring""" #@UnusedVariable
       
   198        
       
   199         def fget(self):
       
   200             return self.__videopath
       
   201            
       
   202         def fset(self, value):
       
   203             self.__videopath = value
       
   204            
       
   205         def fdel(self):
       
   206             del self.__videopath
       
   207            
       
   208         return locals()
       
   209        
       
   210     videopath = property(**videopath())
       
   211 
       
   212     def author(): #@NoSelf
       
   213         doc = """Docstring""" #@UnusedVariable
       
   214        
       
   215         def fget(self):
       
   216             return self.__author
       
   217            
       
   218         def fset(self, value):
       
   219             self.__author = value
       
   220            
       
   221         def fdel(self):
       
   222             del self.__author
       
   223            
       
   224         return locals()
       
   225 
       
   226     author = property(**author())
       
   227     
       
   228        
       
   229 class FileImport(BaseFileImport):
       
   230 
       
   231     def __init__(self, filepath, videopath, flatten):
       
   232         BaseFileImport.__init__(self, filepath, videopath)
       
   233         self.__checkExistingMedia = False
       
   234         self.__flatten = flatten
       
   235         
       
   236     def checkExistingMedia(): #@NoSelf
       
   237         doc = """Docstring""" #@UnusedVariable
       
   238        
       
   239         def fget(self):
       
   240             return self.__checkExistingMedia
       
   241            
       
   242         def fset(self, value):
       
   243             self.__checkExistingMedia = value
       
   244            
       
   245         def fdel(self):
       
   246             del self.__checkExistingMedia
       
   247            
       
   248         return locals()
       
   249 
       
   250     checkExistingMedia = property(**checkExistingMedia())    
       
   251 
       
   252     def flatten(): #@NoSelf
       
   253         doc = """Docstring""" #@UnusedVariable
       
   254        
       
   255         def fget(self):
       
   256             return self.__flatten
       
   257            
       
   258         def fset(self, value):
       
   259             self.__flatten = value
       
   260            
       
   261         def fdel(self):
       
   262             del self.__flatten
       
   263            
       
   264         return locals()
       
   265     flatten = property(**flatten())
       
   266 
       
   267     def processLdt(self, ldtpath=None):
       
   268         
       
   269         # list iri
       
   270         # see if there is some comments
       
   271         # inject comment in iri
       
   272         # copy iri in folder
       
   273         # create or update content
       
   274         contents = {}
       
   275         filepath = ldtpath if ldtpath else self.filepath
       
   276         doc = lxml.etree.parse(filepath)
       
   277         #if ldtpath:
       
   278             #doc = xml.dom.minidom.parse(ldtpath)
       
   279         #    doc = lxml.etree.parse(ldtpath)
       
   280         #else:
       
   281             #doc = xml.dom.minidom.parse(self.filepath)
       
   282         
       
   283         #con = xml.xpath.Context.Context(doc, 1, 1, None)
       
   284         
       
   285         #get author from file ldt
       
   286         #result = xml.xpath.Evaluate("/iri/project", context=con)
       
   287         result = doc.xpath("/iri/project")
       
   288         for pnode in result:
       
   289             #author = pnode.getAttributeNS(None,u"user")
       
   290             author = pnode.attrib[u"user"]
       
   291             if author:
       
   292                 self.author = unicode(author)
       
   293                 break 
       
   294 
       
   295         result = doc.xpath("/iri/medias/media")
       
   296         
       
   297         for i, medianode in  enumerate(result):
       
   298         # get iri file's id from file ldt
       
   299             #id = medianode.attributes['id'].value
       
   300             id = medianode.attrib['id']
       
   301             if self.checkExistingMedia:
       
   302                 try:
       
   303                     Content.objects.get(iri_id=id)
       
   304                     do_pass = True
       
   305                 except ObjectDoesNotExist: #Content.DoesNotExist
       
   306                     do_pass = False
       
   307             else:
       
   308                     do_pass = False
       
   309             if not do_pass:
       
   310                 if not (contents.has_key(id)):
       
   311                     # Create instance iriInfo(id, order, titledesc, basepath="", videopath=settings.STREAM_URL)
       
   312                     if ldtpath:
       
   313                         contents[id] = IriInfo(id, i, "", os.path.dirname(ldtpath), flatten=self.flatten)
       
   314                     else: 
       
   315                         contents[id] = IriInfo(id, i, "", flatten=self.flatten)
       
   316                     # Get iri file's url from ldt. This url can be relative path or absolute path.
       
   317                 #contents[id].src = medianode.attributes['src'].value
       
   318                 contents[id].src = medianode.attrib['src']
       
   319                 if medianode.attrib['video'] !="":
       
   320                     contents[id].videopath = medianode.attrib['video']
       
   321                 elif self.videopath !="" or self.videopath:
       
   322                     contents[id].videopath = self.videopath
       
   323                 else:
       
   324                     contents[id].videopath =settings.STREAM_URL
       
   325                     
       
   326                 
       
   327         #get annotation of file ldt
       
   328         result = doc.xpath("/iri/annotations/content")
       
   329         
       
   330         for contentnode in result:
       
   331             id = contentnode.attrib['id']
       
   332             if contents.has_key(id):
       
   333                 if self.author:
       
   334                     contentnode.set("author", unicode(self.author))
       
   335                 contents[id].annotations = contentnode
       
   336         
       
   337         #go throught values
       
   338         for iriinfo in contents.values():
       
   339             
       
   340             iriinfo.process()
       
   341             
       
   342             # if yes update
       
   343             # if no create
       
   344             # move iri file to the proper place
       
   345             #return list of iriInfo
       
   346         
       
   347     def processFile(self):
       
   348         if self.filepath.name.endswith(".ldt"):
       
   349             self.processLdt()
       
   350         elif self.filepath.name.endswith(".zip"):
       
   351             self.processZip()
       
   352         else:
       
   353             raise FileImportError("Bad file type")
       
   354 
       
   355 
       
   356     def processZip(self):
       
   357     # """ extraire .zip, pass to method processLdt"""
       
   358         # create temp directory
       
   359         self.__tempdir = tempfile.mkdtemp()
       
   360         openfiles = []
       
   361         flvfiles = []
       
   362         processedids = []
       
   363         
       
   364         try:
       
   365             zipfile = zipfileext.ZipFileExt(self.filepath)
       
   366             zipfile.unzip_into_dir(self.__tempdir)
       
   367             #load ldt
       
   368             foldersToProcess = [self.__tempdir]
       
   369             while len(foldersToProcess):
       
   370                 currentFolder = foldersToProcess.pop()
       
   371                 for entry in os.listdir(currentFolder):
       
   372                     if entry in settings.ZIP_BLACKLIST:
       
   373                         continue
       
   374                     entryPath = os.path.join(currentFolder, entry)
       
   375                     if(os.path.isdir(entryPath)):
       
   376                         foldersToProcess.append(entryPath)
       
   377                     elif fnmatch.fnmatch(entry, "*.ldt"):
       
   378                         ldtid = self.processLdt(entryPath)
       
   379                         processedids.append(ldtid)
       
   380                     elif fnmatch.fnmatch(entry, "*.flv"):
       
   381                         flvfiles.append(entryPath)
       
   382              
       
   383             if settings.CONTENT_ROOT and os.path.exists(settings.CONTENT_ROOT): 
       
   384                 for entry in flvfiles:
       
   385                     shutil.copy(entry, settings.CONTENT_ROOT)
       
   386                     
       
   387         finally:
       
   388             for f in openfiles:
       
   389                 f.close()
       
   390             shutil.rmtree(self.__tempdir)
       
   391         # delete directory
       
   392         return processedids
       
   393         
       
   394     # def processFileLdt(self):
       
   395         # processedids = []
       
   396         # ldtid = self.processLdt(self.filepath)
       
   397         # processedids.append(ldtid)
       
   398         # return processedids