Prototype of bcmagic search plugin.
[htsworkflow.git] / htsworkflow / frontend / bcmagic / views.py
1 from django.http import HttpResponse
2 from django.template import RequestContext, Template, Context
3 from django.shortcuts import render_to_response
4 from django.core.exceptions import ObjectDoesNotExist
5
6 from htsworkflow.frontend.bcmagic import models
7 from htsworkflow.frontend.bcmagic.utils import report_error, redirect_to_url
8 from htsworkflow.frontend.bcmagic.plugin import bcm_plugin_processor
9 from htsworkflow.frontend.bcmagic import plugin
10 #from htsworkflow.util.jsonutil import encode_json
11
12 try:
13     import json
14 except ImportError, e:
15     import simplejson as json
16
17 import re
18
19 from htsworkflow.frontend.bcmagic import forms
20
21 def index(request):
22     """
23     Display a barcode magic input box
24     """
25     form = forms.BarcodeMagicForm()
26     
27     return render_to_response('bcmagic/magic.html', {'bcmagic': form},
28                               context_instance=RequestContext(request))
29
30
31 def __plugin_search(text):
32     """
33     Runs registered plugins to search for results
34     """
35     
36     hits = []
37     for label, search_func in plugin._SEARCH_FUNCTIONS.items():
38         result = search_func(text)
39         if result is not None:
40             hits.extend(result)
41             
42     n = len(hits)
43     if n == 0:
44         msg = 'No hits found for: %s' % (text)
45         return report_error(msg)
46     elif n == 1:
47         return redirect_to_url(hits[0][1])
48     else:
49         msg = "%d hits found for (%s); multi-hit not implemented yet." % (n, text)
50         return report_error(msg)
51     
52     
53     #return json.dumps(hits)
54     
55
56 def __magic_process(text):
57     """
58     Based on scanned text, check to see if there is map object to use
59     for a useful redirect.
60     """
61     # Split text on |
62     split_text = text.split('|')
63     
64     # There should always be at least one | in a valid scan.
65     if len(split_text) <= 1:
66         #return report_error('Invalid text: %s' % (text))
67         return __plugin_search(text)
68     
69     # Keyword is the first element in the list
70     keyword = split_text[0]
71     
72     # Attempt to find a KeywordMap based on keyword
73     try:
74         keymap = models.KeywordMap.objects.get(keyword=keyword)
75     except ObjectDoesNotExist, e:
76         return report_error('Keyword (%s) is not defined' % (keyword))
77     
78     # Remove keyword and only scan the content
79     content = '|'.join(split_text[1:])
80     
81     #FIXME: would be faster to cache compiled regex
82     search = re.compile(keymap.regex)
83     
84     mo = search.search(content)
85     
86     # if the search was invalid
87     if not mo:
88         return report_error('(%s) failed to match (%s)' % (keymap.regex, content))
89     
90     t = Template(keymap.url_template)
91     c = Context(mo.groupdict())
92     
93     return redirect_to_url(str(t.render(c)))
94     
95     
96     
97     
98
99 def magic(request):
100     """
101     Let the magic begin
102     """
103     d = {}
104     
105     #Retrieve posted text from processing
106     if 'text' in request.POST:
107         text = request.POST['text']
108     else:
109         text = None
110         
111     #Retrieve bmc_mode for processing
112     if 'bcm_mode' in request.POST:
113         bcm_mode = request.POST['bcm_mode']
114     else:
115         bcm_mode = None
116         
117     ################################
118     # Handle some errors
119     ################################
120     
121     # Did not receive text error
122     if text is None or text.strip() == '':
123         d['mode'] = 'Error'
124         d['status'] = 'Did not recieve text'
125         
126         return HttpResponse(json.dumps(d), 'text/plain')
127     
128     # Did not receive bcm_mode error
129     if bcm_mode is None or bcm_mode.strip() == '':
130         d['mode'] = 'Error'
131         d['status'] = 'Missing bcm_mode information'
132     
133     
134     ################################
135     # Figure out which mode to use
136     ################################
137     keyword = text.split('|')[0]
138     
139     # Handle URL mode by default
140     if keyword == 'url':
141         d['mode'] = 'redirect'
142         d['url'] = text.split('|')[1]
143         
144     # Pass off processing to plugins
145     elif bcm_mode != 'default':
146         d = bcm_plugin_processor(keyword, text, bcm_mode)
147     
148     # Try keyword mapper
149     else:
150         d = __magic_process(text)
151     
152     return HttpResponse(json.dumps(d), 'text/plain')
153
154
155
156 def json_test(request):
157     d = {}
158     
159     if 'text' in request.POST:
160         text = request.POST['text']
161     else:
162         text = None
163     
164     #return HttpResponse(json.dumps(request.POST.items()), 'text/plain')
165     if text is None or text.strip() == '':
166         d['mode'] = 'Error'
167         d['status'] = 'Did not recieve text'
168         return HttpResponse(json.dumps(d), 'text/plain')
169     
170     if text.split('|')[0] == 'url':
171         d['mode'] = 'redirect'
172         d['url'] = text.split('|')[1]
173     else:
174         d['msg'] = 'Recieved text: %s' % (text)
175         d['mode'] = 'clear'
176     
177     return HttpResponse(json.dumps(d), 'text/plain')