Subversion Repositories basico

Rev

Rev 380 | Rev 384 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
340 t00mlabs 1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3
"""
4
# File: srv_annot.py
5
# Author: Tomás Vírseda
6
# License: GPL v3
7
# Description: Annotations service
8
"""
9
 
10
import os
11
import json
12
import uuid
367 t00mlabs 13
from html import escape
340 t00mlabs 14
import glob
15
from os.path import sep as SEP
16
 
17
from basico.core.mod_env import FILE, LPATH
18
from basico.core.mod_srv import Service
19
 
20
 
21
class Annotation(Service):
22
    def initialize(self):
23
        '''
24
        Setup Annotation Service
25
        '''
26
        self.get_services()
351 t00mlabs 27
        self.__fix_annotations()
340 t00mlabs 28
 
29
 
30
    def get_services(self):
31
        self.srvutl = self.get_service('Utils')
32
 
33
 
351 t00mlabs 34
    def __fix_annotations(self):
35
        """
36
        In Basico 0.4, new field 'created' is introduced.
37
        For annotations created before, created timestamp = updated timestamp.
38
        """
39
 
40
        for filename in self.get_all():
41
            metadata = self.get_metadata_from_file(filename)
42
            try:
43
                ts = metadata['Created']
44
            except Exception as error:
45
                # Fix annotation metadata: add 'Created' field
46
                metadata['Created'] = metadata['Timestamp']
47
                with open(filename, 'w') as fa:
48
                    json.dump(metadata, fa)
49
                    self.log.debug("Fixed annotation with AID: %s", metadata['AID'])
50
 
380 t00mlabs 51
 
52
    def gen_aid(self, sid='0000000000'):
340 t00mlabs 53
        '''
54
        Generate new annotation id
55
        '''
56
        return "%s@%s" % (sid, str(uuid.uuid4()))
57
 
58
 
59
    def create(self, annotation):
380 t00mlabs 60
        ANNOTATION_FILE_METADATA = LPATH['ANNOTATIONS'] + annotation['AID'] + '.json'
340 t00mlabs 61
        ANNOTATION_FILE_CONTENT = LPATH['ANNOTATIONS'] + annotation['AID'] + '.adoc'
62
        annotation['Timestamp'] = self.srvutl.timestamp()
354 t00mlabs 63
        annotation['Created'] = self.srvutl.timestamp()
340 t00mlabs 64
 
65
        # Write annotation content first and delete it
66
        with open(ANNOTATION_FILE_CONTENT, 'w') as fc:
67
            fc.write(annotation['Content'])
68
        del annotation['Content']
69
 
70
        # Write annotation metadata
71
        with open(ANNOTATION_FILE_METADATA, 'w') as fa:
72
            json.dump(annotation, fa)
73
 
74
        title = self.get_title(annotation['AID'])
75
        self.log.info("Annotation '%s' (%s) created" % (title, annotation['AID']))
76
 
77
 
360 t00mlabs 78
    def update_metadata(self, metadata):
79
        # Update annotation metadata
80
        ANNOTATION_FILE_METADATA = LPATH['ANNOTATIONS'] + metadata['AID'] + '.json'
81
        annotation = self.get_metadata_from_file(ANNOTATION_FILE_METADATA)
82
        for key in metadata:
83
            annotation[key] = metadata[key]
84
        annotation['Timestamp'] = self.srvutl.timestamp()
380 t00mlabs 85
 
360 t00mlabs 86
        # Write annotation metadata
87
        with open(ANNOTATION_FILE_METADATA, 'w') as fa:
88
            json.dump(annotation, fa)
89
 
90
        title = self.get_title(annotation['AID'])
91
        self.log.info("Annotation '%s' (%s) updated" % (title, annotation['AID']))
92
 
93
 
94
    def update_timestamp(self, aid):
95
        # Update annotation timestamp
96
        ANNOTATION_FILE_METADATA = LPATH['ANNOTATIONS'] + aid + '.json'
97
        annotation = self.get_metadata_from_file(ANNOTATION_FILE_METADATA)
98
        annotation['Timestamp'] = self.srvutl.timestamp()
380 t00mlabs 99
 
360 t00mlabs 100
        # Write annotation metadata
101
        with open(ANNOTATION_FILE_METADATA, 'w') as fa:
102
            json.dump(annotation, fa)
103
 
104
        title = self.get_title(annotation['AID'])
105
        self.log.info("Annotation '%s' (%s) updated" % (title, annotation['AID']))
380 t00mlabs 106
 
107
 
340 t00mlabs 108
    def update(self, annotation):
380 t00mlabs 109
        ANNOTATION_FILE_METADATA = LPATH['ANNOTATIONS'] + annotation['AID'] + '.json'
340 t00mlabs 110
        ANNOTATION_FILE_CONTENT = LPATH['ANNOTATIONS'] + annotation['AID'] + '.adoc'
111
 
112
        annotation['Timestamp'] = self.srvutl.timestamp()
113
        # Write updated annotation first and delete the old one after
114
        with open(ANNOTATION_FILE_CONTENT, 'w') as fc:
115
            fc.write(annotation['Content'])
116
        del annotation['Content']
