init()   B
last analyzed

Complexity

Conditions 1

Size

Total Lines 138
Code Lines 89

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 138
rs 7.36
eloc 89

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
/**
2
 * 
3
 */
4
package unicon.matthews.xapi.service;
5
6
import java.net.URI;
7
import java.net.URISyntaxException;
8
import java.time.Instant;
9
import java.time.LocalDateTime;
10
import java.time.ZoneId;
11
import java.time.ZoneOffset;
12
import java.time.ZonedDateTime;
13
import java.util.Collections;
14
import java.util.HashMap;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.UUID;
18
19
import javax.annotation.PostConstruct;
20
21
import org.apache.commons.collections4.BidiMap;
22
import org.apache.commons.collections4.CollectionUtils;
23
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
24
import org.apache.commons.lang3.StringUtils;
25
import org.imsglobal.caliper.actions.Action;
26
import org.imsglobal.caliper.context.Context;
27
import org.imsglobal.caliper.entities.DigitalResourceType;
28
import org.imsglobal.caliper.entities.EntityType;
29
import org.imsglobal.caliper.entities.Type;
30
import org.imsglobal.caliper.events.EventType;
31
import org.springframework.stereotype.Component;
32
33
import unicon.matthews.caliper.Agent;
34
import unicon.matthews.caliper.Entity;
35
import unicon.matthews.caliper.Event;
36
import unicon.matthews.caliper.Group;
37
import unicon.matthews.caliper.SubOrganizationOf;
38
import unicon.matthews.xapi.Statement;
39
import unicon.matthews.xapi.XApiAccount;
40
import unicon.matthews.xapi.XApiActor;
41
import unicon.matthews.xapi.XApiContext;
42
import unicon.matthews.xapi.XApiContextActivities;
43
import unicon.matthews.xapi.XApiObject;
44
import unicon.matthews.xapi.XApiObjectDefinition;
45
import unicon.matthews.xapi.XApiResult;
46
import unicon.matthews.xapi.XApiScore;
47
import unicon.matthews.xapi.XApiVerb;
48
49
/**
50
 * @author ggilbert
51
 *
52
 */
