1 from ldt.ldt_utils.models import Project |
1 from ldt.ldt_utils.models import Project |
2 from piston.handler import BaseHandler |
2 from piston.handler import BaseHandler |
3 from piston.utils import rc, require_extended |
3 from piston.utils import rc, require_extended |
4 from ldt.ldt_utils.utils import LdtAnnotation |
4 from ldt.ldt_utils.utils import LdtAnnotation |
5 import logging #@UnresolvedImport |
5 import logging #@UnresolvedImport |
|
6 import lxml.etree |
6 |
7 |
7 |
8 |
8 class ProjectHandler(BaseHandler): |
9 class ProjectHandler(BaseHandler): |
9 allowed_methods = ('GET', 'PUT',) |
10 allowed_methods = ('GET', 'PUT',) |
10 model = Project |
11 model = Project |
18 @require_extended |
19 @require_extended |
19 def update(self, request, project_id): |
20 def update(self, request, project_id): |
20 """ |
21 """ |
21 This method is called when a PUT request is sent to http://<plateform_location>/api/ldt/projects/<project_id>.format. The |
22 This method is called when a PUT request is sent to http://<plateform_location>/api/ldt/projects/<project_id>.format. The |
22 request should contain a content-type header whose value can be either "application/json" or "text/xml" and a valid utf-8 |
23 request should contain a content-type header whose value can be either "application/json" or "text/xml" and a valid utf-8 |
23 encoded JSON/Cinelab or LDT/XML file. |
24 encoded JSON Cinelab or LDT XML file. |
24 <project_id> is the ldt_id field of the project. If <projet_id> does not match any project on the platform, a 410 ("Gone") |
25 <project_id> is the ldt_id field of the project. If <projet_id> does not match any project on the platform, a 410 ("Gone") |
25 error will be returned. |
26 error will be returned. |
26 <format> can be 'json', 'yaml', 'xml', 'pickle' |
27 <format> is the format of the data sent back by the server. It can be 'json', 'yaml', 'xml' or 'pickle'. |
27 |
28 |
28 If the submitted file is not valid or if the file refers to a media that is not contained in the project, a 500 ("Bad Request") |
29 If the submitted file is not valid or if the file refers to a media that is not contained in the project, a 500 ("Bad Request") |
29 error will be returned. If the "type" field of an annotation matches an already existing cutting, it will be added to that |
30 error will be returned. If the "type" field of an annotation matches an already existing cutting, it will be added to that |
30 cutting. Otherwise, a new cutting will be added (as well as a new ensemble if needed). Several annotations can be added at |
31 cutting. Otherwise, a new cutting will be added (as well as a new ensemble if needed). Several annotations can be added at |
31 the same time if the submitted file contains multiple annotations. In addition to annotations, the submitted file should contain a |
32 the same time if the submitted file contains multiple annotations. The server returns a 201 ("Created") code if annotations have |
32 meta section with two fields :"date" and "creator". The server returns a 201 ("Created") code if annotations have been added. |
33 been added successfully. |
33 |
34 |
34 Example : |
35 Example : |
|
36 |
|
37 Remark : Both files below contain the minimum necessary fields and attributes for the handler to work. If one field or attribute is |
|
38 missing (e.g. author, or date) during submission, an error will occur. |
35 |
39 |
36 A platform is reachable at http://localhost/. It contains a project with ID a0593b58-f258-11df-80e1-00145ea4a2be. This project has |
40 A platform is reachable at http://localhost/. It contains a project with ID a0593b58-f258-11df-80e1-00145ea4a2be. This project has |
37 a content milosforman_amadeus, which has a cutting Salieri. The following JSON file exists in the current directory : |
41 a content milosforman_amadeus, which has a cutting Salieri. The following JSON file exists in the current directory : |
38 |
42 |
39 { |
43 { |
66 } |
70 } |
67 } |
71 } |
68 |
72 |
69 If we send a PUT request with curl : |
73 If we send a PUT request with curl : |
70 $curl -X PUT http://localhost/api/ldt/projects/a0593b58-f258-11df-80e1-00145ea4a2be.json -d @example.JSON -H "content-type:application/json" |
74 $curl -X PUT http://localhost/api/ldt/projects/a0593b58-f258-11df-80e1-00145ea4a2be.json -d @example.JSON -H "content-type:application/json" |
71 A new cutting titled "New cutting name" will be created with one annotation inside, and the annotation "Annotation about Salieri" |
75 A new cutting titled "New cutting name" will be created with the first annotation inside, and the annotation "Annotation about Salieri" |
72 will be added to the Salieri cutting. |
76 will be added to the Salieri cutting. |
|
77 |
|
78 Similar results can be obtained using the following xml file : |
|
79 |
|
80 <iri> |
|
81 <annotations> |
|
82 <content id="milosforman_amadeus"> |
|
83 <ensemble> |
|
84 <decoupage> |
|
85 <title>New cutting name</title> |
|
86 <abstract/> |
|
87 <elements> |
|
88 <element begin="50000" dur="895000" date="2011-09-10T09:12:58" author="John Doe"> |
|
89 <title>new annotation</title> |
|
90 <abstract/> |
|
91 <audio source=""/> |
|
92 <tags> |
|
93 <tag>json</tag> |
|
94 </tags> |
|
95 </element> |
|
96 </elements> |
|
97 </decoupage> |
|
98 <decoupage > |
|
99 <title>Salieri</title> |
|
100 <abstract/> |
|
101 <elements> |
|
102 <element begin="700000" dur="500000" date="2011-09-10T09:12:58" author="John Doe"> |
|
103 <title>Annotation about Salieri</title> |
|
104 <abstract/> |
|
105 <audio source=""/> |
|
106 <tags> |
|
107 <tag>xml</tag> |
|
108 <tag>test</tag> |
|
109 <tag>blop</tag> |
|
110 </tags> |
|
111 </element> |
|
112 </elements> |
|
113 </decoupage> |
|
114 </ensemble> |
|
115 </content> |
|
116 </annotations> |
|
117 </iri> |
|
118 |
|
119 and the command : |
|
120 |
|
121 $curl -X PUT http://localhost/api/ldt/projects/a0593b58-f258-11df-80e1-00145ea4a2be.json -d @example.LDT -H "content-type:text/xml" |
73 |
122 |
74 """ |
123 """ |
75 |
124 |
76 try: |
125 try: |
77 project = Project.objects.get(ldt_id=project_id) |
126 project = Project.objects.get(ldt_id=project_id) |
78 except Project.DoesNotExist: |
127 except Project.DoesNotExist: |
79 return rc.NOT_HERE |
128 return rc.NOT_HERE |
80 |
129 |
|
130 adder = LdtAnnotation(project) |
|
131 |
81 if request.content_type == 'application/json': |
132 if request.content_type == 'application/json': |
82 |
133 |
83 logging.debug("request json " + repr(request)) |
134 logging.debug("request json " + repr(request.data)) |
84 adder = LdtAnnotation(project) |
|
85 |
135 |
86 meta = request.data['meta'] |
136 meta = request.data['meta'] |
87 author = meta['creator'] |
137 author = meta['creator'] |
88 date = meta['created'] |
138 date = meta['created'] |
89 new_annotations = request.data['annotations'] |
139 new_annotations = request.data['annotations'] |
92 dur = str(a['end'] - a['begin']) |
142 dur = str(a['end'] - a['begin']) |
93 begin = str(a['begin']) |
143 begin = str(a['begin']) |
94 if not adder.add(a['media'], a['type'], a['content']['data'], '', a['tags'], begin, dur, author, date): |
144 if not adder.add(a['media'], a['type'], a['content']['data'], '', a['tags'], begin, dur, author, date): |
95 return rc.BAD_REQUEST |
145 return rc.BAD_REQUEST |
96 |
146 |
97 return rc.ALL_OK |
147 return rc.ALL_OK |
98 |
148 |
99 elif request.content_type == "text/xml": |
149 elif request.content_type == "text/xml": |
100 logging.debug("request xml" + repr(request)) |
150 logging.debug("request xml" + repr(request)) |
101 data = request.data |
|
102 ldt_str = data["ldt"] |
|
103 |
151 |
104 logging.debug("request data" + repr(ldt_str)) |
152 ldtdoc = lxml.etree.fromstring(request.raw_post_data) |
105 |
153 |
106 if not ldt_str: |
154 for content in ldtdoc.xpath('/iri/annotations/content'): |
107 return rc.ALL_OK |
155 content_id = content.get('id') |
108 |
156 |
109 project.ldt = ldt_str |
157 for decoupage in content.xpath('ensemble/decoupage'): |
110 |
158 dec_title = decoupage.xpath('title')[0].text |
111 project.save() |
159 author = decoupage.get('author') |
|
160 |
|
161 for element in decoupage.xpath('elements/element'): |
|
162 begin = element.get('begin') |
|
163 dur = element.get('dur') |
|
164 date = element.get('date') |
|
165 title = element.xpath('title')[0].text |
|
166 abstract = element.xpath('abstract')[0].text |
|
167 tags = [] |
|
168 for tag in element.xpath('tags/tag'): |
|
169 tags.append(tag.text) |
|
170 |
|
171 if not adder.add(content_id, dec_title, title, abstract, tags, begin, dur, author, date): |
|
172 return rc.BAD_REQUEST |
112 |
173 |
113 return rc.ALL_OK |
174 return rc.ALL_OK |
114 |
175 |
115 return rc.NOT_IMPLEMENTED |
176 return rc.NOT_IMPLEMENTED |