117
 
118
        # Write annotation metadata
119
        with open(ANNOTATION_FILE_METADATA, 'w') as fa:
120
            json.dump(annotation, fa)
121
 
122
        title = self.get_title(annotation['AID'])
123
        self.log.info("Annotation '%s' (%s) updated" % (title, annotation['AID']))
124
 
125
 
126
    def delete(self, aid):
127
        sid = self.get_sid(aid)
128
        ANNOTATION_FILE_METADATA = LPATH['ANNOTATIONS'] + aid + '.json'
129
        ANNOTATION_FILE_CONTENT = LPATH['ANNOTATIONS'] + aid + '.adoc'
130
        title = self.get_title(aid)
131
 
132
        if os.path.exists(ANNOTATION_FILE_METADATA):
133
            os.unlink(ANNOTATION_FILE_METADATA)
134
 
135
        if os.path.exists(ANNOTATION_FILE_CONTENT):
136
            os.unlink(ANNOTATION_FILE_CONTENT)
137
 
138
        self.log.info("Annotation '%s' (%s) deleted" % (title, aid))
139
 
140
 
141
    def get_by_sid(self, sid):
142
        ANNOTATION_FILES = LPATH['ANNOTATIONS'] + '%s*.json' % sid
143
        annotations = glob.glob(ANNOTATION_FILES)
144
        annotations.sort(reverse=True)
145
 
146
        return annotations
147
 
148
 
149
    def get_all(self):
150
        return glob.glob(LPATH['ANNOTATIONS'] + '*.json')
151
 
152
 
153
    def get_total(self):
154
        return len(self.get_all())
155
 
156
 
157
    def get_sid(self, aid):
158
        if '@' in aid:
159
            return aid[:aid.find('@')]
160
        else:
161
            return aid # aid = sid
162
 
163
 
351 t00mlabs 164
    def get_metadata_from_aid(self, aid=None):
340 t00mlabs 165
        if aid is not None:
166
            ANNOTATION_FILE_METADATA = LPATH['ANNOTATIONS'] + aid + '.json'
167
            with open(ANNOTATION_FILE_METADATA, 'r') as fa:
168
                annotation = json.load(fa)
169
            return annotation
170
        else:
171
            return None
172
 
173
 
351 t00mlabs 174
    def get_metadata_from_file(self, filename=None):
175
        if filename is not None:
176
            with open(filename, 'r') as fa:
177
                annotation = json.load(fa)
178
            return annotation
179
        else:
180
            return None
181
 
182
 
370 t00mlabs 183
    def get_metadata_value(self, aid, key):
184
        metadata = self.get_metadata_from_aid(aid)
185
        return metadata[key]
186
 
380 t00mlabs 187
 
340 t00mlabs 188
    def is_valid(self, aid):
189
        ANNOTATION_FILE = LPATH['ANNOTATIONS'] + aid + '.json'
190
        valid = os.path.exists(ANNOTATION_FILE)
191
        if valid is False:
192
            self.log.debug("Annotation %s is not valid or it doesn't exist yet." % aid)
193
 
194
        return valid
195
 
196
    def get_title(self, aid):
197
        ANNOTATION_FILE = LPATH['ANNOTATIONS'] + aid + '.json'
383 t00mlabs 198
        try:
199
            with open(ANNOTATION_FILE, 'r') as fa:
200
                metadata = json.load(fa)
201
                return escape(metadata['Title'])
202
        except:
203
            return None
340 t00mlabs 204
 
365 t00mlabs 205
    def get_content_file(self, aid):
206
        return LPATH['ANNOTATIONS'] + aid + '.adoc'
207
 
208
 
340 t00mlabs 209
    def search_term(self, term):
210
        matches = set()
211
        annotations = self.get_all()
212
 
213
        for fname in annotations:
214
            # search only in title
215
            with open(fname, 'r') as fa:
216
                try:
217
                    annotation = json.load(fa)
218
                    text = annotation['Title']
219
                    if term.upper() in text.upper():
220
                        # ~ self.log.debug("Found '%s' in '%s'", term, text)
221
                        matches.add(fname)
222
                except Exception as error:
223
                    self.log.error("%s: %s", fname, error)
224
 
225
            # SEARCH IN ALL PROPERTIES (DISABLED)
226
            # ~ with open(fname, 'r') as fa:
227
                # ~ try:
228
                    # ~ annotation = json.load(fa)
229
                    # ~ text = ''
230
                    # ~ for node in annotation:
231
                        # ~ text += annotation[node]
232
                    # ~ if term.upper() in text.upper():
233
                        # ~ self.log.debug("Found '%s' in '%s'", term, text)
234
                        # ~ matches.add(fname)
235
                # ~ except Exception as error:
236
                    # ~ self.log.error("%s: %s", fname, error)
237
 
238
            # SEARCH IN CONTENT (DISABLED)
239
            # ~ fcontent = fname.replace('.json', '.adoc')
240
            # ~ text = open(fcontent, 'r').read()
241
            # ~ if term.upper() in text.upper():
242
                # ~ matches.add(fname)
243
 
244
        return matches
245
 
246
 
247
    def finalize(self):
248
        pass
249