18dd3e819c46d54c988430a1ba73832e2c0379ac
[redakcja.git] / apps / api / handlers / library_handlers.py
1 # -*- encoding: utf-8 -*-
2
3 __author__= "Ɓukasz Rekucki"
4 __date__ = "$2009-09-25 15:49:50$"
5 __doc__ = "Module documentation."
6
7 from piston.handler import BaseHandler, AnonymousBaseHandler
8
9
10 import settings
11 import librarian
12 import api.forms as forms
13 from datetime import date
14
15 from django.core.urlresolvers import reverse
16
17 from wlrepo import MercurialLibrary, RevisionNotFound, DocumentAlreadyExists
18 from librarian import dcparser
19
20 import api.response as response
21 from api.response import validate_form
22
23 #
24 # Document List Handlers
25 #
26 class BasicLibraryHandler(AnonymousBaseHandler):
27     allowed_methods = ('GET',)
28
29     def read(self, request):
30         """Return the list of documents."""
31         lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
32
33         document_list = [{
34             'url': reverse('document_view', args=[docid]),
35             'name': docid } for docid in lib.documents() ]
36
37         return {'documents' : document_list}
38         
39
40 class LibraryHandler(BaseHandler):
41     allowed_methods = ('GET', 'POST')
42     anonymous = BasicLibraryHandler
43
44     def read(self, request):
45         """Return the list of documents."""
46         lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
47
48         document_list = [{
49             'url': reverse('document_view', args=[docid]),
50             'name': docid } for docid in lib.documents() ]
51
52         return {'documents' : document_list }        
53
54     @validate_form(forms.DocumentUploadForm, 'POST')
55     def create(self, request, form):
56         """Create a new document."""
57         lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
58
59         if form.cleaned_data['ocr_data']:
60             data = form.cleaned_data['ocr_data'].encode('utf-8')
61         else:            
62             data = request.FILES['ocr'].read().decode('utf-8')
63
64         if form.cleaned_data['generate_dc']:
65             data = librarian.wrap_text(data, unicode(date.today()))
66
67         docid = form.cleaned_data['bookname']
68         try:
69             doc = lib.document_create(docid)
70             doc.quickwrite('xml', data, '$AUTO$ XML data uploaded.',
71                 user=request.user.username)
72
73             url = reverse('document_view', args=[doc.id])
74
75
76             return response.EntityCreated().django_response(\
77                 body = {
78                     'url': url,
79                     'name': doc.id,
80                     'revision': doc.revision },
81                 url = url )
82                 
83         except DocumentAlreadyExists:
84             # Document is already there
85             return response.EntityConflict().django_response(\
86                 {"reason": "Document %s already exists." % docid})
87
88 #
89 # Document Handlers
90 #
91 class BasicDocumentHandler(AnonymousBaseHandler):
92     allowed_methods = ('GET',)
93
94     def read(self, request, docid):
95         try:
96             lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
97             doc = lib.document(docid)
98         except RevisionNotFound:
99             return rc.NOT_FOUND
100
101         result = {
102             'name': doc.id,
103             'text_url': reverse('doctext_view', args=[doc.id]),
104             'dc_url': reverse('docdc_view', docid=doc.id),
105             'public_revision': doc.revision,
106         }
107
108         return result
109
110 #
111 # Document Meta Data
112 #
113 class DocumentHandler(BaseHandler):
114     allowed_methods = ('GET', 'PUT')
115     anonymous = BasicDocumentHandler
116
117     def read(self, request, docid):
118         """Read document's meta data"""
119         lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
120         
121         try:
122             doc = lib.document(docid)
123             udoc = doc.take(request.user.username)
124         except RevisionNotFound:
125             return request.EnityNotFound().django_response()
126
127         # is_shared = udoc.ancestorof(doc)
128         # is_uptodate = is_shared or shared.ancestorof(document)
129
130         result = {
131             'name': udoc.id,
132             'text_url': reverse('doctext_view', args=[udoc.id]),
133             'dc_url': reverse('docdc_view', args=[udoc.id]),
134             'parts_url': reverse('docparts_view', args=[udoc.id]),
135             'user_revision': udoc.revision,
136             'public_revision': doc.revision,            
137         }       
138
139         return result
140
141     def update(self, request, docid):
142         """Update information about the document, like display not"""
143         return
144
145 #
146 # Document Text View
147 #
148 class DocumentTextHandler(BaseHandler):
149     allowed_methods = ('GET', 'PUT')
150
151     @validate_form(forms.DocumentEntryRequest)
152     def read(self, request, form, docid):
153         """Read document as raw text"""        
154         lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
155         
156         try:
157             if request.GET['revision'] == 'latest':
158                 document = lib.document(docid)
159             else:
160                 document = lib.document_for_rev(request.GET['revision'])
161             
162             # TODO: some finer-grained access control
163             return document.data('xml')
164         except RevisionNotFound:
165             return response.EntityNotFound().django_response()
166
167     def update(self, request, docid):
168         lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
169         try:
170             data = request.PUT['contents']
171             prev = request.PUT['revision']
172
173             if request.PUT.has_key('message'):
174                 msg = u"$USER$ " + request.PUT['message']
175             else:
176                 msg = u"$AUTO$ XML content update."
177
178             current = lib.document(docid, request.user.username)
179             orig = lib.document_for_rev(prev)
180
181             if current != orig:
182                 return response.EntityConflict().django_response({
183                         "reason": "out-of-date",
184                         "provided_revision": orig.revision,
185                         "latest_revision": current.revision })
186
187             ndoc = doc.quickwrite('xml', data, msg)
188
189             # return the new revision number
190             return {
191                 "document": ndoc.id,
192                 "subview": "xml",
193                 "previous_revision": prev,
194                 "updated_revision": ndoc.revision
195             }
196         
197         except (RevisionNotFound, KeyError):
198             return response.EntityNotFound().django_response()
199
200 #
201 # Dublin Core handlers
202 #
203 # @requires librarian
204 #
205 class DocumentDublinCoreHandler(BaseHandler):
206     allowed_methods = ('GET', 'PUT')
207
208     @validate_form(forms.DocumentEntryRequest)
209     def read(self, request, docid):
210         """Read document as raw text"""
211         lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
212         try:
213             if request.GET['revision'] == 'latest':
214                 document = lib.document(docid)
215             else:
216                 document = lib.document_for_rev(request.GET['revision'])                
217             
218             bookinfo = dcparser.BookInfo.from_string(doc.data('xml'))
219             return bookinfo.serialize()
220         except RevisionNotFound:
221             return response.EntityNotFound().django_response()
222
223     def update(self, request, docid):
224         lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
225         try:
226             bi_json = request.PUT['contents']
227             prev = request.PUT['revision']
228             if request.PUT.has_key('message'):
229                 msg = u"$USER$ " + request.PUT['message']
230             else:
231                 msg = u"$AUTO$ Dublin core update."
232
233             current = lib.document(docid, request.user.username)
234             orig = lib.document_for_rev(prev)
235
236             if current != orig:
237                 return response.EntityConflict().django_response({
238                         "reason": "out-of-date",
239                         "provided": orig.revision,
240                         "latest": current.revision })
241
242             xmldoc = parser.WLDocument.from_string(current.data('xml'))
243             document.book_info = dcparser.BookInfo.from_json(bi_json)
244
245             # zapisz
246             ndoc = current.quickwrite('xml', \
247                 document.serialize().encode('utf-8'),\
248                 message=msg, user=request.user.username)
249
250             return {
251                 "document": ndoc.id,
252                 "subview": "xml",
253                 "previous_revision": prev,
254                 "updated_revision": ndoc.revision
255             }
256         except (RevisionNotFound, KeyError):
257             return response.EntityNotFound().django_response()