53
@Component
54
public class DefaultXapiToCaliperConversionService implements XapiConversionService {
55
  
56
  private BidiMap<Action, String> verbActionMap;
57
  private BidiMap<Type, String> objectEntityMap;
58
  private Map<Action, EventType> actionEventMap;
59
  
60
  @PostConstruct
61
  private void init() {
62
    verbActionMap = new DualHashBidiMap<Action, String>();
63
    verbActionMap.put(Action.ABANDONED, "https://w3id.org/xapi/adl/verbs/abandoned");
64
    //verbActionMap.put(Action.ACTIVATED, );
65
    verbActionMap.put(Action.ATTACHED, "http://activitystrea.ms/schema/1.0/attach");    
66
    verbActionMap.put(Action.BOOKMARKED, "http://id.tincanapi.com/verb/bookmarked");
67
    //verbActionMap.put(Action.CHANGED_RESOLUTION, );
68
    //verbActionMap.put(Action.CHANGED_SIZE, );
69
    //verbActionMap.put(Action.CHANGED_VOLUME, );
70
    //verbActionMap.put(Action.CLASSIFIED, );
71
    //verbActionMap.put(Action.CLOSED_POPOUT, );
72
    verbActionMap.put(Action.COMMENTED, "http://adlnet.gov/expapi/verbs/commented");
73
    verbActionMap.put(Action.COMPLETED, "http://adlnet.gov/expapi/verbs/completed");
74
    //verbActionMap.put(Action.DEACTIVATED, );
75
    //verbActionMap.put(Action.DESCRIBED, );
76
    verbActionMap.put(Action.DISLIKED, "http://activitystrea.ms/schema/1.0/dislike");
77
    //verbActionMap.put(Action.DISABLED_CLOSED_CAPTIONING, );
78
    //verbActionMap.put(Action.ENABLED_CLOSED_CAPTIONING, );
79
    //verbActionMap.put(Action.ENDED, );
80
    //verbActionMap.put(Action.ENTERED_FULLSCREEN, );
81
    //verbActionMap.put(Action.EXITED_FULLSCREEN, );
82
    //verbActionMap.put(Action.FORWARDED_TO, );
83
    verbActionMap.put(Action.GRADED, "http://adlnet.gov/expapi/verbs/scored");
84
    //verbActionMap.put(Action.HID, );
85
    //verbActionMap.put(Action.HIGHLIGHTED, );
86
    //verbActionMap.put(Action.JUMPED_TO, );
87
    //verbActionMap.put(Action.IDENTIFIED, );
88
    verbActionMap.put(Action.LIKED, "http://activitystrea.ms/schema/1.0/like");
89
    //verbActionMap.put(Action.LINKED, );
90
    
91
    // alternatives
92
    // https://w3id.org/xapi/adl/verbs/logged-in
93
    // https://w3id.org/xapi/adl/verbs/logged-out
94
    
95
    verbActionMap.put(Action.LOGGED_IN, "https://brindlewaye.com/xAPITerms/verbs/loggedin/");
96
    verbActionMap.put(Action.LOGGED_OUT, "https://brindlewaye.com/xAPITerms/verbs/loggedout/");
97
    
98
    //verbActionMap.put(Action.MUTED, );
99
    //verbActionMap.put(Action.NAVIGATED_TO, );
100
    //verbActionMap.put(Action.OPENED_POPOUT, );
101
    verbActionMap.put(Action.PAUSED, "http://id.tincanapi.com/verb/paused");
102
    //verbActionMap.put(Action.RANKED, );
103
    verbActionMap.put(Action.QUESTIONED, "http://adlnet.gov/expapi/verbs/asked");
104
    //verbActionMap.put(Action.RECOMMENDED, );
105
    verbActionMap.put(Action.REPLIED, "http://adlnet.gov/expapi/verbs/responded");
106
    //verbActionMap.put(Action.RESTARTED, );
107
    verbActionMap.put(Action.RESUMED, "http://adlnet.gov/expapi/verbs/resumed");
108
    verbActionMap.put(Action.REVIEWED, "http://id.tincanapi.com/verb/reviewed");
109
    //verbActionMap.put(Action.REWOUND, );
110
    verbActionMap.put(Action.SEARCHED, "http://activitystrea.ms/schema/1.0/search");
111
    verbActionMap.put(Action.SHARED, "http://activitystrea.ms/schema/1.0/share");
112
    //verbActionMap.put(Action.SHOWED, );
113
    verbActionMap.put(Action.SKIPPED, "http://id.tincanapi.com/verb/skipped");
114
    verbActionMap.put(Action.STARTED, "http://activitystrea.ms/schema/1.0/start");
115
    verbActionMap.put(Action.SUBMITTED, "http://activitystrea.ms/schema/1.0/submit");
116
    //verbActionMap.put(Action.SUBSCRIBED, );
117
    verbActionMap.put(Action.TAGGED, "http://activitystrea.ms/schema/1.0/tag");
118
    //verbActionMap.put(Action.TIMED_OUT, );
119
    verbActionMap.put(Action.VIEWED, "http://id.tincanapi.com/verb/viewed");
120
    //verbActionMap.put(Action.UNMUTED, );
121
    
122
    objectEntityMap = new DualHashBidiMap<Type, String>();
123
    // TODO support other xapi annotation types
124
    objectEntityMap.put(EntityType.ANNOTATION, "http://risc-inc.com/annotator/activities/highlight");
125
    //objectEntityMap.put(EntityType.ATTEMPT, arg1);
126
    //objectEntityMap.put(EntityType.COURSE_OFFERING, arg1);
127
    objectEntityMap.put(EntityType.COURSE_SECTION, "http://adlnet.gov/expapi/activities/course");
128
    objectEntityMap.put(EntityType.DIGITAL_RESOURCE, "http://adlnet.gov/expapi/activities/media");
129
    //objectEntityMap.put(EntityType.ENTITY, );
130
    objectEntityMap.put(EntityType.GROUP, "http://activitystrea.ms/schema/1.0/group");
131
    objectEntityMap.put(EntityType.LEARNING_OBJECTIVE, "http://adlnet.gov/expapi/activities/objective");
132
    //objectEntityMap.put(EntityType.MEMBERSHIP, arg1);
133
    objectEntityMap.put(EntityType.PERSON, "http://activitystrea.ms/schema/1.0/person");
134
    objectEntityMap.put(EntityType.ORGANIZATION, "http://activitystrea.ms/schema/1.0/organization");
135
    //objectEntityMap.put(EntityType.RESPONSE, arg1);
136
    //objectEntityMap.put(EntityType.RESULT, arg1);
137
    //objectEntityMap.put(EntityType.SESSION, arg1);
138
    objectEntityMap.put(EntityType.SOFTWARE_APPLICATION, "http://activitystrea.ms/schema/1.0/application");
139
    //objectEntityMap.put(EntityType.VIEW, arg1);
140
    //objectEntityMap.put(DigitalResourceType.MEDIA_LOCATION, arg1);
141
    objectEntityMap.put(DigitalResourceType.MEDIA_OBJECT, "http://adlnet.gov/expapi/activities/media");
142
    //objectEntityMap.put(DigitalResourceType.READING, arg1);
143
    objectEntityMap.put(DigitalResourceType.WEB_PAGE, "http://activitystrea.ms/schema/1.0/page");
144
    
145
    actionEventMap = new HashMap<Action,EventType>();
0 ignored issues
show
Performance introduced by
When using a map whose keys are EnumValues, consider using an EnumMap instead, which is more performant in this case.

The Java documentation explain EnumMap.

Loading history...
146
    actionEventMap.put(Action.ABANDONED, EventType.ASSIGNABLE);
147
    actionEventMap.put(Action.ACTIVATED, EventType.ASSIGNABLE);
148
    actionEventMap.put(Action.ATTACHED, EventType.ANNOTATION);    
149
    actionEventMap.put(Action.BOOKMARKED, EventType.ANNOTATION);
150
    actionEventMap.put(Action.CHANGED_RESOLUTION, EventType.MEDIA);
151
    actionEventMap.put(Action.CHANGED_SIZE, EventType.MEDIA);
152
    actionEventMap.put(Action.CHANGED_VOLUME, EventType.MEDIA);
153
    actionEventMap.put(Action.CLASSIFIED, EventType.ANNOTATION);
154
    actionEventMap.put(Action.CLOSED_POPOUT, EventType.MEDIA);
155
    actionEventMap.put(Action.COMMENTED, EventType.ANNOTATION);
156
    actionEventMap.put(Action.COMPLETED, EventType.ASSIGNABLE);
157
    actionEventMap.put(Action.DEACTIVATED, EventType.ASSIGNABLE);
158
    actionEventMap.put(Action.DESCRIBED, EventType.ANNOTATION);
159
    actionEventMap.put(Action.DISLIKED, EventType.ANNOTATION);
160
    actionEventMap.put(Action.DISABLED_CLOSED_CAPTIONING, EventType.MEDIA);
161
    actionEventMap.put(Action.ENABLED_CLOSED_CAPTIONING, EventType.MEDIA);
162
    actionEventMap.put(Action.ENDED, EventType.MEDIA);
163
    actionEventMap.put(Action.ENTERED_FULLSCREEN, EventType.MEDIA);
164
    actionEventMap.put(Action.EXITED_FULLSCREEN, EventType.MEDIA);
165
    actionEventMap.put(Action.FORWARDED_TO, EventType.MEDIA);
166
    actionEventMap.put(Action.GRADED, EventType.OUTCOME);
167
    actionEventMap.put(Action.HID, EventType.ASSIGNABLE);
168
    actionEventMap.put(Action.HIGHLIGHTED, EventType.ANNOTATION);
169
    actionEventMap.put(Action.JUMPED_TO, EventType.MEDIA);
170
    actionEventMap.put(Action.IDENTIFIED, EventType.ANNOTATION);
171
    actionEventMap.put(Action.LIKED, EventType.ANNOTATION);
172
    actionEventMap.put(Action.LINKED, EventType.ANNOTATION);
173
    actionEventMap.put(Action.LOGGED_IN, EventType.SESSION);
174
    actionEventMap.put(Action.LOGGED_OUT, EventType.SESSION);   
175
    actionEventMap.put(Action.MUTED, EventType.MEDIA);
176
    actionEventMap.put(Action.NAVIGATED_TO, EventType.NAVIGATION);
177
    actionEventMap.put(Action.OPENED_POPOUT, EventType.MEDIA);
178
    actionEventMap.put(Action.PAUSED, EventType.MEDIA);
179
    actionEventMap.put(Action.RANKED, EventType.ANNOTATION);
180
    actionEventMap.put(Action.QUESTIONED, EventType.ANNOTATION);
181
    actionEventMap.put(Action.RECOMMENDED, EventType.ANNOTATION);
182
    actionEventMap.put(Action.REPLIED, EventType.ANNOTATION);
183
    actionEventMap.put(Action.RESTARTED, EventType.ASSESSMENT);
184
    actionEventMap.put(Action.RESUMED, EventType.MEDIA);
185
    actionEventMap.put(Action.REVIEWED, EventType.ASSIGNABLE);
186
    actionEventMap.put(Action.REWOUND, EventType.MEDIA);
187
    actionEventMap.put(Action.SEARCHED, EventType.READING);
188
    actionEventMap.put(Action.SHARED, EventType.ANNOTATION);
189
    actionEventMap.put(Action.SHOWED, EventType.ASSIGNABLE);
190
    actionEventMap.put(Action.SKIPPED, EventType.ASSESSMENT_ITEM);
191
    actionEventMap.put(Action.STARTED, EventType.EVENT);
192
    actionEventMap.put(Action.SUBMITTED, EventType.EVENT);
193
    actionEventMap.put(Action.SUBSCRIBED, EventType.ANNOTATION);
194
    actionEventMap.put(Action.TAGGED, EventType.ANNOTATION);
195
    actionEventMap.put(Action.TIMED_OUT, EventType.SESSION);
196
    actionEventMap.put(Action.VIEWED, EventType.EVENT);
197
    actionEventMap.put(Action.UNMUTED, EventType.MEDIA);
198
199
  }
200
201
  public Event fromXapi(Statement statement) {
202
    // EVENT TIME
203
    LocalDateTime eventTime = null;    
204
    String timestamp = statement.getTimestamp(); 
205
    if (StringUtils.isNotBlank(timestamp)) {
206
      if (timestamp.endsWith("Z")) {
207
        Instant instant = Instant.parse(timestamp);
208
        eventTime = LocalDateTime.ofInstant(instant, ZoneId.of(ZoneOffset.UTC.getId()));
209
      }
210
      else {
211
        ZonedDateTime zdt = ZonedDateTime.parse(timestamp);
212
        ZonedDateTime utc_zone = zdt.toLocalDateTime().atZone(ZoneOffset.UTC);
213
        eventTime = utc_zone.toLocalDateTime();
214
      }
215
      
216
    }
217
    else {
218
      eventTime = LocalDateTime.now(ZoneId.of(ZoneOffset.UTC.getId()));
219
    }
220
    // EVENT TIME END
221
    
222
    // ACTOR
223
    Agent caliperActor = null;
224
    String actorId = null;
225
    XApiActor xapiActor = statement.getActor();
226
    if (xapiActor != null) {
227
      
228
      String actorType = null; 
229
      Map<String, String> actorExtensions = new HashMap<>();
230
      String actorName = xapiActor.getName();
231
      
232
      String openId = xapiActor.getOpenid();
233
      String mbox = xapiActor.getMbox();
234
      XApiAccount xapiAccount = xapiActor.getAccount();
235
      
236
      if (StringUtils.isNotBlank(openId)) {
237
        actorId = openId;
238
        actorType = ACTOR_TYPE_OPENID;
239
      }
240
      else if (StringUtils.isNotBlank(mbox)) {
241
        actorId = mbox;
242
        actorType = ACTOR_TYPE_MBOX;
243
      }
244
      else if (xapiAccount != null) {
245
        String accountName = xapiAccount.getName();
246
        String homePage = xapiAccount.getHomePage();
247
        
248
        if (StringUtils.isNotBlank(homePage)) {
249
          
250
          if (StringUtils.isNotBlank(accountName)) {
251
            actorId = accountName;
252
            actorExtensions.put("HOMEPAGE", homePage);
253
          }
254
          else {
255
            actorId = homePage;
256
          }
257
        }
258
        else if (StringUtils.isNotBlank(accountName)) {
259
          actorId = accountName;
260
        }
261
        
262
        actorType = ACTOR_TYPE_ACCOUNT;
263
      }
264
      
265
      caliperActor 
266
        = new Agent.Builder()
267
          .withContext(Context.CONTEXT.getValue())
268
          .withName(actorName)
269
          .withId(actorId)
270
          .withType(actorType)
271
          .withExtensions(actorExtensions)
272
          .build();
273
    }
274
    // ACTOR END
275
    
276
    // RESULT
277
    Entity caliperResult = null;
278
    XApiResult xapiResult = statement.getResult();
279
    if (xapiResult != null) {
280
      Map<String,String> resultExtensions = null;
281
      Map<URI,java.lang.Object> xapiResultExtensions = xapiResult.getExtensions();
282
      if (xapiResultExtensions != null && !xapiResultExtensions.isEmpty()) {
283
        resultExtensions = new HashMap<>();
284
        for (Map.Entry<URI,java.lang.Object> entry : xapiResultExtensions.entrySet()) {
285
          resultExtensions.put(entry.getKey().toString(),entry.getValue().toString());
286
        }
287
      }
288
      
289
      Double score = null;
290
      XApiScore xapiScore = xapiResult.getScore();
291
      if (xapiScore != null) {
292
        score = xapiScore.getRaw();
293
      }
294
      
295
      caliperResult 
296
        = new Entity.Builder()
297
          .withId(UUID.randomUUID().toString())
298
          .withContext(Context.CONTEXT.getValue())
299
          .withExtensions(resultExtensions)
300
          .withActor(actorId)
301
          .withType("http://purl.imsglobal.org/caliper/v1/Result")
302
          .withTotalScore(score)
303
          .build();
304
    }
305
    // END Result
306
    
307
    // ACTION
308
    String caliperAction = null;
309
    XApiVerb xapiVerb = statement.getVerb();
310
    if (xapiVerb != null) {
311
      String verbId = xapiVerb.getId();
312
      caliperAction = xApiVerbToCaliperAction(verbId);
313
    }
314
    // ACTION END
315
    
316
    // OBJECT
317
    Entity caliperObject = null;
318
    XApiObject xapiObject = statement.getObject();
319
    if (xapiObject != null) {
320
      
321
      String objectType = xapiObjectTypeToCaliperEntityType(null);
322
      String objectName = null;
323
      String objectDescription = null;
324
      Map<String,String> objectExtensions = null;
325
      String objectId = xapiObject.getId();
326
      
327
      XApiObjectDefinition xapiObjectDefinition = xapiObject.getDefinition();
328
      if (xapiObjectDefinition != null) {
329
        String xapiObjectDefinitionType = xapiObjectDefinition.getType();
330
        if (StringUtils.isNotBlank(xapiObjectDefinitionType)) {
331
          objectType = xapiObjectTypeToCaliperEntityType(xapiObjectDefinitionType);
332
        }
333
        
334
        Map<String,String> names = xapiObjectDefinition.getName();
335
        if (names != null) {
336
          if (names.size() == 1) {
337
            objectName = CollectionUtils.get(names, 0).getValue();
338
          }
339
          else {
340
            // default to en?
341
            objectName = names.get("en");
342
          }
343
        }
344
        
345
        Map<String,String> descriptions = xapiObjectDefinition.getDescription();
346
        if (descriptions != null) {
347
          if (descriptions.size() == 1) {
348
            objectDescription = CollectionUtils.get(descriptions, 0).getValue();
349
          }
350
          else {
351
            // default to en?
352
            objectDescription = descriptions.get("en");
353
          }
354
        }
355
        
356
        Map<URI,java.lang.Object> extensions = xapiObjectDefinition.getExtensions();
357
        if (extensions != null && !extensions.isEmpty()) {
358
          objectExtensions = new HashMap<String,String>(extensions.size());
359
          for (URI key : extensions.keySet()) {
0 ignored issues
show
Performance introduced by
When you need both the keys and the value of a Map, iterating over entrySet() instead of keySet() is more readable.
Loading history...
360
            objectExtensions.put(key.toString(), extensions.get(key).toString());
361
          }
362
        }
363
      }
364
           
365
      caliperObject 
366
        = new Entity.Builder()
367
          .withId(objectId)
368
          .withContext(Context.CONTEXT.getValue())
369
          .withType(objectType)
370
          .withName(objectName)
371
          .withDescription(objectDescription)
372
          .withExtensions(objectExtensions)
373
          .build();
374
    }
375
    // OBJECT END
376
    
377
    Group caliperGroup = null;
378
    XApiContext xapiContext = statement.getContext();
379
    if (xapiContext != null) {
380
      Map<String,String> contextExtensions = null;
381
      Map<URI,java.lang.Object> extensions = xapiContext.getExtensions();
382
      if (extensions != null && !extensions.isEmpty()) {
383
        contextExtensions = new HashMap<String,String>(extensions.size());
384
        for (URI key : extensions.keySet()) {
0 ignored issues
show
Performance introduced by
When you need both the keys and the value of a Map, iterating over entrySet() instead of keySet() is more readable.
Loading history...
385
          contextExtensions.put(key.toString(), extensions.get(key).toString());
386
        }
387
      }
388
389
      XApiContextActivities xapiContextActivities = xapiContext.getContextActivities();
390
      if (xapiContextActivities != null) {       
391
        List<XApiObject> contextActivityParents = xapiContextActivities.getParent();
392
        
393
        if (contextActivityParents != null && contextActivityParents.size() == 1
394
            && contextActivityParents.get(0).getId().contains("portal/site")) {
395
          caliperGroup 
396
            = new Group.Builder()
397
              .withId(StringUtils.substringAfterLast(contextActivityParents.get(0).getId(), "/"))
398
              .withContext(Context.CONTEXT.getValue())
399
              .withType("http://purl.imsglobal.org/caliper/v1/lis/CourseSection")
400
              .build();
401
        }
402
403
        if (caliperGroup == null) {
404
          List<XApiObject> groupings = xapiContextActivities.getGrouping();
405
          if (groupings != null && !groupings.isEmpty()) {
406
            XApiObject grouping = null;
407
            String id = null;
408
            String type = null;
409
410
            if (groupings.size() == 1) {
411
              grouping = groupings.get(0);
412
              
413
              if (extensions != null) {
414
                Object paramMap = null;
415
                try {
416
                  paramMap = extensions.get(new URI("http://lrs.learninglocker.net/define/extensions/moodle_logstore_standard_log"));
0 ignored issues
show
introduced by
Refactor your code to get this URI from a customizable parameter.
Loading history...
417
                } 
418
                catch (URISyntaxException e) {
419
                  // TODO
420
                }
421
                if (paramMap != null && paramMap instanceof Map) {
422
                  Map<String, String> groupExtMap = (Map<String, String>)paramMap;
423
                  id = groupExtMap.get("courseid");
424
                  type = "http://purl.imsglobal.org/caliper/v1/lis/CourseSection";
425
                }
426
              }
427
            }
428
            else {
429
              for (XApiObject xo : groupings) {
430
                grouping = xo;
431
                XApiObjectDefinition xapiObjectDefinition = xo.getDefinition();
432
                if (xapiObjectDefinition != null) {
433
                  if ("http://lrs.learninglocker.net/define/type/moodle/course".equals(xapiObjectDefinition.getType())) {               
434
                    type = "http://purl.imsglobal.org/caliper/v1/lis/CourseSection";                 
435
                    Map<URI, Object> groupExt = xapiObjectDefinition.getExtensions();
436
                    if (groupExt != null) {
437
                      try {
438
                        Object paramMap = groupExt.get(new URI("http://lrs.learninglocker.net/define/extensions/moodle_course"));
0 ignored issues
show
introduced by
Refactor your code to get this URI from a customizable parameter.
Loading history...
439
                        if (paramMap instanceof Map) {
440
                          Map<String, String> groupExtMap = (Map<String, String>)paramMap;
441
                          id = groupExtMap.get("id");
442
                        }
443
                        
444
                      } 
445
                      catch (URISyntaxException e) {
446
                        //TODO
447
                      }
448
                    }
449
                    
450
                    break;
451
                  }
452
                }
453
              }
454
            }
455
            
456
            if (grouping != null) {
457
              String name = null;
458
              String description = null;
459
              XApiObjectDefinition xapiObjectDefinition = grouping.getDefinition();
460
              if (xapiObjectDefinition != null) {
461
                
462
                if (StringUtils.isBlank(type) && StringUtils.isNoneBlank(xapiObjectDefinition.getType())) {
463
                  type = xapiObjectDefinition.getType();
464
                }
465
                
466
                Map<String,String> names =xapiObjectDefinition.getName();
467
                if (names != null) {
468
                  if (names.size() == 1) {
469
                    name = CollectionUtils.get(names, 0).getValue();
470
                  }
471
                  else {
472
                    // default to en?
473
                    name = names.get("en");
474
                  }
475
                }
476
477
                Map<String,String> descriptions = xapiObjectDefinition.getDescription();
478
                if (descriptions != null) {
479
                  if (descriptions.size() == 1) {
480
                    description = CollectionUtils.get(descriptions, 0).getValue();
481
                  }
482
                  else {
483
                    // default to en?
484
                    description = descriptions.get("en");
485
                  }
486
                }
487
              }
488
              
489
              List<XApiObject> parents = xapiContextActivities.getParent();
490
              SubOrganizationOf subOrganizationOf = null;
491 View Code Duplication
              if (parents != null && parents.size() == 1) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
492
                XApiObject parent = parents.get(0);
493
                String parentId = parent.getId();
494
                String parentType = "http://purl.imsglobal.org/caliper/v1/lis/CourseOffering";
495
                String parentName = null;
496
                String parentDescription = null;
497
                XApiObjectDefinition parentXapiObjectDefinition = parent.getDefinition();
498
                if (parentXapiObjectDefinition != null) {
499
                  
500
                  if (StringUtils.isNoneBlank(parentXapiObjectDefinition.getType())) {
501
                    parentType = parentXapiObjectDefinition.getType();
502
                  }
503
                  
504
                  Map<String,String> names = parentXapiObjectDefinition.getName();
505
                  if (names != null) {
506
                    if (names.size() == 1) {
507
                      parentName = CollectionUtils.get(names, 0).getValue();
508
                    }
509
                    else {
510
                      // default to en?
511
                      parentName = names.get("en");
512
                    }
513
                  }
514
515
                  Map<String,String> descriptions = parentXapiObjectDefinition.getDescription();
516
                  if (descriptions != null) {
517
                    if (descriptions.size() == 1) {
518
                      parentDescription = CollectionUtils.get(descriptions, 0).getValue();
519
                    }
520
                    else {
521
                      // default to en?
522
                      parentDescription = descriptions.get("en");
523
                    }
524
                  }
525
526
                  subOrganizationOf 
527
                    = new SubOrganizationOf.Builder()
528
                      .withId(parentId)
529
                      .withContext(Context.CONTEXT.getValue())
530
                      .withType(parentType)
531
                      .withName(parentName)
532
                      .withDescription(parentDescription)
533
                      .build();
534
                }
535
              }
536
              
537
              caliperGroup 
538
                = new Group.Builder()
539
                  .withId(id)
540
                  .withContext(Context.CONTEXT.getValue())
541
                  .withType(type)
542
                  .withName(name)
543
                  .withDescription(description)
544
                  .withExtensions(contextExtensions)
545
                  .withSubOrganizationOf(subOrganizationOf)
546
                  .build();
547
            }
548 View Code Duplication
            else if (xapiContextActivities.getParent() != null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
549
              XApiObject parent = xapiContextActivities.getParent().get(0);
550
              String name = null;
551
              String description = null;
552
              XApiObjectDefinition xapiObjectDefinition = parent.getDefinition();
553
              if (xapiObjectDefinition != null) {
554
                if (StringUtils.isBlank(type) && StringUtils.isNoneBlank(xapiObjectDefinition.getType())) {
555
                  type = xapiObjectDefinition.getType();
556
                }
557
                
558
                Map<String,String> names = xapiObjectDefinition.getName();
559
                if (names != null) {
560
                  if (names.size() == 1) {
561
                    name = CollectionUtils.get(names, 0).getValue();
562
                  }
563
                  else {
564
                    // default to en?
565
                    name = names.get("en");
566
                  }
567
                }
568
569
                Map<String,String> descriptions = xapiObjectDefinition.getDescription();
570
                if (descriptions != null) {
571
                  if (descriptions.size() == 1) {
572
                    description = CollectionUtils.get(descriptions, 0).getValue();
573
                  }
574
                  else {
575
                    // default to en?
576
                    description = descriptions.get("en");
577
                  }
578
                }
579
              }
580
581
              caliperGroup 
582
                = new Group.Builder()
583
                  .withId(parent.getId())
584
                  .withContext(Context.CONTEXT.getValue())
585
                  .withType(type)
586
                  .withName(name)
587
                  .withDescription(description)
588
                  .withExtensions(contextExtensions)
589
                  .build();
590
            }
591
          }
592
        }
593
      }
594
    }
595
    
596
    return
597
        new Event.Builder()
598
        .withAction(caliperAction)
599
        .withAgent(caliperActor)
600
        .withObject(caliperObject)
601
        .withEventTime(eventTime)
602
        .withContext(xapiToCaliperType(statement))
603
        .withGroup(caliperGroup)
604
        .withGenerated(caliperResult)
605
        .build();
606
    
607
  }
