Add most of the tools as sioc:has_space in project description
[forgeplucker:forgeplucker.git] / trunk / forgeplucker / output_oslccmv2json.py
1 # -*- coding: utf-8 -*-
2 """
3 Output Handler class for OSLC-CM V2 in JSON
4
5 Contributed in the frame of the COCLICO project.
6
7 (C) 2010 Olivier Berger - Institut Telecom
8
9 References :
10  - Example JSON OSLC-CM query results : http://open-services.net/bin/view/Main/CmSpecificationV2Samples?sortcol=table;table=up#Query_results_as_application_jso
11  - "Open Services for Lifecycle Collaboration Change Management Specification Version 2.0" specification : http://open-services.net/bin/view/Main/CmSpecificationV2
12  - OSLC Core Specification - JSON Representation Examples : http://open-services.net/bin/view/Main/OSLCCoreSpecJSONExamples
13 """
14
15 import json
16
17 oslc_prefixes = { 'rdf' : 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
18                       'dcterms' : 'http://purl.org/dc/terms/',
19                       'oslc': 'http://open-services.net/ns/core#',
20                       'oslc_cm' : 'http://open-services.net/ns/cm#',
21                       'forgeplucker' : 'http://planetforge.org/ns/forgeplucker_dump/',
22                       'doap' : 'http://usefulinc.com/ns/doap#',
23                       'sioc' : 'http://rdfs.org/sioc/ns#',
24                       'foaf' : 'http://xmlns.com/foaf/0.1/',
25                       'planetforge' : 'http://coclico-project.org/ontology/planetforge#'}
26
27 def output_oslccmv2json_trackers(data):
28
29     oslc_trackers = []
30
31     if not ('trackers' in data) :
32         return oslc_trackers
33
34     data = data['trackers']
35
36     # Treat all trackers
37     trackers = data['trackers']
38
39     for tracker in trackers:
40         tracker = trackers[tracker]
41
42         tracker_name = tracker['label']
43     
44         oslc_tracker = {'rdf:about' : tracker['url']}
45         
46         oslc_artifacts = []
47         
48         # Treat all artifacts of a tracker
49         artifacts =  tracker['artifacts']
50         for artifact in artifacts :
51             
52             oslc_changerequest = {'rdf:type': 'http://open-services.net/ns/cm#ChangeRequest'}
53
54             url = None
55             if 'URL' in artifact:
56                 url = artifact['URL']
57             if not url:
58                 url = tracker['url'] + '/%d' % artifact['id']
59                 
60             oslc_changerequest['rdf:about'] = url
61             
62             # check that artifact['class'] == 'ARTIFACT'
63             
64             # TODO : this should be dependent on forges probably
65             # Mapping for plucked attributes :
66             #  can be a litteral if no conversion is necessary
67             #  or a lambda returning a dictionnary with new 'predicate' name and new converted 'object' value 
68             oslc_mapping = {
69                             #'comments': 'oslc:discussion' TODO
70                             
71                             # TODO : convert to real FOAF profile or lile
72                             'assigned_to': lambda x: {'predicate': 'dcterms:contributor', 'object': x},
73                             # TODO : convert to real FOAF profile or lile
74                             'submitter': lambda x: {'predicate': 'dcterms:creator', 'object': x},
75                             
76                             #'Severity': None
77                             #'Version': None
78                             'id': 'dcterms:identifier',
79                             #'attachments': []
80                             #'Product': Software A
81                             #'Operating System': Windows XP
82                             #'Component': None
83                             #'priority': 5 - Highest
84                             'type': 'dcterms:type',
85                             'description': 'dcterms:description',
86                             'status': 'oslc_cm:status', 
87                             #'URL': 
88                             'date': 'dcterms:created',
89                             #'Resolution': None
90                             'summary': 'dcterms:title',
91                             #'Hardware': All
92                             
93                             #'history': []
94                             }
95
96             # Treat all fields of an artifact
97             for x in artifact :
98                 #try:
99                     #print x, artifact[x]
100                     if x in oslc_mapping:
101                         mapping = oslc_mapping[x]
102                         mapping_type = type(mapping).__name__
103                         if mapping_type == 'function' :
104                             transformed = mapping(artifact[x])
105                             predicate = transformed['predicate']
106                             object = transformed['object']
107                             oslc_changerequest[predicate] = object
108                         elif mapping_type == 'str' :
109                             oslc_changerequest[mapping] = artifact[x]
110                         else :
111                             print >>sys.stderr, 'Incorrect mapping in oslc_mapping'
112                             raise SystemExit, 1
113                     else :
114                         predicate = 'forgeplucker:' + x
115                         oslc_changerequest[predicate] = artifact[x]
116                         
117                 #except TypeError:
118                 #    print x,
119                 #print
120                 
121                 # treat submitter's target resource
122                 
123                 # treat assigned_to target resource
124                 
125                 # treat comments target resource
126                 
127             oslc_artifacts.append(oslc_changerequest)
128
129         oslc_tracker['oslc:results'] = oslc_artifacts
130
131         oslc_tracker['rdf:type'] = oslc_prefixes['planetforge']+'Tracker'
132         oslc_tracker['sioc:name'] = tracker_name
133         
134         oslc_trackers.append(oslc_tracker)
135
136     return oslc_trackers    
137
138 def output_oslccmv2json(data):
139     oslc_data = {}
140
141     project = data['project']
142     
143     #the_class = project['class']
144     # TODO check that the_class == 'PROJECT'
145     #format_version = project['format_version']
146     # TODO check that format_version == 1
147     
148     host = project['host']
149     project_name = project['project']
150     project_dump_url = 'http://' + host + '/forgeplucker_dump/oslccmv2json/' + project_name + '/' 
151     
152     # Initialize top-level OSLC JSON dump
153     
154     oslc_data['prefixes'] = oslc_prefixes
155     oslc_data['rdf:about'] = project_dump_url
156     oslc_data['rdf:type'] = 'http://planetforge.org/ns/forgeplucker_dump/project_dump#'
157     
158     oslc_project = {}
159     oslc_project['rdf:about'] = project['URL']
160     oslc_project['rdf:type'] = oslc_prefixes['planetforge']+'ForgeProject'
161     oslc_project['doap:name'] = project_name
162     oslc_project['dcterms:description'] = project['description']
163     oslc_project['dcterms:created'] = project['registered']
164     oslc_project['doap:homepage'] = project['homepage']
165
166
167     oslc_persons = []
168     oslc_admin_users = []
169     oslc_regular_users = []
170 #    print data['users']
171     for user in data['users']:
172         oslc_user = {}
173         oslc_person = {}
174
175         user_data=data['users'][user]
176         oslc_user['rdf:about'] = user_data['URL']
177         oslc_user['rdf:type'] = [oslc_prefixes['sioc']+'User', oslc_prefixes['foaf']+'OnlineAccount']
178         oslc_user['foaf:accountName'] = user
179         oslc_user['sioc:email'] = user_data['mail']
180         
181         oslc_person['rdf:about'] = user_data['URL'] + '#me'
182         oslc_person['rdf:type'] = oslc_prefixes['foaf']+'Person'
183         oslc_person['foaf:name'] = user_data['real_name']
184         oslc_person['foaf:holdsAccount'] = user_data['URL']
185
186         if user_data['role'] == 'Admin' :
187             oslc_admin_users.append(oslc_user)
188         else:
189             oslc_regular_users.append(oslc_user)
190         oslc_persons.append(oslc_person)
191
192     oslc_project['sioc:scope_of'] = []
193     oslc_data['forgeplucker:users'] = []
194     if oslc_admin_users:
195         scope_of_admin = {}
196         scope_of_admin['rdf:type'] = oslc_prefixes['sioc']+'Role'
197         scope_of_admin['sioc:name'] = "project_admins"
198         scope_of_admin['sioc:function_of'] = []
199         for u in oslc_admin_users:
200             scope_of_admin['sioc:function_of'].append(u['rdf:about'])
201             oslc_data['forgeplucker:users'].append(u)
202         oslc_project['sioc:scope_of'].append(scope_of_admin)
203     if oslc_regular_users:
204         scope_of_regular = {}
205         scope_of_regular['rdf:type'] = oslc_prefixes['sioc']+'Role'
206         scope_of_regular['sioc:name'] = "project_developers"
207         scope_of_regular['sioc:function_of'] = []
208         for u in oslc_regular_users:
209             scope_of_regular['sioc:function_of'].append(u['rdf:about'])
210             oslc_data['forgeplucker:users'].append(u)
211         oslc_project['sioc:scope_of'].append(scope_of_regular)
212
213     oslc_data['forgeplucker:persons'] = oslc_persons
214     
215     oslc_trackers = output_oslccmv2json_trackers(data)
216
217     project_trackers=[]
218     if oslc_trackers:
219         oslc_data['forgeplucker:trackers'] = output_oslccmv2json_trackers(data)
220         for tracker in oslc_trackers:
221             project_trackers.append(tracker['rdf:about'])
222         oslc_project['sioc:has_space'] = project_trackers
223     else :
224         if 'trackers_list' in project:
225             if not 'sioc:has_space' in oslc_project:
226                 oslc_project['sioc:has_space'] = []
227             for t in project['trackers_list']:
228                 oslc_project['sioc:has_space'].append(t)
229         
230     if 'public_forums' in project:
231         if not 'sioc:has_space' in oslc_project:
232             oslc_project['sioc:has_space'] = []
233         for f in project['public_forums']:
234             oslc_project['sioc:has_space'].append(f)
235     if 'docman' in project:
236         if not 'sioc:has_space' in oslc_project:
237             oslc_project['sioc:has_space'] = []
238         oslc_project['sioc:has_space'].append(project['docman'])
239     if 'mailing_lists' in project:
240         if not 'sioc:has_space' in oslc_project:
241             oslc_project['sioc:has_space'] = []
242         for l in project['mailing_lists']:
243             oslc_project['sioc:has_space'].append(l)
244     if 'task_trackers' in project:
245         if not 'sioc:has_space' in oslc_project:
246             oslc_project['sioc:has_space'] = []
247         for l in project['task_trackers']:
248             oslc_project['sioc:has_space'].append(l)
249     if 'scm_type' in project:
250         if not 'sioc:has_space' in oslc_project:
251             oslc_project['sioc:has_space'] = []
252         oslc_project['sioc:has_space'].append(project['scm'])
253     if 'news' in project:
254         if not 'sioc:has_space' in oslc_project:
255             oslc_project['sioc:has_space'] = []
256         oslc_project['sioc:has_space'].append(project['news'])
257     if 'frs' in project:
258         if not 'sioc:has_space' in oslc_project:
259             oslc_project['sioc:has_space'] = []
260         oslc_project['sioc:has_space'].append(project['frs'])
261
262     oslc_data['forgeplucker:project'] = oslc_project
263
264     # pretty-print 
265     print json.dumps(oslc_data, sort_keys=True, indent=4)