package org.apereo.openlrw.events.xapi.service; import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.bidimap.DualHashBidiMap; import org.apache.commons.lang3.StringUtils; import org.apereo.openlrw.caliper.*; import org.apereo.openlrw.xapi.*; import org.imsglobal.caliper.actions.Action; import org.imsglobal.caliper.context.Context; import org.imsglobal.caliper.entities.DigitalResourceType; import org.imsglobal.caliper.entities.EntityType; import org.imsglobal.caliper.entities.Type; import org.imsglobal.caliper.events.EventType; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.net.URI; import java.net.URISyntaxException; import java.time.*; import java.util.*; /** * @author ggilbert * @author xchopin <[email protected]> * */ @Component public class DefaultXapiToCaliperConversionService implements XapiConversionService { private BidiMap<Action, String> verbActionMap; private BidiMap<Type, String> objectEntityMap; private Map<Action, EventType> actionEventMap; private static final String ACTOR_TYPE_MBOX = "foaf:mbox"; private static final String ACTOR_TYPE_OPENID = "http://openid.net/"; private static final String ACTOR_TYPE_ACCOUNT = "https://github.com/adlnet/xAPI-Spec/blob/master/xAPI.md#agentaccount"; private static final String DEFAULT_XAPI_VERB = "http://adlnet.gov/expapi/verbs/experienced"; @PostConstruct private void init() { verbActionMap = new DualHashBidiMap<>(); verbActionMap.put(Action.ABANDONED, "https://w3id.org/xapi/adl/verbs/abandoned"); verbActionMap.put(Action.ATTACHED, "http://activitystrea.ms/schema/1.0/attach"); verbActionMap.put(Action.BOOKMARKED, "http://id.tincanapi.com/verb/bookmarked"); verbActionMap.put(Action.COMMENTED, "http://adlnet.gov/expapi/verbs/commented"); verbActionMap.put(Action.COMPLETED, "http://adlnet.gov/expapi/verbs/completed"); verbActionMap.put(Action.DISLIKED, "http://activitystrea.ms/schema/1.0/dislike"); verbActionMap.put(Action.GRADED, "http://adlnet.gov/expapi/verbs/scored"); verbActionMap.put(Action.LIKED, "http://activitystrea.ms/schema/1.0/like"); verbActionMap.put(Action.LOGGED_IN, "https://brindlewaye.com/xAPITerms/verbs/loggedin/"); verbActionMap.put(Action.LOGGED_OUT, "https://brindlewaye.com/xAPITerms/verbs/loggedout/"); verbActionMap.put(Action.PAUSED, "http://id.tincanapi.com/verb/paused"); verbActionMap.put(Action.QUESTIONED, "http://adlnet.gov/expapi/verbs/asked"); verbActionMap.put(Action.REPLIED, "http://adlnet.gov/expapi/verbs/responded"); verbActionMap.put(Action.RESUMED, "http://adlnet.gov/expapi/verbs/resumed"); verbActionMap.put(Action.REVIEWED, "http://id.tincanapi.com/verb/reviewed"); verbActionMap.put(Action.SEARCHED, "http://activitystrea.ms/schema/1.0/search"); verbActionMap.put(Action.SHARED, "http://activitystrea.ms/schema/1.0/share"); verbActionMap.put(Action.SKIPPED, "http://id.tincanapi.com/verb/skipped"); verbActionMap.put(Action.STARTED, "http://activitystrea.ms/schema/1.0/start"); verbActionMap.put(Action.SUBMITTED, "http://activitystrea.ms/schema/1.0/submit"); verbActionMap.put(Action.TAGGED, "http://activitystrea.ms/schema/1.0/tag"); verbActionMap.put(Action.VIEWED, "http://id.tincanapi.com/verb/viewed"); objectEntityMap = new DualHashBidiMap<>(); // ToDo support other xapi annotation types objectEntityMap.put(EntityType.ANNOTATION, "http://risc-inc.com/annotator/activities/highlight"); objectEntityMap.put(EntityType.COURSE_SECTION, "http://adlnet.gov/expapi/activities/course"); objectEntityMap.put(EntityType.DIGITAL_RESOURCE, "http://adlnet.gov/expapi/activities/media"); objectEntityMap.put(EntityType.GROUP, "http://activitystrea.ms/schema/1.0/group"); objectEntityMap.put(EntityType.LEARNING_OBJECTIVE, "http://adlnet.gov/expapi/activities/objective"); objectEntityMap.put(EntityType.PERSON, "http://activitystrea.ms/schema/1.0/person"); objectEntityMap.put(EntityType.ORGANIZATION, "http://activitystrea.ms/schema/1.0/organization"); objectEntityMap.put(EntityType.SOFTWARE_APPLICATION, "http://activitystrea.ms/schema/1.0/application"); objectEntityMap.put(DigitalResourceType.MEDIA_OBJECT, "http://adlnet.gov/expapi/activities/media"); objectEntityMap.put(DigitalResourceType.WEB_PAGE, "http://activitystrea.ms/schema/1.0/page"); actionEventMap = new HashMap<>(); actionEventMap.put(Action.ABANDONED, EventType.ASSIGNABLE); actionEventMap.put(Action.ACTIVATED, EventType.ASSIGNABLE); actionEventMap.put(Action.ATTACHED, EventType.ANNOTATION); actionEventMap.put(Action.BOOKMARKED, EventType.ANNOTATION); actionEventMap.put(Action.CHANGED_RESOLUTION, EventType.MEDIA); actionEventMap.put(Action.CHANGED_SIZE, EventType.MEDIA); actionEventMap.put(Action.CHANGED_VOLUME, EventType.MEDIA); actionEventMap.put(Action.CLASSIFIED, EventType.ANNOTATION); actionEventMap.put(Action.CLOSED_POPOUT, EventType.MEDIA); actionEventMap.put(Action.COMMENTED, EventType.ANNOTATION); actionEventMap.put(Action.COMPLETED, EventType.ASSIGNABLE); actionEventMap.put(Action.DEACTIVATED, EventType.ASSIGNABLE); actionEventMap.put(Action.DESCRIBED, EventType.ANNOTATION); actionEventMap.put(Action.DISLIKED, EventType.ANNOTATION); actionEventMap.put(Action.DISABLED_CLOSED_CAPTIONING, EventType.MEDIA); actionEventMap.put(Action.ENABLED_CLOSED_CAPTIONING, EventType.MEDIA); actionEventMap.put(Action.ENDED, EventType.MEDIA); actionEventMap.put(Action.ENTERED_FULLSCREEN, EventType.MEDIA); actionEventMap.put(Action.EXITED_FULLSCREEN, EventType.MEDIA); actionEventMap.put(Action.FORWARDED_TO, EventType.MEDIA); actionEventMap.put(Action.GRADED, EventType.OUTCOME); actionEventMap.put(Action.HID, EventType.ASSIGNABLE); actionEventMap.put(Action.HIGHLIGHTED, EventType.ANNOTATION); actionEventMap.put(Action.JUMPED_TO, EventType.MEDIA); actionEventMap.put(Action.IDENTIFIED, EventType.ANNOTATION); actionEventMap.put(Action.LIKED, EventType.ANNOTATION); actionEventMap.put(Action.LINKED, EventType.ANNOTATION); actionEventMap.put(Action.LOGGED_IN, EventType.SESSION); actionEventMap.put(Action.LOGGED_OUT, EventType.SESSION); actionEventMap.put(Action.MUTED, EventType.MEDIA); actionEventMap.put(Action.NAVIGATED_TO, EventType.NAVIGATION); actionEventMap.put(Action.OPENED_POPOUT, EventType.MEDIA); actionEventMap.put(Action.PAUSED, EventType.MEDIA); actionEventMap.put(Action.RANKED, EventType.ANNOTATION); actionEventMap.put(Action.QUESTIONED, EventType.ANNOTATION); actionEventMap.put(Action.RECOMMENDED, EventType.ANNOTATION); actionEventMap.put(Action.REPLIED, EventType.ANNOTATION); actionEventMap.put(Action.RESTARTED, EventType.ASSESSMENT); actionEventMap.put(Action.RESUMED, EventType.MEDIA); actionEventMap.put(Action.REVIEWED, EventType.ASSIGNABLE); actionEventMap.put(Action.REWOUND, EventType.MEDIA); actionEventMap.put(Action.SEARCHED, EventType.READING); actionEventMap.put(Action.SHARED, EventType.ANNOTATION); actionEventMap.put(Action.SHOWED, EventType.ASSIGNABLE); actionEventMap.put(Action.SKIPPED, EventType.ASSESSMENT_ITEM); actionEventMap.put(Action.STARTED, EventType.EVENT); actionEventMap.put(Action.SUBMITTED, EventType.EVENT); actionEventMap.put(Action.SUBSCRIBED, EventType.ANNOTATION); actionEventMap.put(Action.TAGGED, EventType.ANNOTATION); actionEventMap.put(Action.TIMED_OUT, EventType.SESSION); actionEventMap.put(Action.VIEWED, EventType.EVENT); actionEventMap.put(Action.UNMUTED, EventType.MEDIA); } public Event fromXapi(Statement statement) { LocalDateTime eventTime; String timestamp = statement.getTimestamp(); if (StringUtils.isNotBlank(timestamp)) { if (timestamp.endsWith("Z")) { Instant instant = Instant.parse(timestamp); eventTime = LocalDateTime.ofInstant(instant, ZoneId.of(ZoneOffset.UTC.getId())); } else { ZonedDateTime zdt = ZonedDateTime.parse(timestamp); ZonedDateTime utc_zone = zdt.toLocalDateTime().atZone(ZoneOffset.UTC); eventTime = utc_zone.toLocalDateTime(); } } else { eventTime = LocalDateTime.now(ZoneId.of(ZoneOffset.UTC.getId())); } // ACTOR Agent caliperActor = null; String actorId = null; XApiActor xapiActor = statement.getActor(); if (xapiActor != null) { String actorType = null; Map<String, String> actorExtensions = new HashMap<>(); String actorName = xapiActor.getName(); String openId = xapiActor.getOpenid(); String mbox = xapiActor.getMbox(); XApiAccount xapiAccount = xapiActor.getAccount(); if (StringUtils.isNotBlank(openId)) { actorId = openId; actorType = ACTOR_TYPE_OPENID; } else if (StringUtils.isNotBlank(mbox)) { actorId = mbox; actorType = ACTOR_TYPE_MBOX; } else if (xapiAccount != null) { String accountName = xapiAccount.getName(); String homePage = xapiAccount.getHomePage(); if (StringUtils.isNotBlank(homePage)) { if (StringUtils.isNotBlank(accountName)) { actorId = accountName; actorExtensions.put("HOMEPAGE", homePage); } else { actorId = homePage; } } else if (StringUtils.isNotBlank(accountName)) { actorId = accountName; } actorType = ACTOR_TYPE_ACCOUNT; } caliperActor = new Agent.Builder() .withContext(Context.CONTEXT.getValue()) .withName(actorName) .withId(actorId) .withType(actorType) .withExtensions(actorExtensions) .build(); } // ACTOR END // RESULT Entity caliperResult = null; XApiResult xapiResult = statement.getResult(); if (xapiResult != null) { Map<String,String> resultExtensions = null; Map<URI,java.lang.Object> xapiResultExtensions = xapiResult.getExtensions(); if (xapiResultExtensions != null && !xapiResultExtensions.isEmpty()) { resultExtensions = new HashMap<>(); for (Map.Entry<URI,java.lang.Object> entry : xapiResultExtensions.entrySet()) { resultExtensions.put(entry.getKey().toString(),entry.getValue().toString()); } } Double score = null; XApiScore xapiScore = xapiResult.getScore(); if (xapiScore != null) { score = xapiScore.getRaw(); } caliperResult = new Entity.Builder() .withId(UUID.randomUUID().toString()) .withContext(Context.CONTEXT.getValue()) .withExtensions(resultExtensions) .withActor(actorId) .withType("http://purl.imsglobal.org/caliper/v1/Result") .withTotalScore(score) .build(); } // END Result // ACTION String caliperAction = null; XApiVerb xapiVerb = statement.getVerb(); if (xapiVerb != null) { String verbId = xapiVerb.getId(); caliperAction = xApiVerbToCaliperAction(verbId); } // ACTION END // OBJECT Entity caliperObject = null; XApiObject xapiObject = statement.getObject(); if (xapiObject != null) { String objectType = xapiObjectTypeToCaliperEntityType(null); String objectName = null; String objectDescription = null; Map<String,String> objectExtensions = null; String objectId = xapiObject.getId(); XApiObjectDefinition xapiObjectDefinition = xapiObject.getDefinition(); if (xapiObjectDefinition != null) { String xapiObjectDefinitionType = xapiObjectDefinition.getType(); if (StringUtils.isNotBlank(xapiObjectDefinitionType)) { objectType = xapiObjectTypeToCaliperEntityType(xapiObjectDefinitionType); } Map<String,String> names = xapiObjectDefinition.getName(); if (names != null) { if (names.size() == 1) { objectName = CollectionUtils.get(names, 0).getValue(); } else { // default to en? objectName = names.get("en"); } } Map<String,String> descriptions = xapiObjectDefinition.getDescription(); if (descriptions != null) { if (descriptions.size() == 1) { objectDescription = CollectionUtils.get(descriptions, 0).getValue(); } else { // default to en? objectDescription = descriptions.get("en"); } } Map<URI,java.lang.Object> extensions = xapiObjectDefinition.getExtensions(); if (extensions != null && !extensions.isEmpty()) { objectExtensions = new HashMap<String,String>(extensions.size()); for (URI key : extensions.keySet()) { objectExtensions.put(key.toString(), extensions.get(key).toString()); } } } caliperObject = new Entity.Builder() .withId(objectId) .withContext(Context.CONTEXT.getValue()) .withType(objectType) .withName(objectName) .withDescription(objectDescription) .withExtensions(objectExtensions) .build(); } // OBJECT END Group caliperGroup = null; XApiContext xapiContext = statement.getContext(); if (xapiContext != null) { Map<String,String> contextExtensions = null; Map<URI,java.lang.Object> extensions = xapiContext.getExtensions(); if (extensions != null && !extensions.isEmpty()) { contextExtensions = new HashMap<String,String>(extensions.size()); for (URI key : extensions.keySet()) { contextExtensions.put(key.toString(), extensions.get(key).toString()); } } XApiContextActivities xapiContextActivities = xapiContext.getContextActivities(); if (xapiContextActivities != null) { List<XApiObject> contextActivityParents = xapiContextActivities.getParent(); if (contextActivityParents != null && contextActivityParents.size() == 1 && contextActivityParents.get(0).getId().contains("portal/site")) { caliperGroup = new Group.Builder() .withId(StringUtils.substringAfterLast(contextActivityParents.get(0).getId(), "/")) .withContext(Context.CONTEXT.getValue()) .withType("http://purl.imsglobal.org/caliper/v1/lis/CourseSection") .build(); } if (caliperGroup == null) { List<XApiObject> groupings = xapiContextActivities.getGrouping(); if (groupings != null && !groupings.isEmpty()) { XApiObject grouping = null; String id = null; String type = null; if (groupings.size() == 1) { grouping = groupings.get(0); if (extensions != null) { Object paramMap = null; try { paramMap = extensions.get(new URI("http://lrs.learninglocker.net/define/extensions/moodle_logstore_standard_log")); } catch (URISyntaxException e) { // TODO } if (paramMap != null && paramMap instanceof Map) { Map<String, String> groupExtMap = (Map<String, String>)paramMap; id = groupExtMap.get("courseid"); type = "http://purl.imsglobal.org/caliper/v1/lis/CourseSection"; } } } else { for (XApiObject xo : groupings) { grouping = xo; XApiObjectDefinition xapiObjectDefinition = xo.getDefinition(); if (xapiObjectDefinition != null) { if ("http://lrs.learninglocker.net/define/type/moodle/course".equals(xapiObjectDefinition.getType())) { type = "http://purl.imsglobal.org/caliper/v1/lis/CourseSection"; Map<URI, Object> groupExt = xapiObjectDefinition.getExtensions(); if (groupExt != null) { try { Object paramMap = groupExt.get(new URI("http://lrs.learninglocker.net/define/extensions/moodle_course")); if (paramMap instanceof Map) { Map<String, String> groupExtMap = (Map<String, String>)paramMap; id = groupExtMap.get("id"); } } catch (URISyntaxException e) { //TODO } } break; } } } } if (grouping != null) { String name = null; String description = null; XApiObjectDefinition xapiObjectDefinition = grouping.getDefinition(); if (xapiObjectDefinition != null) { if (StringUtils.isBlank(type) && StringUtils.isNoneBlank(xapiObjectDefinition.getType())) { type = xapiObjectDefinition.getType(); } Map<String,String> names =xapiObjectDefinition.getName(); if (names != null) { if (names.size() == 1) { name = CollectionUtils.get(names, 0).getValue(); } else { // default to en? name = names.get("en"); } } Map<String,String> descriptions = xapiObjectDefinition.getDescription(); if (descriptions != null) { if (descriptions.size() == 1) { description = CollectionUtils.get(descriptions, 0).getValue(); } else { // default to en? description = descriptions.get("en"); } } } List<XApiObject> parents = xapiContextActivities.getParent(); SubOrganizationOf subOrganizationOf = null; if (parents != null && parents.size() == 1) { XApiObject parent = parents.get(0); String parentId = parent.getId(); String parentType = "http://purl.imsglobal.org/caliper/v1/lis/CourseOffering"; String parentName = null; String parentDescription = null; XApiObjectDefinition parentXapiObjectDefinition = parent.getDefinition(); if (parentXapiObjectDefinition != null) { if (StringUtils.isNoneBlank(parentXapiObjectDefinition.getType())) { parentType = parentXapiObjectDefinition.getType(); } Map<String,String> names = parentXapiObjectDefinition.getName(); if (names != null) { if (names.size() == 1) { parentName = CollectionUtils.get(names, 0).getValue(); } else { // default to en? parentName = names.get("en"); } } Map<String,String> descriptions = parentXapiObjectDefinition.getDescription(); if (descriptions != null) { if (descriptions.size() == 1) { parentDescription = CollectionUtils.get(descriptions, 0).getValue(); } else { // default to en? parentDescription = descriptions.get("en"); } } subOrganizationOf = new SubOrganizationOf.Builder() .withId(parentId) .withContext(Context.CONTEXT.getValue()) .withType(parentType) .withName(parentName) .withDescription(parentDescription) .build(); } } caliperGroup = new Group.Builder() .withId(id) .withContext(Context.CONTEXT.getValue()) .withType(type) .withName(name) .withDescription(description) .withExtensions(contextExtensions) .withSubOrganizationOf(subOrganizationOf) .build(); } else if (xapiContextActivities.getParent() != null) { XApiObject parent = xapiContextActivities.getParent().get(0); String name = null; String description = null; XApiObjectDefinition xapiObjectDefinition = parent.getDefinition(); if (xapiObjectDefinition != null) { if (StringUtils.isBlank(type) && StringUtils.isNoneBlank(xapiObjectDefinition.getType())) { type = xapiObjectDefinition.getType(); } Map<String,String> names = xapiObjectDefinition.getName(); if (names != null) { if (names.size() == 1) { name = CollectionUtils.get(names, 0).getValue(); } else { // default to en? name = names.get("en"); } } Map<String,String> descriptions = xapiObjectDefinition.getDescription(); if (descriptions != null) { if (descriptions.size() == 1) { description = CollectionUtils.get(descriptions, 0).getValue(); } else { // default to en? description = descriptions.get("en"); } } } caliperGroup = new Group.Builder() .withId(parent.getId()) .withContext(Context.CONTEXT.getValue()) .withType(type) .withName(name) .withDescription(description) .withExtensions(contextExtensions) .build(); } } } } } Instant instant = eventTime.toInstant(ZoneOffset.UTC); return new Event.Builder() .withAction(caliperAction) .withAgent(caliperActor) .withObject(caliperObject) .withEventTime(instant) .withContext(xapiToCaliperType(statement)) .withGroup(caliperGroup) .withGenerated(caliperResult) .build(); } public Statement toXapi(Event event) throws URISyntaxException { Statement statement = new Statement(); statement.setId(event.getId()); // EVENT TIME Instant eventTime = event.getEventTime(); if (eventTime != null) { statement.setTimestamp(eventTime.toString()); } // END EVENT TIME // ACTOR Agent actor = event.getAgent(); if (actor != null) { Map<String,String> actorExtensions = actor.getExtensions(); XApiActor xapiActor = new XApiActor(); String actorId = actor.getId(); String actorType = actor.getType(); xapiActor.setName(actor.getName()); if (ACTOR_TYPE_OPENID.equals(actorType)) { xapiActor.setOpenid(actorId); } else if (ACTOR_TYPE_MBOX.equals(actorType)) { xapiActor.setMbox(actorId); } else { XApiAccount xapiAccount = new XApiAccount(); if (actorExtensions != null && !actorExtensions.isEmpty()) { String homePage = actorExtensions.get("HOMEPAGE"); if (StringUtils.isNotBlank(homePage)) { xapiAccount.setHomePage(homePage); } } xapiAccount.setName(actorId); xapiActor.setAccount(xapiAccount); } statement.setActor(xapiActor); } // ACTOR END // RESULT Entity caliperGeneratable = event.getGenerated(); if (caliperGeneratable != null) { Map<String,String> caliperResultExtensions = caliperGeneratable.getExtensions(); Map<URI,java.lang.Object> xapiResultExtensions = null; if (caliperResultExtensions != null && !caliperResultExtensions.isEmpty()) { xapiResultExtensions = new HashMap<>(); for (Map.Entry<String,String> entry : caliperResultExtensions.entrySet()) { xapiResultExtensions.put(new URI(entry.getKey()), entry.getValue()); } XApiResult xapiResult = new XApiResult(); xapiResult.setExtensions(xapiResultExtensions); statement.setResult(xapiResult); } } // END Result // ACTION String action = event.getAction(); if (StringUtils.isNotBlank(action)) { XApiVerb xapiVerb = new XApiVerb(); xapiVerb.setId(caliperActionToXapiVerb(action)); statement.setVerb(xapiVerb); } // ACTION END // OBJECT Entity object = event.getObject(); if (object != null) { XApiObject xapiObject = new XApiObject(); XApiObjectDefinition xapiObjectDefinition = new XApiObjectDefinition(); String name = object.getName(); if (StringUtils.isNotBlank(name)) { xapiObjectDefinition.setName(Collections.singletonMap("en", name)); } String description = object.getDescription(); if (StringUtils.isNotBlank(description)) { xapiObjectDefinition.setDescription(Collections.singletonMap("en", description)); } xapiObjectDefinition.setType(caliperEntityTypeToXapiObjectType(object.getType())); Map<String,String> extensions = object.getExtensions(); if (extensions != null && !extensions.isEmpty()) { Map<URI, java.lang.Object> xapiExtensions = new HashMap<>(); for (String key : extensions.keySet()) { xapiExtensions.put(new URI(key), extensions.get(key)); } xapiObjectDefinition.setExtensions(xapiExtensions); } xapiObject.setDefinition(xapiObjectDefinition); xapiObject.setId(object.getId()); statement.setObject(xapiObject); } // OBJECT END Group group = event.getGroup(); if (group != null) { XApiContext xapiContext = new XApiContext(); Map<String,String> contextExtensions = group.getExtensions(); if (contextExtensions != null && !contextExtensions.isEmpty()) { Map<URI,java.lang.Object> extensions = new HashMap<>(); for (String key : contextExtensions.keySet()) { extensions.put(new URI(key), extensions.get(key)); } xapiContext.setExtensions(extensions); } XApiContextActivities xapiContextActivities = new XApiContextActivities(); XApiObject grouping = new XApiObject(); grouping.setId(group.getId()); xapiContextActivities.setGrouping(Collections.singletonList(grouping)); xapiContext.setContextActivities(xapiContextActivities); statement.setContext(xapiContext); } return statement; } private String xApiVerbToCaliperAction(String xapiVerbId) { Action caliperAction = verbActionMap.getKey(xapiVerbId); if (caliperAction == null) { return xapiVerbId; } return caliperAction.getValue(); } private String caliperActionToXapiVerb(String caliperAction) { String verb = null; try { verb = verbActionMap.get(Action.valueOf(caliperAction)); if (StringUtils.isBlank(verb)) { return DEFAULT_XAPI_VERB; } } catch (IllegalArgumentException e) { return DEFAULT_XAPI_VERB; } return verb; } private String xapiObjectTypeToCaliperEntityType(String xapiType) { if (StringUtils.isBlank(xapiType)) { return EntityType.DIGITAL_RESOURCE.getValue(); } Type caliperType = objectEntityMap.getKey(xapiType); if (caliperType == null) { return xapiType; } return caliperType.getValue(); } private String caliperEntityTypeToXapiObjectType(String caliperType) { String xapiType = objectEntityMap.get(caliperType); if (StringUtils.isBlank(xapiType)) { return caliperType; } return xapiType; } private String xapiToCaliperType(Statement statement) { // default to event String type = EventType.EVENT.getValue(); // change if there is something more specific XApiVerb xapiVerb = statement.getVerb(); if (xapiVerb != null) { String verbId = xapiVerb.getId(); Action caliperAction = verbActionMap.getKey(verbId); EventType eventType = actionEventMap.get(caliperAction); if (eventType != null) { type = eventType.getValue(); } } return type; } }