608
  
609
  public Statement toXapi(Event event) throws URISyntaxException {
610
    Statement statement = new Statement();
611
    
612
    // ID
613
    statement.setId(event.getId());
614
    // END ID
615
    
616
    // EVENT TIME
617
    LocalDateTime eventTime = event.getEventTime();    
618
    if (eventTime != null) {
619
      Instant instant = eventTime.toInstant(ZoneOffset.UTC);
620
      //DateTimeFormatter fmt = DateTimeFormatter.ISO_INSTANT;
621
      statement.setTimestamp(instant.toString());
622
    }
623
    // END EVENT TIME
624
    
625
    // ACTOR
626
    Agent actor = event.getAgent();
627
    if (actor != null) {
628
      Map<String,String> actorExtensions = actor.getExtensions();
629
      XApiActor xapiActor = new XApiActor();
630
      
631
      String actorId = actor.getId();
632
      String actorType = actor.getType(); 
633
      xapiActor.setName(actor.getName());
634
      
635
      if (ACTOR_TYPE_OPENID.equals(actorType)) {
636
        xapiActor.setOpenid(actorId);
637
      }
638
      else if (ACTOR_TYPE_MBOX.equals(actorType)) {
639
        xapiActor.setMbox(actorId);
640
      }
641
      else {
642
        XApiAccount xapiAccount = new XApiAccount();
643
        
644
        if (actorExtensions != null && !actorExtensions.isEmpty()) {
645
          String homePage = actorExtensions.get("HOMEPAGE");
646
          if (StringUtils.isNotBlank(homePage)) {
647
            xapiAccount.setHomePage(homePage);
648
          }
649
        }
650
        
651
        xapiAccount.setName(actorId);
652
        xapiActor.setAccount(xapiAccount);
653
      }
654
      statement.setActor(xapiActor);
655
    }
656
    // ACTOR END
657
    
658
    // RESULT
659
    Entity caliperGeneratable = event.getGenerated();
660
    if (caliperGeneratable != null) {
661
      Map<String,String> caliperResultExtensions = caliperGeneratable.getExtensions();
662
      
663
      Map<URI,java.lang.Object> xapiResultExtensions = null;
664
      if (caliperResultExtensions != null && !caliperResultExtensions.isEmpty()) {
665
        xapiResultExtensions = new HashMap<>();
666
        for (Map.Entry<String,String> entry : caliperResultExtensions.entrySet()) {
667
          xapiResultExtensions.put(new URI(entry.getKey()), entry.getValue());
668
        }
669
        
670
        XApiResult xapiResult = new XApiResult();
671
        xapiResult.setExtensions(xapiResultExtensions);
672
        statement.setResult(xapiResult);
673
      }
674
    }
675
    // END Result
676
677
678
    // ACTION
679
    String action = event.getAction();
680
    if (StringUtils.isNotBlank(action)) {
681
      XApiVerb xapiVerb = new XApiVerb();
682
      xapiVerb.setId(caliperActionToXapiVerb(action));
683
      statement.setVerb(xapiVerb);
684
    }
685
    // ACTION END
686
    
687
    // OBJECT
688
    Entity object = event.getObject();
689
    if (object != null) {
690
      
691
      XApiObject xapiObject = new XApiObject();
692
      XApiObjectDefinition xapiObjectDefinition = new XApiObjectDefinition();
693
      
694
      String name = object.getName();
695
      if (StringUtils.isNotBlank(name)) {
696
        xapiObjectDefinition.setName(Collections.singletonMap("en", name));
697
      }
698
      
699
      String description = object.getDescription();
700
      if (StringUtils.isNotBlank(description)) {
701
        xapiObjectDefinition.setDescription(Collections.singletonMap("en", description));
702
      }
703
      
704
      xapiObjectDefinition.setType(caliperEntityTypeToXapiObjectType(object.getType()));
705
      
706
      Map<String,String> extensions = object.getExtensions();
707
      if (extensions != null && !extensions.isEmpty()) {
708
        Map<URI, java.lang.Object> xapiExtensions = new HashMap<>();
709
        for (String key : extensions.keySet()) {
0 ignored issues
show
Performance introduced by
When you need both the keys and the value of a Map, iterating over entrySet() instead of keySet() is more readable.
Loading history...
710
          xapiExtensions.put(new URI(key), extensions.get(key));
711
        }
712
        xapiObjectDefinition.setExtensions(xapiExtensions);
713
      }
714
      
715
      xapiObject.setDefinition(xapiObjectDefinition);
716
      xapiObject.setId(object.getId());
717
      statement.setObject(xapiObject);
718
    }
719
    // OBJECT END
720
    
721
    Group group = event.getGroup();
722
    if (group != null) {
723
      XApiContext xapiContext = new XApiContext();
724
      
725
      Map<String,String> contextExtensions = group.getExtensions();
726
      if (contextExtensions != null && !contextExtensions.isEmpty()) {
727
        Map<URI,java.lang.Object> extensions = new HashMap<>();
728
        for (String key : contextExtensions.keySet()) {
729
          extensions.put(new URI(key), extensions.get(key));
730
        }
731
        xapiContext.setExtensions(extensions);
732
      }
733
      
734
      XApiContextActivities xapiContextActivities = new XApiContextActivities();
735
      XApiObject grouping = new XApiObject();
736
      grouping.setId(group.getId());      
737
      xapiContextActivities.setGrouping(Collections.singletonList(grouping));
738
      
739
      xapiContext.setContextActivities(xapiContextActivities);
740
      statement.setContext(xapiContext);
741
      
742
    }
743
744
    return statement;
745
  }
