from copy import deepcopy
from django.conf import settings
from django.utils.translation import ugettext as _
from StringIO import StringIO
import datetime
import django.core.urlresolvers
import lxml.etree #@UnresolvedImport
import uuid
from ldt.utils.url import request_with_auth
from ldt.utils.url import absurl_norequest
__BOOLEAN_DICT = {
'false':False,
'true':True,
'0':False,
'1':True,
't': True,
'f':False
}
def reduce_text_node(element_node, xpath_str=None):
node_list = []
if xpath_str is not None:
node_list = element_node.xpath(xpath_str, smart_strings=False)
else:
node_list = [element_node.text]
return reduce(lambda t, s: t + s, node_list , "")
def boolean_convert(bool_val):
if bool_val is None:
return False
if bool_val is True or bool_val is False:
return bool_val
key = str(bool_val).lower()
return __BOOLEAN_DICT.get(key, False)
def generate_uuid():
return unicode(uuid.uuid1())
class LdtUtils(object):
def generate_ldt(self, contentList, title=u"", author=u"IRI Web", web_url=u"", startSegment=None, projects=None, types_id_list=None):
iri = lxml.etree.Element(u'iri')
doc = lxml.etree.ElementTree(iri)
project = lxml.etree.SubElement(iri, u'project')
project.set(u"id", generate_uuid())
project.set(u"title", unicode(title))
project.set(u"user", author)
project.set(u"abstract", u"")
medias = lxml.etree.SubElement(iri, u"medias")
for content in contentList:
videopath = unicode(settings.STREAM_URL)
if content.videopath != None :
videopath = unicode(content.videopath)
media = lxml.etree.SubElement(medias, "media")
media.set(u"id", content.iri_id)
media.set(u"src", content.relative_iri_url())
media.set(u"video", videopath)
media.set(u"pict", u"")
media.set(u"extra", u"")
if projects is None:
projects = []
annotations_nodes = {}
for project in projects:
ldtdoc = lxml.etree.fromstring(project.ldt_encoded)
res = ldtdoc.xpath("/iri/annotations/content")
for content in res:
contentid = content.get("id")
if annotations_nodes.has_key(contentid):
contentnode = annotations_nodes[contentid]
else:
contentnode = {"id":contentid, "ensembles":[]}
annotations_nodes[contentid] = contentnode
for ens in content:
if ens.tag.endswith("ensemble"):
contentnode["ensembles"].append(deepcopy(ens))
annotations = lxml.etree.SubElement(iri, "annotations")
if len(annotations_nodes) > 0:
for content in contentList:
if content.iri_id in annotations_nodes:
contentnode = annotations_nodes[content.iri_id]
if contentnode is not None:
content_node = lxml.etree.SubElement(annotations, "content")
content_node.set("id", contentnode["id"])
content_node.text = u""
for ens in contentnode["ensembles"]:
content_node.append(ens)
displays = lxml.etree.SubElement(iri, "displays")
if len(contentList) > 0:
display = lxml.etree.SubElement(displays, "display")
display.set(u"id", u"0")
display.set(u"title", u"generated")
display.set(u"idsel", contentList[0].iri_id)
display.set(u"tc", u"0")
for content in contentList:
contentd = lxml.etree.SubElement(display, "content")
contentd.set(u"id", content.iri_id)
__, content_str = request_with_auth(content.iri_url())
filepath = StringIO(content_str)
udoc = lxml.etree.parse(filepath)
res = udoc.xpath("/iri/body/ensembles/ensemble/decoupage")
for decoupagenode in res:
decoupage_id = decoupagenode.get(u"id")
ensemble_id = decoupagenode.getparent().get(u"id")
decoupage_id = decoupagenode.get(u"id")
ensemble_id = decoupagenode.getparent().get(u"id")
decoupage = lxml.etree.SubElement(contentd, "decoupage")
decoupage.set(u"id", decoupage_id)
decoupage.set(u"idens", ensemble_id)
# We add the project's decoupages in the generated project
if len(annotations_nodes) > 0:
if content.iri_id in annotations_nodes:
contentnode = annotations_nodes[content.iri_id]
if contentnode is not None:
for ens in contentnode["ensembles"]:
for decoupagenode in ens:
type_id = decoupagenode.get(u"id")
if type_id in types_id_list:
decoupage = lxml.etree.SubElement(contentd, "decoupage")
decoupage.set(u"id", decoupagenode.get(u"id"))
decoupage.set(u"idens", ens.get(u"id"))
if startSegment is not None:
activeSegment = lxml.etree.SubElement(display, "activeSegment")
idas = lxml.etree.SubElement(activeSegment, "id")
idas.set(u"idctt", startSegment["idcontent"])
idas.set(u"idens" , startSegment["idgroup"])
idas.set(u"idcut", startSegment["idcutting"])
idas.set(u"idseg", startSegment["idsegment"])
lxml.etree.SubElement(iri, "edits")
return doc
def generate_init(self, url, method, search=None):
iri = lxml.etree.Element('iri')
elementFiles = lxml.etree.SubElement(iri, 'files')
elementInit = lxml.etree.SubElement(elementFiles, 'init')
elementfile = lxml.etree.SubElement(elementInit, 'file')
elementfile.set('src', absurl_norequest(method, args=url))
elementfile.set('src', django.core.urlresolvers.reverse(method, args=url))
if(search):
elementfile.set("segsel", absurl_norequest(search, args=url))
lxml.etree.SubElement(elementFiles, 'recent')
lxml.etree.SubElement(elementFiles, 'library')
return iri
class LdtAnnotation:
def __init__(self, project, force_save=False):
self.project = project
self.parser = lxml.etree.XMLParser(remove_blank_text=True)
self.ldtdoc = lxml.etree.parse(StringIO(project.ldt_encoded), self.parser)
self.to_add = True
# add( a['media'], a['type'], a['type_title, a[data], '', a['tags'], begin, dur, author, date)
def add(self, media, cutting_id, cutting_title, title, text, tags_list, begin, dur, author, date, view_id="0", color="2194379", audio_scr="", audio_href=""):
"""
Add an annotation to a project. begin and dur must be strings. Default color is yellow.
"""
if dur < 0:
self.to_add = False
return False
# We check if the project references the media.
path_media = self.ldtdoc.xpath('/iri/medias/media[@id="%s"]' % media)
if len(path_media) == 0:
self.to_add = False
return False
# We get the content node
path_annotations = self.ldtdoc.xpath('/iri/annotations')[0]
path_content = path_annotations.xpath('content[@id="%s"]' % media)
# If the content node does not exist, we create it
if len(path_content) == 0:
path_content = lxml.etree.SubElement(path_annotations, 'content')
path_content.set('id', media)
path_content = [path_content]
# We generate the cutting id if necessary
if cutting_id is None or cutting_id=="" :
cutting_id = 'c_' + generate_uuid()
# We get the ensemble node
path_ensemble = path_content[0].xpath('ensemble[decoupage[@id="%s"]]' % cutting_id)
if len(path_ensemble) == 0:
# If the ensemble node does not exist, we create it
path_ensemble = lxml.etree.SubElement(path_content[0], 'ensemble')
path_ensemble.set('id', 'g_' + generate_uuid())
path_ensemble.set('title', _('Personal cutting'))
path_ensemble.set('author', 'IRI')
path_ensemble.set('abstract', 'IRI')
path_ensemble = [path_ensemble]
#else:
# path_ensemble = path_content[0].xpath('ensemble')
# We get the elements node in the good decoupage node
ensemble_id = path_ensemble[0].get('id')
decoupage_elements = path_ensemble[0].xpath('decoupage[@id="%s"]/elements' % cutting_id)
if len(decoupage_elements) == 0:
# If the decoupage node does not exist, we create it and its elements node
decoupage = lxml.etree.SubElement(path_ensemble[0], 'decoupage')
#cutting_id = "c_" + generate_uuid()
decoupage.set('id', cutting_id)
decoupage.set('author', author)
decoupage_title = lxml.etree.SubElement(decoupage, 'title')
decoupage_title.text = cutting_title
lxml.etree.SubElement(decoupage, 'abstract')
decoupage_elements = lxml.etree.SubElement(decoupage, 'elements')
decoupage_elements = [decoupage_elements]
#else:
# cutting_id = path_ensemble[0].xpath('decoupage[title="%s"]' % cutting_title)[0].get('id')
# We add the cutting to the view
if view_id is not None and view_id!="" :
path_view = self.ldtdoc.xpath('/iri/displays/display[@id="%s"]' % view_id)
if len(path_view) == 0:
path_view = self.ldtdoc.xpath('/iri/displays/display[@title="Init view"]')
else :
content_display = path_view[0].xpath('content[@id="%s"]' % media)
if len(content_display) == 0:
content_display = lxml.etree.SubElement(path_view[0], 'content')
content_display.set('id', media)
content_display = [content_display]
# We add the decoupage node to the content node
dec = lxml.etree.SubElement(content_display[0], 'decoupage')
dec.set('idens', ensemble_id)
dec.set('id', cutting_id)
dec.set('tagsSelect', '')
# We add the annotation/element node
element = lxml.etree.SubElement(decoupage_elements[0], 'element')
id_annotation = 's_' + generate_uuid()
element.set('id', id_annotation)
element.set('begin', begin)
element.set('dur', dur)
element.set('author', author)
element.set('date', date)
element.set('color', color)
element.set('src', "")
abstract = lxml.etree.SubElement(element, 'abstract')
abstract.text = text
title_node = lxml.etree.SubElement(element, 'title')
title_node.text = title
audio = lxml.etree.SubElement(element, 'audio')
audio.set('source', audio_scr)
audio.text = audio_href
tags = lxml.etree.SubElement(element, 'tags')
polemics = self.get_polemic_syntax(title)
if polemics:
meta = lxml.etree.SubElement(element, 'meta')
polemics_node = lxml.etree.SubElement(meta, 'polemics')
for polemic in polemics:
polemic_node = lxml.etree.SubElement(polemics_node, 'polemic')
polemic_node.text = polemic
for tag in tags_list:
tag_node = lxml.etree.SubElement(tags, 'tag')
tag_node.text = tag
return cutting_id, id_annotation, ensemble_id
def save(self, must_reindex=True):
if self.to_add:
self.project.ldt = lxml.etree.tostring(self.ldtdoc, pretty_print=True)
self.project.save(must_reindex=must_reindex)
def get_polemic_syntax(self, text):
polemics = []
for key in settings.SYNTAX.keys():
if key in text:
polemics.append(settings.SYNTAX[key])
return polemics
def __del__(self):
self.save()
def create_ldt(project, user, cuttings=[]):
"""create xml"""
contentList = project.contents.all()
# create a dom
iri = lxml.etree.Element('iri')
doc = lxml.etree.ElementTree(iri)
#node project
elementProject = lxml.etree.SubElement(iri, 'project')
elementProject.set('abstract', project.description)
elementProject.set('title', project.title)
elementProject.set('user', user.username)
elementProject.set('id', project.ldt_id)
#node medias
elementMedias = lxml.etree.SubElement(iri, 'medias')
idsel = None
for content in contentList:
if not idsel:
idsel = content.iri_id
elementMedia = lxml.etree.SubElement(elementMedias, 'media')
elementMedia.set('id', content.iri_id)
elementMedia.set('src', content.relative_iri_url())
if content.videopath != None :
elementMedia.set('video', content.videopath)
else:
elementMedia.set('video', settings.STREAM_URL)
elementMedia.set('pict', "")
elementMedia.set('extra', "")
if not idsel:
idsel = ""
#node annotations
annotations = lxml.etree.SubElement(iri, 'annotations')
#node displays
elementDisplays = lxml.etree.SubElement(iri, 'displays')
elementDisplay = lxml.etree.SubElement(elementDisplays, 'display')
elementDisplay.set('id', '0')
elementDisplay.set('title', 'Init view')
elementDisplay.set('idsel', idsel)
elementDisplay.set('tc', '0')
elementDisplay.set('zoom', '0')
elementDisplay.set('scroll', '0')
elementDisplay.set('infoBAB', '')
#node content
for content in contentList:
elementContent = lxml.etree.SubElement(elementDisplay, 'content')
elementContent.set('id', content.iri_id)
if not 'http' in content.iriurl:
#eg: "iiiielizabethrosse/ENMI08-III_elizabethrosse.iri"
url = content.iri_url()
else:
url = content.iriurl
__, content = request_with_auth(url)
doc = lxml.etree.parse(StringIO(content))
res = doc.xpath("/iri/body/ensembles/ensemble/decoupage")
#node decoupage
for decoupagenode in res:
decoupage_id = decoupagenode.get(u"id")
parent = decoupagenode.getparent()
ensemble_id = parent.get(u"id")
elementDecoupage = lxml.etree.SubElement(elementContent, 'decoupage')
elementDecoupage.set('idens', ensemble_id)
elementDecoupage.set('id', decoupage_id)
#node edits
lxml.etree.SubElement(iri, 'edits')
# add cuttings to the first content if necessary
if cuttings and contentList:
content = contentList[0]
ensemble_id = "g_%s" % generate_uuid()
cuttings_id = []
content_node = lxml.etree.SubElement(annotations, 'content')
content_node.set('id', content.iri_id)
ensemble = lxml.etree.SubElement(content_node, 'ensemble')
ensemble.set('title', _('Personal cutting'))
ensemble.set('id', ensemble_id)
ensemble.set('author', 'undefined')
ensemble.set('abstract', '')
ensemble.set('idProject', project.ldt_id)
#Add cuttings to tag annotations
for cutting in cuttings:
cutting_node = lxml.etree.SubElement(ensemble, 'decoupage')
cutting_node.set('author', 'perso')
cutting_id = "c_%s" % generate_uuid()
cuttings_id.append(cutting_id)
cutting_node.set('id', cutting_id)
title = lxml.etree.SubElement(cutting_node, 'title')
title.text = cutting
lxml.etree.SubElement(cutting_node, 'abstract')
lxml.etree.SubElement(cutting_node, 'elements')
#Add cuttings to tag displays
content_node = elementDisplays.xpath('display/content[@id=\'%s\']' % content.iri_id)[0]
for cutting_id in cuttings_id:
cutting_node = lxml.etree.SubElement(content_node, 'decoupage')
cutting_node.set('idens', ensemble_id)
cutting_node.set('id', cutting_id)
cutting_node.set('tagSelect', '')
#write dom in Project.ldt
project.ldt = lxml.etree.tostring(iri, pretty_print=True)
#save Project
project.save()
return project
def copy_ldt(project, new_project, user):
new_project.ldt_id = str(uuid.uuid1())
new_project.created_by = user.username
new_project.changed_by = user.username
new_project.state = 1
"""create xml"""
ldt = lxml.etree.fromstring(project.ldt_encoded)
res = ldt.xpath("/iri/project")
for elementProject in res:
elementProject.set('abstract', project.get_description())
elementProject.set('title', new_project.title)
elementProject.set('user', user.username)
elementProject.set('id', new_project.ldt_id)
new_project.ldt = lxml.etree.tostring(ldt, pretty_print=True)
#save Project
new_project.save()
return new_project
def create_empty_iri(iri_file, content, username):
iri = lxml.etree.Element('iri')
doc = lxml.etree.ElementTree(iri)
head = lxml.etree.SubElement(iri, 'head')
meta_id = lxml.etree.SubElement(head, 'meta')
meta_id.set(u'name', u'id')
meta_id.set(u'content', unicode(content.iri_id))
meta_title = lxml.etree.SubElement(head, 'meta')
meta_title.set(u'name', u'title')
meta_title.set(u'content', unicode(content.title))
meta_abstract = lxml.etree.SubElement(head, 'meta')
meta_abstract.set(u'name', u'abstract')
meta_abstract.set(u'content', unicode(content.description))
meta_author = lxml.etree.SubElement(head, 'meta')
meta_author.set(u'name', u'author')
meta_author.set(u'content', unicode(username))
meta_contributor = lxml.etree.SubElement(head, 'meta')
meta_contributor.set(u'name', u'contributor')
meta_contributor.set(u'content', unicode(username))
meta_date = lxml.etree.SubElement(head, 'meta')
meta_date.set(u'name', u'date')
meta_date.set(u'content', unicode(datetime.date.today().isoformat()))
meta_copyright = lxml.etree.SubElement(head, 'meta')
meta_copyright.set(u'name', u'copyright')
meta_copyright.set(u'content', u'IRI')
meta_type = lxml.etree.SubElement(head, 'meta')
meta_type.set(u'name', u'type')
meta_type.set(u'content', u'video')
body = lxml.etree.SubElement(iri, 'body')
lxml.etree.SubElement(body, 'ensembles')
lxml.etree.SubElement(body, 'links')
medias = lxml.etree.SubElement(body, 'medias')
media_video = lxml.etree.SubElement(medias, 'media')
media_video.set(u'id', u'video')
video = lxml.etree.SubElement(media_video, 'video')
video.set(u'src', unicode(content.stream_src))
video.set(u'id', unicode(content.iri_id))
video.set(u'dur', unicode(content.duration))
video.set(u'begin', u'0')
media_tool = lxml.etree.SubElement(medias, 'media')
media_tool.set(u'id', u'tool')
lxml.etree.SubElement(media_tool, 'tool')
lxml.etree.SubElement(body, 'display')
doc.write(iri_file, pretty_print=True)
def update_iri(filepath, content, username):
# open xml
doc = lxml.etree.parse(filepath)
res = doc.xpath("/iri/head/meta")
# update meta
for meta_node in res:
meta_name = meta_node.get("name")
content_attr = None
if meta_name == u'id':
content_attr = unicode(content.iri_id)
elif meta_name == u'title':
content_attr = unicode(content.title)
elif meta_name == u'abstract':
content_attr = unicode(content.description)
elif meta_name == u'contributor':
content_attr = unicode(username)
elif meta_name == u"date":
content_attr = unicode(datetime.date.today().isoformat())
if content_attr is not None:
meta_node.set(u"content", content_attr)
res = doc.xpath("/iri/body/medias/media[@id='video']/video")
if len(res) > 0:
video_node = res[0]
video_node.set(u'src', unicode(content.stream_src))
video_node.set(u'dur', unicode(content.duration))
video_node.set(u'id', unicode(content.iri_id))
# update video
f = open(filepath, "w")
try:
doc.write(f, encoding="UTF-8", pretty_print=True, xml_declaration=True)
finally:
f.close()
def clean_description(description):
""" Remove html tags added by flash if necessary """
new_desc = u''
begin_str = "KERNING=\"0\">"
for chunk in description.split("<TEXTFORMAT"):
begin = chunk.find(begin_str) + len(begin_str)
end = chunk.find("</FONT")
if begin > 0 and end > 0:
new_desc = new_desc + chunk[begin:end] + "<br />"
if new_desc:
return new_desc
return None