746
  
747
  private String xApiVerbToCaliperAction(String xapiVerbId) {
748
    Action caliperAction = verbActionMap.getKey(xapiVerbId);
749
    if (caliperAction == null) {
750
      return xapiVerbId;
751
    }
752
    
753
    return caliperAction.getValue();
754
  }
755
  
756
  private String caliperActionToXapiVerb(String caliperAction) {
757
    String verb = null;
758
    try {
759
      verb = verbActionMap.get(Action.valueOf(caliperAction));
760
      if (StringUtils.isBlank(verb)) {
761
        return DEFAULT_XAPI_VERB;
762
      }
763
764
    }
765
    catch (IllegalArgumentException e) {
766
      return DEFAULT_XAPI_VERB;
767
    }
768
    
769
    return verb;
770
  }
771
  
772
  private String xapiObjectTypeToCaliperEntityType(String xapiType) {
773
    
774
    if (StringUtils.isBlank(xapiType)) {
775
      return EntityType.DIGITAL_RESOURCE.getValue();
776
    }
777
    
778
    Type caliperType = objectEntityMap.getKey(xapiType);
779
    if (caliperType == null) {
780
      return xapiType;
781
    }
782
    
783
    return caliperType.getValue();
784
  }
785
  
786
  private String caliperEntityTypeToXapiObjectType(String caliperType) {
787
    String xapiType = objectEntityMap.get(caliperType);
788
    if (StringUtils.isBlank(xapiType)) {
789
      return caliperType;
790
    }
791
    
792
    return xapiType;
793
  }
794
  
795
  private String xapiToCaliperType(Statement statement) {
796
    // default to event
797
    String type = EventType.EVENT.getValue();
798
    // change if there is something more specific
799
    XApiVerb xapiVerb = statement.getVerb();
800
    if (xapiVerb != null) {
801
      String verbId = xapiVerb.getId();
802
      Action caliperAction = verbActionMap.getKey(verbId);
803
      EventType eventType = actionEventMap.get(caliperAction);
804
      if (eventType != null) {
805
        type = eventType.getValue();
806
      }
807
    }
808
    
809
    return type;
810
  }
811
  
812
  private static final String ACTOR_TYPE_MBOX = "foaf:mbox";
813
  private static final String ACTOR_TYPE_OPENID = "http://openid.net/";
814
  private static final String ACTOR_TYPE_ACCOUNT = "https://github.com/adlnet/xAPI-Spec/blob/master/xAPI.md#agentaccount";
815
  
816
  private static final String DEFAULT_XAPI_VERB = "http://adlnet.gov/expapi/verbs/experienced";
817
}
818