diff --git a/.gitmodules b/.gitmodules index 4c9a7c75a3..aee1af4bf6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "actors/sunbird-lms-mw/sunbird-utils"] path = actors/sunbird-lms-mw/sunbird-utils url = https://github.com/project-sunbird/sunbird-utils - branch = course-batch-refactoring \ No newline at end of file + branch = release-2.2.0 \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index cbff175e5d..728467a6d5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -40,7 +40,7 @@ node('build-slave') { } stage('Unit Tests') { - + sh "mvn test '-Dtest=!%regex[io.opensaber.registry.client.*]' -DfailIfNoTests=false" } stage('Package') { diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/common/quartz/scheduler/CoursePublishedUpdate.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/common/quartz/scheduler/CoursePublishedUpdate.java index 025b2edb92..7e516ceb8a 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/common/quartz/scheduler/CoursePublishedUpdate.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/common/quartz/scheduler/CoursePublishedUpdate.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.sunbird.cassandra.CassandraOperation; @@ -93,6 +94,8 @@ private void addUserToUserCourseTable(List> batchList) { ProjectLogger.log("Adding participants to user course table started", LoggerEnum.INFO.name()); Util.DbInfo courseEnrollmentdbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_COURSE_DB); for (Map batch : batchList) { + Map additionalCourseInfo = + (Map) batch.get(JsonKey.COURSE_ADDITIONAL_INFO); if ((int) batch.get(JsonKey.STATUS) != ProjectUtil.ProgressStatus.COMPLETED.getValue()) { Map participants = (Map) batch.get(JsonKey.PARTICIPANT); if (participants == null) { @@ -112,7 +115,16 @@ private void addUserToUserCourseTable(List> batchList) { userCourses.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.NOT_STARTED.getValue()); userCourses.put(JsonKey.DATE_TIME, ts); userCourses.put(JsonKey.COURSE_PROGRESS, 0); - + userCourses.put( + JsonKey.COURSE_LOGO_URL, additionalCourseInfo.get(JsonKey.COURSE_LOGO_URL)); + userCourses.put(JsonKey.COURSE_NAME, additionalCourseInfo.get(JsonKey.COURSE_NAME)); + userCourses.put(JsonKey.DESCRIPTION, additionalCourseInfo.get(JsonKey.DESCRIPTION)); + if (!StringUtils.isBlank(additionalCourseInfo.get(JsonKey.LEAF_NODE_COUNT))) { + userCourses.put( + JsonKey.LEAF_NODE_COUNT, + Integer.parseInt("" + additionalCourseInfo.get(JsonKey.LEAF_NODE_COUNT))); + } + userCourses.put(JsonKey.TOC_URL, additionalCourseInfo.get(JsonKey.TOC_URL)); try { cassandraOperation.insertRecord( courseEnrollmentdbInfo.getKeySpace(), diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/BackgroundJobManager.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/BackgroundJobManager.java index 5e006d6610..7663d2fdf5 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/BackgroundJobManager.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/BackgroundJobManager.java @@ -2,11 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.json.JSONException; @@ -20,14 +16,15 @@ import org.sunbird.common.inf.ElasticSearchService; import org.sunbird.common.models.response.Response; import org.sunbird.common.models.util.ActorOperations; +import org.sunbird.common.models.util.HttpUtil; import org.sunbird.common.models.util.JsonKey; import org.sunbird.common.models.util.LoggerEnum; import org.sunbird.common.models.util.ProjectLogger; import org.sunbird.common.models.util.ProjectUtil; +import org.sunbird.common.models.util.PropertiesCache; import org.sunbird.common.request.Request; import org.sunbird.common.responsecode.ResponseCode; import org.sunbird.helper.ServiceFactory; -import org.sunbird.learner.actors.coursebatch.service.UserCoursesService; import org.sunbird.learner.util.CourseBatchSchedulerUtil; import org.sunbird.learner.util.Util; import org.sunbird.learner.util.Util.DbInfo; @@ -83,7 +80,9 @@ public void onReceive(Request request) throws Throwable { } String operation = request.getOperation(); ProjectLogger.log("Operation name is ==" + operation); - if (operation.equalsIgnoreCase(ActorOperations.UPDATE_USER_INFO_ELASTIC.getValue())) { + if (operation.equalsIgnoreCase(ActorOperations.PUBLISH_COURSE.getValue())) { + // manageBackgroundJob(request); + } else if (operation.equalsIgnoreCase(ActorOperations.UPDATE_USER_INFO_ELASTIC.getValue())) { ProjectLogger.log("Update user info to ES called.", LoggerEnum.INFO.name()); updateUserInfoToEs(request); } else if (operation.equalsIgnoreCase( @@ -215,13 +214,10 @@ private void insertUserCourseInfoToEs(Request actorMessage) { Map batch = (Map) actorMessage.getRequest().get(JsonKey.USER_COURSES); - String userId = (String) batch.get(JsonKey.USER_ID); - String batchId = (String) batch.get(JsonKey.BATCH_ID); - String identifier = UserCoursesService.generateUserCourseESId(batchId, userId); insertDataToElastic( ProjectUtil.EsIndex.sunbird.getIndexName(), ProjectUtil.EsType.usercourses.getTypeName(), - identifier, + (String) batch.get(JsonKey.ID), batch); } @@ -414,6 +410,74 @@ private void updateUserCount(Request actorMessage) { } } + /** + * @param request + * @return boolean + */ + @SuppressWarnings("unchecked") + private boolean manageBackgroundJob(Request request) { + Map data = null; + if (request.getRequest() == null) { + return false; + } else { + data = request.getRequest(); + } + + List> list = (List>) data.get(JsonKey.RESPONSE); + Map content = list.get(0); + String contentId = (String) content.get(JsonKey.CONTENT_ID); + if (!StringUtils.isBlank(contentId)) { + String contentData = getCourseData(contentId); + if (!StringUtils.isBlank(contentData)) { + Map map = getContentDetails(contentData); + map.put(JsonKey.ID, content.get(JsonKey.COURSE_ID)); + updateCourseManagement(map); + List createdForValue = null; + Object obj = content.get(JsonKey.COURSE_CREATED_FOR); + if (obj != null) { + createdForValue = (List) obj; + } + content.remove(JsonKey.COURSE_CREATED_FOR); + content.put(JsonKey.APPLICABLE_FOR, createdForValue); + Map finalResponseMap = (Map) map.get(JsonKey.RESULT); + finalResponseMap.putAll(content); + finalResponseMap.put(JsonKey.OBJECT_TYPE, ProjectUtil.EsType.course.getTypeName()); + insertDataToElastic( + ProjectUtil.EsIndex.sunbird.getIndexName(), + ProjectUtil.EsType.course.getTypeName(), + (String) map.get(JsonKey.ID), + finalResponseMap); + } + } + return true; + } + + /** + * Method to get the course data. + * + * @param contnetId String + * @return String + */ + private String getCourseData(String contnetId) { + String responseData = null; + try { + String ekStepBaseUrl = System.getenv(JsonKey.EKSTEP_BASE_URL); + if (StringUtils.isBlank(ekStepBaseUrl)) { + ekStepBaseUrl = PropertiesCache.getInstance().getProperty(JsonKey.EKSTEP_BASE_URL); + } + + responseData = + HttpUtil.sendGetRequest( + ekStepBaseUrl + + PropertiesCache.getInstance().getProperty(JsonKey.EKSTEP_CONTENT_URL) + + contnetId, + headerMap); + } catch (IOException e) { + ProjectLogger.log(e.getMessage(), e); + } + return responseData; + } + /** * Method to get the content details of the given content id. * diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/LearnerStateActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/LearnerStateActor.java index e7b333321b..d6434efafc 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/LearnerStateActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/LearnerStateActor.java @@ -5,12 +5,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.slf4j.helpers.MessageFormatter; import org.sunbird.actor.core.BaseActor; import org.sunbird.actor.router.ActorConfig; @@ -25,14 +27,13 @@ import org.sunbird.common.models.util.LoggerEnum; import org.sunbird.common.models.util.ProjectLogger; import org.sunbird.common.models.util.ProjectUtil; +import org.sunbird.common.models.util.datasecurity.OneWayHashing; import org.sunbird.common.request.Request; import org.sunbird.common.responsecode.ResponseCode; import org.sunbird.dto.SearchDTO; import org.sunbird.helper.ServiceFactory; -import org.sunbird.learner.actors.coursebatch.CourseEnrollmentActor; import org.sunbird.learner.actors.coursebatch.service.UserCoursesService; import org.sunbird.learner.util.ContentSearchUtil; -import org.sunbird.learner.util.CourseBatchSchedulerUtil; import org.sunbird.learner.util.Util; import scala.concurrent.Future; @@ -51,7 +52,6 @@ public class LearnerStateActor extends BaseActor { private CassandraOperation cassandraOperation = ServiceFactory.getInstance(); private UserCoursesService userCoursesService = new UserCoursesService(); private ElasticSearchService esService = EsClientFactory.getInstance(JsonKey.REST); - private static final String COMPLETE_PERCENT = "completionPercentage"; /** * Receives the actor message and perform the operation like get course , get content etc. @@ -63,9 +63,11 @@ public void onReceive(Request request) throws Exception { if (request.getOperation().equalsIgnoreCase(ActorOperations.GET_COURSE.getValue())) { getCourse(request); } else if (request.getOperation().equalsIgnoreCase(ActorOperations.GET_CONTENT.getValue())) { + Response res = new Response(); Map requestMap = request.getRequest(); String userId = (String) request.getRequest().get(JsonKey.USER_ID); + res = getCourseContentState(userId, requestMap); removeUnwantedProperties(res); sender().tell(res, self()); @@ -77,7 +79,6 @@ public void onReceive(Request request) throws Exception { public void getCourse(Request request) { String userId = (String) request.getRequest().get(JsonKey.USER_ID); Map result = userCoursesService.getActiveUserCourses(userId); - List> updatedCourses = calculateProgressForUserCourses(request, result); if (MapUtils.isNotEmpty(result)) { addCourseDetails(request, result); } else { @@ -86,7 +87,7 @@ public void getCourse(Request request) { LoggerEnum.INFO.name()); } Response response = new Response(); - response.put(JsonKey.COURSES, updatedCourses); + response.put(JsonKey.COURSES, result.get(JsonKey.CONTENT)); sender().tell(response, self()); } @@ -102,7 +103,7 @@ private void addCourseDetails(Request request, Map userCoursesRe if (CollectionUtils.isEmpty(batches)) { return; } - String requestBody = prepareCourseSearchRequest(batches, null); + String requestBody = prepareCourseSearchRequest(batches); ProjectLogger.log( MessageFormatter.format( "LearnerStateActor:addCourseDetails: request body = {0}, query string = {1}", @@ -166,7 +167,7 @@ private Map getCourseBatch( dto.getAdditionalProperties().put(JsonKey.FILTERS, esQueryMap); Future> responseF = - esService.search(dto, ProjectUtil.EsType.courseBatch.getTypeName()); + esService.search(dto, ProjectUtil.EsType.course.getTypeName()); Map response = (Map) ElasticSearchHelper.getResponseFromFuture(responseF); return response; @@ -242,8 +243,7 @@ private Map getContentAsMap(Map coursesContents) return contentsByCourseId; } - private String prepareCourseSearchRequest( - List> batches, List fields) { + private String prepareCourseSearchRequest(List> batches) { Set courseIds = batches .stream() @@ -256,10 +256,10 @@ private String prepareCourseSearchRequest( ProjectLogger.log( "LearnerStateActor:prepareCourseSearchRequest: courseIds = " + courseIds, LoggerEnum.INFO.name()); - Map requestMap = new HashMap<>(); + Map> requestMap = new HashMap<>(); requestMap.put(JsonKey.FILTERS, filters); - if (fields != null) requestMap.put(JsonKey.FIELDS, fields); - Map> request = new HashMap<>(); + + Map>> request = new HashMap<>(); request.put(JsonKey.REQUEST, requestMap); String requestJson = null; @@ -278,53 +278,147 @@ private String prepareCourseSearchRequest( private Response getCourseContentState(String userId, Map requestMap) { Response response = new Response(); + List> contentList = new ArrayList<>(); + String batchId = (String) requestMap.get(JsonKey.BATCH_ID); - String courseId = (String) requestMap.get(JsonKey.COURSE_ID); + List courseIds = (List) requestMap.get(JsonKey.COURSE_IDS); List contentIds = (List) requestMap.get(JsonKey.CONTENT_IDS); - if (CollectionUtils.isEmpty(contentIds)) { - Map courseData = - CourseEnrollmentActor.getCourseObjectFromEkStep( - courseId, CourseBatchSchedulerUtil.headerMap); - if (MapUtils.isEmpty(courseData)) { + + if (null != courseIds) { + if (courseIds.size() > 1 && StringUtils.isNotBlank(batchId)) { + ProjectLogger.log( + "LearnerStateActor:getContentByBatch: multiple course ids not allowed for batch", + LoggerEnum.ERROR.name()); throw new ProjectCommonException( - ResponseCode.invalidCourseId.getErrorCode(), - ResponseCode.invalidCourseId.getErrorMessage(), + ResponseCode.multipleCoursesNotAllowedForBatch.getErrorCode(), + ResponseCode.multipleCoursesNotAllowedForBatch.getErrorMessage(), ResponseCode.CLIENT_ERROR.getResponseCode()); } - List leafNodes = (List) courseData.get("leafNodes"); - if (CollectionUtils.isNotEmpty(leafNodes)) { - contentIds = leafNodes; - } } - List> contentList = null; - if (CollectionUtils.isEmpty(contentIds)) { - contentList = new ArrayList<>(); - } else { - contentList = getContents(userId, contentIds, batchId, courseId); + + if (CollectionUtils.isNotEmpty(contentIds) + && contentIds.size() > 0 + && CollectionUtils.isNotEmpty(courseIds) + && courseIds.size() == 1 + && StringUtils.isNotBlank(batchId)) { + List primaryKeyList = new ArrayList<>(); + String courseId = courseIds.get(0); + for (String contentId : contentIds) { + String key = generatePrimaryKeyForContent(userId, batchId, courseId, contentId); + primaryKeyList.add(key); + } + contentList = getContentByPrimaryKeys(primaryKeyList); + } else if (StringUtils.isNotBlank(batchId)) { + contentList = getContentByBatch(userId, batchId); + if (CollectionUtils.isNotEmpty(contentIds)) { + contentList = filterForMatchingContentIds(contentList, requestMap); + } + } else if (CollectionUtils.isNotEmpty(courseIds)) { + contentList = getContentByCourses(userId, requestMap); + if (courseIds.size() == 1) { + if (CollectionUtils.isNotEmpty(contentIds)) { + contentList = filterForMatchingContentIds(contentList, requestMap); + } + } + } else if (CollectionUtils.isNotEmpty(contentIds)) { + contentList = getContentByContentIds(userId, requestMap); } response.getResult().put(JsonKey.RESPONSE, contentList); return response; } - private List> getContents( - String userId, List contentIds, String batchId, String courseId) { + private List> filterForMatchingContentIds( + List> contentList, Map requestMap) { + + List contentIds = + new ArrayList((List) requestMap.get(JsonKey.CONTENT_IDS)); + List> matchedContentList = new ArrayList<>(); + + if (CollectionUtils.isNotEmpty(contentIds)) { + for (Map content : contentList) { + for (int i = 0; i < contentIds.size(); i++) { + String contentId = contentIds.get(i); + if (contentId.equals((String) content.get(JsonKey.CONTENT_ID))) { + matchedContentList.add(content); + break; + } + } + } + } + return matchedContentList; + } + + private List> getContentByBatch(String userId, String batchId) { + + Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_CONTENT_DB); List> contentList = new ArrayList>(); + Map queryMap = new HashMap(); + queryMap.put(JsonKey.USER_ID, userId); + queryMap.put(JsonKey.BATCH_ID, batchId); + Response response = + cassandraOperation.getRecordsByProperties( + dbInfo.getKeySpace(), dbInfo.getTableName(), queryMap); + contentList.addAll((List>) response.getResult().get(JsonKey.RESPONSE)); + return contentList; + } + + private List> getContentByPrimaryKeys(List primaryKeyList) { + Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_CONTENT_DB); - Map filters = - new HashMap() { - { - put("userid", userId); - put("contentid", contentIds); - put("batchid", batchId); - put("courseid", courseId); - } - }; + + List> contentList = new ArrayList>(); Response response = - cassandraOperation.getRecords(dbInfo.getKeySpace(), dbInfo.getTableName(), filters, null); + cassandraOperation.getRecordsByProperty( + dbInfo.getKeySpace(), dbInfo.getTableName(), JsonKey.ID, primaryKeyList); contentList.addAll((List>) response.getResult().get(JsonKey.RESPONSE)); return contentList; } + @SuppressWarnings("unchecked") + private List> getContentByCourses( + String userId, Map request) { + + Response response = new Response(); + Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_CONTENT_DB); + List courseIds = new ArrayList((List) request.get(JsonKey.COURSE_IDS)); + List> contentList = new ArrayList>(); + Map queryMap = new HashMap(); + queryMap.put(JsonKey.USER_ID, userId); + + for (String courseId : courseIds) { + queryMap.put(JsonKey.COURSE_ID, courseId); + response = + cassandraOperation.getRecordsByProperties( + dbInfo.getKeySpace(), dbInfo.getTableName(), queryMap); + contentList.addAll((List>) response.getResult().get(JsonKey.RESPONSE)); + } + return contentList; + } + + @SuppressWarnings("unchecked") + private List> getContentByContentIds( + String userId, Map request) { + Response response = null; + Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_CONTENT_DB); + List contentIds = + new ArrayList((List) request.get(JsonKey.CONTENT_IDS)); + + LinkedHashMap queryMap = new LinkedHashMap(); + queryMap.put(JsonKey.USER_ID, userId); + + List> contentList = new ArrayList>(); + + for (String contentId : contentIds) { + queryMap.put(JsonKey.CONTENT_ID, contentId); + response = + cassandraOperation.getRecordsByProperties( + dbInfo.getKeySpace(), dbInfo.getTableName(), queryMap); + contentList.addAll((List>) response.getResult().get(JsonKey.RESPONSE)); + } + return contentList; + } + + @SuppressWarnings("unchecked") private void removeUnwantedProperties(Response response) { List> list = (List>) response.getResult().get(JsonKey.RESPONSE); @@ -334,108 +428,16 @@ private void removeUnwantedProperties(Response response) { } } - private List> calculateProgressForUserCourses( - Request request, Map result) { - List> activeCourses = - (List>) (result.get(JsonKey.CONTENT)); - List> contentsForCourses = getcontentsForCourses(request, activeCourses); - - Map> contentIdsMapForCourses = - contentsForCourses - .stream() - .collect(Collectors.toMap(cMap -> (String) cMap.get(JsonKey.IDENTIFIER), cMap -> cMap)); - Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_CONTENT_DB); - Map primaryKey = new HashMap<>(); - primaryKey.put(JsonKey.USER_ID, request.getRequest().get(JsonKey.USER_ID)); - Response response = - cassandraOperation.getRecordById(dbInfo.getKeySpace(), dbInfo.getTableName(), primaryKey); - List> userContentIdsForCourses = - (List>) response.getResult().get(JsonKey.RESPONSE); - Map>> batchContentIdMap = new HashMap<>(); - userContentIdsForCourses - .stream() - .forEach( - contentConsumption -> { - if (!batchContentIdMap.containsKey( - (String) contentConsumption.get(JsonKey.BATCH_ID))) { - batchContentIdMap.put( - (String) contentConsumption.get(JsonKey.BATCH_ID), - new ArrayList>()); - } - batchContentIdMap - .get(contentConsumption.get(JsonKey.BATCH_ID)) - .add(contentConsumption); - }); - - List> updatedCourses = new ArrayList<>(); - for (Map course : activeCourses) { - course.put(COMPLETE_PERCENT, Integer.valueOf("0")); - if (!contentIdsMapForCourses.containsKey(course.get(JsonKey.COURSE_ID))) { - continue; - } - Map courseContent = - contentIdsMapForCourses.get(course.get(JsonKey.COURSE_ID)); - course.put(JsonKey.COURSE_NAME, courseContent.get(JsonKey.NAME)); - course.put(JsonKey.DESCRIPTION, courseContent.get(JsonKey.DESCRIPTION)); - course.put(JsonKey.LEAF_NODE_COUNT, courseContent.get(JsonKey.LEAF_NODE_COUNT)); - course.put(JsonKey.COURSE_LOGO_URL, courseContent.get(JsonKey.APP_ICON)); - course.put(JsonKey.CONTENT_ID, course.get(JsonKey.COURSE_ID)); - Integer progressPercentage = Integer.valueOf("0"); - int contentIdscompleted = 0; - List> contentIdsForBatch = - batchContentIdMap.get(course.get(JsonKey.BATCH_ID)); - if (CollectionUtils.isEmpty(contentIdsForBatch) - || CollectionUtils.isEmpty((List) courseContent.get("leafNodes"))) { - continue; - } - contentIdscompleted = - (int) - contentIdsForBatch - .stream() - .filter( - content -> - ProjectUtil.ProgressStatus.COMPLETED.getValue() - == (Integer) content.get(JsonKey.STATUS)) - .filter( - content -> - ((List) courseContent.get("leafNodes")) - .contains((String) content.get(JsonKey.CONTENT_ID))) - .count(); - - progressPercentage = - (int) - Math.round( - (contentIdscompleted * 100.0) - / ((List) courseContent.get("leafNodes")).size()); - course.put(JsonKey.PROGRESS, contentIdscompleted); - course.put(COMPLETE_PERCENT, progressPercentage); - updatedCourses.add(course); - } - return updatedCourses; - } - - private List> getcontentsForCourses( - Request request, List> activeCourses) { - List fields = new ArrayList<>(); - fields.add(JsonKey.IDENTIFIER); - fields.add(JsonKey.DESCRIPTION); - fields.add(JsonKey.NAME); - fields.add(JsonKey.LEAF_NODE_COUNT); - fields.add(JsonKey.APP_ICON); - fields.add("leafNodes"); - String requestBody = prepareCourseSearchRequest(activeCourses, fields); - ProjectLogger.log( - "LearnerStateActor:getcontentsForCourses: Request Body = " + requestBody, - LoggerEnum.INFO.name()); - Map contentsList = - ContentSearchUtil.searchContentSync( - null, requestBody, (Map) request.getRequest().get(JsonKey.HEADER)); - if (contentsList == null) { - new ProjectCommonException( - ResponseCode.internalError.getErrorCode(), - ResponseCode.internalError.getErrorMessage(), - ResponseCode.SERVER_ERROR.getResponseCode()); - } - return ((List>) (contentsList.get(JsonKey.CONTENTS))); + private String generatePrimaryKeyForContent( + String userId, String batchId, String courseId, String contentId) { + String key = + userId + + JsonKey.PRIMARY_KEY_DELIMETER + + contentId + + JsonKey.PRIMARY_KEY_DELIMETER + + courseId + + JsonKey.PRIMARY_KEY_DELIMETER + + batchId; + return OneWayHashing.encryptVal(key); } } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/LearnerStateUpdateActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/LearnerStateUpdateActor.java index 2029716ba0..db2a9b12bc 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/LearnerStateUpdateActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/LearnerStateUpdateActor.java @@ -6,19 +6,17 @@ import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.*; -import java.util.stream.Collectors; - -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; import org.apache.commons.lang3.StringUtils; import org.sunbird.actor.core.BaseActor; import org.sunbird.actor.router.ActorConfig; import org.sunbird.cassandra.CassandraOperation; -import org.sunbird.common.ElasticSearchHelper; import org.sunbird.common.exception.ProjectCommonException; -import org.sunbird.common.factory.EsClientFactory; -import org.sunbird.common.inf.ElasticSearchService; import org.sunbird.common.models.response.Response; import org.sunbird.common.models.util.ActorOperations; import org.sunbird.common.models.util.JsonKey; @@ -31,10 +29,9 @@ import org.sunbird.common.request.ExecutionContext; import org.sunbird.common.request.Request; import org.sunbird.common.responsecode.ResponseCode; -import org.sunbird.dto.SearchDTO; import org.sunbird.helper.ServiceFactory; import org.sunbird.learner.util.Util; -import scala.concurrent.Future; +import org.sunbird.telemetry.util.TelemetryUtil; /** * This actor to handle learner's state update operation . @@ -43,565 +40,584 @@ * @author Arvind */ @ActorConfig( - tasks = {"addContent"}, - asyncTasks = {} + tasks = {"addContent"}, + asyncTasks = {} ) public class LearnerStateUpdateActor extends BaseActor { - private CassandraOperation cassandraOperation = ServiceFactory.getInstance(); - - private Util.DbInfo consumptionDBInfo = Util.dbInfoMap.get(JsonKey.LEARNER_CONTENT_DB); - private Util.DbInfo userCourseDBInfo = Util.dbInfoMap.get(JsonKey.LEARNER_COURSE_DB); - private ElasticSearchService esService = EsClientFactory.getInstance(JsonKey.REST); - private SimpleDateFormat simpleDateFormat = ProjectUtil.getDateFormatter(); - - private enum ContentUpdateResponseKeys { - SUCCESS_CONTENTS, NOT_A_ON_GOING_BATCH, BATCH_NOT_EXISTS - } - - /** - * Receives the actor message and perform the add content operation. - * - * @param request Request - */ - @Override - public void onReceive(Request request) throws Throwable { - Util.initializeContext(request, TelemetryEnvKey.USER); - ExecutionContext.setRequestId(request.getRequestId()); - - if (request.getOperation().equalsIgnoreCase(ActorOperations.ADD_CONTENT.getValue())) { - String userId = (String) request.getRequest().get(JsonKey.USER_ID); - List> contentList = (List>) request.getRequest().get(JsonKey.CONTENTS); - if(CollectionUtils.isNotEmpty(contentList)) { - Map>> batchContentList = contentList.stream() - .filter(x -> StringUtils.isNotBlank((String)x.get("batchId"))) - .collect(Collectors.groupingBy(x -> {return (String) x.get("batchId");})); - List batchIds = batchContentList.keySet().stream().collect(Collectors.toList()); - Map>> batches = getBatches(batchIds).stream().collect(Collectors.groupingBy(x -> { return (String) x.get("batchId");})); - Map> respMessages = new HashMap<>(); - for (Map.Entry>> input: batchContentList.entrySet()) { - String batchId = input.getKey(); - if (batches.containsKey(batchId)) { - Map batchDetails = batches.get(batchId).get(0); - String courseId = (String) batchDetails.get("courseId"); - int status = getInteger(batchDetails.get("status"), 0); - if (status == 1) { - List contentIds = input.getValue().stream() - .map(c -> (String) c.get("contentId")).collect(Collectors.toList()); - Map> existingContents = getContents(userId, contentIds, batchId) - .stream().collect(Collectors.groupingBy(x -> { return (String) x.get("contentId"); })) - .entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().get(0))); - List> contents = input.getValue().stream().map(inputContent -> { - Map existingContent = existingContents.get(inputContent.get("contentId")); - return processContent(inputContent, existingContent, userId); - }).collect(Collectors.toList()); - - cassandraOperation.batchInsert(consumptionDBInfo.getKeySpace(), consumptionDBInfo.getTableName(), contents); - Map updatedBatch = getBatchCurrentStatus(batchId, userId, contents); - cassandraOperation.upsertRecord(userCourseDBInfo.getKeySpace(), userCourseDBInfo.getTableName(), updatedBatch); - // TODO: Generate Instruction event. Send userId, batchId, courseId, contents. - updateMessages(respMessages, ContentUpdateResponseKeys.SUCCESS_CONTENTS.name(), contentIds); - } else { - updateMessages(respMessages, ContentUpdateResponseKeys.NOT_A_ON_GOING_BATCH.name(), batchId); - } - } else { - updateMessages(respMessages, ContentUpdateResponseKeys.BATCH_NOT_EXISTS.name(), batchId); - } - } - Response response = new Response(); - response.getResult().putAll(respMessages); - sender().tell(response, self()); + private static final String CONTENT_STATE_INFO = "contentStateInfo"; + + private CassandraOperation cassandraOperation = ServiceFactory.getInstance(); + + /** + * Receives the actor message and perform the add content operation . + * + * @param request Request + */ + @SuppressWarnings("unchecked") + @Override + public void onReceive(Request request) throws Throwable { + Util.initializeContext(request, TelemetryEnvKey.USER); + // set request id fto thread loacl... + ExecutionContext.setRequestId(request.getRequestId()); + + Response response = new Response(); + if (request.getOperation().equalsIgnoreCase(ActorOperations.ADD_CONTENT.getValue())) { + Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_CONTENT_DB); + Util.DbInfo batchdbInfo = Util.dbInfoMap.get(JsonKey.COURSE_BATCH_DB); + // objects of telemetry event... + Map targetObject = null; + List> correlatedObject = null; + + String userId = (String) request.getRequest().get(JsonKey.USER_ID); + List> requestedcontentList = + (List>) request.getRequest().get(JsonKey.CONTENTS); + CopyOnWriteArrayList> contentList = + new CopyOnWriteArrayList<>(requestedcontentList); + request.getRequest().put(JsonKey.CONTENTS, contentList); + // map to hold the status of requested state of contents + Map contentStatusHolder = new HashMap<>(); + List validBatchIds = new ArrayList<>(); + List invalidBatchIds = new ArrayList<>(); + if (!(contentList.isEmpty())) { + ProjectLogger.log( + "LearnerStateUpdateActor:onReceive content state update method called for user and total content " + + userId + + " Contnet length=" + + contentList.size(), + LoggerEnum.INFO.name()); + int count = 0; + for (Map map : contentList) { + // replace the course id (equivalent to Ekstep content id) with One way hashing + // userId#courseId , bcoz in cassndra we are saving course id as userId#courseId + String batchId = (String) map.get(JsonKey.BATCH_ID); + boolean flag = true; + + // code to validate the whether request for valid batch range(start and end + // date) + if (!(StringUtils.isBlank(batchId)) && !validBatchIds.contains(batchId)) { + if (invalidBatchIds.contains(batchId)) { + contentList.remove(map); + continue; + } + Response batchResponse = + cassandraOperation.getRecordById( + batchdbInfo.getKeySpace(), batchdbInfo.getTableName(), batchId); + List> batches = + (List>) batchResponse.getResult().get(JsonKey.RESPONSE); + if (batches.isEmpty()) { + invalidBatchIds.add(batchId); + flag = false; } else { - throw new ProjectCommonException(ResponseCode.emptyContentsForUpdateBatchStatus.getErrorCode(), ResponseCode.emptyContentsForUpdateBatchStatus.getErrorMessage(), ResponseCode.CLIENT_ERROR.getResponseCode()); + Map batchInfo = batches.get(0); + flag = validateBatchRange(batchInfo); + if (flag) { + validBatchIds.add(batchId); + } } - } else { - onReceiveUnsupportedOperation(request.getOperation()); - } - } - - private List> getBatches(List batchIds) { - Map filters = new HashMap() {{ - put("batchId", batchIds); - }}; - SearchDTO dto = new SearchDTO(); - dto.getAdditionalProperties().put(JsonKey.FILTERS, filters); - Future> searchFuture = esService.search(dto, ProjectUtil.EsType.courseBatch.getTypeName()); - Map response = - (Map) ElasticSearchHelper.getResponseFromFuture(searchFuture); - return (List>) response.get(JsonKey.CONTENT); - } - private List> getContents(String userId, List contentIds, String batchId) { - Map filters = new HashMap() {{ - put("userid", userId); - put("contentid", contentIds); - put("batchid", batchId); - }}; - Response response = cassandraOperation.getRecords(consumptionDBInfo.getKeySpace(), consumptionDBInfo.getTableName(), filters, null); - List> resultList = (List>) response.getResult().get(JsonKey.RESPONSE); - if (CollectionUtils.isEmpty(resultList)) { - resultList = new ArrayList<>(); - } - return resultList; - } - - private Map processContent(Map inputContent, Map existingContent, String userId) { - int inputStatus = getInteger(inputContent.get("status"),0); - Date inputCompletedDate = parseDate(inputContent.get(JsonKey.LAST_COMPLETED_TIME), simpleDateFormat); - Date inputAccessTime = parseDate(inputContent.get(JsonKey.LAST_ACCESS_TIME), simpleDateFormat); - if (MapUtils.isNotEmpty(existingContent)) { - int viewCount = getInteger(existingContent.get(JsonKey.VIEW_COUNT), 0); - inputContent.put(JsonKey.VIEW_COUNT, viewCount + 1); - - Date accessTime = parseDate(existingContent.get(JsonKey.LAST_ACCESS_TIME), simpleDateFormat); - inputContent.put(JsonKey.LAST_ACCESS_TIME, compareTime(accessTime, inputAccessTime)); - - int existingStatus = getInteger(existingContent.get(JsonKey.PROGRESS), 0); - int inputProgress = getInteger(inputContent.get(JsonKey.PROGRESS), 0); - int existingProgress = getInteger(existingContent.get(JsonKey.PROGRESS), 0); - int progress = Collections.max(Arrays.asList(inputProgress, existingProgress)); - inputContent.put(JsonKey.PROGRESS, progress); - Date completedDate = parseDate(existingContent.get(JsonKey.LAST_COMPLETED_TIME), simpleDateFormat); - - int completedCount = getInteger(existingContent.get(JsonKey.COMPLETED_COUNT), 0); - if (inputStatus >= existingStatus) { - if (inputStatus == 2) { - completedCount = completedCount + 1; - inputContent.put(JsonKey.PROGRESS, 100); - inputContent.put(JsonKey.LAST_COMPLETED_TIME, compareTime(completedDate, inputCompletedDate)); - } - inputContent.put(JsonKey.COMPLETED_COUNT, completedCount); - } - if (completedCount >= 1) { - inputContent.put(JsonKey.STATUS, 2); + if (!flag) { + response + .getResult() + .put((String) map.get(JsonKey.CONTENT_ID), "BATCH NOT STARTED OR BATCH CLOSED"); + contentList.remove(map); + continue; } - } else { - if (inputStatus == 2) { - inputContent.put(JsonKey.COMPLETED_COUNT, 1); - inputContent.put(JsonKey.PROGRESS, 100); - inputContent.put(JsonKey.LAST_COMPLETED_TIME, compareTime(null, inputCompletedDate)); + } + map.putIfAbsent(JsonKey.COURSE_ID, JsonKey.NOT_AVAILABLE); + preOperation(map, userId, contentStatusHolder); + map.put(JsonKey.USER_ID, userId); + map.put(JsonKey.DATE_TIME, new Timestamp(new Date().getTime())); + try { + ProjectLogger.log( + "LearnerStateUpdateActor:onReceive: map " + map, LoggerEnum.INFO.name()); + if (count == 0 + && map.get(JsonKey.COURSE_ID) != null + && !(JsonKey.NOT_AVAILABLE.equalsIgnoreCase((String) map.get(JsonKey.COURSE_ID)))) { + updateUserCourseStatus( + generateUserCoursesPrimaryKey(map), + ProjectUtil.BulkProcessStatus.IN_PROGRESS.name()); + count++; } - inputContent.put(JsonKey.VIEW_COUNT, 1); - inputContent.put(JsonKey.LAST_ACCESS_TIME, compareTime(null, inputAccessTime)); + cassandraOperation.upsertRecord(dbInfo.getKeySpace(), dbInfo.getTableName(), map); + response.getResult().put((String) map.get(JsonKey.CONTENT_ID), JsonKey.SUCCESS); + } catch (Exception e) { + ProjectLogger.log( + "LearnerStateUpdateActor:onReceive Error occured during db update:" + e, + LoggerEnum.ERROR.name()); + response.getResult().put((String) map.get(JsonKey.CONTENT_ID), JsonKey.FAILED); + contentList.remove(map); + continue; + } + // create telemetry for user for each content ... + try { + targetObject = + TelemetryUtil.generateTargetObject( + (String) map.get(JsonKey.CONTENT_ID), + StringUtils.capitalize(JsonKey.CONTENT), + JsonKey.CREATE, + null); + // since this event will generate multiple times so nedd to recreate correlated + // objects every time ... + correlatedObject = new ArrayList<>(); + TelemetryUtil.generateCorrelatedObject( + (String) map.get(JsonKey.COURSE_ID), JsonKey.COURSE, null, correlatedObject); + TelemetryUtil.generateCorrelatedObject( + (String) map.get(JsonKey.BATCH_ID), TelemetryEnvKey.BATCH, null, correlatedObject); + Map rollUp = new HashMap<>(); + rollUp.put("l1", (String) map.get(JsonKey.COURSE_ID)); + TelemetryUtil.addTargetObjectRollUp(rollUp, targetObject); + TelemetryUtil.telemetryProcessingCall( + request.getRequest(), targetObject, correlatedObject); + } catch (Exception ex) { + ProjectLogger.log( + "LearnerStateUpdateActor:onReceive Error occured during telemetry:" + ex, + LoggerEnum.ERROR.name()); + } } - inputContent.put(JsonKey.LAST_UPDATED_TIME, ProjectUtil.getFormattedDate()); - inputContent.put("status", inputStatus); - inputContent.put("userId", userId); - return inputContent; - } - - private Map getBatchCurrentStatus(String batchId, String userId, List> contents) { - Map lastAccessedContent = contents.stream().max(Comparator.comparing(x -> { - return parseDate(x.get(JsonKey.LAST_ACCESS_TIME), simpleDateFormat); - })).get(); - Map courseBatch = new HashMap() {{ - put("batchId", batchId); - put("userId", userId); - put("lastreadcontentid", lastAccessedContent.get("contentId")); - put("lastreadcontentstatus", lastAccessedContent.get("status")); - }}; - return courseBatch; + } else { + ProjectLogger.log( + "LearnerStateUpdateActor:onReceive content state update method called for user and total content " + + userId + + " Contnet length= 0 ", + LoggerEnum.INFO.name()); + } + request.getRequest().put(CONTENT_STATE_INFO, contentStatusHolder); + updateUserCourses(request); + sender().tell(response, self()); + } else { + onReceiveUnsupportedOperation(request.getOperation()); } - - private void updateMessages(Map> messages, String key, Object value) { - if (!messages.containsKey(key)) { - messages.put(key, new ArrayList()); - } - if (value instanceof List) { - List list = (List) value; - messages.get(key).addAll(list); + } + + private void updateUserCourses(Request request) { + // get the list of content objects + List> contentList = + (List>) request.getRequest().get(JsonKey.CONTENTS); + // get the content state info + Map contentStateInfo = + (Map) request.get(this.CONTENT_STATE_INFO); + Map temp = new HashMap<>(); + ProjectLogger.log( + "LearnerStateUpdateActor:updateUserCourses method call started :", LoggerEnum.INFO.name()); + for (Map map : contentList) { + String contentid = (String) map.get(JsonKey.ID); + if (map.get(JsonKey.COURSE_ID) != null) { + // generate course table primary key as hash of userid##courseid##batchId + String primary = generateUserCoursesPrimaryKey(map); + if (temp.containsKey(primary)) { + Map innerMap = (Map) temp.get(primary); + innerMap.put( + JsonKey.CONTENT, + getLatestContent( + (Map) + ((Map) temp.get(primary)).get(JsonKey.CONTENT), + map)); + if (((int) map.get(JsonKey.COMPLETED_COUNT)) == 1 + && contentStateInfo.get(contentid) == 2) { + innerMap.put(JsonKey.PROGRESS, (Integer) innerMap.get(JsonKey.PROGRESS) + 1); + } } else { - messages.get(key).add(value); + Map innerMap = new HashMap<>(); + innerMap.put(JsonKey.CONTENT, map); + if (((int) map.get(JsonKey.COMPLETED_COUNT)) == 1 + && contentStateInfo.get(contentid) == 2) { + innerMap.put(JsonKey.PROGRESS, Integer.valueOf(1)); + } else { + innerMap.put(JsonKey.PROGRESS, Integer.valueOf(0)); + } + temp.put(primary, innerMap); } + } else { + ProjectLogger.log( + "LearnerStateUpdateActor:updateUserCourses Courseid is not present in request: " + + map.get(JsonKey.BATCH_ID) + + " userId " + + map.get(JsonKey.USER_ID), + LoggerEnum.INFO.name()); + } } - - private int getInteger(Object obj, int defaultValue) { - int value = defaultValue; - Number number = (Number) obj; - if (null != number) { - value = number.intValue(); + // logic to update the course + updateCourse(temp, contentStateInfo); + } + + /** + * Method to update the course_enrollment with the latest content information + * + * @param temp Map + * @param contentStateInfo Map + */ + @SuppressWarnings("unchecked") + private void updateCourse(Map temp, Map contentStateInfo) { + Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_COURSE_DB); + ProjectLogger.log( + "LearnerStateUpdateActor:updateCourse method called started:", LoggerEnum.INFO.name()); + for (Map.Entry entry : temp.entrySet()) { + String key = entry.getKey(); + Map value = (Map) entry.getValue(); + Response response = + cassandraOperation.getRecordById(dbInfo.getKeySpace(), dbInfo.getTableName(), key); + List> courseList = + (List>) response.getResult().get(JsonKey.RESPONSE); + Map course = null; + if (null != courseList && !courseList.isEmpty()) { + Map updateDb = new HashMap<>(); + course = courseList.get(0); + Integer courseProgress = 0; + if (ProjectUtil.isNotNull(course.get(JsonKey.COURSE_PROGRESS))) { + courseProgress = (Integer) course.get(JsonKey.COURSE_PROGRESS); } - return value; - } - - /** - * Method to update the course_enrollment with the latest content information - * - * @param temp Map - * @param contentStateInfo Map - */ - @SuppressWarnings("unchecked") - private void updateCourse(Map temp, Map contentStateInfo) { - Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_COURSE_DB); - ProjectLogger.log( - "LearnerStateUpdateActor:updateCourse method called started:", LoggerEnum.INFO.name()); - for (Map.Entry entry : temp.entrySet()) { - String key = entry.getKey(); - Map value = (Map) entry.getValue(); - Response response = - cassandraOperation.getRecordById(dbInfo.getKeySpace(), dbInfo.getTableName(), key); - List> courseList = - (List>) response.getResult().get(JsonKey.RESPONSE); - Map course = null; - if (null != courseList && !courseList.isEmpty()) { - Map updateDb = new HashMap<>(); - course = courseList.get(0); - Integer courseProgress = 0; - if (ProjectUtil.isNotNull(course.get(JsonKey.COURSE_PROGRESS))) { - courseProgress = (Integer) course.get(JsonKey.COURSE_PROGRESS); - } - courseProgress = courseProgress + (Integer) value.get("progress"); - // update status on basis of leaf node count and progress --- - if (course.containsKey(JsonKey.LEAF_NODE_COUNT) - && ProjectUtil.isNotNull(course.get(JsonKey.LEAF_NODE_COUNT))) { - Integer leafNodeCount = (Integer) course.get(JsonKey.LEAF_NODE_COUNT); - courseProgress = courseProgress > leafNodeCount ? leafNodeCount : courseProgress; - if (0 == leafNodeCount || (leafNodeCount > courseProgress)) { - updateDb.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.STARTED.getValue()); - } else { - if (ProgressStatus.COMPLETED.getValue() != (Integer) course.get(JsonKey.STATUS)) { - updateDb.put(JsonKey.COMPLETED_ON, new Timestamp(new Date().getTime())); - } - updateDb.put(JsonKey.STATUS, ProgressStatus.COMPLETED.getValue()); - } - } else if (ProjectUtil.isNull(course.get(JsonKey.LEAF_NODE_COUNT))) { - updateDb.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.STARTED.getValue()); - } - Timestamp ts = new Timestamp(new Date().getTime()); - updateDb.put(JsonKey.ID, course.get(JsonKey.ID)); - updateDb.put(JsonKey.COURSE_PROGRESS, courseProgress); - updateDb.put(JsonKey.DATE_TIME, ts); - updateDb.put( - JsonKey.LAST_READ_CONTENTID, - ((Map) value.get("content")).get(JsonKey.CONTENT_ID)); - updateDb.put( - JsonKey.LAST_READ_CONTENT_STATUS, - (contentStateInfo.get(((Map) value.get("content")).get(JsonKey.ID)))); - updateDb.put(JsonKey.PROCESSING_STATUS, ProjectUtil.BulkProcessStatus.COMPLETED.name()); - try { - cassandraOperation.upsertRecord(dbInfo.getKeySpace(), dbInfo.getTableName(), updateDb); - updateUserCourseStatus( - (String) course.get(JsonKey.ID), ProjectUtil.BulkProcessStatus.COMPLETED.name()); - ProjectLogger.log( - "LearnerStateUpdateActor:updateCourse user courses DB updated successfully : ", - LoggerEnum.INFO.name()); - updateDb.put(JsonKey.BATCH_ID, course.get(JsonKey.BATCH_ID)); - updateDb.put(JsonKey.USER_ID, course.get(JsonKey.USER_ID)); - updateDb.put(JsonKey.DATE_TIME, ProjectUtil.formatDate(ts)); - if (updateDb.containsKey(JsonKey.COMPLETED_ON)) { - updateDb.put( - JsonKey.COMPLETED_ON, - ProjectUtil.formatDate((Date) updateDb.get(JsonKey.COMPLETED_ON))); - } - updateUserCoursesToES(updateDb); - } catch (Exception ex) { - ProjectLogger.log( - "LearnerStateUpdateActor:updateCourse exception occured: " + ex, - LoggerEnum.ERROR.name()); - } - } else { - ProjectLogger.log( - "LearnerStateUpdateActor:updateCourse CourseList is empty or null: ", - LoggerEnum.ERROR.name()); + courseProgress = courseProgress + (Integer) value.get("progress"); + // update status on basis of leaf node count and progress --- + if (course.containsKey(JsonKey.LEAF_NODE_COUNT) + && ProjectUtil.isNotNull(course.get(JsonKey.LEAF_NODE_COUNT))) { + Integer leafNodeCount = (Integer) course.get(JsonKey.LEAF_NODE_COUNT); + courseProgress = courseProgress > leafNodeCount ? leafNodeCount : courseProgress; + if (0 == leafNodeCount || (leafNodeCount > courseProgress)) { + updateDb.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.STARTED.getValue()); + } else { + if (ProgressStatus.COMPLETED.getValue() != (Integer) course.get(JsonKey.STATUS)) { + updateDb.put(JsonKey.COMPLETED_ON, new Timestamp(new Date().getTime())); } + updateDb.put(JsonKey.STATUS, ProgressStatus.COMPLETED.getValue()); + } + } else if (ProjectUtil.isNull(course.get(JsonKey.LEAF_NODE_COUNT))) { + updateDb.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.STARTED.getValue()); } - } - - private Map getLatestContent( - Map current, Map next) { - SimpleDateFormat simpleDateFormat = ProjectUtil.getDateFormatter(); - simpleDateFormat.setLenient(false); - if (current.get(JsonKey.LAST_ACCESS_TIME) == null - && next.get(JsonKey.LAST_ACCESS_TIME) == null) { - return next; - } else if (current.get(JsonKey.LAST_ACCESS_TIME) == null) { - return next; - } else if (next.get(JsonKey.LAST_ACCESS_TIME) == null) { - return current; - } + Timestamp ts = new Timestamp(new Date().getTime()); + updateDb.put(JsonKey.ID, course.get(JsonKey.ID)); + updateDb.put(JsonKey.COURSE_PROGRESS, courseProgress); + updateDb.put(JsonKey.DATE_TIME, ts); + updateDb.put( + JsonKey.LAST_READ_CONTENTID, + ((Map) value.get("content")).get(JsonKey.CONTENT_ID)); + updateDb.put( + JsonKey.LAST_READ_CONTENT_STATUS, + (contentStateInfo.get(((Map) value.get("content")).get(JsonKey.ID)))); + updateDb.put(JsonKey.PROCESSING_STATUS, ProjectUtil.BulkProcessStatus.COMPLETED.name()); try { - Date currentUpdatedTime = - simpleDateFormat.parse((String) current.get(JsonKey.LAST_ACCESS_TIME)); - Date nextUpdatedTime = simpleDateFormat.parse((String) next.get(JsonKey.LAST_ACCESS_TIME)); - if (currentUpdatedTime.after(nextUpdatedTime)) { - return current; - } else { - return next; - } - } catch (ParseException e) { - ProjectLogger.log(e.getMessage(), e); + cassandraOperation.upsertRecord(dbInfo.getKeySpace(), dbInfo.getTableName(), updateDb); + updateUserCourseStatus( + (String) course.get(JsonKey.ID), ProjectUtil.BulkProcessStatus.COMPLETED.name()); + ProjectLogger.log( + "LearnerStateUpdateActor:updateCourse user courses DB updated successfully : ", + LoggerEnum.INFO.name()); + updateDb.put(JsonKey.BATCH_ID, course.get(JsonKey.BATCH_ID)); + updateDb.put(JsonKey.USER_ID, course.get(JsonKey.USER_ID)); + updateDb.put(JsonKey.DATE_TIME, ProjectUtil.formatDate(ts)); + if (updateDb.containsKey(JsonKey.COMPLETED_ON)) { + updateDb.put( + JsonKey.COMPLETED_ON, + ProjectUtil.formatDate((Date) updateDb.get(JsonKey.COMPLETED_ON))); + } + updateUserCoursesToES(updateDb); + } catch (Exception ex) { + ProjectLogger.log( + "LearnerStateUpdateActor:updateCourse exception occured: " + ex, + LoggerEnum.ERROR.name()); } - return null; + } else { + ProjectLogger.log( + "LearnerStateUpdateActor:updateCourse CourseList is empty or null: ", + LoggerEnum.ERROR.name()); + } + } + } + + private Map getLatestContent( + Map current, Map next) { + SimpleDateFormat simpleDateFormat = ProjectUtil.getDateFormatter(); + simpleDateFormat.setLenient(false); + if (current.get(JsonKey.LAST_ACCESS_TIME) == null + && next.get(JsonKey.LAST_ACCESS_TIME) == null) { + return next; + } else if (current.get(JsonKey.LAST_ACCESS_TIME) == null) { + return next; + } else if (next.get(JsonKey.LAST_ACCESS_TIME) == null) { + return current; + } + try { + Date currentUpdatedTime = + simpleDateFormat.parse((String) current.get(JsonKey.LAST_ACCESS_TIME)); + Date nextUpdatedTime = simpleDateFormat.parse((String) next.get(JsonKey.LAST_ACCESS_TIME)); + if (currentUpdatedTime.after(nextUpdatedTime)) { + return current; + } else { + return next; + } + } catch (ParseException e) { + ProjectLogger.log(e.getMessage(), e); + } + return null; + } + + private boolean validateBatchRange(Map batchInfo) { + + String start = (String) batchInfo.get(JsonKey.START_DATE); + String end = (String) batchInfo.get(JsonKey.END_DATE); + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + Date todaydate = null; + Date startDate = null; + Date endDate = null; + + try { + todaydate = format.parse(format.format(new Date())); + startDate = format.parse(start); + endDate = null; + if (!(StringUtils.isBlank(end))) { + endDate = format.parse(end); + } + } catch (ParseException e) { + ProjectLogger.log("Date parse exception while parsing batch start and end date", e); + return false; } - private boolean validateBatchRange(Map batchInfo) { - - String start = (String) batchInfo.get(JsonKey.START_DATE); - String end = (String) batchInfo.get(JsonKey.END_DATE); - - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); - Date todaydate = null; - Date startDate = null; - Date endDate = null; + if (todaydate.compareTo(startDate) < 0) { + return false; + } - try { - todaydate = format.parse(format.format(new Date())); - startDate = format.parse(start); - endDate = null; - if (!(StringUtils.isBlank(end))) { - endDate = format.parse(end); - } - } catch (ParseException e) { - ProjectLogger.log("Date parse exception while parsing batch start and end date", e); - return false; + return (!(null != endDate && todaydate.compareTo(endDate) > 0)); + } + + /** + * Method te perform the per operation on contents like setting the status , last completed and + * access time etc. + */ + @SuppressWarnings("unchecked") + private void preOperation( + Map req, String userId, Map contentStateHolder) + throws ParseException { + ProjectLogger.log( + "LearnerStateUpdateActor:preOperation method called.", LoggerEnum.INFO.name()); + SimpleDateFormat simpleDateFormat = ProjectUtil.getDateFormatter(); + simpleDateFormat.setLenient(false); + + Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_CONTENT_DB); + req.put(JsonKey.ID, generatePrimaryKey(req, userId)); + contentStateHolder.put( + (String) req.get(JsonKey.ID), ((BigInteger) req.get(JsonKey.STATUS)).intValue()); + Response response = + cassandraOperation.getRecordById( + dbInfo.getKeySpace(), dbInfo.getTableName(), (String) req.get(JsonKey.ID)); + + List> resultList = + (List>) response.getResult().get(JsonKey.RESPONSE); + + if (!(resultList.isEmpty())) { + Map result = resultList.get(0); + int currentStatus = (int) result.get(JsonKey.STATUS); + int requestedStatus = ((BigInteger) req.get(JsonKey.STATUS)).intValue(); + + Integer currentProgressStatus = 0; + if (isNotNull(result.get(JsonKey.CONTENT_PROGRESS))) { + currentProgressStatus = (Integer) result.get(JsonKey.CONTENT_PROGRESS); + } + if (isNotNull(req.get(JsonKey.CONTENT_PROGRESS))) { + Integer requestedProgressStatus = + ((BigInteger) req.get(JsonKey.CONTENT_PROGRESS)).intValue(); + if (requestedProgressStatus > currentProgressStatus) { + req.put(JsonKey.CONTENT_PROGRESS, requestedProgressStatus); + } else { + req.put(JsonKey.CONTENT_PROGRESS, currentProgressStatus); } - - if (todaydate.compareTo(startDate) < 0) { - return false; + } else { + req.put(JsonKey.CONTENT_PROGRESS, currentProgressStatus); + } + + Date accessTime = parseDate(result.get(JsonKey.LAST_ACCESS_TIME), simpleDateFormat); + Date requestAccessTime = parseDate(req.get(JsonKey.LAST_ACCESS_TIME), simpleDateFormat); + + Date completedDate = parseDate(result.get(JsonKey.LAST_COMPLETED_TIME), simpleDateFormat); + Date requestCompletedTime = parseDate(req.get(JsonKey.LAST_COMPLETED_TIME), simpleDateFormat); + + int completedCount; + if (!(isNullCheck(result.get(JsonKey.COMPLETED_COUNT)))) { + completedCount = (int) result.get(JsonKey.COMPLETED_COUNT); + } else { + completedCount = 0; + } + int viewCount; + if (!(isNullCheck(result.get(JsonKey.VIEW_COUNT)))) { + viewCount = (int) result.get(JsonKey.VIEW_COUNT); + } else { + viewCount = 0; + } + + if (requestedStatus >= currentStatus) { + req.put(JsonKey.STATUS, requestedStatus); + if (requestedStatus == 2) { + req.put(JsonKey.COMPLETED_COUNT, completedCount + 1); + req.put(JsonKey.LAST_COMPLETED_TIME, compareTime(completedDate, requestCompletedTime)); + } else { + req.put(JsonKey.COMPLETED_COUNT, completedCount); } - - return (!(null != endDate && todaydate.compareTo(endDate) > 0)); - } - - /** - * Method te perform the per operation on contents like setting the status , last completed and - * access time etc. - */ - @SuppressWarnings("unchecked") - private void preOperation( - Map req, String userId, Map contentStateHolder) - throws ParseException { - ProjectLogger.log( - "LearnerStateUpdateActor:preOperation method called.", LoggerEnum.INFO.name()); - SimpleDateFormat simpleDateFormat = ProjectUtil.getDateFormatter(); - simpleDateFormat.setTimeZone(TimeZone.getTimeZone("IST")); - simpleDateFormat.setLenient(false); - - Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_CONTENT_DB); - req.put(JsonKey.ID, generatePrimaryKey(req, userId)); - contentStateHolder.put( - (String) req.get(JsonKey.ID), ((BigInteger) req.get(JsonKey.STATUS)).intValue()); - Response response = - cassandraOperation.getRecordById( - dbInfo.getKeySpace(), dbInfo.getTableName(), (String) req.get(JsonKey.ID)); - - List> resultList = - (List>) response.getResult().get(JsonKey.RESPONSE); - - if (!(resultList.isEmpty())) { - Map result = resultList.get(0); - int currentStatus = (int) result.get(JsonKey.STATUS); - int requestedStatus = ((BigInteger) req.get(JsonKey.STATUS)).intValue(); - - Integer currentProgressStatus = 0; - if (isNotNull(result.get(JsonKey.CONTENT_PROGRESS))) { - currentProgressStatus = (Integer) result.get(JsonKey.CONTENT_PROGRESS); - } - if (isNotNull(req.get(JsonKey.CONTENT_PROGRESS))) { - Integer requestedProgressStatus = - ((BigInteger) req.get(JsonKey.CONTENT_PROGRESS)).intValue(); - if (requestedProgressStatus > currentProgressStatus) { - req.put(JsonKey.CONTENT_PROGRESS, requestedProgressStatus); - } else { - req.put(JsonKey.CONTENT_PROGRESS, currentProgressStatus); - } - } else { - req.put(JsonKey.CONTENT_PROGRESS, currentProgressStatus); - } - - Date accessTime = parseDate(result.get(JsonKey.LAST_ACCESS_TIME), simpleDateFormat); - Date requestAccessTime = parseDate(req.get(JsonKey.LAST_ACCESS_TIME), simpleDateFormat); - - Date completedDate = parseDate(result.get(JsonKey.LAST_COMPLETED_TIME), simpleDateFormat); - Date requestCompletedTime = parseDate(req.get(JsonKey.LAST_COMPLETED_TIME), simpleDateFormat); - - int completedCount; - if (!(isNullCheck(result.get(JsonKey.COMPLETED_COUNT)))) { - completedCount = (int) result.get(JsonKey.COMPLETED_COUNT); - } else { - completedCount = 0; - } - int viewCount; - if (!(isNullCheck(result.get(JsonKey.VIEW_COUNT)))) { - viewCount = (int) result.get(JsonKey.VIEW_COUNT); - } else { - viewCount = 0; - } - - if (requestedStatus >= currentStatus) { - req.put(JsonKey.STATUS, requestedStatus); - if (requestedStatus == 2) { - req.put(JsonKey.COMPLETED_COUNT, completedCount + 1); - req.put(JsonKey.LAST_COMPLETED_TIME, compareTime(completedDate, requestCompletedTime)); - } else { - req.put(JsonKey.COMPLETED_COUNT, completedCount); - } - req.put(JsonKey.VIEW_COUNT, viewCount + 1); - req.put(JsonKey.LAST_ACCESS_TIME, compareTime(accessTime, requestAccessTime)); - req.put(JsonKey.LAST_UPDATED_TIME, ProjectUtil.getFormattedDate()); - - } else { - req.put(JsonKey.STATUS, currentStatus); - req.put(JsonKey.VIEW_COUNT, viewCount + 1); - req.put(JsonKey.LAST_ACCESS_TIME, compareTime(accessTime, requestAccessTime)); - req.put(JsonKey.LAST_UPDATED_TIME, ProjectUtil.getFormattedDate()); - req.put(JsonKey.COMPLETED_COUNT, completedCount); - } - ProjectLogger.log( - "LearnerStateUpdateActor:preOperation User already read this content." - + req.get(JsonKey.ID), - LoggerEnum.INFO.name()); + req.put(JsonKey.VIEW_COUNT, viewCount + 1); + req.put(JsonKey.LAST_ACCESS_TIME, compareTime(accessTime, requestAccessTime)); + req.put(JsonKey.LAST_UPDATED_TIME, ProjectUtil.getFormattedDate()); + + } else { + req.put(JsonKey.STATUS, currentStatus); + req.put(JsonKey.VIEW_COUNT, viewCount + 1); + req.put(JsonKey.LAST_ACCESS_TIME, compareTime(accessTime, requestAccessTime)); + req.put(JsonKey.LAST_UPDATED_TIME, ProjectUtil.getFormattedDate()); + req.put(JsonKey.COMPLETED_COUNT, completedCount); + } + ProjectLogger.log( + "LearnerStateUpdateActor:preOperation User already read this content." + + req.get(JsonKey.ID), + LoggerEnum.INFO.name()); + } else { + ProjectLogger.log( + "LearnerStateUpdateActor:preOperation User is reading this content first time." + + req.get(JsonKey.ID), + LoggerEnum.INFO.name()); + // IT IS NEW CONTENT SIMPLY ADD IT + Date requestCompletedTime = parseDate(req.get(JsonKey.LAST_COMPLETED_TIME), simpleDateFormat); + if (null != req.get(JsonKey.STATUS)) { + int requestedStatus = ((BigInteger) req.get(JsonKey.STATUS)).intValue(); + req.put(JsonKey.STATUS, requestedStatus); + if (requestedStatus == 2) { + req.put(JsonKey.COMPLETED_COUNT, 1); + req.put(JsonKey.LAST_COMPLETED_TIME, compareTime(null, requestCompletedTime)); } else { - ProjectLogger.log( - "LearnerStateUpdateActor:preOperation User is reading this content first time." - + req.get(JsonKey.ID), - LoggerEnum.INFO.name()); - // IT IS NEW CONTENT SIMPLY ADD IT - Date requestCompletedTime = parseDate(req.get(JsonKey.LAST_COMPLETED_TIME), simpleDateFormat); - if (null != req.get(JsonKey.STATUS)) { - int requestedStatus = ((BigInteger) req.get(JsonKey.STATUS)).intValue(); - req.put(JsonKey.STATUS, requestedStatus); - if (requestedStatus == 2) { - req.put(JsonKey.COMPLETED_COUNT, 1); - req.put(JsonKey.LAST_COMPLETED_TIME, compareTime(null, requestCompletedTime)); - } else { - req.put(JsonKey.COMPLETED_COUNT, 0); - } - - } else { - req.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.NOT_STARTED.getValue()); - req.put(JsonKey.COMPLETED_COUNT, 0); - } - - int progressStatus = 0; - if (isNotNull(req.get(JsonKey.CONTENT_PROGRESS))) { - progressStatus = ((BigInteger) req.get(JsonKey.CONTENT_PROGRESS)).intValue(); - } - req.put(JsonKey.CONTENT_PROGRESS, progressStatus); + req.put(JsonKey.COMPLETED_COUNT, 0); + } - req.put(JsonKey.VIEW_COUNT, 1); - Date requestAccessTime = parseDate(req.get(JsonKey.LAST_ACCESS_TIME), simpleDateFormat); + } else { + req.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.NOT_STARTED.getValue()); + req.put(JsonKey.COMPLETED_COUNT, 0); + } - req.put(JsonKey.LAST_UPDATED_TIME, ProjectUtil.getFormattedDate()); + int progressStatus = 0; + if (isNotNull(req.get(JsonKey.CONTENT_PROGRESS))) { + progressStatus = ((BigInteger) req.get(JsonKey.CONTENT_PROGRESS)).intValue(); + } + req.put(JsonKey.CONTENT_PROGRESS, progressStatus); - if (requestAccessTime != null) { - req.put(JsonKey.LAST_ACCESS_TIME, req.get(JsonKey.LAST_ACCESS_TIME)); - } else { - req.put(JsonKey.LAST_ACCESS_TIME, ProjectUtil.getFormattedDate()); - } - } - ProjectLogger.log( - "LearnerStateUpdateActor:preOperation end for content ." + req.get(JsonKey.ID), - LoggerEnum.INFO.name()); - } + req.put(JsonKey.VIEW_COUNT, 1); + Date requestAccessTime = parseDate(req.get(JsonKey.LAST_ACCESS_TIME), simpleDateFormat); - private Date parseDate(Object obj, SimpleDateFormat formatter) { - if (null == obj || ((String) obj).equalsIgnoreCase(JsonKey.NULL)) { - return null; - } - Date date; - try { - date = formatter.parse((String) obj); - } catch (ParseException ex) { - ProjectLogger.log(ex.getMessage(), ex); - throw new ProjectCommonException( - ResponseCode.invalidDateFormat.getErrorCode(), - ResponseCode.invalidDateFormat.getErrorMessage(), - ResponseCode.CLIENT_ERROR.getResponseCode()); - } - return date; - } + req.put(JsonKey.LAST_UPDATED_TIME, ProjectUtil.getFormattedDate()); - private String compareTime(Date currentValue, Date requestedValue) { - SimpleDateFormat simpleDateFormat = ProjectUtil.getDateFormatter(); - simpleDateFormat.setLenient(false); - if (currentValue == null && requestedValue == null) { - return ProjectUtil.getFormattedDate(); - } else if (currentValue == null) { - return simpleDateFormat.format(requestedValue); - } else if (null == requestedValue) { - return simpleDateFormat.format(currentValue); - } - return (requestedValue.after(currentValue) - ? simpleDateFormat.format(requestedValue) - : simpleDateFormat.format(currentValue)); + if (requestAccessTime != null) { + req.put(JsonKey.LAST_ACCESS_TIME, req.get(JsonKey.LAST_ACCESS_TIME)); + } else { + req.put(JsonKey.LAST_ACCESS_TIME, ProjectUtil.getFormattedDate()); + } } - - private String generatePrimaryKey(Map req, String userId) { - String contentId = (String) req.get(JsonKey.CONTENT_ID); - String courseId = (String) req.get(JsonKey.COURSE_ID); - String batchId = (String) req.get(JsonKey.BATCH_ID); - String key = - userId - + JsonKey.PRIMARY_KEY_DELIMETER - + contentId - + JsonKey.PRIMARY_KEY_DELIMETER - + courseId - + JsonKey.PRIMARY_KEY_DELIMETER - + batchId; - return OneWayHashing.encryptVal(key); + ProjectLogger.log( + "LearnerStateUpdateActor:preOperation end for content ." + req.get(JsonKey.ID), + LoggerEnum.INFO.name()); + } + + private Date parseDate(Object obj, SimpleDateFormat formatter) throws ParseException { + if (null == obj || ((String) obj).equalsIgnoreCase(JsonKey.NULL)) { + return null; } - - private boolean isNullCheck(Object obj) { - return null == obj; + Date date; + try { + date = formatter.parse((String) obj); + } catch (ParseException ex) { + ProjectLogger.log(ex.getMessage(), ex); + throw new ProjectCommonException( + ResponseCode.invalidDateFormat.getErrorCode(), + ResponseCode.invalidDateFormat.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); } - - /** - * This method will combined map values with delimiter and create an encrypted key. - * - * @param req Map - * @return String encrypted value - */ - private String generateUserCoursesPrimaryKey(Map req) { - String userId = (String) req.get(JsonKey.USER_ID); - String courseId = (String) req.get(JsonKey.COURSE_ID); - String batchId = (String) req.get(JsonKey.BATCH_ID); - return OneWayHashing.encryptVal( - userId - + JsonKey.PRIMARY_KEY_DELIMETER - + courseId - + JsonKey.PRIMARY_KEY_DELIMETER - + batchId); + return date; + } + + private String compareTime(Date currentValue, Date requestedValue) { + SimpleDateFormat simpleDateFormat = ProjectUtil.getDateFormatter(); + simpleDateFormat.setLenient(false); + if (currentValue == null && requestedValue == null) { + return ProjectUtil.getFormattedDate(); + } else if (currentValue == null) { + return simpleDateFormat.format(requestedValue); + } else if (null == requestedValue) { + return simpleDateFormat.format(currentValue); } - - private void updateUserCoursesToES(Map courseMap) { - Request request = new Request(); - request.setOperation(ActorOperations.UPDATE_USR_COURSES_INFO_ELASTIC.getValue()); - request.getRequest().put(JsonKey.USER_COURSES, courseMap); - try { - ProjectLogger.log( - "LearnerStateUpdateActor:updateUserCoursesToES call for background to save in ES:", - LoggerEnum.INFO.name()); - tellToAnother(request); - } catch (Exception ex) { - ProjectLogger.log( - "LearnerStateUpdateActor:updateUserCoursesToES Exception occurred during saving user count to Es : " - + ex, - LoggerEnum.ERROR.name()); - } + return (requestedValue.after(currentValue) + ? simpleDateFormat.format(requestedValue) + : simpleDateFormat.format(currentValue)); + } + + private String generatePrimaryKey(Map req, String userId) { + String contentId = (String) req.get(JsonKey.CONTENT_ID); + String courseId = (String) req.get(JsonKey.COURSE_ID); + String batchId = (String) req.get(JsonKey.BATCH_ID); + String key = + userId + + JsonKey.PRIMARY_KEY_DELIMETER + + contentId + + JsonKey.PRIMARY_KEY_DELIMETER + + courseId + + JsonKey.PRIMARY_KEY_DELIMETER + + batchId; + return OneWayHashing.encryptVal(key); + } + + private boolean isNullCheck(Object obj) { + return null == obj; + } + + /** + * This method will combined map values with delimiter and create an encrypted key. + * + * @param req Map + * @return String encrypted value + */ + private String generateUserCoursesPrimaryKey(Map req) { + String userId = (String) req.get(JsonKey.USER_ID); + String courseId = (String) req.get(JsonKey.COURSE_ID); + String batchId = (String) req.get(JsonKey.BATCH_ID); + return OneWayHashing.encryptVal( + userId + + JsonKey.PRIMARY_KEY_DELIMETER + + courseId + + JsonKey.PRIMARY_KEY_DELIMETER + + batchId); + } + + private void updateUserCoursesToES(Map courseMap) { + Request request = new Request(); + request.setOperation(ActorOperations.UPDATE_USR_COURSES_INFO_ELASTIC.getValue()); + request.getRequest().put(JsonKey.USER_COURSES, courseMap); + try { + ProjectLogger.log( + "LearnerStateUpdateActor:updateUserCoursesToES call for background to save in ES:", + LoggerEnum.INFO.name()); + tellToAnother(request); + } catch (Exception ex) { + ProjectLogger.log( + "LearnerStateUpdateActor:updateUserCoursesToES Exception occurred during saving user count to Es : " + + ex, + LoggerEnum.ERROR.name()); } - - private void updateUserCourseStatus(String key, String status) { - Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_COURSE_DB); - Map request = new HashMap<>(); - request.put(JsonKey.PROCESSING_STATUS, status); - request.put(JsonKey.ID, key); - Response response = - cassandraOperation.updateRecord(dbInfo.getKeySpace(), dbInfo.getTableName(), request); - if (response != null) { - ProjectLogger.log( - "LearnerStateUpdateActor:updateUserCourseStatus course process status updated :" - + "status= " - + status - + " " - + response.get(JsonKey.RESPONSE), - LoggerEnum.INFO.name()); - } else { - ProjectLogger.log( - "LearnerStateUpdateActor:updateUserCourseStatus course process status update fail :" - + "status= " - + status, - LoggerEnum.INFO.name()); - } + } + + private void updateUserCourseStatus(String key, String status) { + Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_COURSE_DB); + Map request = new HashMap<>(); + request.put(JsonKey.PROCESSING_STATUS, status); + request.put(JsonKey.ID, key); + Response response = + cassandraOperation.updateRecord(dbInfo.getKeySpace(), dbInfo.getTableName(), request); + if (response != null) { + ProjectLogger.log( + "LearnerStateUpdateActor:updateUserCourseStatus course process status updated :" + + "status= " + + status + + " " + + response.get(JsonKey.RESPONSE), + LoggerEnum.INFO.name()); + } else { + ProjectLogger.log( + "LearnerStateUpdateActor:updateUserCourseStatus course process status update fail :" + + "status= " + + status, + LoggerEnum.INFO.name()); } + } } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/PageManagementActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/PageManagementActor.java index 53e00a44c5..f31cbe2e9a 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/PageManagementActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/PageManagementActor.java @@ -1,7 +1,5 @@ package org.sunbird.learner.actors; -import static org.sunbird.common.models.util.JsonKey.*; - import akka.dispatch.Futures; import akka.dispatch.Mapper; import akka.pattern.Patterns; @@ -51,6 +49,9 @@ import scala.concurrent.Future; import scala.concurrent.Promise; +import static org.sunbird.common.models.util.JsonKey.*; +import static org.sunbird.common.models.util.ProjectLogger.log; + /** * This actor will handle page management operation . * @@ -697,7 +698,7 @@ private Map searchFromES(Map map, String dataSou searcDto.setSortBy((Map) map.get(JsonKey.SORT_BY)); String type = ""; if (JsonKey.BATCH.equalsIgnoreCase(dataSource)) { - type = ProjectUtil.EsType.courseBatch.getTypeName(); + type = ProjectUtil.EsType.course.getTypeName(); } else { return null; } @@ -819,7 +820,7 @@ private List> parsePage(Map pageDO, String m private void validateOrg(String orgId) { Map result = userOrgService.getOrganisationById(orgId); - if (MapUtils.isEmpty(result) || !orgId.equals(result.get(ID))) { + if(MapUtils.isEmpty(result) || !orgId.equals(result.get(ID))){ throw new ProjectCommonException( ResponseCode.invalidOrgId.getErrorCode(), ResponseCode.invalidOrgId.getErrorMessage(), diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BaseBulkUploadActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BaseBulkUploadActor.java index 5ac2751817..9cd1d926cc 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BaseBulkUploadActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BaseBulkUploadActor.java @@ -8,23 +8,32 @@ import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.ArrayUtils; import org.sunbird.actor.core.BaseActor; import org.sunbird.common.exception.ProjectCommonException; +import org.sunbird.common.models.response.Response; import org.sunbird.common.models.util.JsonKey; +import org.sunbird.common.models.util.LoggerEnum; import org.sunbird.common.models.util.ProjectLogger; import org.sunbird.common.models.util.ProjectUtil; import org.sunbird.common.models.util.ProjectUtil.BulkProcessStatus; +import org.sunbird.common.request.Request; import org.sunbird.common.responsecode.ResponseCode; import org.sunbird.learner.actors.bulkupload.dao.BulkUploadProcessDao; import org.sunbird.learner.actors.bulkupload.dao.BulkUploadProcessTaskDao; import org.sunbird.learner.actors.bulkupload.dao.impl.BulkUploadProcessDaoImpl; import org.sunbird.learner.actors.bulkupload.dao.impl.BulkUploadProcessTaskDaoImpl; import org.sunbird.learner.actors.bulkupload.model.BulkUploadProcess; +import org.sunbird.learner.actors.bulkupload.model.BulkUploadProcessTask; +import org.sunbird.learner.util.Util; /** * Actor contains the common functionality for bulk upload. @@ -225,4 +234,260 @@ protected Integer getBatchSize(String key) { } return batchSize; } + + protected Integer validateAndParseRecords( + byte[] fileByteArray, String processId, Map additionalRowFields) + throws IOException { + return validateAndParseRecords(fileByteArray, processId, additionalRowFields, null, false); + } + + protected Integer validateAndParseRecords( + byte[] fileByteArray, + String processId, + Map additionalRowFields, + Map csvColumnMap, + boolean toLowerCase) + throws IOException { + + Integer sequence = 0; + Integer count = 0; + CSVReader csvReader = null; + String[] csvLine; + String[] csvColumns = null; + Map record = new HashMap<>(); + List records = new ArrayList<>(); + try { + csvReader = getCsvReader(fileByteArray, ',', '"', 0); + while ((csvLine = csvReader.readNext()) != null) { + if (ProjectUtil.isNotEmptyStringArray(csvLine)) { + continue; + } + if (sequence == 0) { + csvColumns = trimColumnAttributes(csvLine); + } else { + for (int j = 0; j < csvColumns.length && j < csvLine.length; j++) { + String value = (csvLine[j].trim().length() == 0 ? null : csvLine[j].trim()); + String coulumn = toLowerCase ? csvColumns[j].toLowerCase() : csvColumns[j]; + if (csvColumnMap != null && csvColumnMap.get(coulumn) != null) { + record.put((String) csvColumnMap.get(coulumn), value); + } else { + record.put(csvColumns[j], value); + } + } + record.putAll(additionalRowFields); + BulkUploadProcessTask tasks = new BulkUploadProcessTask(); + tasks.setStatus(ProjectUtil.BulkProcessStatus.NEW.getValue()); + tasks.setSequenceId(sequence); + tasks.setProcessId(processId); + tasks.setData(mapper.writeValueAsString(record)); + tasks.setCreatedOn(new Timestamp(System.currentTimeMillis())); + records.add(tasks); + count++; + if (count >= CASSANDRA_BATCH_SIZE) { + performBatchInsert(records); + records.clear(); + count = 0; + } + record.clear(); + } + sequence++; + } + if (count != 0) { + performBatchInsert(records); + count = 0; + records.clear(); + } + } catch (Exception ex) { + BulkUploadProcess bulkUploadProcess = + getBulkUploadProcessForFailedStatus(processId, BulkProcessStatus.FAILED.getValue(), ex); + bulkUploadDao.update(bulkUploadProcess); + throw ex; + } finally { + IOUtils.closeQuietly(csvReader); + } + // since one record represents the header + return sequence - 1; + } + + protected void performBatchInsert(List records) { + try { + bulkUploadProcessTaskDao.insertBatchRecord(records); + } catch (Exception ex) { + ProjectLogger.log("Cassandra batch insert failed , performing retry logic.", LoggerEnum.INFO); + for (BulkUploadProcessTask task : records) { + try { + bulkUploadProcessTaskDao.create(task); + } catch (Exception exception) { + ProjectLogger.log( + "Cassandra Insert failed for BulkUploadProcessTask-" + + task.getProcessId() + + task.getSequenceId(), + exception); + } + } + } + } + + protected void performBatchUpdate(List records) { + try { + bulkUploadProcessTaskDao.updateBatchRecord(records); + } catch (Exception ex) { + ProjectLogger.log("Cassandra batch update failed , performing retry logic.", LoggerEnum.INFO); + for (BulkUploadProcessTask task : records) { + try { + bulkUploadProcessTaskDao.update(task); + } catch (Exception exception) { + ProjectLogger.log( + "Cassandra Update failed for BulkUploadProcessTask-" + + task.getProcessId() + + task.getSequenceId(), + exception); + } + } + } + } + + protected void validateFileHeaderFields( + Map req, String[] bulkAllowedFields, Boolean allFieldsMandatory) + throws IOException { + validateFileHeaderFields(req, bulkAllowedFields, allFieldsMandatory, false, null, null); + } + + protected void validateFileHeaderFields( + Map req, + String[] bulkAllowedFields, + Boolean allFieldsMandatory, + boolean toLower) + throws IOException { + validateFileHeaderFields(req, bulkAllowedFields, allFieldsMandatory, toLower, null, null); + } + + protected void validateFileHeaderFields( + Map req, + String[] bulkLocationAllowedFields, + Boolean allFieldsMandatory, + boolean toLower, + List mandatoryColumns, + Map supportedColumnsMap) + throws IOException { + byte[] fileByteArray = (byte[]) req.get(JsonKey.FILE); + + CSVReader csvReader = null; + Boolean flag = true; + String[] csvLine; + try { + csvReader = getCsvReader(fileByteArray, ',', '"', 0); + while (flag) { + csvLine = csvReader.readNext(); + if (csvLine == null) { + ProjectCommonException.throwClientErrorException( + ResponseCode.csvFileEmpty, ResponseCode.csvFileEmpty.getErrorMessage()); + } + if (ProjectUtil.isNotEmptyStringArray(csvLine)) { + continue; + } + csvLine = trimColumnAttributes(csvLine); + validateBulkUploadFields(csvLine, bulkLocationAllowedFields, allFieldsMandatory, toLower); + if (mandatoryColumns != null) { + validateMandatoryColumns(mandatoryColumns, csvLine, supportedColumnsMap); + } + flag = false; + } + csvLine = csvReader.readNext(); + if (csvLine == null) { + ProjectCommonException.throwClientErrorException( + ResponseCode.errorCsvNoDataRows, ResponseCode.errorCsvNoDataRows.getErrorMessage()); + } + } catch (Exception ex) { + ProjectLogger.log( + "BaseBulkUploadActor:validateFileHeaderFields: Exception = " + ex.getMessage(), ex); + throw ex; + } finally { + IOUtils.closeQuietly(csvReader); + } + } + + private void validateMandatoryColumns( + List mandatoryColumns, String[] csvLine, Map supportedColumnsMap) { + List csvColumns = new ArrayList<>(); + List csvMappedColumns = new ArrayList<>(); + Arrays.stream(csvLine) + .forEach( + x -> { + csvColumns.add(x.toLowerCase()); + csvMappedColumns.add((String) supportedColumnsMap.get(x.toLowerCase())); + }); + + mandatoryColumns.forEach( + column -> { + if (!(csvMappedColumns.contains(column))) { + throw new ProjectCommonException( + ResponseCode.mandatoryParamsMissing.getErrorCode(), + ResponseCode.mandatoryParamsMissing.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode(), + column); + } + }); + } + + public BulkUploadProcess handleUpload(String objectType, String createdBy) throws IOException { + String processId = ProjectUtil.getUniqueIdFromTimestamp(1); + Response response = new Response(); + response.getResult().put(JsonKey.PROCESS_ID, processId); + BulkUploadProcess bulkUploadProcess = getBulkUploadProcess(processId, objectType, createdBy, 0); + Response res = bulkUploadDao.create(bulkUploadProcess); + if (((String) res.get(JsonKey.RESPONSE)).equalsIgnoreCase(JsonKey.SUCCESS)) { + sender().tell(response, self()); + } else { + ProjectLogger.log( + "BaseBulkUploadActor:handleUpload: Error creating record in bulk_upload_process."); + throw new ProjectCommonException( + ResponseCode.SERVER_ERROR.getErrorCode(), + ResponseCode.SERVER_ERROR.getErrorMessage(), + ResponseCode.SERVER_ERROR.getResponseCode()); + } + return bulkUploadProcess; + } + + public void processBulkUpload( + int recordCount, + String processId, + BulkUploadProcess bulkUploadProcess, + String operation, + String[] allowedFields) + throws IOException { + ProjectLogger.log( + "BaseBulkUploadActor: processBulkUpload called with operation = " + operation); + + bulkUploadProcess.setTaskCount(recordCount); + bulkUploadDao.update(bulkUploadProcess); + + Request request = new Request(); + request.put(JsonKey.PROCESS_ID, processId); + request.put(JsonKey.FIELDS, allowedFields); + request.setOperation(operation); + + tellToAnother(request); + } + + public BulkUploadProcess getBulkUploadProcess( + String processId, String objectType, String requestedBy, Integer taskCount) { + BulkUploadProcess bulkUploadProcess = new BulkUploadProcess(); + bulkUploadProcess.setId(processId); + bulkUploadProcess.setObjectType(objectType); + bulkUploadProcess.setUploadedBy(requestedBy); + bulkUploadProcess.setUploadedDate(ProjectUtil.getFormattedDate()); + bulkUploadProcess.setCreatedBy(requestedBy); + bulkUploadProcess.setCreatedOn(new Timestamp(Calendar.getInstance().getTime().getTime())); + bulkUploadProcess.setProcessStartTime(ProjectUtil.getFormattedDate()); + bulkUploadProcess.setStatus(ProjectUtil.BulkProcessStatus.NEW.getValue()); + bulkUploadProcess.setTaskCount(taskCount); + + Map user = Util.getUserbyUserId(requestedBy); + if (user != null) { + bulkUploadProcess.setOrganisationId((String) user.get(JsonKey.ROOT_ORG_ID)); + } + + return bulkUploadProcess; + } } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BaseBulkUploadBackgroundJobActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BaseBulkUploadBackgroundJobActor.java new file mode 100644 index 0000000000..5c5abd36a8 --- /dev/null +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BaseBulkUploadBackgroundJobActor.java @@ -0,0 +1,316 @@ +package org.sunbird.learner.actors.bulkupload; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.opencsv.CSVWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.sunbird.common.Constants; +import org.sunbird.common.exception.ProjectCommonException; +import org.sunbird.common.models.util.BulkUploadJsonKey; +import org.sunbird.common.models.util.JsonKey; +import org.sunbird.common.models.util.LoggerEnum; +import org.sunbird.common.models.util.ProjectLogger; +import org.sunbird.common.models.util.ProjectUtil; +import org.sunbird.common.request.Request; +import org.sunbird.common.responsecode.ResponseCode; +import org.sunbird.common.util.CloudStorageUtil; +import org.sunbird.common.util.CloudStorageUtil.CloudStorageType; +import org.sunbird.learner.actors.bulkupload.model.BulkUploadProcess; +import org.sunbird.learner.actors.bulkupload.model.BulkUploadProcessTask; +import org.sunbird.learner.actors.bulkupload.model.StorageDetails; + +public abstract class BaseBulkUploadBackgroundJobActor extends BaseBulkUploadActor { + + protected void setSuccessTaskStatus( + BulkUploadProcessTask task, + ProjectUtil.BulkProcessStatus status, + Map row, + String action) + throws JsonProcessingException { + row.put(JsonKey.OPERATION, action); + task.setSuccessResult(mapper.writeValueAsString(row)); + task.setStatus(status.getValue()); + } + + protected void setTaskStatus( + BulkUploadProcessTask task, + ProjectUtil.BulkProcessStatus status, + String failureMessage, + Map row, + String action) + throws JsonProcessingException { + row.put(JsonKey.OPERATION, action); + if (ProjectUtil.BulkProcessStatus.COMPLETED.getValue() == status.getValue()) { + task.setSuccessResult(mapper.writeValueAsString(row)); + task.setStatus(status.getValue()); + } else if (ProjectUtil.BulkProcessStatus.FAILED.getValue() == status.getValue()) { + row.put(JsonKey.ERROR_MSG, failureMessage); + task.setStatus(status.getValue()); + task.setFailureResult(mapper.writeValueAsString(row)); + } + } + + public void handleBulkUploadBackground(Request request, Function function) { + String processId = (String) request.get(JsonKey.PROCESS_ID); + String logMessagePrefix = + MessageFormat.format( + "BaseBulkUploadBackGroundJobActor:handleBulkUploadBackground:{0}: ", processId); + + ProjectLogger.log(logMessagePrefix + "called", LoggerEnum.INFO); + + BulkUploadProcess bulkUploadProcess = bulkUploadDao.read(processId); + if (null == bulkUploadProcess) { + ProjectLogger.log(logMessagePrefix + "Invalid process ID.", LoggerEnum.ERROR); + return; + } + + int status = bulkUploadProcess.getStatus(); + if (!(ProjectUtil.BulkProcessStatus.COMPLETED.getValue() == status) + || ProjectUtil.BulkProcessStatus.INTERRUPT.getValue() == status) { + try { + function.apply(bulkUploadProcess); + } catch (Exception e) { + bulkUploadProcess.setStatus(ProjectUtil.BulkProcessStatus.FAILED.getValue()); + bulkUploadProcess.setFailureResult(e.getMessage()); + bulkUploadDao.update(bulkUploadProcess); + ProjectLogger.log( + logMessagePrefix + "Exception occurred with error message = " + e.getMessage(), + LoggerEnum.INFO, + e); + } + } + + bulkUploadProcess.setStatus(ProjectUtil.BulkProcessStatus.COMPLETED.getValue()); + bulkUploadDao.update(bulkUploadProcess); + } + + public void processBulkUpload( + BulkUploadProcess bulkUploadProcess, + Function function, + Map outputColumnMap, + String[] outputColumnsOrder) { + String logMessagePrefix = + MessageFormat.format( + "BaseBulkUploadBackGroundJobActor:processBulkUpload:{0}: ", bulkUploadProcess.getId()); + Integer sequence = 0; + Integer taskCount = bulkUploadProcess.getTaskCount(); + List> successList = new LinkedList<>(); + List> failureList = new LinkedList<>(); + while (sequence < taskCount) { + Integer nextSequence = sequence + CASSANDRA_BATCH_SIZE; + Map queryMap = new HashMap<>(); + queryMap.put(JsonKey.PROCESS_ID, bulkUploadProcess.getId()); + Map sequenceRange = new HashMap<>(); + sequenceRange.put(Constants.GT, sequence); + sequenceRange.put(Constants.LTE, nextSequence); + queryMap.put(BulkUploadJsonKey.SEQUENCE_ID, sequenceRange); + List tasks = bulkUploadProcessTaskDao.readByPrimaryKeys(queryMap); + if (tasks == null) { + ProjectLogger.log( + logMessagePrefix + + "No bulkUploadProcessTask found for process id: " + + bulkUploadProcess.getId() + + " and range " + + sequence + + ":" + + nextSequence, + LoggerEnum.INFO); + sequence = nextSequence; + continue; + } + function.apply(tasks); + + try { + for (BulkUploadProcessTask task : tasks) { + + if (task.getStatus().equals(ProjectUtil.BulkProcessStatus.FAILED.getValue())) { + failureList.add( + mapper.readValue( + task.getFailureResult(), new TypeReference>() {})); + } else if (task.getStatus().equals(ProjectUtil.BulkProcessStatus.COMPLETED.getValue())) { + successList.add( + mapper.readValue( + task.getSuccessResult(), new TypeReference>() {})); + } + } + + } catch (IOException e) { + ProjectLogger.log( + logMessagePrefix + "Exception occurred with error message = " + e.getMessage(), + LoggerEnum.INFO, + e); + } + performBatchUpdate(tasks); + sequence = nextSequence; + } + setCompletionStatus( + bulkUploadProcess, successList, failureList, outputColumnMap, outputColumnsOrder); + } + + private void setCompletionStatus( + BulkUploadProcess bulkUploadProcess, + List successList, + List failureList, + Map outputColumnsMap, + String[] outputColumnsOrder) { + String logMessagePrefix = + MessageFormat.format( + "BaseBulkUploadBackGroundJobActor:processBulkUpload:{0}: ", bulkUploadProcess.getId()); + try { + + ProjectLogger.log(logMessagePrefix + "completed", LoggerEnum.INFO); + bulkUploadProcess.setSuccessResult(ProjectUtil.convertMapToJsonString(successList)); + bulkUploadProcess.setFailureResult(ProjectUtil.convertMapToJsonString(failureList)); + bulkUploadProcess.setStatus(ProjectUtil.BulkProcessStatus.COMPLETED.getValue()); + StorageDetails storageDetails = + uploadResultToCloud( + bulkUploadProcess, successList, failureList, outputColumnsMap, outputColumnsOrder); + bulkUploadProcess.setEncryptedStorageDetails(storageDetails); + + } catch (Exception e) { + ProjectLogger.log( + logMessagePrefix + "Exception occurred with error message = " + e.getMessage(), + LoggerEnum.INFO, + e); + } + bulkUploadDao.update(bulkUploadProcess); + } + + protected void validateMandatoryFields( + Map csvColumns, BulkUploadProcessTask task, String[] mandatoryFields) + throws JsonProcessingException { + if (mandatoryFields != null) { + for (String field : mandatoryFields) { + if (StringUtils.isEmpty((String) csvColumns.get(field))) { + String errorMessage = + MessageFormat.format( + ResponseCode.mandatoryParamsMissing.getErrorMessage(), new Object[] {field}); + + setTaskStatus( + task, ProjectUtil.BulkProcessStatus.FAILED, errorMessage, csvColumns, JsonKey.CREATE); + + ProjectCommonException.throwClientErrorException( + ResponseCode.mandatoryParamsMissing, errorMessage); + } + } + } + } + + private StorageDetails uploadResultToCloud( + BulkUploadProcess bulkUploadProcess, + List> successList, + List> failureList, + Map outputColumnsMap, + String[] outputColumnsOrder) + throws IOException { + + String objKey = generateObjectKey(bulkUploadProcess); + File file = null; + try { + file = getFileHandle(bulkUploadProcess.getObjectType(), bulkUploadProcess.getId()); + writeResultsToFile(file, successList, failureList, outputColumnsMap, outputColumnsOrder); + CloudStorageUtil.upload( + CloudStorageType.AZURE, + bulkUploadProcess.getObjectType(), + objKey, + file.getAbsolutePath()); + return new StorageDetails( + CloudStorageType.AZURE.getType(), bulkUploadProcess.getObjectType(), objKey); + } finally { + FileUtils.deleteQuietly(file); + } + } + + private File getFileHandle(String objType, String processId) { + String logMessagePrefix = + MessageFormat.format("BaseBulkUploadBackGroundJobActor:getFileHandle:{0}: ", processId); + File file = null; + try { + file = File.createTempFile(objType, "upload"); + } catch (IOException e) { + ProjectLogger.log( + logMessagePrefix + "Exception occurred with error message = " + e.getMessage(), + LoggerEnum.INFO, + e); + } + return file; + } + + private String generateObjectKey(BulkUploadProcess bulkUploadProcess) { + String objType = bulkUploadProcess.getObjectType(); + String processId = bulkUploadProcess.getId(); + return "bulk_upload_" + objType + "_" + processId + ".csv"; + } + + private void writeResultsToFile( + File file, + List> successList, + List> failureList, + Map outputColumnsMap, + String[] outputColumnsOrder) + throws IOException { + try (CSVWriter csvWriter = new CSVWriter(new FileWriter(file)); ) { + List headerRowWithInternalNames = new ArrayList<>(Arrays.asList(outputColumnsOrder)); + + headerRowWithInternalNames.add(JsonKey.BULK_UPLOAD_STATUS); + headerRowWithInternalNames.add(JsonKey.BULK_UPLOAD_ERROR); + + if (MapUtils.isNotEmpty(outputColumnsMap)) { + List headerRowWithDisplayNames = new ArrayList<>(); + headerRowWithInternalNames.forEach( + s -> { + if (outputColumnsMap.containsKey(s)) { + headerRowWithDisplayNames.add(outputColumnsMap.get(s)); + } else { + headerRowWithDisplayNames.add(s); + } + }); + csvWriter.writeNext(headerRowWithDisplayNames.toArray(new String[0])); + } else { + csvWriter.writeNext(headerRowWithInternalNames.toArray(new String[0])); + } + + addResults(successList, headerRowWithInternalNames, csvWriter); + addResults(failureList, headerRowWithInternalNames, csvWriter); + csvWriter.flush(); + } + } + + private void addResults( + List> resultList, List headerRows, CSVWriter csvWriter) { + resultList + .stream() + .forEach( + map -> { + preProcessResult(map); + String[] nextLine = new String[headerRows.size()]; + String errMsg = (String) map.get(JsonKey.ERROR_MSG); + int i = 0; + for (String field : headerRows) { + if (JsonKey.BULK_UPLOAD_STATUS.equals(field)) { + nextLine[i++] = errMsg == null ? JsonKey.SUCCESS : JsonKey.FAILED; + } else if (JsonKey.BULK_UPLOAD_ERROR.equals(field)) { + nextLine[i++] = errMsg == null ? "" : errMsg; + } else { + nextLine[i++] = String.valueOf(map.get(field)); + } + } + csvWriter.writeNext(nextLine); + }); + } + + public abstract void preProcessResult(Map result); +} diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BulkUploadBackGroundJobActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BulkUploadBackGroundJobActor.java index e30f3b92b8..9c4d178af5 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BulkUploadBackGroundJobActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BulkUploadBackGroundJobActor.java @@ -1,5 +1,8 @@ package org.sunbird.learner.actors.bulkupload; +import static org.sunbird.learner.util.Util.isNotNull; +import static org.sunbird.learner.util.Util.isNull; + import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; @@ -13,32 +16,36 @@ import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.sunbird.actor.core.BaseActor; import org.sunbird.actor.router.ActorConfig; import org.sunbird.cassandra.CassandraOperation; import org.sunbird.common.ElasticSearchHelper; +import org.sunbird.common.exception.ProjectCommonException; import org.sunbird.common.factory.EsClientFactory; import org.sunbird.common.inf.ElasticSearchService; import org.sunbird.common.models.response.Response; -import org.sunbird.common.models.util.ActorOperations; -import org.sunbird.common.models.util.JsonKey; -import org.sunbird.common.models.util.LoggerEnum; -import org.sunbird.common.models.util.ProjectLogger; -import org.sunbird.common.models.util.ProjectUtil; +import org.sunbird.common.models.util.*; +import org.sunbird.common.models.util.ProjectUtil.EsIndex; import org.sunbird.common.models.util.ProjectUtil.EsType; -import org.sunbird.common.models.util.TelemetryEnvKey; +import org.sunbird.common.models.util.ProjectUtil.Status; +import org.sunbird.common.models.util.datasecurity.DecryptionService; +import org.sunbird.common.models.util.datasecurity.EncryptionService; +import org.sunbird.common.models.util.datasecurity.OneWayHashing; import org.sunbird.common.request.ExecutionContext; import org.sunbird.common.request.Request; +import org.sunbird.common.request.UserRequestValidator; import org.sunbird.common.responsecode.ResponseCode; +import org.sunbird.common.responsecode.ResponseMessage; +import org.sunbird.dto.SearchDTO; import org.sunbird.helper.ServiceFactory; -import org.sunbird.learner.actors.coursebatch.dao.UserCoursesDao; -import org.sunbird.learner.actors.coursebatch.dao.impl.UserCoursesDaoImpl; -import org.sunbird.learner.actors.coursebatch.service.UserCoursesService; +import org.sunbird.learner.util.DataCacheHandler; +import org.sunbird.learner.util.UserUtility; import org.sunbird.learner.util.Util; -import org.sunbird.models.user.courses.UserCourses; +import org.sunbird.models.user.User; +import org.sunbird.services.sso.SSOManager; +import org.sunbird.services.sso.SSOServiceFactory; import org.sunbird.telemetry.util.TelemetryUtil; -import org.sunbird.userorg.UserOrgService; -import org.sunbird.userorg.UserOrgServiceImpl; import scala.concurrent.Future; /** @@ -54,11 +61,18 @@ public class BulkUploadBackGroundJobActor extends BaseActor { private String processId = ""; private final Util.DbInfo bulkDb = Util.dbInfoMap.get(JsonKey.BULK_OP_DB); + private final EncryptionService encryptionService = + org.sunbird.common.models.util.datasecurity.impl.ServiceFactory.getEncryptionServiceInstance( + null); + private final DecryptionService decryptionService = + org.sunbird.common.models.util.datasecurity.impl.ServiceFactory.getDecryptionServiceInstance( + null); + private final PropertiesCache propertiesCache = PropertiesCache.getInstance(); + private final List locnIdList = new ArrayList<>(); private final CassandraOperation cassandraOperation = ServiceFactory.getInstance(); + private final SSOManager ssoManager = SSOServiceFactory.getInstance(); private ObjectMapper mapper = new ObjectMapper(); private static ElasticSearchService esService = EsClientFactory.getInstance(JsonKey.REST); - private UserCoursesDao userCourseDao = UserCoursesDaoImpl.getInstance(); - private UserOrgService userOrgService = new UserOrgServiceImpl(); @Override public void onReceive(Request request) throws Throwable { @@ -87,19 +101,29 @@ private void process(Request actorMessage) { "Exception occurred while converting json String to List in BulkUploadBackGroundJobActor : ", e); } - if (((String) dataMap.get(JsonKey.OBJECT_TYPE)).equalsIgnoreCase(JsonKey.BATCH_LEARNER_ENROL) - || ((String) dataMap.get(JsonKey.OBJECT_TYPE)) - .equalsIgnoreCase(JsonKey.BATCH_LEARNER_UNENROL)) { - processBatchEnrollment(jsonList, processId, (String) dataMap.get(JsonKey.OBJECT_TYPE)); + if (((String) dataMap.get(JsonKey.OBJECT_TYPE)).equalsIgnoreCase(JsonKey.USER)) { + long startTime = System.currentTimeMillis(); + ProjectLogger.log( + "BulkUploadBackGroundJobActor:processUserInfo start at : " + startTime, + LoggerEnum.INFO.name()); + processUserInfo(jsonList, processId, (String) dataMap.get(JsonKey.UPLOADED_BY)); + ProjectLogger.log( + "BulkUploadBackGroundJobActor:processUserInfo Total time taken : for processId : " + + processId + + " : " + + (System.currentTimeMillis() - startTime), + LoggerEnum.INFO.name()); + } else if (((String) dataMap.get(JsonKey.OBJECT_TYPE)).equalsIgnoreCase(JsonKey.BATCH)) { + processBatchEnrollment(jsonList, processId); } } } @SuppressWarnings("unchecked") - private void processBatchEnrollment( - List> jsonList, String processId, String objectType) { + private void processBatchEnrollment(List> jsonList, String processId) { // update status from NEW to INProgress updateStatusForProcessing(processId); + Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.COURSE_BATCH_DB); List> successResultList = new ArrayList<>(); List> failureResultList = new ArrayList<>(); @@ -112,30 +136,18 @@ private void processBatchEnrollment( Map tempSuccessList = new HashMap<>(); String batchId = (String) batchMap.get(JsonKey.BATCH_ID); - Future> resultF = - esService.getDataByIdentifier(ProjectUtil.EsType.course.getTypeName(), batchId); - Map courseBatchObject = - (Map) ElasticSearchHelper.getResponseFromFuture(resultF); - String msg = validateBatchInfo(courseBatchObject); + Response courseBatchResult = + cassandraOperation.getRecordById(dbInfo.getKeySpace(), dbInfo.getTableName(), batchId); + String msg = validateBatchInfo(courseBatchResult); if (msg.equals(JsonKey.SUCCESS)) { - try { - List userList = - new ArrayList<>( - Arrays.asList((((String) batchMap.get(JsonKey.USER_IDs)).split(",")))); - if (JsonKey.BATCH_LEARNER_ENROL.equalsIgnoreCase(objectType)) { - validateBatchUserListAndAdd( - courseBatchObject, batchId, userList, tempFailList, tempSuccessList); - } else if (JsonKey.BATCH_LEARNER_UNENROL.equalsIgnoreCase(objectType)) { - validateBatchUserListAndRemove( - courseBatchObject, batchId, userList, tempFailList, tempSuccessList); - } - failureListMap.put(batchId, tempFailList.get(JsonKey.FAILURE_RESULT)); - successListMap.put(batchId, tempSuccessList.get(JsonKey.SUCCESS_RESULT)); - } catch (Exception ex) { - ProjectLogger.log("Exception Occurred while bulk enrollment : batchId=" + batchId, ex); - batchMap.put(JsonKey.ERROR_MSG, ex.getMessage()); - failureResultList.add(batchMap); - } + List> courseList = + (List>) courseBatchResult.get(JsonKey.RESPONSE); + List userList = + new ArrayList<>(Arrays.asList((((String) batchMap.get(JsonKey.USER_IDs)).split(",")))); + validateBatchUserListAndAdd( + courseList.get(0), batchId, userList, tempFailList, tempSuccessList); + failureListMap.put(batchId, tempFailList.get(JsonKey.FAILURE_RESULT)); + successListMap.put(batchId, tempSuccessList.get(JsonKey.SUCCESS_RESULT)); } else { batchMap.put(JsonKey.ERROR_MSG, msg); failureResultList.add(batchMap); @@ -171,88 +183,133 @@ private void validateBatchUserListAndAdd( List userIds, Map failList, Map successList) { + Util.DbInfo dbInfo = Util.dbInfoMap.get(JsonKey.COURSE_BATCH_DB); + Util.DbInfo userOrgdbInfo = Util.dbInfoMap.get(JsonKey.USR_ORG_DB); List> failedUserList = new ArrayList<>(); List> passedUserList = new ArrayList<>(); Map map = null; List createdFor = (List) courseBatchObject.get(JsonKey.COURSE_CREATED_FOR); - List> userDetails = userOrgService.getUsersByIds(userIds); - Map userToRootOrg = - userDetails - .stream() - .collect( - Collectors.toMap( - user -> (String) user.get(JsonKey.ID), user -> getRootOrgFromUserMap(user))); + Map participants = + (Map) courseBatchObject.get(JsonKey.PARTICIPANT); + if (participants == null) { + participants = new HashMap<>(); + } // check whether can update user or not for (String userId : userIds) { - if (!userToRootOrg.containsKey(userId) || createdFor.contains(userToRootOrg.get(userId))) { - map = new HashMap<>(); - map.put(userId, ResponseCode.userNotAssociatedToOrg.getErrorMessage()); - failedUserList.add(map); - continue; - } - UserCourses userCourses = userCourseDao.read(batchId, userId); - if (userCourses != null) { - if (!userCourses.isActive()) { - Map updateAttributes = new HashMap<>(); - updateAttributes.put(JsonKey.ACTIVE, ProjectUtil.ActiveStatus.ACTIVE.getValue()); - updateAttributes.put(JsonKey.COURSE_ENROLL_DATE, ProjectUtil.getFormattedDate()); - userCourseDao.update(batchId, userId, updateAttributes); - String id = UserCoursesService.generateUserCourseESId(batchId, userId); - esService.update(EsType.usercourses.getTypeName(), id, updateAttributes); + if (!(participants.containsKey(userId))) { + Response dbResponse = + cassandraOperation.getRecordsByProperty( + userOrgdbInfo.getKeySpace(), userOrgdbInfo.getTableName(), JsonKey.USER_ID, userId); + List> userOrgResult = + (List>) dbResponse.get(JsonKey.RESPONSE); + + if (userOrgResult.isEmpty()) { + map = new HashMap<>(); + map.put(userId, ResponseCode.userNotAssociatedToOrg.getErrorMessage()); + failedUserList.add(map); + continue; } + boolean flag = false; + for (int i = 0; i < userOrgResult.size() && !flag; i++) { + Map usrOrgDetail = userOrgResult.get(i); + if (createdFor.contains(usrOrgDetail.get(JsonKey.ORGANISATION_ID))) { + participants.put( + userId, + addUserCourses( + batchId, + (String) courseBatchObject.get(JsonKey.COURSE_ID), + userId, + (Map) (courseBatchObject.get(JsonKey.COURSE_ADDITIONAL_INFO)))); + flag = true; + } + } + if (flag) { + map = new HashMap<>(); + map.put(userId, JsonKey.SUCCESS); + passedUserList.add(map); + } else { + map = new HashMap<>(); + map.put(userId, ResponseCode.userNotAssociatedToOrg.getErrorMessage()); + failedUserList.add(map); + } + } else { - addUserCourses( - batchId, - (String) courseBatchObject.get(JsonKey.COURSE_ID), - userId, - (Map) (courseBatchObject.get(JsonKey.COURSE_ADDITIONAL_INFO))); + map = new HashMap<>(); + map.put(userId, JsonKey.SUCCESS); + passedUserList.add(map); } - map = new HashMap<>(); - map.put(userId, JsonKey.SUCCESS); - passedUserList.add(map); } - + courseBatchObject.put(JsonKey.PARTICIPANT, participants); + cassandraOperation.updateRecord(dbInfo.getKeySpace(), dbInfo.getTableName(), courseBatchObject); successList.put(JsonKey.SUCCESS_RESULT, passedUserList); failList.put(JsonKey.FAILURE_RESULT, failedUserList); - } - - @SuppressWarnings("unchecked") - private String getRootOrgFromUserMap(Map userInfo) { - String rootOrg = (String) userInfo.get(JsonKey.ROOT_ORG_ID); - Map registeredOrgInfo = - (Map) userInfo.get(JsonKey.REGISTERED_ORG); - if (registeredOrgInfo != null && !registeredOrgInfo.isEmpty()) { - if (null != registeredOrgInfo.get(JsonKey.IS_ROOT_ORG) - && (Boolean) registeredOrgInfo.get(JsonKey.IS_ROOT_ORG)) { - rootOrg = (String) registeredOrgInfo.get(JsonKey.ID); - } + // process Audit Log + ProjectLogger.log("method call going to satrt for ES--....."); + Request request = new Request(); + request.setOperation(ActorOperations.UPDATE_COURSE_BATCH_ES.getValue()); + request.getRequest().put(JsonKey.BATCH, courseBatchObject); + ProjectLogger.log("making a call to save Course Batch data to ES"); + try { + tellToAnother(request); + } catch (Exception ex) { + ProjectLogger.log( + "Exception Occurred during saving Course Batch to Es while updating Course Batch : ", ex); } - return rootOrg; } private Boolean addUserCourses( String batchId, String courseId, String userId, Map additionalCourseInfo) { Util.DbInfo courseEnrollmentdbInfo = Util.dbInfoMap.get(JsonKey.LEARNER_COURSE_DB); + Util.DbInfo coursePublishdbInfo = Util.dbInfoMap.get(JsonKey.COURSE_PUBLISHED_STATUS); + Response response = + cassandraOperation.getRecordById( + coursePublishdbInfo.getKeySpace(), coursePublishdbInfo.getTableName(), courseId); + List> resultList = + (List>) response.get(JsonKey.RESPONSE); + if (!ProjectUtil.CourseMgmtStatus.LIVE + .getValue() + .equalsIgnoreCase(additionalCourseInfo.get(JsonKey.STATUS))) { + if (resultList.isEmpty()) { + return false; + } + Map publishStatus = resultList.get(0); + if (Status.ACTIVE.getValue() != (Integer) publishStatus.get(JsonKey.STATUS)) { + return false; + } + } Boolean flag = false; Timestamp ts = new Timestamp(new Date().getTime()); Map userCourses = new HashMap<>(); - userCourses.put(JsonKey.BATCH_ID, batchId); userCourses.put(JsonKey.USER_ID, userId); + userCourses.put(JsonKey.BATCH_ID, batchId); userCourses.put(JsonKey.COURSE_ID, courseId); + userCourses.put(JsonKey.ID, generatePrimaryKey(userCourses)); + userCourses.put(JsonKey.CONTENT_ID, courseId); userCourses.put(JsonKey.COURSE_ENROLL_DATE, ProjectUtil.getFormattedDate()); userCourses.put(JsonKey.ACTIVE, ProjectUtil.ActiveStatus.ACTIVE.getValue()); userCourses.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.NOT_STARTED.getValue()); userCourses.put(JsonKey.DATE_TIME, ts); userCourses.put(JsonKey.COURSE_PROGRESS, 0); + userCourses.put(JsonKey.COURSE_LOGO_URL, additionalCourseInfo.get(JsonKey.COURSE_LOGO_URL)); + userCourses.put(JsonKey.COURSE_NAME, additionalCourseInfo.get(JsonKey.COURSE_NAME)); + userCourses.put(JsonKey.DESCRIPTION, additionalCourseInfo.get(JsonKey.DESCRIPTION)); + if (!StringUtils.isBlank(additionalCourseInfo.get(JsonKey.LEAF_NODE_COUNT))) { + userCourses.put( + JsonKey.LEAF_NODE_COUNT, + Integer.parseInt("" + additionalCourseInfo.get(JsonKey.LEAF_NODE_COUNT))); + } + userCourses.put(JsonKey.TOC_URL, additionalCourseInfo.get(JsonKey.TOC_URL)); try { cassandraOperation.insertRecord( courseEnrollmentdbInfo.getKeySpace(), courseEnrollmentdbInfo.getTableName(), userCourses); + // TODO: for some reason, ES indexing is failing with TimestelemetryProcessingCalltamp value. + // need to + // check and + // correct it. userCourses.put(JsonKey.DATE_TIME, ProjectUtil.formatDate(ts)); - String id = UserCoursesService.generateUserCourseESId(batchId, userId); - userCourses.put(JsonKey.ID, id); insertUserCoursesToES(userCourses); flag = true; Map targetObject = @@ -278,104 +335,431 @@ private void insertUserCoursesToES(Map courseMap) { } } - private void updateUserCoursesToES(Map courseMap) { - Request request = new Request(); - request.setOperation(ActorOperations.UPDATE_USR_COURSES_INFO_ELASTIC.getValue()); - request.getRequest().put(JsonKey.USER_COURSES, courseMap); + @SuppressWarnings("unchecked") + private String validateBatchInfo(Response courseBatchResult) { + // check batch exist in db or not + List> courseList = + (List>) courseBatchResult.get(JsonKey.RESPONSE); + if ((courseList.isEmpty())) { + return ResponseCode.invalidCourseBatchId.getErrorMessage(); + } + Map courseBatchObject = courseList.get(0); + // check whether coursebbatch type is invite only or not ... + if (ProjectUtil.isNull(courseBatchObject.get(JsonKey.ENROLLMENT_TYPE)) + || !((String) courseBatchObject.get(JsonKey.ENROLLMENT_TYPE)) + .equalsIgnoreCase(JsonKey.INVITE_ONLY)) { + return ResponseCode.enrollmentTypeValidation.getErrorMessage(); + } + if (ProjectUtil.isNull(courseBatchObject.get(JsonKey.COURSE_CREATED_FOR)) + || ((List) courseBatchObject.get(JsonKey.COURSE_CREATED_FOR)).isEmpty()) { + return ResponseCode.courseCreatedForIsNull.getErrorMessage(); + } + return JsonKey.SUCCESS; + } + + private List> searchOrgByChannel(String channel, Util.DbInfo orgDbInfo) { + Map filters = new HashMap<>(); + filters.put(JsonKey.CHANNEL, channel); + filters.put(JsonKey.IS_ROOT_ORG, true); + + Response orgResponse = + cassandraOperation.getRecordsByProperties( + orgDbInfo.getKeySpace(), orgDbInfo.getTableName(), filters); + List> rootOrgListRes = + (List>) orgResponse.get(JsonKey.RESPONSE); + return rootOrgListRes; + } + + private void generateTelemetryForOrganisation( + Map map, String id, boolean isOrgUpdated) { + + String orgState = JsonKey.CREATE; + if (isOrgUpdated) { + orgState = JsonKey.UPDATE; + } + Map targetObject = + TelemetryUtil.generateTargetObject(id, JsonKey.ORGANISATION, orgState, null); + List> correlatedObject = new ArrayList<>(); + TelemetryUtil.generateCorrelatedObject(id, JsonKey.ORGANISATION, null, correlatedObject); + TelemetryUtil.telemetryProcessingCall(map, targetObject, correlatedObject); + } + + private String validateLocationId(String locId) { + String locnId = null; try { - tellToAnother(request); + if (locnIdList.isEmpty()) { + Util.DbInfo geoLocDbInfo = Util.dbInfoMap.get(JsonKey.GEO_LOCATION_DB); + Response response = + cassandraOperation.getAllRecords( + geoLocDbInfo.getKeySpace(), geoLocDbInfo.getTableName()); + List> list = (List>) response.get(JsonKey.RESPONSE); + if (!list.isEmpty()) { + for (Map map : list) { + locnIdList.add(((String) map.get(JsonKey.ID))); + } + } + } + if (locnIdList.contains(locId)) { + return locId; + } else { + return null; + } } catch (Exception ex) { - ProjectLogger.log("Exception Occurred during saving user count to Es : ", ex); + ProjectLogger.log("Exception occurred while validating location id ", ex); } + return locnId; } - @SuppressWarnings("unchecked") - private void validateBatchUserListAndRemove( - Map courseBatchObject, - String batchId, - List userIds, - Map failList, - Map successList) { - if (CollectionUtils.isEmpty(userIds)) { - return; + private String validateOrgType(String orgType) { + String orgTypeId = null; + try { + if (!StringUtils.isBlank(DataCacheHandler.getOrgTypeMap().get(orgType.toLowerCase()))) { + orgTypeId = DataCacheHandler.getOrgTypeMap().get(orgType.toLowerCase()); + } else { + Util.DbInfo orgTypeDbInfo = Util.dbInfoMap.get(JsonKey.ORG_TYPE_DB); + Response response = + cassandraOperation.getAllRecords( + orgTypeDbInfo.getKeySpace(), orgTypeDbInfo.getTableName()); + List> list = (List>) response.get(JsonKey.RESPONSE); + if (!list.isEmpty()) { + for (Map map : list) { + if ((((String) map.get(JsonKey.NAME)).toLowerCase()) + .equalsIgnoreCase(orgType.toLowerCase())) { + orgTypeId = (String) map.get(JsonKey.ID); + DataCacheHandler.getOrgTypeMap() + .put( + ((String) map.get(JsonKey.NAME)).toLowerCase(), (String) map.get(JsonKey.ID)); + } + } + } + } + } catch (Exception ex) { + ProjectLogger.log("Exception occurred while getting orgTypeId from OrgType", ex); } - List> failedUserList = new ArrayList<>(); - List> passedUserList = new ArrayList<>(); - for (String userId : userIds) { - try { - UserCourses userCourses = userCourseDao.read(batchId, userId); - ProjectLogger.log( - "userId=" - + userId - + ", batchId=" - + batchId - + ", unenrolling with " - + userCourses.isActive(), - LoggerEnum.INFO.name()); - if (userCourses == null || !userCourses.isActive()) { - Map map = new HashMap<>(); - map.put(userId, ResponseCode.userNotEnrolledCourse.getErrorMessage()); - failedUserList.add(map); - } else if (userCourses.getStatus() == ProjectUtil.ProgressStatus.COMPLETED.getValue()) { - Map map = new HashMap<>(); - map.put(userId, ResponseCode.userAlreadyCompletedCourse.getErrorMessage()); - failedUserList.add(map); - } else { - Map updateAttributes = new HashMap<>(); - Timestamp ts = new Timestamp(new Date().getTime()); - updateAttributes.put(JsonKey.ACTIVE, ProjectUtil.ActiveStatus.INACTIVE.getValue()); - updateAttributes.put(JsonKey.DATE_TIME, ts); - ProjectLogger.log( - "userId=" + userId + ", batchId=" + batchId + ", unenrolling", - LoggerEnum.INFO.name()); - userCourseDao.update(batchId, userId, updateAttributes); - userCourses.setActive(false); - Map map = new HashMap<>(); - map.put(userId, JsonKey.SUCCESS); - passedUserList.add(map); - Map userCoursesMap = - mapper.convertValue(userCourses, new TypeReference>() {}); - if (userCoursesMap.containsKey(JsonKey.COMPLETED_ON)) { - userCoursesMap.put( - JsonKey.COMPLETED_ON, - ProjectUtil.formatDate((Date) userCoursesMap.get(JsonKey.COMPLETED_ON))); + return orgTypeId; + } + + private Map elasticSearchComplexSearch( + Map filters, String index, String type) { + + SearchDTO searchDTO = new SearchDTO(); + searchDTO.getAdditionalProperties().put(JsonKey.FILTERS, filters); + + Future> resultF = esService.search(searchDTO, type); + return (Map) ElasticSearchHelper.getResponseFromFuture(resultF); + } + + private void processUserInfo( + List> dataMapList, String processId, String updatedBy) { + // update status from NEW to INProgress + updateStatusForProcessing(processId); + Util.DbInfo usrDbInfo = Util.dbInfoMap.get(JsonKey.USER_DB); + List> failureUserReq = new ArrayList<>(); + List> successUserReq = new ArrayList<>(); + Map userMap = null; + /* + * To store hashTagId inside user_org table, first we need to get hashTagId from + * provided organisation ID. Currently in bulk user upload, we are passing only + * one organisation, so we can get the details before for loop and reuse it. + */ + String hashTagId = null; + if (dataMapList != null && dataMapList.size() > 0) { + String orgId = (String) dataMapList.get(0).get(JsonKey.ORGANISATION_ID); + hashTagId = Util.getHashTagIdFromOrgId(orgId); + } + for (int i = 0; i < dataMapList.size(); i++) { + userMap = dataMapList.get(i); + Map welcomeMailTemplateMap = new HashMap<>(); + String errMsg = validateUser(userMap); + if (JsonKey.SUCCESS.equalsIgnoreCase(errMsg)) { + try { + + // convert userName,provide,loginId,externalId.. value to lowercase + updateMapSomeValueTOLowerCase(userMap); + Map foundUserMap = findUser(userMap); + foundUserMap = insertRecordToKeyCloak(userMap, foundUserMap, updatedBy); + Map tempMap = new HashMap<>(); + tempMap.putAll(userMap); + tempMap.remove(JsonKey.EMAIL_VERIFIED); + tempMap.remove(JsonKey.POSITION); + // remove externalID and Provider as we are not saving these to user table + tempMap.remove(JsonKey.EXTERNAL_ID); + tempMap.remove(JsonKey.EXTERNAL_ID_PROVIDER); + tempMap.remove(JsonKey.EXTERNAL_ID_TYPE); + tempMap.remove(JsonKey.ORGANISATION_ID); + tempMap.put(JsonKey.EMAIL_VERIFIED, false); + Response response = null; + if (null == tempMap.get(JsonKey.OPERATION)) { + // will allowing only PUBLIC role at user level. + tempMap.remove(JsonKey.ROLES); + // insert user record + // Add only PUBLIC role to user + List list = new ArrayList<>(); + list.add(ProjectUtil.UserRole.PUBLIC.getValue()); + tempMap.put(JsonKey.ROLES, list); + try { + UserUtility.encryptUserData(tempMap); + } catch (Exception ex) { + ProjectLogger.log( + "Exception occurred while bulk user upload in BulkUploadBackGroundJobActor during data encryption :", + ex); + throw new ProjectCommonException( + ResponseCode.userDataEncryptionError.getErrorCode(), + ResponseCode.userDataEncryptionError.getErrorMessage(), + ResponseCode.SERVER_ERROR.getResponseCode()); + } + tempMap.put(JsonKey.CREATED_BY, updatedBy); + tempMap.put(JsonKey.IS_DELETED, false); + tempMap.remove(JsonKey.EXTERNAL_IDS); + try { + response = + cassandraOperation.insertRecord( + usrDbInfo.getKeySpace(), usrDbInfo.getTableName(), tempMap); + // insert details to user_org table + + userMap.put(JsonKey.HASHTAGID, hashTagId); + registerUserToOrg(userMap, JsonKey.CREATE); + // removing added hashTagId + userMap.remove(JsonKey.HASHTAGID); + } catch (Exception ex) { + // incase of exception also removing added hashTagId + userMap.remove(JsonKey.HASHTAGID); + ProjectLogger.log( + "Exception occurred while bulk user upload in BulkUploadBackGroundJobActor:", ex); + userMap.remove(JsonKey.ID); + userMap.remove(JsonKey.PASSWORD); + userMap.put(JsonKey.ERROR_MSG, ex.getMessage() + " ,user insertion failed."); + removeOriginalExternalIds(userMap.get(JsonKey.EXTERNAL_IDS)); + failureUserReq.add(userMap); + continue; + } finally { + if (null == response) { + ssoManager.removeUser(userMap); + } + } + sendEmailAndSms(userMap, welcomeMailTemplateMap); + // object of telemetry event... + Map targetObject = null; + List> correlatedObject = new ArrayList<>(); + + targetObject = + TelemetryUtil.generateTargetObject( + (String) userMap.get(JsonKey.ID), JsonKey.USER, JsonKey.CREATE, null); + TelemetryUtil.telemetryProcessingCall(userMap, targetObject, correlatedObject); + } else { + // update user record + tempMap.put(JsonKey.UPDATED_BY, updatedBy); + tempMap.put(JsonKey.UPDATED_DATE, ProjectUtil.getFormattedDate()); + try { + UserUtility.encryptUserData(tempMap); + } catch (Exception ex) { + ProjectLogger.log( + "Exception occurred while bulk user upload in BulkUploadBackGroundJobActor during data encryption :", + ex); + throw new ProjectCommonException( + ResponseCode.userDataEncryptionError.getErrorCode(), + ResponseCode.userDataEncryptionError.getErrorMessage(), + ResponseCode.SERVER_ERROR.getResponseCode()); + } + try { + removeFieldsFrmUpdateReq(tempMap); + response = + cassandraOperation.updateRecord( + usrDbInfo.getKeySpace(), usrDbInfo.getTableName(), tempMap); + // update user-org table(role update) + userMap.put(JsonKey.UPDATED_BY, updatedBy); + userMap.put(JsonKey.HASHTAGID, hashTagId); + registerUserToOrg(userMap, JsonKey.UPDATE); + userMap.remove(JsonKey.HASHTAGID); + } catch (Exception ex) { + userMap.remove(JsonKey.HASHTAGID); + ProjectLogger.log( + "Exception occurred while bulk user upload in BulkUploadBackGroundJobActor:", ex); + userMap.remove(JsonKey.ID); + userMap.remove(JsonKey.PASSWORD); + userMap.put(JsonKey.ERROR_MSG, ex.getMessage() + " ,user updation failed."); + removeOriginalExternalIds(userMap.get(JsonKey.EXTERNAL_IDS)); + failureUserReq.add(userMap); + continue; + } } - userCoursesMap.put(JsonKey.DATE_TIME, ProjectUtil.formatDate(ts)); - String id = UserCoursesService.generateUserCourseESId(batchId, userId); - userCoursesMap.put(JsonKey.ID, id); - updateUserCoursesToES(userCoursesMap); + + // update the user external identity data + try { + if (null != userMap.get(JsonKey.EXTERNAL_IDS)) { + Util.updateUserExtId(userMap); + removeOriginalExternalIds(userMap.get(JsonKey.EXTERNAL_IDS)); + } + } catch (Exception ex) { + removeOriginalExternalIds(userMap.get(JsonKey.EXTERNAL_IDS)); + userMap.put( + JsonKey.ERROR_MSG, "Update of user external IDs failed. " + ex.getMessage()); + } + // save successfully created user data + tempMap.putAll(userMap); + tempMap.remove(JsonKey.STATUS); + tempMap.remove(JsonKey.CREATED_DATE); + tempMap.remove(JsonKey.CREATED_BY); + tempMap.remove(JsonKey.ID); + tempMap.remove(JsonKey.LOGIN_ID); + tempMap.put(JsonKey.PASSWORD, "*****"); + successUserReq.add(tempMap); + + // update elastic search + ProjectLogger.log( + "making a call to save user data to ES in BulkUploadBackGroundJobActor"); + Request request = new Request(); + request.setOperation(ActorOperations.UPDATE_USER_INFO_ELASTIC.getValue()); + request.getRequest().put(JsonKey.ID, userMap.get(JsonKey.ID)); + tellToAnother(request); + // object of telemetry event... + Map targetObject = null; + List> correlatedObject = new ArrayList<>(); + targetObject = + TelemetryUtil.generateTargetObject( + (String) userMap.get(JsonKey.ID), JsonKey.USER, JsonKey.UPDATE, null); + TelemetryUtil.telemetryProcessingCall(userMap, targetObject, correlatedObject); + } catch (Exception ex) { + ProjectLogger.log( + "Exception occurred while bulk user upload in BulkUploadBackGroundJobActor:", ex); + userMap.remove(JsonKey.ID); + userMap.remove(JsonKey.PASSWORD); + userMap.put(JsonKey.ERROR_MSG, ex.getMessage()); + removeOriginalExternalIds(userMap.get(JsonKey.EXTERNAL_IDS)); + failureUserReq.add(userMap); } - } catch (Exception ex) { - ProjectLogger.log( - "BulkUploadBackgroundJobActor:validateBatchUserListAndRemove Exception Occurred while removing bulk user : " - + userId, - ex); - Map map = new HashMap<>(); - map.put(userId, ex.getMessage()); - failedUserList.add(map); + } else { + userMap.put(JsonKey.ERROR_MSG, errMsg); + removeOriginalExternalIds(userMap.get(JsonKey.EXTERNAL_IDS)); + failureUserReq.add(userMap); } } - successList.put(JsonKey.SUCCESS_RESULT, passedUserList); - failList.put(JsonKey.FAILURE_RESULT, failedUserList); + updateSuccessAndFailureResultToDb(processId, failureUserReq, successUserReq); } - @SuppressWarnings("unchecked") - private String validateBatchInfo(Map courseBatchObject) { + private void updateSuccessAndFailureResultToDb( + String processId, + List> failureUserReq, + List> successUserReq) { + // Insert record to BulkDb table + // After Successful completion of bulk upload process , encrypt the success and + // failure result + // and delete the user data(csv file data) + Map map = new HashMap<>(); + map.put(JsonKey.ID, processId); + try { + map.put( + JsonKey.SUCCESS_RESULT, + UserUtility.encryptData(ProjectUtil.convertMapToJsonString(successUserReq))); + map.put( + JsonKey.FAILURE_RESULT, + UserUtility.encryptData(ProjectUtil.convertMapToJsonString(failureUserReq))); + } catch (Exception e1) { + ProjectLogger.log( + "Exception occurred while encrypting success and failure result in bulk upload process : ", + e1); + } + map.put(JsonKey.PROCESS_END_TIME, ProjectUtil.getFormattedDate()); + map.put(JsonKey.STATUS, ProjectUtil.BulkProcessStatus.COMPLETED.getValue()); + map.put(JsonKey.DATA, ""); + try { + cassandraOperation.updateRecord(bulkDb.getKeySpace(), bulkDb.getTableName(), map); + } catch (Exception e) { + ProjectLogger.log( + "Exception Occurred while updating bulk_upload_process in BulkUploadBackGroundJobActor : ", + e); + } + } - if ((MapUtils.isEmpty(courseBatchObject))) { - return ResponseCode.invalidCourseBatchId.getErrorMessage(); + private void sendEmailAndSms( + Map userMap, Map welcomeMailTemplateMap) { + Map usrMap = new HashMap<>(userMap); + usrMap.put(JsonKey.REDIRECT_URI, Util.getSunbirdWebUrlPerTenent(userMap)); + usrMap.put(JsonKey.USERNAME, userMap.get(JsonKey.LOGIN_ID)); + // generate required action link and shorten the url + Util.getUserRequiredActionLink(usrMap); + // send the welcome mail to user + welcomeMailTemplateMap.putAll(usrMap); + Request welcomeMailReqObj = Util.sendOnboardingMail(welcomeMailTemplateMap); + if (null != welcomeMailReqObj) { + tellToAnother(welcomeMailReqObj); } - // check whether coursebbatch type is invite only or not ... - if (ProjectUtil.isNull(courseBatchObject.get(JsonKey.ENROLLMENT_TYPE)) - || !((String) courseBatchObject.get(JsonKey.ENROLLMENT_TYPE)) - .equalsIgnoreCase(JsonKey.INVITE_ONLY)) { - return ResponseCode.enrollmentTypeValidation.getErrorMessage(); + + if (StringUtils.isNotBlank((String) usrMap.get(JsonKey.PHONE))) { + Util.sendSMS(usrMap); } - if (ProjectUtil.isNull(courseBatchObject.get(JsonKey.COURSE_CREATED_FOR)) - || ((List) courseBatchObject.get(JsonKey.COURSE_CREATED_FOR)).isEmpty()) { - return ResponseCode.courseCreatedForIsNull.getErrorMessage(); + } + + private void registerUserToOrg(Map userMap, String operation) { + if (((String) userMap.get(JsonKey.ORGANISATION_ID)) + .equalsIgnoreCase((String) userMap.get(JsonKey.ROOT_ORG_ID))) { + if (operation.equalsIgnoreCase(JsonKey.CREATE)) { + Util.registerUserToOrg(userMap); + } else { + // for update + Util.upsertUserOrgData(userMap); + } + } else { + Map map = new HashMap<>(userMap); + if (operation.equalsIgnoreCase(JsonKey.CREATE)) { + // first register for subOrg then root org + Util.registerUserToOrg(map); + prepareRequestForAddingUserToRootOrg(userMap, map); + // register user to root org + Util.registerUserToOrg(map); + } else { + // for update + // first register for subOrg then root org + Util.upsertUserOrgData(map); + prepareRequestForAddingUserToRootOrg(userMap, map); + // register user to root org + Util.upsertUserOrgData(userMap); + } } - return JsonKey.SUCCESS; + } + + private void prepareRequestForAddingUserToRootOrg( + Map userMap, Map map) { + map.put(JsonKey.ORGANISATION_ID, userMap.get(JsonKey.ROOT_ORG_ID)); + List roles = Arrays.asList(ProjectUtil.UserRole.PUBLIC.getValue()); + map.put(JsonKey.ROLES, roles); + } + + private void removeOriginalExternalIds(Object externalIds) { + if (externalIds instanceof List) { + @SuppressWarnings("unchecked") + List> request = (List>) externalIds; + try { + request.forEach( + externalId -> { + externalId.put(JsonKey.ID, externalId.get(JsonKey.ORIGINAL_EXTERNAL_ID)); + externalId.remove(JsonKey.ORIGINAL_EXTERNAL_ID); + externalId.put(JsonKey.PROVIDER, externalId.get(JsonKey.ORIGINAL_PROVIDER)); + externalId.remove(JsonKey.ORIGINAL_PROVIDER); + externalId.put(JsonKey.ID_TYPE, externalId.get(JsonKey.ORIGINAL_ID_TYPE)); + externalId.remove(JsonKey.ORIGINAL_ID_TYPE); + }); + } catch (Exception ex) { + ProjectLogger.log( + "BulkUploadBackGroundJobActor:removeOriginalExternalIds : exception msg: " + ex); + } + } + } + + private void parseExternalIds(Map userMap) throws IOException { + if (userMap.containsKey(JsonKey.EXTERNAL_IDS) + && StringUtils.isNotBlank((String) userMap.get(JsonKey.EXTERNAL_IDS))) { + String externalIds = (String) userMap.get(JsonKey.EXTERNAL_IDS); + List> externalIdList = new ArrayList<>(); + externalIdList = mapper.readValue(externalIds, List.class); + userMap.put(JsonKey.EXTERNAL_IDS, externalIdList); + } + } + + private void convertCommaSepStringToList(Map map, String property) { + String[] props = ((String) map.get(property)).split(","); + List list = new ArrayList<>(Arrays.asList(props)); + map.put(property, list); } private void updateStatusForProcessing(String processId) { @@ -410,4 +794,363 @@ private Map getBulkData(String processId) { cassandraOperation.getRecordById(bulkDb.getKeySpace(), bulkDb.getTableName(), processId); return (((List>) res.get(JsonKey.RESPONSE)).get(0)); } + + private void updateRecordToUserOrgTable(Map map, String updatedBy) { + Util.DbInfo usrOrgDb = Util.dbInfoMap.get(JsonKey.USR_ORG_DB); + Map reqMap = new HashMap<>(); + reqMap.put(JsonKey.ID, map.get(JsonKey.ID)); + reqMap.put(JsonKey.IS_DELETED, false); + reqMap.put(JsonKey.UPDATED_BY, updatedBy); + reqMap.put(JsonKey.UPDATED_DATE, ProjectUtil.getFormattedDate()); + try { + cassandraOperation.updateRecord(usrOrgDb.getKeySpace(), usrOrgDb.getTableName(), reqMap); + } catch (Exception e) { + ProjectLogger.log(e.getMessage(), e); + } + } + + private Map findUser(Map requestedUserMap) { + Map foundUserMap = null; + String extId = (String) requestedUserMap.get(JsonKey.EXTERNAL_ID); + String provider = (String) requestedUserMap.get(JsonKey.EXTERNAL_ID_PROVIDER); + String idType = (String) requestedUserMap.get(JsonKey.EXTERNAL_ID_TYPE); + String userName = (String) requestedUserMap.get(JsonKey.USERNAME); + if (StringUtils.isNotBlank(extId) + && StringUtils.isNotBlank(provider) + && StringUtils.isNotBlank(idType) + && StringUtils.isBlank(userName)) { + foundUserMap = Util.getUserFromExternalId(requestedUserMap); + if (MapUtils.isEmpty(foundUserMap)) { + throw new ProjectCommonException( + ResponseCode.externalIdNotFound.getErrorCode(), + ProjectUtil.formatMessage( + ResponseCode.externalIdNotFound.getErrorMessage(), extId, idType, provider), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + } else { + foundUserMap = getRecordByLoginId(requestedUserMap); + } + return foundUserMap; + } + + private Map insertRecordToKeyCloak( + Map requestedUserMap, Map foundUserMap, String updatedBy) + throws Exception { + requestedUserMap.put(JsonKey.UPDATED_BY, updatedBy); + if (MapUtils.isNotEmpty(foundUserMap)) { + updateUser(requestedUserMap, foundUserMap); + } else { + createUser(requestedUserMap); + } + return requestedUserMap; + } + + private Map getRecordByLoginId(Map userMap) { + Util.DbInfo usrDbInfo = Util.dbInfoMap.get(JsonKey.USER_DB); + Map user = null; + userMap.put(JsonKey.LOGIN_ID, Util.getLoginId(userMap)); + String loginId = Util.getEncryptedData((String) userMap.get(JsonKey.LOGIN_ID)); + Response resultFrUserName = + cassandraOperation.getRecordsByProperty( + usrDbInfo.getKeySpace(), usrDbInfo.getTableName(), JsonKey.LOGIN_ID, loginId); + if (CollectionUtils.isNotEmpty( + (List>) resultFrUserName.get(JsonKey.RESPONSE))) { + user = ((List>) resultFrUserName.get(JsonKey.RESPONSE)).get(0); + } + return user; + } + + private void createUser(Map userMap) throws Exception { + // user doesn't exist + validateExternalIds(userMap, JsonKey.CREATE); + + try { + String userId = ""; + userMap.put(JsonKey.BULK_USER_UPLOAD, true); + Util.checkEmailUniqueness(userMap, JsonKey.CREATE); + Util.checkPhoneUniqueness(userMap, JsonKey.CREATE); + ssoManager.updatePassword(userId, (String) userMap.get(JsonKey.PASSWORD)); + userMap.remove(JsonKey.BULK_USER_UPLOAD); + + if (!StringUtils.isBlank(userId)) { + userMap.put(JsonKey.USER_ID, userId); + userMap.put(JsonKey.ID, userId); + } else { + throw new ProjectCommonException( + ResponseCode.userRegUnSuccessfull.getErrorCode(), + ResponseCode.userRegUnSuccessfull.getErrorMessage(), + ResponseCode.SERVER_ERROR.getResponseCode()); + } + } catch (Exception exception) { + ProjectLogger.log("Exception occurred while creating user in keycloak ", exception); + throw exception; + } + userMap.put(JsonKey.CREATED_DATE, ProjectUtil.getFormattedDate()); + userMap.put(JsonKey.STATUS, ProjectUtil.Status.ACTIVE.getValue()); + userMap.put(JsonKey.IS_DELETED, false); + if (!StringUtils.isBlank((String) userMap.get(JsonKey.COUNTRY_CODE))) { + userMap.put( + JsonKey.COUNTRY_CODE, propertiesCache.getProperty("sunbird_default_country_code")); + } + /** + * set role as PUBLIC by default if role is empty in request body. And if roles are coming in + * request body, then check for PUBLIC role , if not present then add PUBLIC role to the list + */ + if (null == userMap.get(JsonKey.ROLES)) { + userMap.put(JsonKey.ROLES, new ArrayList()); + } + List roles = (List) userMap.get(JsonKey.ROLES); + if (!roles.contains(ProjectUtil.UserRole.PUBLIC.getValue())) { + roles.add(ProjectUtil.UserRole.PUBLIC.getValue()); + userMap.put(JsonKey.ROLES, roles); + } + } + + private void updateUser(Map userMap, Map userDbRecord) { + // user exist + if (null != userDbRecord.get(JsonKey.IS_DELETED) + && (boolean) userDbRecord.get(JsonKey.IS_DELETED)) { + throw new ProjectCommonException( + ResponseCode.inactiveUser.getErrorCode(), + ResponseCode.inactiveUser.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + + userMap.put(JsonKey.ID, userDbRecord.get(JsonKey.ID)); + userMap.put(JsonKey.USER_ID, userDbRecord.get(JsonKey.ID)); + userMap.put(JsonKey.OPERATION, JsonKey.UPDATE); + + validateExternalIds(userMap, JsonKey.UPDATE); + + Util.checkEmailUniqueness(userMap, JsonKey.UPDATE); + Util.checkPhoneUniqueness(userMap, JsonKey.UPDATE); + String email = ""; + try { + email = encryptionService.encryptData((String) userMap.get(JsonKey.EMAIL)); + } catch (Exception ex) { + ProjectLogger.log( + "Exception occurred while bulk user upload in BulkUploadBackGroundJobActor during encryption of loginId:", + ex); + throw new ProjectCommonException( + ResponseCode.userDataEncryptionError.getErrorCode(), + ResponseCode.userDataEncryptionError.getErrorMessage(), + ResponseCode.SERVER_ERROR.getResponseCode()); + } + if (null != (String) userDbRecord.get(JsonKey.EMAIL) + && ((String) userDbRecord.get(JsonKey.EMAIL)).equalsIgnoreCase(email)) { + // DB email value and req email value both are same , no need to update + email = (String) userMap.get(JsonKey.EMAIL); + userMap.remove(JsonKey.EMAIL); + } + // check user is active for this Organisation or not + isUserDeletedFromOrg(userMap, (String) userMap.get(JsonKey.UPDATED_BY)); + updateKeyCloakUserBase(userMap); + email = decryptionService.decryptData(email); + userMap.put(JsonKey.EMAIL, email); + } + + private void validateExternalIds(Map userMap, String operation) { + if (CollectionUtils.isNotEmpty((List>) userMap.get(JsonKey.EXTERNAL_IDS))) { + List> list = + Util.copyAndConvertExternalIdsToLower( + (List>) userMap.get(JsonKey.EXTERNAL_IDS)); + userMap.put(JsonKey.EXTERNAL_IDS, list); + } + User user = mapper.convertValue(userMap, User.class); + Util.checkExternalIdUniqueness(user, operation); + if (JsonKey.UPDATE.equalsIgnoreCase(operation)) { + Util.validateUserExternalIds(userMap); + } + } + + private boolean isUserDeletedFromOrg(Map userMap, String updatedBy) { + Util.DbInfo usrOrgDbInfo = Util.dbInfoMap.get(JsonKey.USER_ORG_DB); + Map map = new HashMap<>(); + map.put(JsonKey.USER_ID, userMap.get(JsonKey.ID)); + map.put(JsonKey.ORGANISATION_ID, userMap.get(JsonKey.ORGANISATION_ID)); + Response response = + cassandraOperation.getRecordsByProperties( + usrOrgDbInfo.getKeySpace(), usrOrgDbInfo.getTableName(), map); + List> resList = (List>) response.get(JsonKey.RESPONSE); + if (!resList.isEmpty()) { + Map res = resList.get(0); + if (null != res.get(JsonKey.IS_DELETED)) { + boolean bool = (boolean) (res.get(JsonKey.IS_DELETED)); + // if deleted then add this user to org and proceed + try { + if (bool) { + updateRecordToUserOrgTable(res, updatedBy); + } + } catch (Exception ex) { + throw new ProjectCommonException( + ResponseCode.userUpdateToOrgFailed.getErrorCode(), + ResponseCode.userUpdateToOrgFailed.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + return bool; + } else { + return false; + } + } + return false; + } + + private String validateUser(Map userMap) { + if (null != userMap.get(JsonKey.EXTERNAL_IDS)) { + try { + parseExternalIds(userMap); + } catch (Exception ex) { + return ProjectUtil.formatMessage( + ResponseMessage.Message.PARSING_FAILED, JsonKey.EXTERNAL_IDS); + } + } + userMap.put(JsonKey.EMAIL_VERIFIED, false); + if (!StringUtils.isBlank((String) userMap.get(JsonKey.PHONE_VERIFIED))) { + try { + userMap.put( + JsonKey.PHONE_VERIFIED, + Boolean.parseBoolean((String) userMap.get(JsonKey.PHONE_VERIFIED))); + } catch (Exception ex) { + return ProjectUtil.formatMessage( + ResponseMessage.Message.DATA_TYPE_ERROR, JsonKey.PHONE_VERIFIED, "Boolean"); + } + } + if (null != userMap.get(JsonKey.ROLES)) { + convertCommaSepStringToList(userMap, JsonKey.ROLES); + } + if (null != userMap.get(JsonKey.GRADE)) { + convertCommaSepStringToList(userMap, JsonKey.GRADE); + } + + if (null != userMap.get(JsonKey.SUBJECT)) { + convertCommaSepStringToList(userMap, JsonKey.SUBJECT); + } + + if (null != userMap.get(JsonKey.LANGUAGE)) { + convertCommaSepStringToList(userMap, JsonKey.LANGUAGE); + } + Request request = new Request(); + request.getRequest().putAll(userMap); + try { + new UserRequestValidator().validateBulkUserData(request); + List roles = (List) userMap.get(JsonKey.ROLES); + if (CollectionUtils.isNotEmpty(roles)) { + String response = Util.validateRoles(roles); + if (!JsonKey.SUCCESS.equalsIgnoreCase(response)) { + return ResponseMessage.Message.INVALID_ROLE; + } + roles = roles.stream().map(s -> s.trim()).collect(Collectors.toList()); + userMap.put(JsonKey.ROLES, roles); + } + } catch (Exception ex) { + return ex.getMessage(); + } + + return JsonKey.SUCCESS; + } + + private String generatePrimaryKey(Map req) { + String userId = (String) req.get(JsonKey.USER_ID); + String courseId = (String) req.get(JsonKey.COURSE_ID); + String batchId = (String) req.get(JsonKey.BATCH_ID); + return OneWayHashing.encryptVal( + userId + + JsonKey.PRIMARY_KEY_DELIMETER + + courseId + + JsonKey.PRIMARY_KEY_DELIMETER + + batchId); + } + + /** + * This method will make some requested key value as lower case. + * + * @param map Request + */ + public static void updateMapSomeValueTOLowerCase(Map map) { + if (map.get(JsonKey.SOURCE) != null) { + map.put(JsonKey.SOURCE, ((String) map.get(JsonKey.SOURCE)).toLowerCase()); + } + if (map.get(JsonKey.EXTERNAL_ID) != null) { + map.put(JsonKey.EXTERNAL_ID, ((String) map.get(JsonKey.EXTERNAL_ID)).toLowerCase()); + } + if (map.get(JsonKey.USERNAME) != null) { + map.put(JsonKey.USERNAME, ((String) map.get(JsonKey.USERNAME)).toLowerCase()); + } + if (map.get(JsonKey.USER_NAME) != null) { + map.put(JsonKey.USER_NAME, ((String) map.get(JsonKey.USER_NAME)).toLowerCase()); + } + if (map.get(JsonKey.PROVIDER) != null) { + map.put(JsonKey.PROVIDER, ((String) map.get(JsonKey.PROVIDER)).toLowerCase()); + } + if (map.get(JsonKey.LOGIN_ID) != null) { + map.put(JsonKey.LOGIN_ID, ((String) map.get(JsonKey.LOGIN_ID)).toLowerCase()); + } + } + + private void updateKeyCloakUserBase(Map userMap) { + try { + String userId = ssoManager.updateUser(userMap); + if (!(!StringUtils.isBlank(userId) && userId.equalsIgnoreCase(JsonKey.SUCCESS))) { + throw new ProjectCommonException( + ResponseCode.userUpdationUnSuccessfull.getErrorCode(), + ResponseCode.userUpdationUnSuccessfull.getErrorMessage(), + ResponseCode.SERVER_ERROR.getResponseCode()); + } + } catch (Exception e) { + ProjectLogger.log(e.getMessage(), e); + throw new ProjectCommonException( + ResponseCode.userUpdationUnSuccessfull.getErrorCode(), + ResponseCode.userUpdationUnSuccessfull.getErrorMessage(), + ResponseCode.SERVER_ERROR.getResponseCode()); + } + } + + // method will compare two strings and return true id both are same otherwise + // false ... + private boolean compareStrings(String first, String second) { + + if (isNull(first) && isNull(second)) { + return true; + } + if ((isNull(first) && isNotNull(second)) || (isNull(second) && isNotNull(first))) { + return false; + } + return first.equalsIgnoreCase(second); + } + + /** + * Fields which are not allowed to update while updating user info. + * + * @param userMap + */ + private void removeFieldsFrmUpdateReq(Map userMap) { + userMap.remove(JsonKey.OPERATION); + userMap.remove(JsonKey.EXTERNAL_IDS); + userMap.remove(JsonKey.ENC_EMAIL); + userMap.remove(JsonKey.ENC_PHONE); + userMap.remove(JsonKey.EMAIL_VERIFIED); + userMap.remove(JsonKey.STATUS); + userMap.remove(JsonKey.USERNAME); + userMap.remove(JsonKey.ROOT_ORG_ID); + userMap.remove(JsonKey.LOGIN_ID); + userMap.remove(JsonKey.ROLES); + userMap.remove(JsonKey.CHANNEL); + } + + private boolean isSlugUnique(String slug) { + if (!StringUtils.isBlank(slug)) { + Map filters = new HashMap<>(); + filters.put(JsonKey.SLUG, slug); + filters.put(JsonKey.IS_ROOT_ORG, true); + Map esResult = + elasticSearchComplexSearch( + filters, EsIndex.sunbird.getIndexName(), EsType.organisation.getTypeName()); + if (isNotNull(esResult) + && esResult.containsKey(JsonKey.CONTENT) + && isNotNull(esResult.get(JsonKey.CONTENT))) { + return (((List) esResult.get(JsonKey.CONTENT)).isEmpty()); + } + } + return false; + } } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BulkUploadManagementActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BulkUploadManagementActor.java index c7d66dfc00..206e1d93a3 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BulkUploadManagementActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/bulkupload/BulkUploadManagementActor.java @@ -8,18 +8,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.sunbird.actor.router.ActorConfig; import org.sunbird.cassandra.CassandraOperation; import org.sunbird.common.exception.ProjectCommonException; import org.sunbird.common.models.response.Response; -import org.sunbird.common.models.util.ActorOperations; -import org.sunbird.common.models.util.BulkUploadJsonKey; -import org.sunbird.common.models.util.JsonKey; -import org.sunbird.common.models.util.LoggerEnum; -import org.sunbird.common.models.util.ProjectLogger; -import org.sunbird.common.models.util.ProjectUtil; -import org.sunbird.common.models.util.PropertiesCache; -import org.sunbird.common.models.util.TelemetryEnvKey; +import org.sunbird.common.models.util.*; +import org.sunbird.common.models.util.ProjectUtil.BulkProcessStatus; +import org.sunbird.common.models.util.datasecurity.DecryptionService; import org.sunbird.common.request.ExecutionContext; import org.sunbird.common.request.Request; import org.sunbird.common.responsecode.ResponseCode; @@ -30,8 +26,11 @@ import org.sunbird.learner.actors.bulkupload.dao.impl.BulkUploadProcessDaoImpl; import org.sunbird.learner.actors.bulkupload.dao.impl.BulkUploadProcessTaskDaoImpl; import org.sunbird.learner.actors.bulkupload.model.BulkUploadProcess; +import org.sunbird.learner.actors.bulkupload.model.BulkUploadProcessTask; import org.sunbird.learner.actors.bulkupload.model.StorageDetails; +import org.sunbird.learner.util.UserUtility; import org.sunbird.learner.util.Util; +import org.sunbird.learner.util.Util.DbInfo; /** * This actor will handle bulk upload operation . @@ -46,11 +45,54 @@ public class BulkUploadManagementActor extends BaseBulkUploadActor { private CassandraOperation cassandraOperation = ServiceFactory.getInstance(); private Util.DbInfo bulkDb = Util.dbInfoMap.get(JsonKey.BULK_OP_DB); + private int userDataSize = 0; + private int orgDataSize = 0; private int batchDataSize = 0; BulkUploadProcessTaskDao bulkUploadProcessTaskDao = new BulkUploadProcessTaskDaoImpl(); private ObjectMapper mapper = new ObjectMapper(); + private String[] bulkUserAllowedFields = { + JsonKey.FIRST_NAME, + JsonKey.LAST_NAME, + JsonKey.PHONE, + JsonKey.COUNTRY_CODE, + JsonKey.EMAIL, + JsonKey.USERNAME, + JsonKey.PHONE_VERIFIED, + JsonKey.EMAIL_VERIFIED, + JsonKey.ROLES, + JsonKey.POSITION, + JsonKey.GRADE, + JsonKey.LOCATION, + JsonKey.DOB, + JsonKey.GENDER, + JsonKey.LANGUAGE, + JsonKey.PROFILE_SUMMARY, + JsonKey.SUBJECT, + JsonKey.WEB_PAGES, + JsonKey.EXTERNAL_ID_PROVIDER, + JsonKey.EXTERNAL_ID, + JsonKey.EXTERNAL_ID_TYPE, + JsonKey.EXTERNAL_IDS + }; private String[] bulkBatchAllowedFields = {JsonKey.BATCH_ID, JsonKey.USER_IDs}; + private String[] bulkOrgAllowedFields = { + JsonKey.ORGANISATION_NAME, + JsonKey.CHANNEL, + JsonKey.IS_ROOT_ORG, + JsonKey.PROVIDER, + JsonKey.EXTERNAL_ID, + JsonKey.DESCRIPTION, + JsonKey.HOME_URL, + JsonKey.ORG_CODE, + JsonKey.ORG_TYPE, + JsonKey.PREFERRED_LANGUAGE, + JsonKey.THEME, + JsonKey.CONTACT_DETAILS, + JsonKey.LOC_ID, + JsonKey.HASHTAGID, + JsonKey.LOCATION_CODE + }; @Override public void onReceive(Request request) throws Throwable { @@ -110,6 +152,9 @@ private void getBulkUploadDownloadStatusLink(Request actorMessage) { private void getUploadStatus(Request actorMessage) { String processId = (String) actorMessage.getRequest().get(JsonKey.PROCESS_ID); + DecryptionService decryptionService = + org.sunbird.common.models.util.datasecurity.impl.ServiceFactory + .getDecryptionServiceInstance(null); Response response = null; List fields = Arrays.asList( @@ -126,10 +171,68 @@ private void getUploadStatus(Request actorMessage) { ((List>) response.get(JsonKey.RESPONSE)); if (!resList.isEmpty()) { Map resMap = resList.get(0); + String objectType = (String) resMap.get(JsonKey.OBJECT_TYPE); if ((int) resMap.get(JsonKey.STATUS) == ProjectUtil.BulkProcessStatus.COMPLETED.getValue()) { resMap.put(JsonKey.PROCESS_ID, resMap.get(JsonKey.ID)); updateResponseStatus(resMap); ProjectUtil.removeUnwantedFields(resMap, JsonKey.ID); + if (!(JsonKey.LOCATION.equalsIgnoreCase(objectType))) { + Object[] successMap = null; + Object[] failureMap = null; + try { + if (null != resMap.get(JsonKey.SUCCESS_RESULT)) { + successMap = + mapper.readValue( + decryptionService.decryptData((String) resMap.get(JsonKey.SUCCESS_RESULT)), + Object[].class); + if (JsonKey.USER.equalsIgnoreCase(objectType)) { + Arrays.stream(successMap) + .forEach( + x -> { + UserUtility.decryptUserData((Map) x); + Util.addMaskEmailAndPhone((Map) x); + }); + } + resMap.put(JsonKey.SUCCESS_RESULT, successMap); + } + if (null != resMap.get(JsonKey.FAILURE_RESULT)) { + failureMap = + mapper.readValue( + decryptionService.decryptData((String) resMap.get(JsonKey.FAILURE_RESULT)), + Object[].class); + if (JsonKey.USER.equalsIgnoreCase(objectType)) { + Arrays.stream(successMap) + .forEach( + x -> { + UserUtility.decryptUserData((Map) x); + Util.addMaskEmailAndPhone((Map) x); + }); + } + resMap.put(JsonKey.FAILURE_RESULT, failureMap); + } + } catch (IOException e) { + ProjectLogger.log(e.getMessage(), e); + } + } else { + Map queryMap = new HashMap<>(); + queryMap.put(JsonKey.PROCESS_ID, processId); + List tasks = bulkUploadProcessTaskDao.readByPrimaryKeys(queryMap); + + List successList = new ArrayList<>(); + List failureList = new ArrayList<>(); + tasks + .stream() + .forEach( + x -> { + if (x.getStatus() == BulkProcessStatus.COMPLETED.getValue()) { + addTaskDataToList(successList, x.getSuccessResult()); + } else { + addTaskDataToList(failureList, x.getFailureResult()); + } + }); + resMap.put(JsonKey.SUCCESS_RESULT, successList); + resMap.put(JsonKey.FAILURE_RESULT, failureList); + } sender().tell(response, self()); } else { resMap.put(JsonKey.PROCESS_ID, resMap.get(JsonKey.ID)); @@ -176,14 +279,17 @@ private void upload(Request actorMessage) throws IOException { String processId = ProjectUtil.getUniqueIdFromTimestamp(1); Map req = (Map) actorMessage.getRequest().get(JsonKey.DATA); req.put(JsonKey.CREATED_BY, req.get(JsonKey.CREATED_BY)); - if (((String) req.get(JsonKey.OBJECT_TYPE)).equals(JsonKey.BATCH_LEARNER_ENROL) - || ((String) req.get(JsonKey.OBJECT_TYPE)).equals(JsonKey.BATCH_LEARNER_UNENROL)) { - processBulkBatchEnrollment(req, processId, (String) req.get(JsonKey.OBJECT_TYPE)); + if (((String) req.get(JsonKey.OBJECT_TYPE)).equals(JsonKey.USER)) { + processBulkUserUpload(req, processId); + } else if (((String) req.get(JsonKey.OBJECT_TYPE)).equals(JsonKey.ORGANISATION)) { + processBulkOrgUpload(req, processId); + } else if (((String) req.get(JsonKey.OBJECT_TYPE)).equals(JsonKey.BATCH)) { + processBulkBatchEnrollment(req, processId); } } - private void processBulkBatchEnrollment( - Map req, String processId, String objectType) throws IOException { + private void processBulkBatchEnrollment(Map req, String processId) + throws IOException { List batchList = parseCsvFile((byte[]) req.get(JsonKey.FILE), processId); if (null != batchList) { @@ -211,7 +317,137 @@ private void processBulkBatchEnrollment( } // save csv file to db uploadCsvToDB( - batchList, processId, null, objectType, (String) req.get(JsonKey.CREATED_BY), null); + batchList, processId, null, JsonKey.BATCH, (String) req.get(JsonKey.CREATED_BY), null); + } + + private void processBulkOrgUpload(Map req, String processId) throws IOException { + + ProjectLogger.log("BulkUploadManagementActor: processBulkOrgUpload called.", LoggerEnum.INFO); + List orgList = null; + orgList = parseCsvFile((byte[]) req.get(JsonKey.FILE), processId); + if (null != orgList) { + if (null != PropertiesCache.getInstance().getProperty(JsonKey.BULK_UPLOAD_ORG_DATA_SIZE)) { + orgDataSize = + (Integer.parseInt( + PropertiesCache.getInstance().getProperty(JsonKey.BULK_UPLOAD_ORG_DATA_SIZE))); + ProjectLogger.log("bulk upload org data size read from config file " + orgDataSize); + } + validateFileSizeAgainstLineNumbers(orgDataSize, orgList.size()); + if (!orgList.isEmpty()) { + String[] columns = orgList.get(0); + validateBulkUploadFields(columns, bulkOrgAllowedFields, false); + } else { + throw new ProjectCommonException( + ResponseCode.dataSizeError.getErrorCode(), + ProjectUtil.formatMessage(ResponseCode.dataSizeError.getErrorMessage(), orgDataSize), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + } else { + throw new ProjectCommonException( + ResponseCode.dataSizeError.getErrorCode(), + ProjectUtil.formatMessage(ResponseCode.dataSizeError.getErrorMessage(), orgDataSize), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + // save csv file to db + uploadCsvToDB( + orgList, processId, null, JsonKey.ORGANISATION, (String) req.get(JsonKey.CREATED_BY), null); + } + + private void processBulkUserUpload(Map req, String processId) { + DbInfo orgDb = Util.dbInfoMap.get(JsonKey.ORG_DB); + String orgId = ""; + Response response = null; + if (!StringUtils.isBlank((String) req.get(JsonKey.ORGANISATION_ID))) { + response = + cassandraOperation.getRecordById( + orgDb.getKeySpace(), orgDb.getTableName(), (String) req.get(JsonKey.ORGANISATION_ID)); + } else { + Map map = new HashMap<>(); + map.put(JsonKey.EXTERNAL_ID, ((String) req.get(JsonKey.ORG_EXTERNAL_ID)).toLowerCase()); + map.put(JsonKey.PROVIDER, ((String) req.get(JsonKey.ORG_PROVIDER)).toLowerCase()); + response = + cassandraOperation.getRecordsByProperties(orgDb.getKeySpace(), orgDb.getTableName(), map); + } + List> responseList = + (List>) response.get(JsonKey.RESPONSE); + + if (responseList.isEmpty()) { + throw new ProjectCommonException( + ResponseCode.invalidOrgData.getErrorCode(), + ResponseCode.invalidOrgData.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } else { + orgId = (String) responseList.get(0).get(JsonKey.ID); + } + + String rootOrgId = ""; + Map orgMap = responseList.get(0); + boolean isRootOrg = false; + if (null != orgMap.get(JsonKey.IS_ROOT_ORG)) { + isRootOrg = (boolean) orgMap.get(JsonKey.IS_ROOT_ORG); + } else { + isRootOrg = false; + } + if (isRootOrg) { + rootOrgId = orgId; + } else { + if (!StringUtils.isBlank((String) orgMap.get(JsonKey.ROOT_ORG_ID))) { + rootOrgId = (String) orgMap.get(JsonKey.ROOT_ORG_ID); + } else { + String msg = ""; + if (StringUtils.isBlank((String) req.get(JsonKey.ORGANISATION_ID))) { + msg = + ((String) req.get(JsonKey.ORG_EXTERNAL_ID)) + + " and " + + ((String) req.get(JsonKey.ORG_PROVIDER)); + } else { + msg = (String) req.get(JsonKey.ORGANISATION_ID); + } + throw new ProjectCommonException( + ResponseCode.rootOrgAssociationError.getErrorCode(), + ProjectUtil.formatMessage(ResponseCode.rootOrgAssociationError.getErrorMessage(), msg), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + } + List userList = null; + try { + userList = parseCsvFile((byte[]) req.get(JsonKey.FILE), processId); + } catch (IOException e) { + throw new ProjectCommonException( + ResponseCode.csvError.getErrorCode(), + ResponseCode.csvError.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + if (null != userList) { + if (StringUtils.isNotBlank(ProjectUtil.getConfigValue(JsonKey.BULK_UPLOAD_USER_DATA_SIZE))) { + userDataSize = + (Integer.parseInt( + ProjectUtil.getConfigValue(JsonKey.BULK_UPLOAD_USER_DATA_SIZE).trim())); + + ProjectLogger.log( + "BulkUploadManagementActor:processBulkUserUpload : bulk upload user data size" + + userDataSize, + LoggerEnum.INFO.name()); + } + validateFileSizeAgainstLineNumbers(userDataSize, userList.size()); + if (!userList.isEmpty()) { + String[] columns = userList.get(0); + validateBulkUploadFields(columns, bulkUserAllowedFields, false); + } else { + throw new ProjectCommonException( + ResponseCode.csvError.getErrorCode(), + ResponseCode.csvError.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + } else { + throw new ProjectCommonException( + ResponseCode.csvError.getErrorCode(), + ResponseCode.csvError.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + // save csv file to db + uploadCsvToDB( + userList, processId, orgId, JsonKey.USER, (String) req.get(JsonKey.CREATED_BY), rootOrgId); } private void uploadCsvToDB( @@ -228,6 +464,11 @@ private void uploadCsvToDB( String[] columnArr = dataList.get(0); columnArr = trimColumnAttributes(columnArr); Map dataMap = null; + String channel = null; + // channel is required only in case of the user type bulk upload. + if (StringUtils.isNotBlank(objectType) && objectType.equalsIgnoreCase(JsonKey.USER)) { + channel = Util.getChannel(rootOrgId); + } for (int i = 1; i < dataList.size(); i++) { dataMap = new HashMap<>(); String[] valueArr = dataList.get(i); @@ -235,6 +476,11 @@ private void uploadCsvToDB( String value = (valueArr[j].trim().length() == 0 ? null : valueArr[j].trim()); dataMap.put(columnArr[j], value); } + if (!StringUtils.isBlank(objectType) && objectType.equalsIgnoreCase(JsonKey.USER)) { + dataMap.put(JsonKey.ROOT_ORG_ID, rootOrgId); + dataMap.put(JsonKey.ORGANISATION_ID, orgId); + dataMap.put(JsonKey.CHANNEL, channel); + } dataMapList.add(dataMap); } } catch (Exception e) { diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseBatchManagementActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseBatchManagementActor.java index 02a877b4fd..2491b602b9 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseBatchManagementActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseBatchManagementActor.java @@ -1,11 +1,9 @@ package org.sunbird.learner.actors.coursebatch; -import static org.sunbird.common.models.util.JsonKey.ID; -import static org.sunbird.common.models.util.JsonKey.PARTICIPANTS; +import static org.sunbird.common.models.util.JsonKey.*; import static org.sunbird.common.models.util.ProjectLogger.log; import com.fasterxml.jackson.databind.ObjectMapper; -import java.text.MessageFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -13,8 +11,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TimeZone; -import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -37,6 +35,7 @@ import org.sunbird.common.request.ExecutionContext; import org.sunbird.common.request.Request; import org.sunbird.common.responsecode.ResponseCode; +import org.sunbird.dto.SearchDTO; import org.sunbird.learner.actors.coursebatch.dao.CourseBatchDao; import org.sunbird.learner.actors.coursebatch.dao.impl.CourseBatchDaoImpl; import org.sunbird.learner.actors.coursebatch.service.UserCoursesService; @@ -56,7 +55,7 @@ "addUserBatch", "removeUserFromBatch", "getBatch", - "getParticipants" + "getCourseBatchDetail" }, asyncTasks = {} ) @@ -93,11 +92,8 @@ public void onReceive(Request request) throws Throwable { case "addUserBatch": addUserCourseBatch(request); break; - case "removeUserFromBatch": - removeUserCourseBatch(request); - break; - case "getParticipants": - getParticipants(request); + case "getCourseBatchDetail": + getCourseBatchDetails(request); break; default: onReceiveUnsupportedOperation(request.getOperation()); @@ -105,6 +101,7 @@ public void onReceive(Request request) throws Throwable { } } + @SuppressWarnings("unchecked") private void createCourseBatch(Request actorMessage) { Map request = actorMessage.getRequest(); Map targetObject; @@ -114,20 +111,26 @@ private void createCourseBatch(Request actorMessage) { (Map) actorMessage.getContext().get(JsonKey.HEADER); String requestedBy = (String) actorMessage.getContext().get(JsonKey.REQUESTED_BY); - if (Util.isNotNull(request.get(JsonKey.PARTICIPANTS))) { - ProjectCommonException.throwClientErrorException( - ResponseCode.invalidRequestParameter, - ProjectUtil.formatMessage( - ResponseCode.invalidRequestParameter.getErrorMessage(), PARTICIPANTS)); - } + List participants = (List) request.get(JsonKey.PARTICIPANTS); + request.remove(JsonKey.PARTICIPANTS); + request.remove(JsonKey.PARTICIPANT); CourseBatch courseBatch = new ObjectMapper().convertValue(request, CourseBatch.class); + courseBatch.initCount(); + courseBatch.setId(courseBatchId); courseBatch.setStatus(setCourseBatchStatus((String) request.get(JsonKey.START_DATE))); + courseBatch.setHashTagId( + getHashTagId((String) request.get(JsonKey.HASH_TAG_ID), JsonKey.CREATE, "", courseBatchId)); String courseId = (String) request.get(JsonKey.COURSE_ID); Map contentDetails = getContentDetails(courseId, headers); courseBatch.setContentDetails(contentDetails, requestedBy); validateContentOrg(courseBatch.getCreatedFor()); validateMentors(courseBatch); - courseBatch.setBatchId(courseBatchId); + Map participantsMap = null; + if (participants != null) { + validateParticipants(participants, courseBatch); + participantsMap = getParticipantsMap(participants, courseBatch); + } + Response result = courseBatchDao.create(courseBatch); result.put(JsonKey.BATCH_ID, courseBatchId); @@ -146,10 +149,12 @@ private void createCourseBatch(Request actorMessage) { TelemetryUtil.addTargetObjectRollUp(rollUp, targetObject); TelemetryUtil.telemetryProcessingCall(request, targetObject, correlatedObject); - updateBatchCount(courseBatch); if (courseNotificationActive()) { + if (participantsMap != null) + courseBatch.setParticipant((List) participantsMap.get(JsonKey.PARTICIPANTS)); batchOperationNotifier(courseBatch, null); } + updateBatchCount(courseBatch); } private boolean courseNotificationActive() { @@ -185,6 +190,7 @@ private void batchOperationNotifier( } else { batchNotificationMap.put(JsonKey.OPERATION_TYPE, JsonKey.ADD); batchNotificationMap.put(JsonKey.ADDED_MENTORS, courseBatch.getMentors()); + batchNotificationMap.put(JsonKey.ADDED_PARTICIPANTS, courseBatch.getParticipant()); } batchNotificationMap.put(JsonKey.COURSE_BATCH, courseBatch); batchNotification.setRequest(batchNotificationMap); @@ -194,40 +200,44 @@ private void batchOperationNotifier( @SuppressWarnings("unchecked") private void updateCourseBatch(Request actorMessage) { Map targetObject = null; - Map participantsMap = new HashMap<>(); + Map participantsMap = null; List> correlatedObject = new ArrayList<>(); Map request = actorMessage.getRequest(); - if (Util.isNotNull(request.get(JsonKey.PARTICIPANTS))) { - ProjectCommonException.throwClientErrorException( - ResponseCode.invalidRequestParameter, - ProjectUtil.formatMessage( - ResponseCode.invalidRequestParameter.getErrorMessage(), PARTICIPANTS)); - } - String batchId = - request.containsKey(JsonKey.BATCH_ID) - ? (String) request.get(JsonKey.BATCH_ID) - : (String) request.get(JsonKey.ID); + List participants = (List) request.get(JsonKey.PARTICIPANTS); String requestedBy = (String) actorMessage.getContext().get(JsonKey.REQUESTED_BY); - CourseBatch oldBatch = - courseBatchDao.readById((String) request.get(JsonKey.COURSE_ID), batchId); + + CourseBatch oldBatch = courseBatchDao.readById((String) request.get(JsonKey.ID)); CourseBatch courseBatch = getUpdateCourseBatch(request); courseBatch.setUpdatedDate(ProjectUtil.getFormattedDate()); checkBatchStatus(courseBatch); validateUserPermission(courseBatch, requestedBy); validateContentOrg(courseBatch.getCreatedFor()); validateMentors(courseBatch); + if (participants != null + && JsonKey.INVITE_ONLY.equalsIgnoreCase(courseBatch.getEnrollmentType())) { + validateParticipants(participants, courseBatch); + participantsMap = getParticipantsMap(participants, courseBatch); + } else { + participantsMap = new HashMap<>(); + } participantsMap = getMentorLists(participantsMap, oldBatch, courseBatch); Map courseBatchMap = new ObjectMapper().convertValue(courseBatch, Map.class); - Response result = - courseBatchDao.update((String) request.get(JsonKey.COURSE_ID), batchId, courseBatchMap); + Response result = courseBatchDao.update(courseBatchMap); sender().tell(result, self()); - CourseBatchUtil.syncCourseBatchForeground(batchId, courseBatchMap); - + if (((String) result.get(JsonKey.RESPONSE)).equalsIgnoreCase(JsonKey.SUCCESS)) { + CourseBatchUtil.syncCourseBatchForeground( + (String) courseBatchMap.get(JsonKey.ID), courseBatchMap); + } else { + ProjectLogger.log( + "CourseBatchManagementActor:updateCourseBatch: Course batch not synced to ES as response is not successful", + LoggerEnum.INFO.name()); + } targetObject = - TelemetryUtil.generateTargetObject(batchId, TelemetryEnvKey.BATCH, JsonKey.UPDATE, null); + TelemetryUtil.generateTargetObject( + (String) request.get(JsonKey.ID), TelemetryEnvKey.BATCH, JsonKey.UPDATE, null); Map rollUp = new HashMap<>(); rollUp.put("l1", courseBatch.getCourseId()); @@ -235,6 +245,10 @@ private void updateCourseBatch(Request actorMessage) { TelemetryUtil.telemetryProcessingCall(courseBatchMap, targetObject, correlatedObject); if (courseNotificationActive()) { + if (participants != null + && JsonKey.INVITE_ONLY.equalsIgnoreCase(courseBatch.getEnrollmentType())) { + courseBatch.setParticipant((List) participantsMap.get(JsonKey.PARTICIPANTS)); + } batchOperationNotifier(courseBatch, participantsMap); } } @@ -276,9 +290,7 @@ private void checkBatchStatus(CourseBatch courseBatch) { @SuppressWarnings("unchecked") private CourseBatch getUpdateCourseBatch(Map request) { - CourseBatch courseBatch = - courseBatchDao.readById( - (String) request.get(JsonKey.COURSE_ID), (String) request.get(JsonKey.ID)); + CourseBatch courseBatch = courseBatchDao.readById((String) request.get(JsonKey.ID)); courseBatch.setEnrollmentType( getEnrollmentType( @@ -288,6 +300,12 @@ private CourseBatch getUpdateCourseBatch(Map request) { (List) request.get(JsonKey.COURSE_CREATED_FOR), courseBatch.getEnrollmentType(), courseBatch.getCreatedFor())); + courseBatch.setHashTagId( + getHashTagId( + (String) request.get(JsonKey.HASHTAGID), + JsonKey.UPDATE, + (String) request.get(JsonKey.ID), + "")); if (request.containsKey(JsonKey.NAME)) courseBatch.setName((String) request.get(JsonKey.NAME)); @@ -317,13 +335,35 @@ private void addUserCourseBatch(Request actorMessage) { String batchId = (String) req.get(JsonKey.BATCH_ID); TelemetryUtil.generateCorrelatedObject(batchId, TelemetryEnvKey.BATCH, null, correlatedObject); - Map courseBatchObject = getValidatedCourseBatch(batchId); + + CourseBatch courseBatch = courseBatchDao.readById(batchId); + Map courseBatchObject = new ObjectMapper().convertValue(courseBatch, Map.class); + + if (ProjectUtil.isNull(courseBatchObject.get(JsonKey.ENROLLMENT_TYPE)) + || !((String) courseBatchObject.get(JsonKey.ENROLLMENT_TYPE)) + .equalsIgnoreCase(JsonKey.INVITE_ONLY)) { + throw new ProjectCommonException( + ResponseCode.enrollmentTypeValidation.getErrorCode(), + ResponseCode.enrollmentTypeValidation.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + if (ProjectUtil.isNull(courseBatchObject.get(JsonKey.COURSE_CREATED_FOR)) + || ((List) courseBatchObject.get(JsonKey.COURSE_CREATED_FOR)).isEmpty()) { + throw new ProjectCommonException( + ResponseCode.courseCreatedForIsNull.getErrorCode(), + ResponseCode.courseCreatedForIsNull.getErrorMessage(), + ResponseCode.RESOURCE_NOT_FOUND.getResponseCode()); + } String batchCreator = (String) courseBatchObject.get(JsonKey.CREATED_BY); + if (StringUtils.isBlank(batchCreator)) { + throw new ProjectCommonException( + ResponseCode.invalidCourseCreatorId.getErrorCode(), + ResponseCode.invalidCourseCreatorId.getErrorMessage(), + ResponseCode.RESOURCE_NOT_FOUND.getResponseCode()); + } String batchCreatorRootOrgId = getRootOrg(batchCreator); - List participants = - userCoursesService.getEnrolledUserFromBatch( - (String) courseBatchObject.get(JsonKey.BATCH_ID)); - CourseBatch courseBatch = new ObjectMapper().convertValue(courseBatchObject, CourseBatch.class); + List participants = userCoursesService.getEnrolledUserFromBatch(courseBatch.getId()); + courseBatch.setParticipant(participants); List userIds = (List) req.get(JsonKey.USER_IDs); if (participants == null) { participants = new ArrayList<>(); @@ -334,10 +374,7 @@ private void addUserCourseBatch(Request actorMessage) { if (!(participants.contains(userId))) { if (!participantWithRootOrgIds.containsKey(userId) || (!batchCreatorRootOrgId.equals(participantWithRootOrgIds.get(userId)))) { - response.put( - userId, - MessageFormat.format( - ResponseCode.userNotAssociatedToRootOrg.getErrorMessage(), userId)); + response.put(userId, ResponseCode.userNotAssociatedToRootOrg.getErrorMessage()); continue; } addedParticipants.add(userId); @@ -348,7 +385,10 @@ private void addUserCourseBatch(Request actorMessage) { } userCoursesService.enroll( - batchId, (String) courseBatchObject.get(JsonKey.COURSE_ID), addedParticipants); + batchId, + (String) courseBatchObject.get(JsonKey.COURSE_ID), + addedParticipants, + (Map) (courseBatchObject.get(JsonKey.COURSE_ADDITIONAL_INFO))); for (String userId : addedParticipants) { participants.add(userId); response.getResult().put(userId, JsonKey.SUCCESS); @@ -360,109 +400,79 @@ private void addUserCourseBatch(Request actorMessage) { batchId, TelemetryEnvKey.BATCH, null, correlatedObject); TelemetryUtil.telemetryProcessingCall(req, targetObject, correlatedObject); } - sender().tell(response, self()); - if (courseNotificationActive()) { - Map participantMentorMap = new HashMap<>(); - participantMentorMap.put(JsonKey.ADDED_PARTICIPANTS, addedParticipants); - batchOperationNotifier(courseBatch, participantMentorMap); - } - } - - @SuppressWarnings("unchecked") - private void removeUserCourseBatch(Request actorMessage) { - Map req = actorMessage.getRequest(); - Response response = new Response(); - - Map targetObject = null; - List> correlatedObject = new ArrayList<>(); - - String batchId = (String) req.get(JsonKey.BATCH_ID); - TelemetryUtil.generateCorrelatedObject(batchId, TelemetryEnvKey.BATCH, null, correlatedObject); - Map courseBatchObject = getValidatedCourseBatch(batchId); - List participants = - userCoursesService.getEnrolledUserFromBatch( - (String) courseBatchObject.get(JsonKey.BATCH_ID)); - CourseBatch courseBatch = new ObjectMapper().convertValue(courseBatchObject, CourseBatch.class); - List userIds = (List) req.get(JsonKey.USER_IDs); - if (participants == null) { - participants = new ArrayList<>(); - } - List participantsList = - CollectionUtils.isEmpty(participants) ? new ArrayList<>() : participants; - List removedParticipants = new ArrayList<>(); - userIds.forEach( - id -> { - if (!participantsList.contains(id)) { - response.getResult().put(id, ResponseCode.userNotEnrolledCourse.getErrorMessage()); - } else { - try { - userCoursesService.unenroll(batchId, id); - removedParticipants.add(id); - response.getResult().put(id, JsonKey.SUCCESS); - } catch (ProjectCommonException ex) { - response.getResult().put(id, ex.getMessage()); - } - } - }); - for (String userId : removedParticipants) { - targetObject = - TelemetryUtil.generateTargetObject(userId, TelemetryEnvKey.USER, JsonKey.REMOVE, null); - correlatedObject = new ArrayList<>(); - TelemetryUtil.generateCorrelatedObject( - batchId, TelemetryEnvKey.BATCH, null, correlatedObject); - TelemetryUtil.telemetryProcessingCall(req, targetObject, correlatedObject); - } sender().tell(response, self()); + Request request = new Request(); + request.setOperation(ActorOperations.UPDATE_COURSE_BATCH_ES.getValue()); + request.getRequest().put(JsonKey.BATCH, courseBatchObject); if (courseNotificationActive()) { - Map participantMentorMap = new HashMap<>(); - participantMentorMap.put(JsonKey.REMOVED_PARTICIPANTS, removedParticipants); - batchOperationNotifier(courseBatch, participantMentorMap); + courseBatch.setParticipant(getAddedParticipants(participants, courseBatch)); + batchOperationNotifier(courseBatch, null); + } + try { + ProjectLogger.log( + "CourseBatchManagementActor:addUserCourseBatch: Sync course batch details to ES called"); + tellToAnother(request); + } catch (Exception ex) { + ProjectLogger.log( + "CourseBatchManagementActor:addUserCourseBatch: Exception occurred with error message = " + + ex.getMessage(), + ex); } } - private Map getValidatedCourseBatch(String batchId) { - Future> resultF = - esService.getDataByIdentifier(ProjectUtil.EsType.courseBatch.getTypeName(), batchId); - Map courseBatchObject = - (Map) ElasticSearchHelper.getResponseFromFuture(resultF); + private List getAddedParticipants(List participants, CourseBatch courseBatch) { + List currentParticipants = courseBatch.getParticipant(); + if (participants == null) return courseBatch.getParticipant(); + else if (currentParticipants == null || currentParticipants.isEmpty()) { + return participants; + } else { - if (ProjectUtil.isNull(courseBatchObject.get(JsonKey.ENROLLMENT_TYPE)) - || !((String) courseBatchObject.get(JsonKey.ENROLLMENT_TYPE)) - .equalsIgnoreCase(JsonKey.INVITE_ONLY)) { - throw new ProjectCommonException( - ResponseCode.enrollmentTypeValidation.getErrorCode(), - ResponseCode.enrollmentTypeValidation.getErrorMessage(), - ResponseCode.CLIENT_ERROR.getResponseCode()); - } - if (CollectionUtils.isEmpty((List) courseBatchObject.get(JsonKey.COURSE_CREATED_FOR))) { - throw new ProjectCommonException( - ResponseCode.courseCreatedForIsNull.getErrorCode(), - ResponseCode.courseCreatedForIsNull.getErrorMessage(), - ResponseCode.RESOURCE_NOT_FOUND.getResponseCode()); - } - String batchCreator = (String) courseBatchObject.get(JsonKey.CREATED_BY); - if (StringUtils.isBlank(batchCreator)) { - throw new ProjectCommonException( - ResponseCode.invalidCourseCreatorId.getErrorCode(), - ResponseCode.invalidCourseCreatorId.getErrorMessage(), - ResponseCode.RESOURCE_NOT_FOUND.getResponseCode()); + for (String key : currentParticipants) { + if (participants.contains(key)) { + participants.remove(key); + } + } } - return courseBatchObject; + return participants; } private void getCourseBatch(Request actorMessage) { Future> resultF = esService.getDataByIdentifier( - ProjectUtil.EsType.courseBatch.getTypeName(), + ProjectUtil.EsType.course.getTypeName(), (String) actorMessage.getContext().get(JsonKey.BATCH_ID)); Map result = (Map) ElasticSearchHelper.getResponseFromFuture(resultF); Response response = new Response(); - response.put(JsonKey.RESPONSE, result); + if (null != result) { + if (JsonKey.INVITE_ONLY.equalsIgnoreCase((String) result.get(JsonKey.ENROLLMENT_TYPE))) { + List participants = + userCoursesService.getEnrolledUserFromBatch( + (String) actorMessage.getContext().get(JsonKey.BATCH_ID)); + result.put(JsonKey.PARTICIPANTS, participants); + } + response.put(JsonKey.RESPONSE, result); + } else { + result = new HashMap<>(); + response.put(JsonKey.RESPONSE, result); + } sender().tell(response, self()); } + @SuppressWarnings("unchecked") + private void getCourseBatchDetails(Request actorMessage) { + String batchId = (String) actorMessage.getContext().get(JsonKey.BATCH_ID); + CourseBatch courseBatch = courseBatchDao.readById(batchId); + List> courseBatchList = new ArrayList<>(); + ObjectMapper mapper = new ObjectMapper(); + courseBatchList.add(mapper.convertValue(courseBatch, Map.class)); + Response result = new Response(); + result.getResult().put(JsonKey.RESPONSE, courseBatchList); + + sender().tell(result, self()); + } + private int setCourseBatchStatus(String startDate) { try { Date todayDate = DATE_FORMAT.parse(DATE_FORMAT.format(new Date())); @@ -521,6 +531,108 @@ private void validateMentors(CourseBatch courseBatch) { } } + private Map getParticipantsMap( + List participants, CourseBatch courseBatchObject) { + Map participantsList = new HashMap<>(); + String batchId = courseBatchObject.getId(); + List dbParticipants = getParticipantsFromUserCourses(courseBatchObject.getId()); + if (CollectionUtils.isEmpty(dbParticipants)) { + dbParticipants = new ArrayList<>(); + } + List finalParticipants = new ArrayList<>(); + List addedParticipants = new ArrayList<>(); + for (String userId : participants) { + if (!(dbParticipants.contains(userId))) { + finalParticipants.add(userId); + addedParticipants.add(userId); + } else { + finalParticipants.add(userId); + dbParticipants.remove(userId); + } + } + userCoursesService.enroll( + batchId, + courseBatchObject.getCourseId(), + addedParticipants, + (courseBatchObject.getCourseAdditionalInfo())); + if (!dbParticipants.isEmpty()) { + removeParticipants(dbParticipants, batchId, courseBatchObject.getCourseId()); + } + participantsList.put(JsonKey.REMOVED_PARTICIPANTS, dbParticipants); + participantsList.put(JsonKey.ADDED_PARTICIPANTS, addedParticipants); + participantsList.put(JsonKey.PARTICIPANTS, finalParticipants); + return participantsList; + } + + private List getParticipantsFromUserCourses(String id) { + return userCoursesService.getEnrolledUserFromBatch(id); + } + + private List getParticipantsList(Map participantsMap) { + List participantsList = null; + + if (participantsMap != null) { + participantsList = new ArrayList<>(); + Set keys = participantsMap.keySet(); + for (String user : keys) { + if (participantsMap.get(user)) { + participantsList.add(user); + } + } + } + + return participantsList; + } + + private void validateParticipants(List participants, CourseBatch courseBatch) { + + String batchCreator = courseBatch.getCreatedBy(); + if (StringUtils.isBlank(batchCreator)) { + throw new ProjectCommonException( + ResponseCode.invalidCourseCreatorId.getErrorCode(), + ResponseCode.invalidCourseCreatorId.getErrorMessage(), + ResponseCode.RESOURCE_NOT_FOUND.getResponseCode()); + } + validateCourseBatchData(courseBatch); + String batchCreatorRootOrgId = getRootOrg(batchCreator); + Map participantWithRootOrgIds = getRootOrgForMultipleUsers(participants); + for (String userId : participants) { + if (!participantWithRootOrgIds.containsKey(userId) + || (!batchCreatorRootOrgId.equals(participantWithRootOrgIds.get(userId)))) { + throw new ProjectCommonException( + ResponseCode.userNotAssociatedToRootOrg.getErrorCode(), + ResponseCode.userNotAssociatedToRootOrg.getErrorMessage(), + ResponseCode.RESOURCE_NOT_FOUND.getResponseCode(), + userId); + } + } + } + + private void removeParticipants( + List removedParticipant, String batchId, String courseId) { + removedParticipant.forEach( + (userId) -> { + new UserCoursesService().unenroll(userId, courseId, batchId); + }); + } + + private void validateCourseBatchData(CourseBatch courseBatchObject) { + if (ProjectUtil.isNull(courseBatchObject.getCreatedFor()) + || courseBatchObject.getCreatedFor().isEmpty()) { + throw new ProjectCommonException( + ResponseCode.courseCreatedForIsNull.getErrorCode(), + ResponseCode.courseCreatedForIsNull.getErrorMessage(), + ResponseCode.RESOURCE_NOT_FOUND.getResponseCode()); + } + if (ProjectUtil.isNull(courseBatchObject.getEnrollmentType()) + || !(courseBatchObject.getEnrollmentType()).equalsIgnoreCase(JsonKey.INVITE_ONLY)) { + throw new ProjectCommonException( + ResponseCode.enrollmentTypeValidation.getErrorCode(), + ResponseCode.enrollmentTypeValidation.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + } + private List getUpdatedCreatedFor( List createdFor, String enrolmentType, List dbValueCreatedFor) { if (createdFor != null) { @@ -622,6 +734,41 @@ private String getRootOrgFromUserMap(Map userInfo) { return rootOrg; } + private String getHashTagId(String hasTagId, String operation, String id, String uniqueId) { + if (hasTagId != null) return validateHashTagId(hasTagId, operation, id); + return uniqueId; + } + + @SuppressWarnings("unchecked") + private String validateHashTagId(String hashTagId, String opType, String id) { + Map filters = new HashMap<>(); + filters.put(JsonKey.HASHTAGID, hashTagId); + SearchDTO searchDto = new SearchDTO(); + searchDto.getAdditionalProperties().put(JsonKey.FILTERS, filters); + Future> resultF = + esService.search(searchDto, ProjectUtil.EsType.course.getTypeName()); + Map result = + (Map) ElasticSearchHelper.getResponseFromFuture(resultF); + List> dataMapList = (List>) result.get(JsonKey.CONTENT); + if (opType.equalsIgnoreCase(JsonKey.CREATE)) { + if (!dataMapList.isEmpty()) { + throw new ProjectCommonException( + ResponseCode.invalidHashTagId.getErrorCode(), + ResponseCode.invalidHashTagId.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + } else if (opType.equalsIgnoreCase(JsonKey.UPDATE) && !dataMapList.isEmpty()) { + Map batchMap = dataMapList.get(0); + if (!(((String) batchMap.get(JsonKey.ID)).equalsIgnoreCase(id))) { + throw new ProjectCommonException( + ResponseCode.invalidHashTagId.getErrorCode(), + ResponseCode.invalidHashTagId.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + } + return hashTagId; + } + private void validateUpdateBatchStartDate(Date startDate) { if (startDate != null) { try { @@ -807,29 +954,21 @@ private void validateContentOrg(List createdFor) { @SuppressWarnings("unchecked") private void updateBatchCount(CourseBatch courseBatch) { - CourseBatchSchedulerUtil.doOperationInEkStepCourse( - courseBatch.getCourseId(), true, courseBatch.getEnrollmentType()); - } - - private void getParticipants(Request actorMessage) { - Map request = - (Map) actorMessage.getRequest().get(JsonKey.BATCH); - boolean active = true; - if (null != request.get(JsonKey.ACTIVE)) { - active = (boolean) request.get(JsonKey.ACTIVE); - } - String batchID = (String) request.get(JsonKey.BATCH_ID); - List participants = userCoursesService.getParticipantsList(batchID, active); - - if (CollectionUtils.isEmpty(participants)) { - participants = new ArrayList<>(); + if (CourseBatchSchedulerUtil.doOperationInEkStepCourse( + courseBatch.getCourseId(), true, courseBatch.getEnrollmentType())) { + courseBatch.setCountIncrementStatus(true); + courseBatch.setCountIncrementDate(ProjectUtil.getFormattedDate()); + Map courseBatchMap = new ObjectMapper().convertValue(courseBatch, Map.class); + Response response = courseBatchDao.update(courseBatchMap); + + if (JsonKey.SUCCESS.equalsIgnoreCase((String) response.get(JsonKey.RESPONSE))) { + CourseBatchUtil.syncCourseBatchForeground( + (String) courseBatchMap.get(JsonKey.ID), courseBatchMap); + } else { + ProjectLogger.log( + "CourseBatchManagementActor:updateBatchCount: Course batch not synced to ES as response is not successful", + LoggerEnum.INFO.name()); + } } - - Response response = new Response(); - Map result = new HashMap(); - result.put(JsonKey.COUNT, participants.size()); - result.put(JsonKey.PARTICIPANTS, participants); - response.put(JsonKey.BATCH, result); - sender().tell(response, self()); } } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseBatchNotificationActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseBatchNotificationActor.java index ae93dc1dfc..0ae1c47340 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseBatchNotificationActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseBatchNotificationActor.java @@ -24,7 +24,6 @@ import org.sunbird.common.responsecode.ResponseCode; import org.sunbird.helper.ServiceFactory; import org.sunbird.learner.actors.notificationservice.EmailServiceActor; -import org.sunbird.learner.util.CourseBatchSchedulerUtil; import org.sunbird.learner.util.Util; import org.sunbird.models.course.batch.CourseBatch; @@ -79,10 +78,6 @@ private void courseBatchNotification(Request request) { "CourseBatchNotificationActor:courseBatchNotification: userId = " + userId, LoggerEnum.INFO); - Map headers = CourseBatchSchedulerUtil.headerMap; - Map contentDetails = - CourseEnrollmentActor.getCourseObjectFromEkStep(courseBatch.getCourseId(), headers); - if (userId != null) { ProjectLogger.log( "CourseBatchNotificationActor:courseBatchNotification: Open batch", LoggerEnum.INFO); @@ -98,8 +93,7 @@ private void courseBatchNotification(Request request) { subject = JsonKey.COURSE_INVITATION; } - triggerEmailNotification( - Arrays.asList(userId), courseBatch, subject, template, contentDetails); + triggerEmailNotification(Arrays.asList(userId), courseBatch, subject, template); } else { ProjectLogger.log( @@ -110,43 +104,29 @@ private void courseBatchNotification(Request request) { List removedMentors = (List) requestMap.get(JsonKey.REMOVED_MENTORS); triggerEmailNotification( - addedMentors, - courseBatch, - JsonKey.COURSE_INVITATION, - JsonKey.BATCH_MENTOR_ENROL, - contentDetails); + addedMentors, courseBatch, JsonKey.COURSE_INVITATION, JsonKey.BATCH_MENTOR_ENROL); triggerEmailNotification( removedMentors, courseBatch, JsonKey.UNENROLL_FROM_COURSE_BATCH, - JsonKey.BATCH_MENTOR_UNENROL, - contentDetails); + JsonKey.BATCH_MENTOR_UNENROL); List addedParticipants = (List) requestMap.get(JsonKey.ADDED_PARTICIPANTS); List removedParticipants = (List) requestMap.get(JsonKey.REMOVED_PARTICIPANTS); triggerEmailNotification( - addedParticipants, - courseBatch, - JsonKey.COURSE_INVITATION, - JsonKey.BATCH_LEARNER_ENROL, - contentDetails); + addedParticipants, courseBatch, JsonKey.COURSE_INVITATION, JsonKey.BATCH_LEARNER_ENROL); triggerEmailNotification( removedParticipants, courseBatch, JsonKey.UNENROLL_FROM_COURSE_BATCH, - JsonKey.BATCH_LEARNER_UNENROL, - contentDetails); + JsonKey.BATCH_LEARNER_UNENROL); } } private void triggerEmailNotification( - List userIdList, - CourseBatch courseBatch, - String subject, - String template, - Map contentDetails) { + List userIdList, CourseBatch courseBatch, String subject, String template) { ProjectLogger.log( "CourseBatchNotificationActor:triggerEmailNotification: userIdList = " @@ -158,7 +138,7 @@ private void triggerEmailNotification( List> userMapList = getUsersFromDB(userIdList); for (Map user : userMapList) { - Map requestMap = this.createEmailRequest(user, courseBatch, contentDetails); + Map requestMap = this.createEmailRequest(user, courseBatch); requestMap.put(JsonKey.SUBJECT, subject); requestMap.put(JsonKey.EMAIL_TEMPLATE_TYPE, template); @@ -198,24 +178,26 @@ private List> getUsersFromDB(List userIds) { @SuppressWarnings("unchecked") private Map createEmailRequest( - Map userMap, CourseBatch courseBatch, Map contentDetails) { + Map userMap, CourseBatch courseBatch) { ProjectLogger.log("CourseBatchNotificationActor: createEmailRequest: ", LoggerEnum.INFO); Map courseBatchObject = new ObjectMapper().convertValue(courseBatch, Map.class); + Map additionalCourseInfo = + (Map) courseBatchObject.get(JsonKey.COURSE_ADDITIONAL_INFO); Map requestMap = new HashMap(); requestMap.put(JsonKey.REQUEST, BackgroundOperations.emailService.name()); requestMap.put(JsonKey.ORG_NAME, courseBatchObject.get(JsonKey.ORG_NAME)); - requestMap.put(JsonKey.COURSE_LOGO_URL, contentDetails.get(JsonKey.APP_ICON)); + requestMap.put(JsonKey.COURSE_LOGO_URL, additionalCourseInfo.get(JsonKey.COURSE_LOGO_URL)); requestMap.put(JsonKey.START_DATE, courseBatchObject.get(JsonKey.START_DATE)); requestMap.put(JsonKey.END_DATE, courseBatchObject.get(JsonKey.END_DATE)); requestMap.put(JsonKey.COURSE_ID, courseBatchObject.get(JsonKey.COURSE_ID)); requestMap.put(JsonKey.BATCH_NAME, courseBatch.getName()); - requestMap.put(JsonKey.COURSE_NAME, contentDetails.get(JsonKey.NAME)); + requestMap.put(JsonKey.COURSE_NAME, additionalCourseInfo.get(JsonKey.COURSE_NAME)); requestMap.put( JsonKey.COURSE_BATCH_URL, - getCourseBatchUrl(courseBatch.getCourseId(), courseBatch.getBatchId())); + getCourseBatchUrl(courseBatch.getCourseId(), courseBatch.getId())); requestMap.put(JsonKey.SIGNATURE, courseBatchNotificationSignature); String userId = (String) userMap.get(JsonKey.USER_ID); diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseEnrollmentActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseEnrollmentActor.java index c13862863f..4d12da64e7 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseEnrollmentActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/CourseEnrollmentActor.java @@ -31,6 +31,7 @@ import org.sunbird.learner.actors.coursebatch.dao.impl.CourseBatchDaoImpl; import org.sunbird.learner.actors.coursebatch.dao.impl.UserCoursesDaoImpl; import org.sunbird.learner.actors.coursebatch.service.UserCoursesService; +import org.sunbird.learner.util.CourseBatchUtil; import org.sunbird.learner.util.EkStepRequestUtil; import org.sunbird.learner.util.Util; import org.sunbird.models.course.batch.CourseBatch; @@ -74,19 +75,14 @@ public void onReceive(Request request) throws Throwable { private void enrollCourseBatch(Request actorMessage) { ProjectLogger.log("enrollCourseClass called"); Map courseMap = (Map) actorMessage.getRequest(); - courseMap.remove(JsonKey.ID); - CourseBatch courseBatch = - courseBatchDao.readById( - (String) courseMap.get(JsonKey.COURSE_ID), (String) courseMap.get(JsonKey.BATCH_ID)); + CourseBatch courseBatch = courseBatchDao.readById((String) courseMap.get(JsonKey.BATCH_ID)); validateCourseBatch( courseBatch, courseMap, (String) actorMessage.getContext().get(JsonKey.REQUESTED_BY), ActorOperations.ENROLL_COURSE.getValue()); - UserCourses userCourseResult = - userCourseDao.read( - (String) courseMap.get(JsonKey.BATCH_ID), (String) courseMap.get(JsonKey.USER_ID)); + UserCourses userCourseResult = userCourseDao.read(UserCoursesService.getPrimaryKey(courseMap)); if (!ProjectUtil.isNull(userCourseResult) && userCourseResult.isActive()) { ProjectLogger.log("User Already Enrolled Course "); @@ -95,28 +91,23 @@ private void enrollCourseBatch(Request actorMessage) { ResponseCode.userAlreadyEnrolledCourse.getErrorMessage()); } courseMap = createUserCourseMap(courseMap, courseBatch, userCourseResult); - Response result = new Response(); + Response result = null; if (userCourseResult == null) { // user is doing enrollment first time - userCourseDao.insert(courseMap); + result = userCourseDao.insert(courseMap); } else { // second time user is doing enrollment for same course batch - userCourseDao.update(userCourseResult.getBatchId(), userCourseResult.getUserId(), courseMap); + result = userCourseDao.update(courseMap); } - result.put("response", "SUCCESS"); sender().tell(result, self()); if (userCourseResult == null) { courseMap.put(JsonKey.DATE_TIME, ProjectUtil.formatDate(new Timestamp(new Date().getTime()))); updateUserCoursesToES(courseMap); - } else { ProjectLogger.log( "CourseEnrollmentActor:enrollCourseBatch user is enrolling second time.", LoggerEnum.INFO.name()); - UserCoursesService.sync( - courseMap, - (String) courseMap.get(JsonKey.BATCH_ID), - (String) courseMap.get(JsonKey.USER_ID)); + UserCoursesService.sync(courseMap, (String) courseMap.get(JsonKey.ID)); } if (courseNotificationActive()) { batchOperationNotifier(courseMap, courseBatch, JsonKey.ADD); @@ -138,16 +129,35 @@ private boolean courseNotificationActive() { private Map createUserCourseMap( Map courseMap, CourseBatch courseBatchResult, UserCourses userCourseResult) { + courseMap.put(JsonKey.ID, UserCoursesService.getPrimaryKey(courseMap)); courseMap.put(JsonKey.ACTIVE, ProjectUtil.ActiveStatus.ACTIVE.getValue()); if (userCourseResult == null) { // this will create user batch data for new user Timestamp ts = new Timestamp(new Date().getTime()); String addedBy = (String) courseMap.get(JsonKey.REQUESTED_BY); + courseMap.put( + JsonKey.COURSE_LOGO_URL, + courseBatchResult.getCourseAdditionalInfo().get(JsonKey.COURSE_LOGO_URL)); + courseMap.put(JsonKey.CONTENT_ID, (String) courseMap.get(JsonKey.COURSE_ID)); + courseMap.put( + JsonKey.COURSE_NAME, + courseBatchResult.getCourseAdditionalInfo().get(JsonKey.COURSE_NAME)); + courseMap.put( + JsonKey.DESCRIPTION, + courseBatchResult.getCourseAdditionalInfo().get(JsonKey.DESCRIPTION)); courseMap.put(JsonKey.ADDED_BY, addedBy); courseMap.put(JsonKey.COURSE_ENROLL_DATE, ProjectUtil.getFormattedDate()); courseMap.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.NOT_STARTED.getValue()); courseMap.put(JsonKey.DATE_TIME, ts); courseMap.put(JsonKey.COURSE_PROGRESS, 0); + if (null != courseBatchResult.getCourseAdditionalInfo().get(JsonKey.LEAF_NODE_COUNT)) { + courseMap.put( + JsonKey.LEAF_NODE_COUNT, + Integer.parseInt( + courseBatchResult.getCourseAdditionalInfo().get(JsonKey.LEAF_NODE_COUNT).trim())); + } else { + courseMap.put(JsonKey.LEAF_NODE_COUNT, 0); + } } return courseMap; } @@ -156,10 +166,7 @@ private void unenrollCourseBatch(Request actorMessage) { ProjectLogger.log("unenrollCourseClass called"); // objects of telemetry event... Map request = actorMessage.getRequest(); - request.remove(JsonKey.ID); - CourseBatch courseBatch = - courseBatchDao.readById( - (String) request.get(JsonKey.COURSE_ID), (String) request.get(JsonKey.BATCH_ID)); + CourseBatch courseBatch = courseBatchDao.readById((String) request.get(JsonKey.BATCH_ID)); validateCourseBatch( courseBatch, request, @@ -313,14 +320,32 @@ private void verifyRequestedByAndThrowErrorIfNotMatch(String userId, String requ } private Response updateUserCourses(UserCourses userCourses) { - Map userCourseUpdateAttributes = new HashMap<>(); - userCourseUpdateAttributes.put(JsonKey.ACTIVE, false); - Response result = new Response(); - userCourseDao.update( - userCourses.getBatchId(), userCourses.getUserId(), userCourseUpdateAttributes); - result.put("response", "SUCCESS"); - UserCoursesService.sync( - userCourseUpdateAttributes, userCourses.getBatchId(), userCourses.getUserId()); + Map UserCourseUpdateAttributes = new HashMap<>(); + UserCourseUpdateAttributes.put(JsonKey.ACTIVE, false); + UserCourseUpdateAttributes.put(JsonKey.ID, userCourses.getId()); + Response result = userCourseDao.update(UserCourseUpdateAttributes); + if (((String) result.get(JsonKey.RESPONSE)).equalsIgnoreCase(JsonKey.SUCCESS)) { + UserCoursesService.sync(UserCourseUpdateAttributes, userCourses.getId()); + } else { + ProjectLogger.log( + "CourseEnrollmentActor:updateUserCourses: User Courses not synced to ES as response is not successful", + LoggerEnum.INFO.name()); + } return result; } + + @SuppressWarnings("unchecked") + private void updateCourseBatch(CourseBatch courseBatch) { + Map CourseBatchUpdatedAttributes = new HashMap<>(); + CourseBatchUpdatedAttributes.put(JsonKey.ID, (String) courseBatch.getId()); + Response response = courseBatchDao.update(CourseBatchUpdatedAttributes); + Map courseBatchMap = mapper.convertValue(courseBatch, Map.class); + if (((String) response.get(JsonKey.RESPONSE)).equalsIgnoreCase(JsonKey.SUCCESS)) { + CourseBatchUtil.syncCourseBatchForeground((String) courseBatch.getId(), courseBatchMap); + } else { + ProjectLogger.log( + "CourseBatchManagementActor:updateCourseBatch: Course batch not synced to ES as response is not successful", + LoggerEnum.INFO.name()); + } + } } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/CourseBatchDao.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/CourseBatchDao.java index 0f93808895..e5807e073a 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/CourseBatchDao.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/CourseBatchDao.java @@ -20,7 +20,7 @@ public interface CourseBatchDao { * @param courseBatchMap Course batch information to be updated * @return Response containing status of course batch update */ - Response update(String courseId, String batchId, Map courseBatchMap); + Response update(Map courseBatchMap); /** * Read course batch for given identifier. @@ -28,7 +28,7 @@ public interface CourseBatchDao { * @param courseBatchId Course batch identifier * @return Course batch information */ - CourseBatch readById(String courseId, String batchId); + CourseBatch readById(String courseBatchId); /** * Delete specified course batch. diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/UserCoursesDao.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/UserCoursesDao.java index 5e43d9e871..5472f69fde 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/UserCoursesDao.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/UserCoursesDao.java @@ -10,10 +10,10 @@ public interface UserCoursesDao { /** * Get user courses information. * - * @param batchId,userId user courses identifiers + * @param id Identifier generated using courseId, batchId and userId * @return User courses information */ - UserCourses read(String batchId, String userId); + UserCourses read(String id); /** * Create an entry for user courses information @@ -27,7 +27,7 @@ public interface UserCoursesDao { * * @param updateAttributes Map containing user courses attributes which needs to be updated */ - Response update(String batchId, String userId, Map updateAttributes); + Response update(Map updateAttributes); /** * Get all active participant IDs in given batch @@ -42,12 +42,4 @@ public interface UserCoursesDao { * @param userCoursesDetails List of participant details */ Response batchInsert(List> userCoursesDetails); - - /** - * Get all active participant IDs in given batch - * - * @param batchId Batch ID - * @param active - */ - List getBatchParticipants(String batchId, boolean active); } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/impl/CourseBatchDaoImpl.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/impl/CourseBatchDaoImpl.java index 5d431143e0..5bc0872536 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/impl/CourseBatchDaoImpl.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/impl/CourseBatchDaoImpl.java @@ -1,7 +1,6 @@ package org.sunbird.learner.actors.coursebatch.dao.impl; import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.HashMap; import java.util.List; import java.util.Map; import org.sunbird.cassandra.CassandraOperation; @@ -28,26 +27,16 @@ public Response create(CourseBatch courseBatch) { } @Override - public Response update(String courseId, String batchId, Map map) { - Map primaryKey = new HashMap<>(); - primaryKey.put(JsonKey.COURSE_ID, courseId); - primaryKey.put(JsonKey.BATCH_ID, batchId); - Map attributeMap = new HashMap<>(); - attributeMap.putAll(map); - attributeMap.remove(JsonKey.COURSE_ID); - attributeMap.remove(JsonKey.BATCH_ID); + public Response update(Map map) { return cassandraOperation.updateRecord( - courseBatchDb.getKeySpace(), courseBatchDb.getTableName(), attributeMap, primaryKey); + courseBatchDb.getKeySpace(), courseBatchDb.getTableName(), map); } @Override - public CourseBatch readById(String courseId, String batchId) { - Map primaryKey = new HashMap<>(); - primaryKey.put(JsonKey.COURSE_ID, courseId); - primaryKey.put(JsonKey.BATCH_ID, batchId); + public CourseBatch readById(String id) { Response courseBatchResult = cassandraOperation.getRecordById( - courseBatchDb.getKeySpace(), courseBatchDb.getTableName(), primaryKey); + courseBatchDb.getKeySpace(), courseBatchDb.getTableName(), id); List> courseList = (List>) courseBatchResult.get(JsonKey.RESPONSE); if (courseList.isEmpty()) { diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/impl/UserCoursesDaoImpl.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/impl/UserCoursesDaoImpl.java index 6808b6fe07..53daf7472f 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/impl/UserCoursesDaoImpl.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/dao/impl/UserCoursesDaoImpl.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.util.*; -import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.sunbird.cassandra.CassandraOperation; import org.sunbird.common.models.response.Response; @@ -31,11 +30,8 @@ public static UserCoursesDao getInstance() { } @Override - public UserCourses read(String batchId, String userId) { - Map primaryKey = new HashMap<>(); - primaryKey.put(JsonKey.BATCH_ID, batchId); - primaryKey.put(JsonKey.USER_ID, userId); - Response response = cassandraOperation.getRecordById(KEYSPACE_NAME, TABLE_NAME, primaryKey); + public UserCourses read(String id) { + Response response = cassandraOperation.getRecordById(KEYSPACE_NAME, TABLE_NAME, id); List> userCoursesList = (List>) response.get(JsonKey.RESPONSE); if (CollectionUtils.isEmpty(userCoursesList)) { @@ -50,20 +46,33 @@ public UserCourses read(String batchId, String userId) { } @Override - public Response update(String batchId, String userId, Map updateAttributes) { - Map primaryKey = new HashMap<>(); - primaryKey.put(JsonKey.BATCH_ID, batchId); - primaryKey.put(JsonKey.USER_ID, userId); - Map updateList = new HashMap<>(); - updateList.putAll(updateAttributes); - updateList.remove(JsonKey.BATCH_ID); - updateList.remove(JsonKey.USER_ID); - return cassandraOperation.updateRecord(KEYSPACE_NAME, TABLE_NAME, updateList, primaryKey); + public Response update(Map updateAttributes) { + return cassandraOperation.updateRecord(KEYSPACE_NAME, TABLE_NAME, updateAttributes); } @Override public List getAllActiveUserOfBatch(String batchId) { - return getBatchParticipants(batchId, true); + Map queryMap = new HashMap<>(); + queryMap.put(JsonKey.BATCH_ID, batchId); + Response response = + cassandraOperation.getRecordsByProperties( + KEYSPACE_NAME, + TABLE_NAME, + queryMap, + Arrays.asList(JsonKey.USER_ID, JsonKey.ACTIVE, JsonKey.ID)); + List> userCoursesList = + (List>) response.get(JsonKey.RESPONSE); + if (CollectionUtils.isEmpty(userCoursesList)) { + return null; + } + List users = new ArrayList<>(); + + userCoursesList.forEach( + userCourses -> { + if ((boolean) userCourses.get(JsonKey.ACTIVE)) + users.add((String) userCourses.get(JsonKey.USER_ID)); + }); + return users; } @Override @@ -75,22 +84,4 @@ public Response batchInsert(List> userCoursesDetails) { public Response insert(Map userCoursesDetails) { return cassandraOperation.insertRecord(KEYSPACE_NAME, TABLE_NAME, userCoursesDetails); } - - - @Override - public List getBatchParticipants(String batchId, boolean active) { - Map queryMap = new HashMap<>(); - queryMap.put(JsonKey.BATCH_ID, batchId); - Response response = cassandraOperation.getRecords(KEYSPACE_NAME, TABLE_NAME, queryMap, Arrays.asList(JsonKey.USER_ID, JsonKey.ACTIVE)); - List> userCoursesList = - (List>) response.get(JsonKey.RESPONSE); - if (CollectionUtils.isEmpty(userCoursesList)) { - return null; - } - return userCoursesList - .stream() - .filter(userCourse -> (active == (boolean) userCourse.get(JsonKey.ACTIVE))) - .map(userCourse -> (String) userCourse.get(JsonKey.USER_ID)) - .collect(Collectors.toList()); - } } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/service/UserCoursesService.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/service/UserCoursesService.java index f196bef043..b209bf0e41 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/service/UserCoursesService.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/coursebatch/service/UserCoursesService.java @@ -1,6 +1,7 @@ package org.sunbird.learner.actors.coursebatch.service; import java.util.*; +import org.apache.commons.lang3.StringUtils; import org.sunbird.common.ElasticSearchHelper; import org.sunbird.common.exception.ProjectCommonException; import org.sunbird.common.factory.EsClientFactory; @@ -20,16 +21,11 @@ public class UserCoursesService { private UserCoursesDao userCourseDao = UserCoursesDaoImpl.getInstance(); private static ElasticSearchService esService = EsClientFactory.getInstance(JsonKey.REST); - public static final String UNDERSCORE = "_"; protected Integer CASSANDRA_BATCH_SIZE = getBatchSize(JsonKey.CASSANDRA_WRITE_BATCH_SIZE); - public static String generateUserCourseESId(String batchId, String userId) { - return (OneWayHashing.encryptVal(batchId + UNDERSCORE + userId)); - } - public static void validateUserUnenroll(UserCourses userCourseResult) { - if (userCourseResult == null || !userCourseResult.isActive()) { + if (userCourseResult == null) { ProjectLogger.log( "UserCoursesService:validateUserUnenroll: User is not enrolled yet", LoggerEnum.INFO.name()); @@ -38,7 +34,16 @@ public static void validateUserUnenroll(UserCourses userCourseResult) { ResponseCode.userNotEnrolledCourse.getErrorMessage(), ResponseCode.CLIENT_ERROR.getResponseCode()); } - if (userCourseResult.getStatus() == ProjectUtil.ProgressStatus.COMPLETED.getValue()) { + if (!userCourseResult.isActive()) { + ProjectLogger.log( + "UserCoursesService:validateUserUnenroll: User does not have an enrolled course"); + throw new ProjectCommonException( + ResponseCode.userNotEnrolledCourse.getErrorCode(), + ResponseCode.userNotEnrolledCourse.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); + } + if (userCourseResult.getProgress() > 0 + && (userCourseResult.getProgress() == userCourseResult.getLeafNodesCount())) { ProjectLogger.log( "UserCoursesService:validateUserUnenroll: User already completed the course"); throw new ProjectCommonException( @@ -64,22 +69,34 @@ public static String getPrimaryKey(String userId, String courseId, String batchI + batchId); } - public void enroll(String batchId, String courseId, List userIds) { + public void enroll( + String batchId, + String courseId, + List userIds, + Map additionalCourseInfo) { Integer count = 0; List> records = new ArrayList<>(); - Map userCoursesCommon = new HashMap<>(); - userCoursesCommon.put(JsonKey.BATCH_ID, batchId); - userCoursesCommon.put(JsonKey.COURSE_ID, courseId); - userCoursesCommon.put(JsonKey.COURSE_ENROLL_DATE, ProjectUtil.getFormattedDate()); - userCoursesCommon.put(JsonKey.ACTIVE, ProjectUtil.ActiveStatus.ACTIVE.getValue()); - userCoursesCommon.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.NOT_STARTED.getValue()); - userCoursesCommon.put(JsonKey.COURSE_PROGRESS, 0); - for (String userId : userIds) { Map userCourses = new HashMap<>(); userCourses.put(JsonKey.USER_ID, userId); - userCourses.putAll(userCoursesCommon); + userCourses.put(JsonKey.BATCH_ID, batchId); + userCourses.put(JsonKey.COURSE_ID, courseId); + userCourses.put(JsonKey.ID, getPrimaryKey(userId, courseId, batchId)); + userCourses.put(JsonKey.CONTENT_ID, courseId); + userCourses.put(JsonKey.COURSE_ENROLL_DATE, ProjectUtil.getFormattedDate()); + userCourses.put(JsonKey.ACTIVE, ProjectUtil.ActiveStatus.ACTIVE.getValue()); + userCourses.put(JsonKey.STATUS, ProjectUtil.ProgressStatus.NOT_STARTED.getValue()); + userCourses.put(JsonKey.COURSE_PROGRESS, 0); + userCourses.put(JsonKey.COURSE_LOGO_URL, additionalCourseInfo.get(JsonKey.COURSE_LOGO_URL)); + userCourses.put(JsonKey.COURSE_NAME, additionalCourseInfo.get(JsonKey.COURSE_NAME)); + userCourses.put(JsonKey.DESCRIPTION, additionalCourseInfo.get(JsonKey.DESCRIPTION)); + if (!StringUtils.isBlank(additionalCourseInfo.get(JsonKey.LEAF_NODE_COUNT))) { + userCourses.put( + JsonKey.LEAF_NODE_COUNT, + Integer.parseInt("" + additionalCourseInfo.get(JsonKey.LEAF_NODE_COUNT))); + } + userCourses.put(JsonKey.TOC_URL, additionalCourseInfo.get(JsonKey.TOC_URL)); count++; records.add(userCourses); @@ -101,10 +118,7 @@ public void enroll(String batchId, String courseId, List userIds) { private void syncUsersToES(List> records) { for (Map userCourses : records) { - sync( - userCourses, - (String) userCourses.get(JsonKey.BATCH_ID), - (String) userCourses.get(JsonKey.USER_ID)); + sync(userCourses, (String) userCourses.get(JsonKey.ID)); } } @@ -131,13 +145,14 @@ protected void performBatchInsert(List> records) { } } - public void unenroll(String batchId, String userId) { - UserCourses userCourses = userCourseDao.read(batchId, userId); + public void unenroll(String userId, String courseId, String batchId) { + UserCourses userCourses = userCourseDao.read(getPrimaryKey(userId, courseId, batchId)); validateUserUnenroll(userCourses); Map updateAttributes = new HashMap<>(); updateAttributes.put(JsonKey.ACTIVE, ProjectUtil.ActiveStatus.INACTIVE.getValue()); - userCourseDao.update(userCourses.getBatchId(), userCourses.getUserId(), updateAttributes); - sync(updateAttributes, userCourses.getBatchId(), userCourses.getUserId()); + updateAttributes.put(JsonKey.ID, userCourses.getId()); + userCourseDao.update(updateAttributes); + sync(updateAttributes, userCourses.getId()); } public Map getActiveUserCourses(String userId) { @@ -153,8 +168,7 @@ public Map getActiveUserCourses(String userId) { return result; } - public static void sync(Map courseMap, String batchId, String userId) { - String id = generateUserCourseESId(batchId, userId); + public static void sync(Map courseMap, String id) { Future responseF = esService.upsert(ProjectUtil.EsType.usercourses.getTypeName(), id, courseMap); boolean response = (boolean) ElasticSearchHelper.getResponseFromFuture(responseF); @@ -163,9 +177,9 @@ public static void sync(Map courseMap, String batchId, String us LoggerEnum.INFO.name()); } - public List getEnrolledUserFromBatch(String batchId) { + public List getEnrolledUserFromBatch(String id) { - return userCourseDao.getAllActiveUserOfBatch(batchId); + return userCourseDao.getAllActiveUserOfBatch(id); } public Integer getBatchSize(String key) { @@ -178,8 +192,4 @@ public Integer getBatchSize(String key) { } return batchSize; } - - public List getParticipantsList(String batchId, boolean active) { - return userCourseDao.getBatchParticipants(batchId, active); - } } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/search/SearchHandlerActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/search/SearchHandlerActor.java index 8573ebdfa8..d45733220f 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/search/SearchHandlerActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/actors/search/SearchHandlerActor.java @@ -1,17 +1,30 @@ package org.sunbird.learner.actors.search; +import akka.dispatch.Mapper; +import akka.pattern.Patterns; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.sunbird.actor.core.BaseActor; import org.sunbird.actor.router.ActorConfig; +import org.sunbird.actorutil.org.OrganisationClient; +import org.sunbird.actorutil.org.impl.OrganisationClientImpl; import org.sunbird.common.ElasticSearchHelper; import org.sunbird.common.factory.EsClientFactory; import org.sunbird.common.inf.ElasticSearchService; import org.sunbird.common.models.response.Response; import org.sunbird.common.models.util.ActorOperations; import org.sunbird.common.models.util.JsonKey; +import org.sunbird.common.models.util.LoggerEnum; +import org.sunbird.common.models.util.ProjectLogger; +import org.sunbird.common.models.util.ProjectUtil; import org.sunbird.common.models.util.ProjectUtil.EsType; import org.sunbird.common.models.util.PropertiesCache; import org.sunbird.common.models.util.TelemetryEnvKey; @@ -19,9 +32,12 @@ import org.sunbird.common.request.Request; import org.sunbird.dto.SearchDTO; import org.sunbird.learner.actors.coursebatch.service.UserCoursesService; +import org.sunbird.learner.util.UserUtility; import org.sunbird.learner.util.Util; +import org.sunbird.models.organisation.Organisation; import org.sunbird.telemetry.util.TelemetryLmaxWriter; import org.sunbird.telemetry.util.TelemetryUtil; +import scala.concurrent.Await; import scala.concurrent.Future; /** @@ -35,7 +51,9 @@ ) public class SearchHandlerActor extends BaseActor { + private List supportedFields = Arrays.asList(JsonKey.ID, JsonKey.ORG_NAME); private String topn = PropertiesCache.getInstance().getProperty(JsonKey.SEARCH_TOP_N); + private OrganisationClient orgClient = new OrganisationClientImpl(); private ElasticSearchService esService = EsClientFactory.getInstance(JsonKey.REST); @SuppressWarnings({"unchecked", "rawtypes"}) @@ -45,6 +63,7 @@ public void onReceive(Request request) throws Throwable { Util.initializeContext(request, TelemetryEnvKey.USER); // set request id fto thread loacl... ExecutionContext.setRequestId(request.getRequestId()); + String requestedFields = (String) request.getContext().get(JsonKey.FIELDS); if (request.getOperation().equalsIgnoreCase(ActorOperations.COMPOSITE_SEARCH.getValue())) { Map searchQueryMap = request.getRequest(); @@ -58,32 +77,50 @@ public void onReceive(Request request) throws Throwable { ((Map) searchQueryMap.get(JsonKey.FILTERS)).remove(JsonKey.OBJECT_TYPE); String filterObjectType = ""; for (String type : types) { - if (EsType.courseBatch.getTypeName().equalsIgnoreCase(type)) { - filterObjectType = EsType.courseBatch.getTypeName(); + if (EsType.user.getTypeName().equalsIgnoreCase(type)) { + filterObjectType = EsType.user.getTypeName(); + UserUtility.encryptUserSearchFilterQueryData(searchQueryMap); + } else if (EsType.course.getTypeName().equalsIgnoreCase(type)) { + filterObjectType = EsType.course.getTypeName(); + } else if (EsType.organisation.getTypeName().equalsIgnoreCase(type)) { + filterObjectType = EsType.organisation.getTypeName(); } } - if (!searchQueryMap.containsKey(JsonKey.LIMIT)) { - // set default limit for course bath as 30 - searchQueryMap.put(JsonKey.LIMIT, 30); - } SearchDTO searchDto = Util.createSearchDto(searchQueryMap); - + if (filterObjectType.equalsIgnoreCase(EsType.user.getTypeName())) { + searchDto.setExcludedFields(Arrays.asList(ProjectUtil.excludes)); + } Map result = null; - - Future> resultF = esService.search(searchDto, types[0]); - result = (Map) ElasticSearchHelper.getResponseFromFuture(resultF); - if (EsType.courseBatch.getTypeName().equalsIgnoreCase(filterObjectType)) { - if (JsonKey.PARTICIPANTS.equalsIgnoreCase( - (String) request.getContext().get(JsonKey.PARTICIPANTS))) { - List> courseBatchList = + if (EsType.organisation.getTypeName().equalsIgnoreCase(filterObjectType)) { + handleOrgSearchAsyncRequest( + ProjectUtil.EsIndex.sunbird.getIndexName(), + EsType.organisation.getTypeName(), + searchDto); + } else { + Future> resultF = esService.search(searchDto, types[0]); + result = (Map) ElasticSearchHelper.getResponseFromFuture(resultF); + // Decrypt the data + if (EsType.user.getTypeName().equalsIgnoreCase(filterObjectType)) { + List> userMapList = (List>) result.get(JsonKey.CONTENT); - for (Map courseBatch : courseBatchList) { - courseBatch.put( - JsonKey.PARTICIPANTS, - getParticipantList((String) courseBatch.get(JsonKey.BATCH_ID))); + for (Map userMap : userMapList) { + UserUtility.decryptUserDataFrmES(userMap); + userMap.remove(JsonKey.ENC_EMAIL); + userMap.remove(JsonKey.ENC_PHONE); + } + updateUserDetailsWithOrgName(requestedFields, userMapList); + } + if (EsType.course.getTypeName().equalsIgnoreCase(filterObjectType)) { + if (JsonKey.PARTICIPANTS.equalsIgnoreCase( + (String) request.getContext().get(JsonKey.PARTICIPANTS))) { + List> courseBatchList = + (List>) result.get(JsonKey.CONTENT); + for (Map courseBatch : courseBatchList) { + courseBatch.put( + JsonKey.PARTICIPANTS, getParticipantList((String) courseBatch.get(JsonKey.ID))); + } } } - Response response = new Response(); if (result != null) { response.put(JsonKey.RESPONSE, result); @@ -100,11 +137,164 @@ public void onReceive(Request request) throws Throwable { } } + private void handleOrgSearchAsyncRequest( + String indexName, String indexType, SearchDTO searchDto) { + Future> futureResponse = esService.search(searchDto, indexType); + Future response = + futureResponse.map( + new Mapper, Response>() { + @Override + public Response apply(Map responseMap) { + ProjectLogger.log( + "SearchHandlerActor:handleOrgSearchAsyncRequest org search call ", + LoggerEnum.INFO); + Response response = new Response(); + response.put(JsonKey.RESPONSE, responseMap); + return response; + } + }, + getContext().dispatcher()); + Patterns.pipe(response, getContext().dispatcher()).to(sender()); + Response orgSearchResponse = null; + try { + orgSearchResponse = Await.result(response, BaseActor.timeout.duration()); + String[] types = new String[] {indexType}; + Map contentMap = new HashMap<>(); + List contentList = new ArrayList<>(); + if (orgSearchResponse != null + && MapUtils.isNotEmpty(orgSearchResponse.getResult()) + && MapUtils.isNotEmpty( + (Map) orgSearchResponse.getResult().get(JsonKey.RESPONSE))) { + HashMap contentListMap = + (HashMap) orgSearchResponse.getResult().get(JsonKey.RESPONSE); + contentList.add(contentListMap.get(JsonKey.CONTENT)); + if (CollectionUtils.isNotEmpty(contentList)) { + contentMap.put(JsonKey.CONTENT, contentList.get(0)); + contentMap.put( + JsonKey.COUNT, + contentListMap.get(JsonKey.COUNT) != null ? contentListMap.get(JsonKey.COUNT) : 0); + generateSearchTelemetryEvent(searchDto, types, contentMap); + } + } + } catch (Exception e) { + ProjectLogger.log( + "SearchHandlerActor:handelOrgSearchAsyncRequest: Error occured in generating Telemetry for orgSearch ", + e, + LoggerEnum.ERROR.name()); + } + } + private List getParticipantList(String id) { UserCoursesService userCourseService = new UserCoursesService(); return userCourseService.getEnrolledUserFromBatch(id); } + @SuppressWarnings("unchecked") + private void updateUserDetailsWithOrgName( + String requestedFields, List> userMapList) { + Map orgMap = null; + if (StringUtils.isNotBlank(requestedFields)) { + try { + List fields = Arrays.asList(requestedFields.toLowerCase().split(",")); + List filteredRequestedFields = new ArrayList<>(); + fields + .stream() + .forEach( + rField -> { + for (String sField : supportedFields) { + if (sField.equalsIgnoreCase(rField)) { + filteredRequestedFields.add(sField); + break; + } + } + }); + if (filteredRequestedFields.isEmpty()) { + return; + } + if (!filteredRequestedFields.contains(JsonKey.ID)) { + filteredRequestedFields.add(JsonKey.ID); + } + orgMap = fetchOrgDetails(userMapList, filteredRequestedFields); + if (fields.contains(JsonKey.ORG_NAME.toLowerCase())) { + Map filteredOrg = new HashMap<>(orgMap); + userMapList + .stream() + .forEach( + userMap -> { + String rootOrgId = (String) userMap.get(JsonKey.ROOT_ORG_ID); + if (StringUtils.isNotBlank(rootOrgId)) { + Organisation org = filteredOrg.get(rootOrgId); + if (null != org) { + userMap.put(JsonKey.ROOT_ORG_NAME, org.getOrgName()); + } + } + List> userOrgList = + (List>) userMap.get(JsonKey.ORGANISATIONS); + if (CollectionUtils.isNotEmpty(userOrgList)) { + userOrgList + .stream() + .forEach( + userOrg -> { + String userOrgId = (String) userOrg.get(JsonKey.ORGANISATION_ID); + if (StringUtils.isNotBlank(userOrgId)) { + Organisation org = filteredOrg.get(userOrgId); + if (null != org) { + userOrg.put(JsonKey.ORG_NAME, org.getOrgName()); + } + } + }); + } + }); + } + } catch (Exception ex) { + ProjectLogger.log( + "SearchHandlerActor:updateUserDetailsWithOrgName: Exception occurred with error message = " + + ex.getMessage(), + ex); + } + } + } + + @SuppressWarnings("unchecked") + private Map fetchOrgDetails( + List> userMapList, List filteredRequestedFileds) { + Set orgIdList = new HashSet<>(); + userMapList + .stream() + .forEach( + userMap -> { + String rootOrgId = (String) userMap.get(JsonKey.ROOT_ORG_ID); + if (StringUtils.isNotBlank(rootOrgId)) { + orgIdList.add(rootOrgId); + } + List> userOrgList = + (List>) userMap.get(JsonKey.ORGANISATIONS); + if (CollectionUtils.isNotEmpty(userOrgList)) { + userOrgList + .stream() + .forEach( + userOrg -> { + String userOrgId = (String) userOrg.get(JsonKey.ORGANISATION_ID); + if (StringUtils.isNotBlank(userOrgId)) { + orgIdList.add(userOrgId); + } + }); + } + }); + + List orgIds = new ArrayList<>(orgIdList); + + List organisations = orgClient.esSearchOrgByIds(orgIds, filteredRequestedFileds); + Map orgMap = new HashMap<>(); + organisations + .stream() + .forEach( + org -> { + orgMap.put(org.getId(), org); + }); + return orgMap; + } + private void generateSearchTelemetryEvent( SearchDTO searchDto, String[] types, Map result) { diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/CourseBatchUtil.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/CourseBatchUtil.java index a18db11bfa..24fca9cf0d 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/CourseBatchUtil.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/CourseBatchUtil.java @@ -20,7 +20,7 @@ public static void syncCourseBatchForeground(String uniqueId, Map esResponseF = - esUtil.save(ProjectUtil.EsType.courseBatch.getTypeName(), uniqueId, req); + esUtil.save(ProjectUtil.EsType.course.getTypeName(), uniqueId, req); String esResponse = (String) ElasticSearchHelper.getResponseFromFuture(esResponseF); ProjectLogger.log( diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/SearchUtil.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/SearchUtil.java deleted file mode 100644 index af1255db28..0000000000 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/SearchUtil.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.sunbird.learner.util; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.mashape.unirest.http.HttpResponse; -import com.mashape.unirest.http.Unirest; -import com.mashape.unirest.http.exceptions.UnirestException; -import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpHeaders; -import org.sunbird.common.exception.ProjectCommonException; -import org.sunbird.common.models.response.Response; -import org.sunbird.common.models.util.JsonKey; -import org.sunbird.common.models.util.ProjectUtil; -import org.sunbird.common.responsecode.ResponseCode; - -import javax.ws.rs.core.MediaType; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class SearchUtil { - private static final String BASE_URL = ProjectUtil.getConfigValue(JsonKey.SEARCH_SERVICE_API_BASE_URL); - private static final String SEARCH_URL ="/v3/search"; - private static ObjectMapper mapper = new ObjectMapper(); - - - private static Map getHeaders() { - return new HashMap() {{ - put(JsonKey.AUTHORIZATION, JsonKey.BEARER + System.getenv(JsonKey.EKSTEP_AUTHORIZATION)); - put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); - put(HttpHeaders.ACCEPT_ENCODING.toLowerCase(), "UTF-8"); - }}; - } - - public static List> search(String payload) throws UnirestException, IOException { - if(StringUtils.isNotBlank(payload)){ - HttpResponse httpResponse = Unirest.post(BASE_URL + SEARCH_URL).headers(getHeaders()).body(payload).asString(); - if(httpResponse.getStatus() == 200){ - Response response = mapper.readValue(httpResponse.getBody(), Response.class); - return (List>) response.get("content"); - } else { - throw new ProjectCommonException(ResponseCode.SERVER_ERROR.name(), httpResponse.getBody(), ResponseCode.SERVER_ERROR.getResponseCode()); - } - } - return null; - } - - -} diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/Util.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/Util.java index a6c935ce58..08104fe9bc 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/Util.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/learner/util/Util.java @@ -1,7 +1,5 @@ package org.sunbird.learner.util; -import static org.sunbird.common.models.util.ProjectLogger.log; - import akka.actor.ActorRef; import com.fasterxml.jackson.databind.ObjectMapper; import com.typesafe.config.Config; @@ -75,6 +73,8 @@ import org.sunbird.userorg.UserOrgServiceImpl; import scala.concurrent.Future; +import static org.sunbird.common.models.util.ProjectLogger.log; + /** * Utility class for actors * @@ -88,21 +88,20 @@ public final class Util { private static PropertiesCache propertiesCache = PropertiesCache.getInstance(); public static final int DEFAULT_ELASTIC_DATA_LIMIT = 10000; public static final String KEY_SPACE_NAME = "sunbird"; - public static final String COURSE_KEY_SPACE_NAME = "sunbird_courses"; private static Properties prop = new Properties(); private static Map headers = new HashMap<>(); private static Map> orgStatusTransition = new HashMap<>(); private static final String SUNBIRD_WEB_URL = "sunbird_web_url"; private static CassandraOperation cassandraOperation = ServiceFactory.getInstance(); private static EncryptionService encryptionService = - org.sunbird.common.models.util.datasecurity.impl.ServiceFactory.getEncryptionServiceInstance( - null); + org.sunbird.common.models.util.datasecurity.impl.ServiceFactory.getEncryptionServiceInstance( + null); private static DecryptionService decService = - org.sunbird.common.models.util.datasecurity.impl.ServiceFactory.getDecryptionServiceInstance( - null); + org.sunbird.common.models.util.datasecurity.impl.ServiceFactory.getDecryptionServiceInstance( + null); private static DataMaskingService maskingService = - org.sunbird.common.models.util.datasecurity.impl.ServiceFactory.getMaskingServiceInstance( - null); + org.sunbird.common.models.util.datasecurity.impl.ServiceFactory.getMaskingServiceInstance( + null); private static ObjectMapper mapper = new ObjectMapper(); private static ElasticSearchService esService = EsClientFactory.getInstance(JsonKey.REST); @@ -120,7 +119,7 @@ public void run() { SchedulerManager.getInstance(); } }) - .start(); + .start(); } private Util() {} @@ -131,30 +130,30 @@ private Util() {} */ private static void initializeOrgStatusTransition() { orgStatusTransition.put( - OrgStatus.ACTIVE.getValue(), - Arrays.asList( OrgStatus.ACTIVE.getValue(), - OrgStatus.INACTIVE.getValue(), - OrgStatus.BLOCKED.getValue(), - OrgStatus.RETIRED.getValue())); + Arrays.asList( + OrgStatus.ACTIVE.getValue(), + OrgStatus.INACTIVE.getValue(), + OrgStatus.BLOCKED.getValue(), + OrgStatus.RETIRED.getValue())); orgStatusTransition.put( - OrgStatus.INACTIVE.getValue(), - Arrays.asList(OrgStatus.ACTIVE.getValue(), OrgStatus.INACTIVE.getValue())); + OrgStatus.INACTIVE.getValue(), + Arrays.asList(OrgStatus.ACTIVE.getValue(), OrgStatus.INACTIVE.getValue())); orgStatusTransition.put( - OrgStatus.BLOCKED.getValue(), - Arrays.asList( - OrgStatus.ACTIVE.getValue(), OrgStatus.BLOCKED.getValue(), - OrgStatus.RETIRED.getValue())); + Arrays.asList( + OrgStatus.ACTIVE.getValue(), + OrgStatus.BLOCKED.getValue(), + OrgStatus.RETIRED.getValue())); orgStatusTransition.put( - OrgStatus.RETIRED.getValue(), Arrays.asList(OrgStatus.RETIRED.getValue())); + OrgStatus.RETIRED.getValue(), Arrays.asList(OrgStatus.RETIRED.getValue())); orgStatusTransition.put( - null, - Arrays.asList( - OrgStatus.ACTIVE.getValue(), - OrgStatus.INACTIVE.getValue(), - OrgStatus.BLOCKED.getValue(), - OrgStatus.RETIRED.getValue())); + null, + Arrays.asList( + OrgStatus.ACTIVE.getValue(), + OrgStatus.INACTIVE.getValue(), + OrgStatus.BLOCKED.getValue(), + OrgStatus.RETIRED.getValue())); } /** This method will initialize the cassandra data base property */ @@ -163,12 +162,11 @@ private static void initializeDBProperty() { // this map will be used during cassandra data base interaction. // this map will have each DB name and it's corresponding keyspace and table // name. + dbInfoMap.put(JsonKey.LEARNER_COURSE_DB, getDbInfoObject(KEY_SPACE_NAME, "user_courses")); dbInfoMap.put( - JsonKey.LEARNER_COURSE_DB, getDbInfoObject(COURSE_KEY_SPACE_NAME, "user_courses")); - dbInfoMap.put( - JsonKey.LEARNER_CONTENT_DB, getDbInfoObject(COURSE_KEY_SPACE_NAME, "content_consumption")); + JsonKey.LEARNER_CONTENT_DB, getDbInfoObject(KEY_SPACE_NAME, "content_consumption")); dbInfoMap.put( - JsonKey.COURSE_MANAGEMENT_DB, getDbInfoObject(KEY_SPACE_NAME, "course_management")); + JsonKey.COURSE_MANAGEMENT_DB, getDbInfoObject(KEY_SPACE_NAME, "course_management")); dbInfoMap.put(JsonKey.USER_DB, getDbInfoObject(KEY_SPACE_NAME, "user")); dbInfoMap.put(JsonKey.USER_AUTH_DB, getDbInfoObject(KEY_SPACE_NAME, "user_auth")); dbInfoMap.put(JsonKey.ORG_DB, getDbInfoObject(KEY_SPACE_NAME, "organisation")); @@ -192,11 +190,10 @@ private static void initializeDBProperty() { dbInfoMap.put(JsonKey.USER_ACTION_ROLE, getDbInfoObject(KEY_SPACE_NAME, "user_action_role")); dbInfoMap.put(JsonKey.ROLE_GROUP, getDbInfoObject(KEY_SPACE_NAME, "role_group")); dbInfoMap.put(JsonKey.USER_ORG_DB, getDbInfoObject(KEY_SPACE_NAME, "user_org")); + dbInfoMap.put(JsonKey.BULK_OP_DB, getDbInfoObject(KEY_SPACE_NAME, "bulk_upload_process")); + dbInfoMap.put(JsonKey.COURSE_BATCH_DB, getDbInfoObject(KEY_SPACE_NAME, "course_batch")); dbInfoMap.put( - JsonKey.BULK_OP_DB, getDbInfoObject(COURSE_KEY_SPACE_NAME, "bulk_upload_process")); - dbInfoMap.put(JsonKey.COURSE_BATCH_DB, getDbInfoObject(COURSE_KEY_SPACE_NAME, "course_batch")); - dbInfoMap.put( - JsonKey.COURSE_PUBLISHED_STATUS, getDbInfoObject(KEY_SPACE_NAME, "course_publish_status")); + JsonKey.COURSE_PUBLISHED_STATUS, getDbInfoObject(KEY_SPACE_NAME, "course_publish_status")); dbInfoMap.put(JsonKey.REPORT_TRACKING_DB, getDbInfoObject(KEY_SPACE_NAME, "report_tracking")); dbInfoMap.put(JsonKey.BADGES_DB, getDbInfoObject(KEY_SPACE_NAME, "badge")); dbInfoMap.put(JsonKey.USER_BADGES_DB, getDbInfoObject(KEY_SPACE_NAME, "user_badge")); @@ -205,19 +202,19 @@ private static void initializeDBProperty() { dbInfoMap.put(JsonKey.USER_SKILL_DB, getDbInfoObject(KEY_SPACE_NAME, "user_skills")); dbInfoMap.put(JsonKey.SKILLS_LIST_DB, getDbInfoObject(KEY_SPACE_NAME, "skills")); dbInfoMap.put( - JsonKey.TENANT_PREFERENCE_DB, getDbInfoObject(KEY_SPACE_NAME, "tenant_preference")); + JsonKey.TENANT_PREFERENCE_DB, getDbInfoObject(KEY_SPACE_NAME, "tenant_preference")); dbInfoMap.put(JsonKey.GEO_LOCATION_DB, getDbInfoObject(KEY_SPACE_NAME, "geo_location")); dbInfoMap.put(JsonKey.CLIENT_INFO_DB, getDbInfoObject(KEY_SPACE_NAME, "client_info")); dbInfoMap.put(JsonKey.SYSTEM_SETTINGS_DB, getDbInfoObject(KEY_SPACE_NAME, "system_settings")); dbInfoMap.put( - BadgingJsonKey.USER_BADGE_ASSERTION_DB, - getDbInfoObject(KEY_SPACE_NAME, "user_badge_assertion")); + BadgingJsonKey.USER_BADGE_ASSERTION_DB, + getDbInfoObject(KEY_SPACE_NAME, "user_badge_assertion")); dbInfoMap.put( - BadgingJsonKey.CONTENT_BADGE_ASSOCIATION_DB, - getDbInfoObject(KEY_SPACE_NAME, "content_badge_association")); + BadgingJsonKey.CONTENT_BADGE_ASSOCIATION_DB, + getDbInfoObject(KEY_SPACE_NAME, "content_badge_association")); } /** @@ -248,17 +245,17 @@ public static void checkCassandraDbConnections(String keySpace) { String cassandraMode = propertiesCache.getProperty(JsonKey.SUNBIRD_CASSANDRA_MODE); if (StringUtils.isBlank(cassandraMode) - || cassandraMode.equalsIgnoreCase(JsonKey.EMBEDDED_MODE)) { + || cassandraMode.equalsIgnoreCase(JsonKey.EMBEDDED_MODE)) { // configure the Embedded mode and return true here .... CassandraConnectionManager cassandraConnectionManager = - CassandraConnectionMngrFactory.getObject(cassandraMode); + CassandraConnectionMngrFactory.getObject(cassandraMode); boolean result = - cassandraConnectionManager.createConnection(null, null, null, null, keySpace); + cassandraConnectionManager.createConnection(null, null, null, null, keySpace); if (result) { ProjectLogger.log( - "CONNECTION CREATED SUCCESSFULLY FOR IP:" + " : KEYSPACE :" + keySpace, - LoggerEnum.INFO.name()); + "CONNECTION CREATED SUCCESSFULLY FOR IP:" + " : KEYSPACE :" + keySpace, + LoggerEnum.INFO.name()); } else { ProjectLogger.log("CONNECTION CREATION FAILED FOR IP: " + " : KEYSPACE :" + keySpace); } @@ -269,7 +266,7 @@ public static void checkCassandraDbConnections(String keySpace) { return; } CassandraConnectionManager cassandraConnectionManager = - CassandraConnectionMngrFactory.getObject(JsonKey.STANDALONE_MODE); + CassandraConnectionMngrFactory.getObject(JsonKey.STANDALONE_MODE); String[] ipList = prop.getProperty(JsonKey.DB_IP).split(","); String[] portList = prop.getProperty(JsonKey.DB_PORT).split(","); // String[] keyspaceList = prop.getProperty(JsonKey.DB_KEYSPACE).split(","); @@ -285,14 +282,14 @@ public static void checkCassandraDbConnections(String keySpace) { try { boolean result = - cassandraConnectionManager.createConnection(ip, port, userName, password, keySpace); + cassandraConnectionManager.createConnection(ip, port, userName, password, keySpace); if (result) { ProjectLogger.log( - "CONNECTION CREATED SUCCESSFULLY FOR IP: " + ip + " : KEYSPACE :" + keySpace, - LoggerEnum.INFO.name()); + "CONNECTION CREATED SUCCESSFULLY FOR IP: " + ip + " : KEYSPACE :" + keySpace, + LoggerEnum.INFO.name()); } else { ProjectLogger.log( - "CONNECTION CREATION FAILED FOR IP: " + ip + " : KEYSPACE :" + keySpace); + "CONNECTION CREATION FAILED FOR IP: " + ip + " : KEYSPACE :" + keySpace); } } catch (ProjectCommonException ex) { @@ -312,7 +309,7 @@ public static boolean readConfigFromEnv(String keyspace) { String ips = System.getenv(JsonKey.SUNBIRD_CASSANDRA_IP); String envPort = System.getenv(JsonKey.SUNBIRD_CASSANDRA_PORT); CassandraConnectionManager cassandraConnectionManager = - CassandraConnectionMngrFactory.getObject(JsonKey.STANDALONE_MODE); + CassandraConnectionMngrFactory.getObject(JsonKey.STANDALONE_MODE); if (StringUtils.isBlank(ips) || StringUtils.isBlank(envPort)) { ProjectLogger.log("Configuration value is not coming form System variable."); @@ -327,28 +324,28 @@ public static boolean readConfigFromEnv(String keyspace) { String port = portList[i]; try { boolean result = - cassandraConnectionManager.createConnection(ip, port, userName, password, keyspace); + cassandraConnectionManager.createConnection(ip, port, userName, password, keyspace); if (result) { response = true; ProjectLogger.log( - "CONNECTION CREATED SUCCESSFULLY FOR IP: " + ip + " : KEYSPACE :" + keyspace, - LoggerEnum.INFO.name()); + "CONNECTION CREATED SUCCESSFULLY FOR IP: " + ip + " : KEYSPACE :" + keyspace, + LoggerEnum.INFO.name()); } else { ProjectLogger.log( - "CONNECTION CREATION FAILED FOR IP: " + ip + " : KEYSPACE :" + keyspace, - LoggerEnum.INFO.name()); + "CONNECTION CREATION FAILED FOR IP: " + ip + " : KEYSPACE :" + keyspace, + LoggerEnum.INFO.name()); } } catch (ProjectCommonException ex) { ProjectLogger.log( - "Util:readConfigFromEnv: Exception occurred with message = " + ex.getMessage(), - LoggerEnum.ERROR); + "Util:readConfigFromEnv: Exception occurred with message = " + ex.getMessage(), + LoggerEnum.ERROR); } } if (!response) { throw new ProjectCommonException( - ResponseCode.invaidConfiguration.getErrorCode(), - ResponseCode.invaidConfiguration.getErrorCode(), - ResponseCode.SERVER_ERROR.hashCode()); + ResponseCode.invaidConfiguration.getErrorCode(), + ResponseCode.invaidConfiguration.getErrorCode(), + ResponseCode.SERVER_ERROR.hashCode()); } return response; } @@ -405,12 +402,12 @@ public static class DbInfo { * @param password */ DbInfo( - String keySpace, - String tableName, - String userName, - String password, - String ip, - String port) { + String keySpace, + String tableName, + String userName, + String password, + String ip, + String port) { this.keySpace = keySpace; this.tableName = tableName; this.userName = userName; @@ -427,8 +424,8 @@ public boolean equals(Object obj) { if (obj instanceof DbInfo) { DbInfo ob = (DbInfo) obj; if (this.ip.equals(ob.getIp()) - && this.port.equals(ob.getPort()) - && this.keySpace.equals(ob.getKeySpace())) { + && this.port.equals(ob.getPort()) + && this.keySpace.equals(ob.getKeySpace())) { return true; } } @@ -534,13 +531,13 @@ public static SearchDTO createSearchDto(Map searchQueryMap) { } if (searchQueryMap.containsKey(JsonKey.NOT_EXISTS)) { search - .getAdditionalProperties() - .put(JsonKey.NOT_EXISTS, searchQueryMap.get(JsonKey.NOT_EXISTS)); + .getAdditionalProperties() + .put(JsonKey.NOT_EXISTS, searchQueryMap.get(JsonKey.NOT_EXISTS)); } if (searchQueryMap.containsKey(JsonKey.SORT_BY)) { search - .getSortBy() - .putAll((Map) searchQueryMap.get(JsonKey.SORT_BY)); + .getSortBy() + .putAll((Map) searchQueryMap.get(JsonKey.SORT_BY)); } if (searchQueryMap.containsKey(JsonKey.OFFSET)) { if ((searchQueryMap.get(JsonKey.OFFSET)) instanceof Integer) { @@ -564,16 +561,16 @@ public static SearchDTO createSearchDto(Map searchQueryMap) { } if (searchQueryMap.containsKey(JsonKey.GROUP_QUERY)) { search - .getGroupQuery() - .addAll( - (Collection>) searchQueryMap.get(JsonKey.GROUP_QUERY)); + .getGroupQuery() + .addAll( + (Collection>) searchQueryMap.get(JsonKey.GROUP_QUERY)); } if (searchQueryMap.containsKey(JsonKey.SOFT_CONSTRAINTS)) { // Play is converting int value to bigInt so need to cnvert back those data to iny // SearchDto soft constraints expect Map Map constraintsMap = new HashMap<>(); Set> entrySet = - ((Map) searchQueryMap.get(JsonKey.SOFT_CONSTRAINTS)).entrySet(); + ((Map) searchQueryMap.get(JsonKey.SOFT_CONSTRAINTS)).entrySet(); Iterator> itr = entrySet.iterator(); while (itr.hasNext()) { Entry entry = itr.next(); @@ -598,18 +595,18 @@ public static void getContentData(Map section) { try { String baseSearchUrl = ProjectUtil.getConfigValue(JsonKey.SEARCH_SERVICE_API_BASE_URL); headers.put( - JsonKey.AUTHORIZATION, JsonKey.BEARER + System.getenv(JsonKey.EKSTEP_AUTHORIZATION)); + JsonKey.AUTHORIZATION, JsonKey.BEARER + System.getenv(JsonKey.EKSTEP_AUTHORIZATION)); if (StringUtils.isBlank(headers.get(JsonKey.AUTHORIZATION))) { headers.put( - JsonKey.AUTHORIZATION, - PropertiesCache.getInstance().getProperty(JsonKey.EKSTEP_AUTHORIZATION)); + JsonKey.AUTHORIZATION, + PropertiesCache.getInstance().getProperty(JsonKey.EKSTEP_AUTHORIZATION)); } response = - HttpUtil.sendPostRequest( - baseSearchUrl - + PropertiesCache.getInstance().getProperty(JsonKey.EKSTEP_CONTENT_SEARCH_URL), - (String) section.get(JsonKey.SEARCH_QUERY), - headers); + HttpUtil.sendPostRequest( + baseSearchUrl + + PropertiesCache.getInstance().getProperty(JsonKey.EKSTEP_CONTENT_SEARCH_URL), + (String) section.get(JsonKey.SEARCH_QUERY), + headers); jObject = new JSONObject(response); data = jObject.getJSONObject(JsonKey.RESULT); JSONArray contentArray = data.getJSONArray(JsonKey.CONTENT); @@ -650,8 +647,8 @@ public static String getUserNamebyUserId(String userId) { CassandraOperation cassandraOperation = ServiceFactory.getInstance(); Util.DbInfo userdbInfo = Util.dbInfoMap.get(JsonKey.USER_DB); Response result = - cassandraOperation.getRecordById( - userdbInfo.getKeySpace(), userdbInfo.getTableName(), userId); + cassandraOperation.getRecordById( + userdbInfo.getKeySpace(), userdbInfo.getTableName(), userId); List> list = (List>) result.get(JsonKey.RESPONSE); if (!(list.isEmpty())) { return (String) (list.get(0).get(JsonKey.USERNAME)); @@ -671,8 +668,8 @@ public static Map getUserbyUserId(String userId) { CassandraOperation cassandraOperation = ServiceFactory.getInstance(); Util.DbInfo userdbInfo = Util.dbInfoMap.get(JsonKey.USER_DB); Response result = - cassandraOperation.getRecordById( - userdbInfo.getKeySpace(), userdbInfo.getTableName(), userId); + cassandraOperation.getRecordById( + userdbInfo.getKeySpace(), userdbInfo.getTableName(), userId); List> list = (List>) result.get(JsonKey.RESPONSE); if (!(list.isEmpty())) { return list.get(0); @@ -684,9 +681,9 @@ public static String getHashTagIdFromOrgId(String orgId) { String hashTagId = ""; Map organisation = getOrgDetails(orgId); hashTagId = - StringUtils.isNotEmpty((String) organisation.get(JsonKey.HASHTAGID)) - ? (String) organisation.get(JsonKey.HASHTAGID) - : (String) organisation.get(JsonKey.ID); + StringUtils.isNotEmpty((String) organisation.get(JsonKey.HASHTAGID)) + ? (String) organisation.get(JsonKey.HASHTAGID) + : (String) organisation.get(JsonKey.ID); return hashTagId; } @@ -713,40 +710,40 @@ public static String getRootOrgIdOrNameFromChannel(String channel, boolean isNam filters.put(JsonKey.CHANNEL, ProjectUtil.getConfigValue(JsonKey.SUNBIRD_DEFAULT_CHANNEL)); } else { throw new ProjectCommonException( - ResponseCode.mandatoryParamsMissing.getErrorCode(), - ProjectUtil.formatMessage( - ResponseCode.mandatoryParamsMissing.getErrorMessage(), JsonKey.CHANNEL), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.mandatoryParamsMissing.getErrorCode(), + ProjectUtil.formatMessage( + ResponseCode.mandatoryParamsMissing.getErrorMessage(), JsonKey.CHANNEL), + ResponseCode.CLIENT_ERROR.getResponseCode()); } } Map esResult = - elasticSearchComplexSearch( - filters, EsIndex.sunbird.getIndexName(), EsType.organisation.getTypeName()); + elasticSearchComplexSearch( + filters, EsIndex.sunbird.getIndexName(), EsType.organisation.getTypeName()); if (MapUtils.isNotEmpty(esResult) - && CollectionUtils.isNotEmpty((List) esResult.get(JsonKey.CONTENT))) { + && CollectionUtils.isNotEmpty((List) esResult.get(JsonKey.CONTENT))) { Map esContent = - ((List>) esResult.get(JsonKey.CONTENT)).get(0); + ((List>) esResult.get(JsonKey.CONTENT)).get(0); if (!isName) return (String) esContent.get(JsonKey.ID); else return (String) esContent.get(JsonKey.ORG_NAME); } else { if (StringUtils.isNotBlank(channel)) { throw new ProjectCommonException( - ResponseCode.invalidParameterValue.getErrorCode(), - ProjectUtil.formatMessage( - ResponseCode.invalidParameterValue.getErrorMessage(), channel, JsonKey.CHANNEL), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.invalidParameterValue.getErrorCode(), + ProjectUtil.formatMessage( + ResponseCode.invalidParameterValue.getErrorMessage(), channel, JsonKey.CHANNEL), + ResponseCode.CLIENT_ERROR.getResponseCode()); } else { throw new ProjectCommonException( - ResponseCode.mandatoryParamsMissing.getErrorCode(), - ProjectUtil.formatMessage( - ResponseCode.mandatoryParamsMissing.getErrorMessage(), JsonKey.CHANNEL), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.mandatoryParamsMissing.getErrorCode(), + ProjectUtil.formatMessage( + ResponseCode.mandatoryParamsMissing.getErrorMessage(), JsonKey.CHANNEL), + ResponseCode.CLIENT_ERROR.getResponseCode()); } } } private static Map elasticSearchComplexSearch( - Map filters, String index, String type) { + Map filters, String index, String type) { SearchDTO searchDTO = new SearchDTO(); searchDTO.getAdditionalProperties().put(JsonKey.FILTERS, filters); @@ -786,7 +783,7 @@ public static boolean registerChannel(Map req) { String regStatus = ""; try { ProjectLogger.log( - "start call for registering the channel for hashTag id ==" + req.get(JsonKey.HASHTAGID)); + "start call for registering the channel for hashTag id ==" + req.get(JsonKey.HASHTAGID)); String ekStepBaseUrl = System.getenv(JsonKey.EKSTEP_BASE_URL); if (StringUtils.isBlank(ekStepBaseUrl)) { ekStepBaseUrl = PropertiesCache.getInstance().getProperty(JsonKey.EKSTEP_BASE_URL); @@ -805,16 +802,16 @@ public static boolean registerChannel(Map req) { reqString = mapper.writeValueAsString(map); ProjectLogger.log( - "Util:registerChannel: Channel registration request data = " + reqString, - LoggerEnum.DEBUG.name()); + "Util:registerChannel: Channel registration request data = " + reqString, + LoggerEnum.DEBUG.name()); regStatus = - HttpUtil.sendPostRequest( - (ekStepBaseUrl - + PropertiesCache.getInstance().getProperty(JsonKey.EKSTEP_CHANNEL_REG_API_URL)), - reqString, - headerMap); + HttpUtil.sendPostRequest( + (ekStepBaseUrl + + PropertiesCache.getInstance().getProperty(JsonKey.EKSTEP_CHANNEL_REG_API_URL)), + reqString, + headerMap); ProjectLogger.log( - "end call for channel registration for hashTag id ==" + req.get(JsonKey.HASHTAGID)); + "end call for channel registration for hashTag id ==" + req.get(JsonKey.HASHTAGID)); } catch (Exception e) { ProjectLogger.log("Exception occurred while registarting channel in ekstep.", e); } @@ -839,7 +836,7 @@ public static boolean updateChannel(Map req) { String regStatus = ""; try { ProjectLogger.log( - "start call for registering the channel for hashTag id ==" + req.get(JsonKey.HASHTAGID)); + "start call for registering the channel for hashTag id ==" + req.get(JsonKey.HASHTAGID)); String ekStepBaseUrl = System.getenv(JsonKey.EKSTEP_BASE_URL); if (StringUtils.isBlank(ekStepBaseUrl)) { ekStepBaseUrl = PropertiesCache.getInstance().getProperty(JsonKey.EKSTEP_BASE_URL); @@ -856,16 +853,16 @@ public static boolean updateChannel(Map req) { reqString = mapper.writeValueAsString(map); regStatus = - HttpUtil.sendPatchRequest( - (ekStepBaseUrl - + PropertiesCache.getInstance() - .getProperty(JsonKey.EKSTEP_CHANNEL_UPDATE_API_URL)) - + "/" - + req.get(JsonKey.HASHTAGID), - reqString, - headerMap); + HttpUtil.sendPatchRequest( + (ekStepBaseUrl + + PropertiesCache.getInstance() + .getProperty(JsonKey.EKSTEP_CHANNEL_UPDATE_API_URL)) + + "/" + + req.get(JsonKey.HASHTAGID), + reqString, + headerMap); ProjectLogger.log( - "end call for channel registration for hashTag id ==" + req.get(JsonKey.HASHTAGID)); + "end call for channel registration for hashTag id ==" + req.get(JsonKey.HASHTAGID)); } catch (Exception e) { ProjectLogger.log("Exception occurred while registarting channel in ekstep.", e); } @@ -880,7 +877,7 @@ public static void initializeContext(Request actorMessage, String env) { if (actorMessage.getContext().get(JsonKey.TELEMETRY_CONTEXT) != null) { // means request context is already set by some other actor ... requestContext = - (Map) actorMessage.getContext().get(JsonKey.TELEMETRY_CONTEXT); + (Map) actorMessage.getContext().get(JsonKey.TELEMETRY_CONTEXT); } else { requestContext = new HashMap<>(); // request level info ... @@ -902,12 +899,10 @@ public static void initializeContext(Request actorMessage, String env) { requestContext.put(JsonKey.DEVICE_ID, deviceId); if (JsonKey.USER.equalsIgnoreCase( - (String) actorMessage.getContext().get(JsonKey.ACTOR_TYPE))) { + (String) actorMessage.getContext().get(JsonKey.ACTOR_TYPE))) { // assign rollup of user ... try { - Map result = - userOrgService.getUserById( - (String) actorMessage.getContext().get(JsonKey.REQUESTED_BY)); + Map result = userOrgService.getUserById((String) actorMessage.getContext().get(JsonKey.REQUESTED_BY)); if (result != null) { String rootOrgId = (String) result.get(JsonKey.ROOT_ORG_ID); @@ -918,8 +913,12 @@ public static void initializeContext(Request actorMessage, String env) { requestContext.put(JsonKey.ROLLUP, rollup); } } - } catch (Exception e) { - log("Util:initializeContext:Exception occurred with error message = ", e); + } + catch(Exception e) + { + log( + "Util:initializeContext:Exception occurred with error message = ", + e); } } context.setRequestContext(requestContext); @@ -930,12 +929,12 @@ public static void initializeContext(Request actorMessage, String env) { public static String getKeyFromContext(String key, Request actorMessage) { return actorMessage.getContext() != null && actorMessage.getContext().containsKey(key) - ? (String) actorMessage.getContext().get(key) - : ""; + ? (String) actorMessage.getContext().get(key) + : ""; } public static void initializeContextForSchedulerJob( - String actorType, String actorId, String environment) { + String actorType, String actorId, String environment) { ExecutionContext context = ExecutionContext.getCurrent(); Map requestContext = new HashMap<>(); @@ -967,8 +966,8 @@ public static String getSunbirdWebUrlPerTenent(Map userMap) { public static Map getOrgDetails(String identifier) { DbInfo orgDbInfo = Util.dbInfoMap.get(JsonKey.ORG_DB); Response response = - cassandraOperation.getRecordById( - orgDbInfo.getKeySpace(), orgDbInfo.getTableName(), identifier); + cassandraOperation.getRecordById( + orgDbInfo.getKeySpace(), orgDbInfo.getTableName(), identifier); List> res = (List>) response.get(JsonKey.RESPONSE); if (null != res && !res.isEmpty()) { return res.get(0); @@ -984,9 +983,9 @@ public static String getEncryptedData(String value) { return encryptionService.encryptData(value); } catch (Exception e) { throw new ProjectCommonException( - ResponseCode.userDataEncryptionError.getErrorCode(), - ResponseCode.userDataEncryptionError.getErrorMessage(), - ResponseCode.SERVER_ERROR.getResponseCode()); + ResponseCode.userDataEncryptionError.getErrorCode(), + ResponseCode.userDataEncryptionError.getErrorMessage(), + ResponseCode.SERVER_ERROR.getResponseCode()); } } @@ -1001,10 +1000,10 @@ public static void checkUserExistOrNot(User user) { searchQueryMap.put(JsonKey.LOGIN_ID, getEncryptedData(user.getLoginId())); if (CollectionUtils.isNotEmpty(searchUser(searchQueryMap))) { throw new ProjectCommonException( - ResponseCode.userAlreadyExists.getErrorCode(), - ProjectUtil.formatMessage( - ResponseCode.userAlreadyExists.getErrorMessage(), JsonKey.USERNAME), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.userAlreadyExists.getErrorCode(), + ProjectUtil.formatMessage( + ResponseCode.userAlreadyExists.getErrorMessage(), JsonKey.USERNAME), + ResponseCode.CLIENT_ERROR.getResponseCode()); } } @@ -1017,53 +1016,53 @@ public static void checkExternalIdUniqueness(User user, String operation) { if (CollectionUtils.isNotEmpty(user.getExternalIds())) { for (Map externalId : user.getExternalIds()) { if (StringUtils.isNotBlank(externalId.get(JsonKey.ID)) - && StringUtils.isNotBlank(externalId.get(JsonKey.PROVIDER)) - && StringUtils.isNotBlank(externalId.get(JsonKey.ID_TYPE))) { + && StringUtils.isNotBlank(externalId.get(JsonKey.PROVIDER)) + && StringUtils.isNotBlank(externalId.get(JsonKey.ID_TYPE))) { Map externalIdReq = new HashMap<>(); externalIdReq.put(JsonKey.PROVIDER, externalId.get(JsonKey.PROVIDER)); externalIdReq.put(JsonKey.ID_TYPE, externalId.get(JsonKey.ID_TYPE)); externalIdReq.put(JsonKey.EXTERNAL_ID, encryptData(externalId.get(JsonKey.ID))); Response response = - cassandraOperation.getRecordsByCompositeKey( - KEY_SPACE_NAME, JsonKey.USR_EXT_IDNT_TABLE, externalIdReq); + cassandraOperation.getRecordsByCompositeKey( + KEY_SPACE_NAME, JsonKey.USR_EXT_IDNT_TABLE, externalIdReq); List> externalIdsRecord = - (List>) response.get(JsonKey.RESPONSE); + (List>) response.get(JsonKey.RESPONSE); if (CollectionUtils.isNotEmpty(externalIdsRecord)) { if (JsonKey.CREATE.equalsIgnoreCase(operation)) { throwUserAlreadyExistsException( - externalId.get(JsonKey.ID), - externalId.get(JsonKey.ID_TYPE), - externalId.get(JsonKey.PROVIDER)); + externalId.get(JsonKey.ID), + externalId.get(JsonKey.ID_TYPE), + externalId.get(JsonKey.PROVIDER)); } else if (JsonKey.UPDATE.equalsIgnoreCase(operation)) { // If end user will try to add,edit or remove other user extIds throw exception String userId = (String) externalIdsRecord.get(0).get(JsonKey.USER_ID); if (!(user.getUserId().equalsIgnoreCase(userId))) { if (JsonKey.ADD.equalsIgnoreCase(externalId.get(JsonKey.OPERATION)) - || StringUtils.isBlank(externalId.get(JsonKey.OPERATION))) { + || StringUtils.isBlank(externalId.get(JsonKey.OPERATION))) { throw new ProjectCommonException( - ResponseCode.externalIdAssignedToOtherUser.getErrorCode(), - ProjectUtil.formatMessage( - ResponseCode.externalIdAssignedToOtherUser.getErrorMessage(), - externalId.get(JsonKey.ID), - externalId.get(JsonKey.ID_TYPE), - externalId.get(JsonKey.PROVIDER)), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.externalIdAssignedToOtherUser.getErrorCode(), + ProjectUtil.formatMessage( + ResponseCode.externalIdAssignedToOtherUser.getErrorMessage(), + externalId.get(JsonKey.ID), + externalId.get(JsonKey.ID_TYPE), + externalId.get(JsonKey.PROVIDER)), + ResponseCode.CLIENT_ERROR.getResponseCode()); } else { throwExternalIDNotFoundException( - externalId.get(JsonKey.ID), - externalId.get(JsonKey.ID_TYPE), - externalId.get(JsonKey.PROVIDER)); + externalId.get(JsonKey.ID), + externalId.get(JsonKey.ID_TYPE), + externalId.get(JsonKey.PROVIDER)); } } } } else { // if user will try to delete non existing extIds if (JsonKey.UPDATE.equalsIgnoreCase(operation) - && JsonKey.REMOVE.equalsIgnoreCase(externalId.get(JsonKey.OPERATION))) { + && JsonKey.REMOVE.equalsIgnoreCase(externalId.get(JsonKey.OPERATION))) { throwExternalIDNotFoundException( - externalId.get(JsonKey.ID), - externalId.get(JsonKey.ID_TYPE), - externalId.get(JsonKey.PROVIDER)); + externalId.get(JsonKey.ID), + externalId.get(JsonKey.ID_TYPE), + externalId.get(JsonKey.PROVIDER)); } } } @@ -1076,30 +1075,30 @@ public static String encryptData(String value) { return encryptionService.encryptData(value); } catch (Exception e) { throw new ProjectCommonException( - ResponseCode.userDataEncryptionError.getErrorCode(), - ResponseCode.userDataEncryptionError.getErrorMessage(), - ResponseCode.SERVER_ERROR.getResponseCode()); + ResponseCode.userDataEncryptionError.getErrorCode(), + ResponseCode.userDataEncryptionError.getErrorMessage(), + ResponseCode.SERVER_ERROR.getResponseCode()); } } private static void throwExternalIDNotFoundException( - String externalId, String idType, String provider) { + String externalId, String idType, String provider) { throw new ProjectCommonException( - ResponseCode.externalIdNotFound.getErrorCode(), - ProjectUtil.formatMessage( - ResponseCode.externalIdNotFound.getErrorMessage(), externalId, idType, provider), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.externalIdNotFound.getErrorCode(), + ProjectUtil.formatMessage( + ResponseCode.externalIdNotFound.getErrorMessage(), externalId, idType, provider), + ResponseCode.CLIENT_ERROR.getResponseCode()); } private static void throwUserAlreadyExistsException( - String externalId, String idType, String provider) { + String externalId, String idType, String provider) { throw new ProjectCommonException( - ResponseCode.userAlreadyExists.getErrorCode(), - ProjectUtil.formatMessage( - ResponseCode.userAlreadyExists.getErrorMessage(), + ResponseCode.userAlreadyExists.getErrorCode(), ProjectUtil.formatMessage( - ResponseMessage.Message.EXTERNAL_ID_FORMAT, externalId, idType, provider)), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.userAlreadyExists.getErrorMessage(), + ProjectUtil.formatMessage( + ResponseMessage.Message.EXTERNAL_ID_FORMAT, externalId, idType, provider)), + ResponseCode.CLIENT_ERROR.getResponseCode()); } /** @@ -1114,18 +1113,18 @@ private static List searchUser(Map searchQueryMap) { searchRequestMap.put(JsonKey.FILTERS, searchQueryMap); SearchDTO searchDto = Util.createSearchDto(searchRequestMap); Future> resultf = - esService.search(searchDto, ProjectUtil.EsType.user.getTypeName()); + esService.search(searchDto, ProjectUtil.EsType.user.getTypeName()); Map result = - (Map) ElasticSearchHelper.getResponseFromFuture(resultf); + (Map) ElasticSearchHelper.getResponseFromFuture(resultf); if (MapUtils.isNotEmpty(result)) { List> searchResult = - (List>) result.get(JsonKey.CONTENT); + (List>) result.get(JsonKey.CONTENT); if (CollectionUtils.isNotEmpty(searchResult)) { userList = - searchResult - .stream() - .map(s -> mapper.convertValue(s, User.class)) - .collect(Collectors.toList()); + searchResult + .stream() + .map(s -> mapper.convertValue(s, User.class)) + .collect(Collectors.toList()); } } return userList; @@ -1135,7 +1134,7 @@ public static String getLoginId(Map userMap) { String loginId; if (StringUtils.isNotBlank((String) userMap.get(JsonKey.CHANNEL))) { loginId = - (String) userMap.get(JsonKey.USERNAME) + "@" + (String) userMap.get(JsonKey.CHANNEL); + (String) userMap.get(JsonKey.USERNAME) + "@" + (String) userMap.get(JsonKey.CHANNEL); } else { loginId = (String) userMap.get(JsonKey.USERNAME); } @@ -1144,11 +1143,11 @@ public static String getLoginId(Map userMap) { public static void addUserExtIds(Map requestMap) { List> externalIds = - (List>) requestMap.get(JsonKey.EXTERNAL_IDS); + (List>) requestMap.get(JsonKey.EXTERNAL_IDS); if (CollectionUtils.isNotEmpty(externalIds)) { for (Map extIdsMap : externalIds) { if (StringUtils.isBlank(extIdsMap.get(JsonKey.OPERATION)) - || JsonKey.ADD.equalsIgnoreCase(extIdsMap.get(JsonKey.OPERATION))) { + || JsonKey.ADD.equalsIgnoreCase(extIdsMap.get(JsonKey.OPERATION))) { upsertUserExternalIdentityData(extIdsMap, requestMap, JsonKey.CREATE); } } @@ -1156,12 +1155,12 @@ public static void addUserExtIds(Map requestMap) { } private static void upsertUserExternalIdentityData( - Map extIdsMap, Map requestMap, String operation) { + Map extIdsMap, Map requestMap, String operation) { try { Map map = new HashMap<>(); map.put(JsonKey.EXTERNAL_ID, encryptData(extIdsMap.get(JsonKey.ID))); map.put( - JsonKey.ORIGINAL_EXTERNAL_ID, encryptData(extIdsMap.get(JsonKey.ORIGINAL_EXTERNAL_ID))); + JsonKey.ORIGINAL_EXTERNAL_ID, encryptData(extIdsMap.get(JsonKey.ORIGINAL_EXTERNAL_ID))); map.put(JsonKey.PROVIDER, extIdsMap.get(JsonKey.PROVIDER)); map.put(JsonKey.ORIGINAL_PROVIDER, extIdsMap.get(JsonKey.ORIGINAL_PROVIDER)); map.put(JsonKey.ID_TYPE, extIdsMap.get(JsonKey.ID_TYPE)); @@ -1183,11 +1182,11 @@ private static void upsertUserExternalIdentityData( private static List> getUserExternalIds(Map requestMap) { List> dbResExternalIds = new ArrayList<>(); Response response = - cassandraOperation.getRecordsByIndexedProperty( - KEY_SPACE_NAME, - JsonKey.USR_EXT_IDNT_TABLE, - JsonKey.USER_ID, - requestMap.get(JsonKey.USER_ID)); + cassandraOperation.getRecordsByIndexedProperty( + KEY_SPACE_NAME, + JsonKey.USR_EXT_IDNT_TABLE, + JsonKey.USER_ID, + requestMap.get(JsonKey.USER_ID)); if (null != response && null != response.getResult()) { dbResExternalIds = (List>) response.getResult().get(JsonKey.RESPONSE); } @@ -1197,7 +1196,7 @@ private static List> getUserExternalIds(Map public static void updateUserExtId(Map requestMap) { List> dbResExternalIds = getUserExternalIds(requestMap); List> externalIds = - (List>) requestMap.get(JsonKey.EXTERNAL_IDS); + (List>) requestMap.get(JsonKey.EXTERNAL_IDS); if (CollectionUtils.isNotEmpty(externalIds)) { // will not allow user to update idType value, if user will try to update idType will // ignore @@ -1208,7 +1207,7 @@ public static void updateUserExtId(Map requestMap) { Map map = extMap.orElse(null); // Allowed operation type for externalIds ("add", "remove", "edit") if (JsonKey.ADD.equalsIgnoreCase(extIdMap.get(JsonKey.OPERATION)) - || StringUtils.isBlank(extIdMap.get(JsonKey.OPERATION))) { + || StringUtils.isBlank(extIdMap.get(JsonKey.OPERATION))) { if (MapUtils.isEmpty(map)) { upsertUserExternalIdentityData(extIdMap, requestMap, JsonKey.CREATE); } else { @@ -1223,8 +1222,8 @@ public static void updateUserExtId(Map requestMap) { if (MapUtils.isNotEmpty(map)) { if (JsonKey.REMOVE.equalsIgnoreCase(extIdMap.get(JsonKey.OPERATION))) { if (StringUtils.isNotBlank(map.get(JsonKey.ID_TYPE)) - && StringUtils.isNotBlank((String) requestMap.get(JsonKey.USER_ID)) - && StringUtils.isNotBlank(map.get(JsonKey.PROVIDER))) { + && StringUtils.isNotBlank((String) requestMap.get(JsonKey.USER_ID)) + && StringUtils.isNotBlank(map.get(JsonKey.PROVIDER))) { deleteUserExternalId(requestMap, map); } } else if (JsonKey.EDIT.equalsIgnoreCase(extIdMap.get(JsonKey.OPERATION))) { @@ -1235,9 +1234,9 @@ public static void updateUserExtId(Map requestMap) { } } else { throwExternalIDNotFoundException( - extIdMap.get(JsonKey.ID), - extIdMap.get(JsonKey.ID_TYPE), - extIdMap.get(JsonKey.PROVIDER)); + extIdMap.get(JsonKey.ID), + extIdMap.get(JsonKey.ID_TYPE), + extIdMap.get(JsonKey.PROVIDER)); } } } @@ -1245,7 +1244,7 @@ public static void updateUserExtId(Map requestMap) { } private static void deleteUserExternalId( - Map requestMap, Map map) { + Map requestMap, Map map) { map.remove(JsonKey.LAST_UPDATED_BY); map.remove(JsonKey.CREATED_BY); map.remove(JsonKey.LAST_UPDATED_ON); @@ -1283,25 +1282,25 @@ public static Map getUserFromExternalId(Map user Map user = null; Map externalIdReq = new WeakHashMap<>(); externalIdReq.put( - JsonKey.PROVIDER, ((String) userMap.get(JsonKey.EXTERNAL_ID_PROVIDER)).toLowerCase()); + JsonKey.PROVIDER, ((String) userMap.get(JsonKey.EXTERNAL_ID_PROVIDER)).toLowerCase()); externalIdReq.put( - JsonKey.ID_TYPE, ((String) userMap.get(JsonKey.EXTERNAL_ID_TYPE)).toLowerCase()); + JsonKey.ID_TYPE, ((String) userMap.get(JsonKey.EXTERNAL_ID_TYPE)).toLowerCase()); externalIdReq.put( - JsonKey.EXTERNAL_ID, - encryptData(((String) userMap.get(JsonKey.EXTERNAL_ID)).toLowerCase())); + JsonKey.EXTERNAL_ID, + encryptData(((String) userMap.get(JsonKey.EXTERNAL_ID)).toLowerCase())); Response response = - cassandraOperation.getRecordsByCompositeKey( - KEY_SPACE_NAME, JsonKey.USR_EXT_IDNT_TABLE, externalIdReq); + cassandraOperation.getRecordsByCompositeKey( + KEY_SPACE_NAME, JsonKey.USR_EXT_IDNT_TABLE, externalIdReq); List> userRecordList = - (List>) response.get(JsonKey.RESPONSE); + (List>) response.get(JsonKey.RESPONSE); if (CollectionUtils.isNotEmpty(userRecordList)) { Map userExtIdRecord = userRecordList.get(0); Response res = - cassandraOperation.getRecordById( - usrDbInfo.getKeySpace(), - usrDbInfo.getTableName(), - (String) userExtIdRecord.get(JsonKey.USER_ID)); + cassandraOperation.getRecordById( + usrDbInfo.getKeySpace(), + usrDbInfo.getTableName(), + (String) userExtIdRecord.get(JsonKey.USER_ID)); if (CollectionUtils.isNotEmpty((List>) res.get(JsonKey.RESPONSE))) { // user exist user = ((List>) res.get(JsonKey.RESPONSE)).get(0); @@ -1314,12 +1313,12 @@ public static String getChannel(String rootOrgId) { Util.DbInfo orgDbInfo = Util.dbInfoMap.get(JsonKey.ORG_DB); String channel = null; Response resultFrRootOrg = - cassandraOperation.getRecordById( - orgDbInfo.getKeySpace(), orgDbInfo.getTableName(), rootOrgId); + cassandraOperation.getRecordById( + orgDbInfo.getKeySpace(), orgDbInfo.getTableName(), rootOrgId); if (CollectionUtils.isNotEmpty( - (List>) resultFrRootOrg.get(JsonKey.RESPONSE))) { + (List>) resultFrRootOrg.get(JsonKey.RESPONSE))) { Map rootOrg = - ((List>) resultFrRootOrg.get(JsonKey.RESPONSE)).get(0); + ((List>) resultFrRootOrg.get(JsonKey.RESPONSE)).get(0); channel = (String) rootOrg.get(JsonKey.CHANNEL); } return channel; @@ -1332,8 +1331,8 @@ public static void upsertUserOrgData(Map userMap) { map.put(JsonKey.USER_ID, userMap.get(JsonKey.ID)); map.put(JsonKey.ORGANISATION_ID, userMap.get(JsonKey.ORGANISATION_ID)); Response response = - cassandraOperation.getRecordsByProperties( - usrOrgDb.getKeySpace(), usrOrgDb.getTableName(), map); + cassandraOperation.getRecordsByProperties( + usrOrgDb.getKeySpace(), usrOrgDb.getTableName(), map); List> resList = (List>) response.get(JsonKey.RESPONSE); if (!resList.isEmpty()) { Map res = resList.get(0); @@ -1361,20 +1360,20 @@ public static void upsertUserOrgData(Map userMap) { public static void validateUserExternalIds(Map requestMap) { List> dbResExternalIds = getUserExternalIds(requestMap); List> externalIds = - (List>) requestMap.get(JsonKey.EXTERNAL_IDS); + (List>) requestMap.get(JsonKey.EXTERNAL_IDS); if (CollectionUtils.isNotEmpty(externalIds)) { for (Map extIdMap : externalIds) { Optional> extMap = checkExternalID(dbResExternalIds, extIdMap); Map map = extMap.orElse(null); // Allowed operation type for externalIds ("add", "remove", "edit") if (!(JsonKey.ADD.equalsIgnoreCase(extIdMap.get(JsonKey.OPERATION)) - || StringUtils.isBlank(extIdMap.get(JsonKey.OPERATION)))) { + || StringUtils.isBlank(extIdMap.get(JsonKey.OPERATION)))) { // operation is either edit or remove if (MapUtils.isEmpty(map)) { throwExternalIDNotFoundException( - extIdMap.get(JsonKey.ID), - extIdMap.get(JsonKey.ID_TYPE), - extIdMap.get(JsonKey.PROVIDER)); + extIdMap.get(JsonKey.ID), + extIdMap.get(JsonKey.ID_TYPE), + extIdMap.get(JsonKey.PROVIDER)); } } } @@ -1382,43 +1381,43 @@ public static void validateUserExternalIds(Map requestMap) { } private static Optional> checkExternalID( - List> dbResExternalIds, Map extIdMap) { + List> dbResExternalIds, Map extIdMap) { Optional> extMap = - dbResExternalIds - .stream() - .filter( - s -> { - if (((s.get(JsonKey.ID_TYPE)).equalsIgnoreCase(extIdMap.get(JsonKey.ID_TYPE))) - && ((s.get(JsonKey.PROVIDER)) - .equalsIgnoreCase(extIdMap.get(JsonKey.PROVIDER)))) { - return true; - } else { - return false; - } - }) - .findFirst(); + dbResExternalIds + .stream() + .filter( + s -> { + if (((s.get(JsonKey.ID_TYPE)).equalsIgnoreCase(extIdMap.get(JsonKey.ID_TYPE))) + && ((s.get(JsonKey.PROVIDER)) + .equalsIgnoreCase(extIdMap.get(JsonKey.PROVIDER)))) { + return true; + } else { + return false; + } + }) + .findFirst(); return extMap; } public static List> convertExternalIdsValueToLowerCase( - List> externalIds) { + List> externalIds) { ConvertValuesToLowerCase mapper = - s -> { - s.put(JsonKey.ID, s.get(JsonKey.ID).toLowerCase()); - s.put(JsonKey.PROVIDER, s.get(JsonKey.PROVIDER).toLowerCase()); - s.put(JsonKey.ID_TYPE, s.get(JsonKey.ID_TYPE).toLowerCase()); - return s; - }; + s -> { + s.put(JsonKey.ID, s.get(JsonKey.ID).toLowerCase()); + s.put(JsonKey.PROVIDER, s.get(JsonKey.PROVIDER).toLowerCase()); + s.put(JsonKey.ID_TYPE, s.get(JsonKey.ID_TYPE).toLowerCase()); + return s; + }; return externalIds.stream().map(s -> mapper.convertToLowerCase(s)).collect(Collectors.toList()); } public static void storeOriginalExternalIdsValue(List> externalIds) { externalIds.forEach( - externalIdMap -> { - externalIdMap.put(JsonKey.ORIGINAL_EXTERNAL_ID, externalIdMap.get(JsonKey.ID)); - externalIdMap.put(JsonKey.ORIGINAL_PROVIDER, externalIdMap.get(JsonKey.PROVIDER)); - externalIdMap.put(JsonKey.ORIGINAL_ID_TYPE, externalIdMap.get(JsonKey.ID_TYPE)); - }); + externalIdMap -> { + externalIdMap.put(JsonKey.ORIGINAL_EXTERNAL_ID, externalIdMap.get(JsonKey.ID)); + externalIdMap.put(JsonKey.ORIGINAL_PROVIDER, externalIdMap.get(JsonKey.PROVIDER)); + externalIdMap.put(JsonKey.ORIGINAL_ID_TYPE, externalIdMap.get(JsonKey.ID_TYPE)); + }); } @SuppressWarnings("unchecked") @@ -1430,12 +1429,12 @@ public static Map getUserDetails(String userId, ActorRef actorRe Map userDetails = null; try { response = - cassandraOperation.getRecordById( - userDbInfo.getKeySpace(), userDbInfo.getTableName(), userId); + cassandraOperation.getRecordById( + userDbInfo.getKeySpace(), userDbInfo.getTableName(), userId); userList = (List>) response.getResult().get(JsonKey.RESPONSE); ProjectLogger.log( - "Util:getUserProfile: collecting user data to save for userId : " + userId, - LoggerEnum.INFO.name()); + "Util:getUserProfile: collecting user data to save for userId : " + userId, + LoggerEnum.INFO.name()); } catch (Exception e) { ProjectLogger.log(e.getMessage(), e); } @@ -1464,8 +1463,8 @@ public static Map getUserDetails(String userId, ActorRef actorRe addEmailAndPhone(userDetails); } else { ProjectLogger.log( - "Util:getUserProfile: User data not available to save in ES for userId : " + userId, - LoggerEnum.INFO.name()); + "Util:getUserProfile: User data not available to save in ES for userId : " + userId, + LoggerEnum.INFO.name()); } userDetails.put(JsonKey.USERNAME, username); return userDetails; @@ -1488,20 +1487,20 @@ public static void checkProfileCompleteness(Map userMap) { public static void checkUserProfileVisibility(Map userMap, ActorRef actorRef) { ProjectLogger.log( - "Util:checkUserProfileVisibility: userId = " + userMap.get(JsonKey.USER_ID), - LoggerEnum.INFO.name()); + "Util:checkUserProfileVisibility: userId = " + userMap.get(JsonKey.USER_ID), + LoggerEnum.INFO.name()); Map userProfileVisibilityMap = - (Map) userMap.get(JsonKey.PROFILE_VISIBILITY); + (Map) userMap.get(JsonKey.PROFILE_VISIBILITY); Map completeProfileVisibilityMap = - getCompleteProfileVisibilityMap(userProfileVisibilityMap, actorRef); + getCompleteProfileVisibilityMap(userProfileVisibilityMap, actorRef); ProjectLogger.log( - "Util:checkUserProfileVisibility: completeProfileVisibilityMap is " - + completeProfileVisibilityMap, - LoggerEnum.INFO.name()); + "Util:checkUserProfileVisibility: completeProfileVisibilityMap is " + + completeProfileVisibilityMap, + LoggerEnum.INFO.name()); ProjectLogger.log( - "Util:checkUserProfileVisibility: userMap contains username and the encrypted value before removing" - + userMap.get(JsonKey.USER_NAME), - LoggerEnum.INFO.name()); + "Util:checkUserProfileVisibility: userMap contains username and the encrypted value before removing" + + userMap.get(JsonKey.USER_NAME), + LoggerEnum.INFO.name()); if (MapUtils.isNotEmpty(completeProfileVisibilityMap)) { Map privateFieldsMap = new HashMap<>(); for (String field : completeProfileVisibilityMap.keySet()) { @@ -1510,25 +1509,25 @@ public static void checkUserProfileVisibility(Map userMap, Actor } } ProjectLogger.log( - "Util:checkUserProfileVisibility: private fields key are " + privateFieldsMap.keySet(), - LoggerEnum.INFO.name()); + "Util:checkUserProfileVisibility: private fields key are " + privateFieldsMap.keySet(), + LoggerEnum.INFO.name()); ProjectLogger.log( - "Util:checkUserProfileVisibility: userMap contains username and the encrypted value after removing" - + userMap.get(JsonKey.USER_NAME), - LoggerEnum.INFO.name()); + "Util:checkUserProfileVisibility: userMap contains username and the encrypted value after removing" + + userMap.get(JsonKey.USER_NAME), + LoggerEnum.INFO.name()); esService.upsert( - ProjectUtil.EsType.userprofilevisibility.getTypeName(), - (String) userMap.get(JsonKey.USER_ID), - privateFieldsMap); + ProjectUtil.EsType.userprofilevisibility.getTypeName(), + (String) userMap.get(JsonKey.USER_ID), + privateFieldsMap); } else { userMap.put(JsonKey.PROFILE_VISIBILITY, new HashMap()); } } public static Map getCompleteProfileVisibilityPrivateMap( - Map userProfileVisibilityMap, ActorRef actorRef) { + Map userProfileVisibilityMap, ActorRef actorRef) { Map completeProfileVisibilityMap = - getCompleteProfileVisibilityMap(userProfileVisibilityMap, actorRef); + getCompleteProfileVisibilityMap(userProfileVisibilityMap, actorRef); Map completeProfileVisibilityPrivateMap = new HashMap(); for (String key : completeProfileVisibilityMap.keySet()) { if (JsonKey.PRIVATE.equalsIgnoreCase(completeProfileVisibilityMap.get(key))) { @@ -1539,16 +1538,16 @@ public static Map getCompleteProfileVisibilityPrivateMap( } public static Map getCompleteProfileVisibilityMap( - Map userProfileVisibilityMap, ActorRef actorRef) { + Map userProfileVisibilityMap, ActorRef actorRef) { String defaultProfileVisibility = - ProjectUtil.getConfigValue(JsonKey.SUNBIRD_USER_PROFILE_FIELD_DEFAULT_VISIBILITY); + ProjectUtil.getConfigValue(JsonKey.SUNBIRD_USER_PROFILE_FIELD_DEFAULT_VISIBILITY); if (!(JsonKey.PUBLIC.equalsIgnoreCase(defaultProfileVisibility) - || JsonKey.PRIVATE.equalsIgnoreCase(defaultProfileVisibility))) { + || JsonKey.PRIVATE.equalsIgnoreCase(defaultProfileVisibility))) { ProjectLogger.log( - "Util:getCompleteProfileVisibilityMap: Invalid configuration - " - + defaultProfileVisibility - + " - for default profile visibility (public / private)", - LoggerEnum.ERROR.name()); + "Util:getCompleteProfileVisibilityMap: Invalid configuration - " + + defaultProfileVisibility + + " - for default profile visibility (public / private)", + LoggerEnum.ERROR.name()); ProjectCommonException.throwServerErrorException(ResponseCode.invaidConfiguration, ""); } @@ -1589,10 +1588,10 @@ public static void addMaskEmailAndPhone(Map userMap) { public static List> getUserSkills(String userId) { Util.DbInfo userSkillDbInfo = Util.dbInfoMap.get(JsonKey.USER_SKILL_DB); Response skillresponse = - cassandraOperation.getRecordsByIndexedProperty( - userSkillDbInfo.getKeySpace(), userSkillDbInfo.getTableName(), JsonKey.USER_ID, userId); + cassandraOperation.getRecordsByIndexedProperty( + userSkillDbInfo.getKeySpace(), userSkillDbInfo.getTableName(), JsonKey.USER_ID, userId); List> responseList = - (List>) skillresponse.get(JsonKey.RESPONSE); + (List>) skillresponse.get(JsonKey.RESPONSE); return responseList; } @@ -1601,8 +1600,8 @@ public static List> getUserBadge(String userId) { List> badges = new ArrayList<>(); try { Response result = - cassandraOperation.getRecordsByIndexedProperty( - badgeDbInfo.getKeySpace(), badgeDbInfo.getTableName(), JsonKey.USER_ID, userId); + cassandraOperation.getRecordsByIndexedProperty( + badgeDbInfo.getKeySpace(), badgeDbInfo.getTableName(), JsonKey.USER_ID, userId); badges = (List>) result.get(JsonKey.RESPONSE); } catch (Exception e) { ProjectLogger.log(e.getMessage(), e); @@ -1619,23 +1618,23 @@ public static List> getUserOrgDetails(String userId) { reqMap.put(JsonKey.IS_DELETED, false); Util.DbInfo orgUsrDbInfo = Util.dbInfoMap.get(JsonKey.USER_ORG_DB); Response result = - cassandraOperation.getRecordsByProperties( - orgUsrDbInfo.getKeySpace(), orgUsrDbInfo.getTableName(), reqMap); + cassandraOperation.getRecordsByProperties( + orgUsrDbInfo.getKeySpace(), orgUsrDbInfo.getTableName(), reqMap); userOrgList = (List>) result.get(JsonKey.RESPONSE); if (CollectionUtils.isNotEmpty(userOrgList)) { List organisationIds = - userOrgList - .stream() - .map(m -> (String) m.get(JsonKey.ORGANISATION_ID)) - .distinct() - .collect(Collectors.toList()); + userOrgList + .stream() + .map(m -> (String) m.get(JsonKey.ORGANISATION_ID)) + .distinct() + .collect(Collectors.toList()); List fields = Arrays.asList(JsonKey.ORG_NAME, JsonKey.PARENT_ORG_ID, JsonKey.ID); Future>> orgInfoMapF = - esService.getEsResultByListOfIds(organisationIds, fields, EsType.organisation.name()); + esService.getEsResultByListOfIds(organisationIds, fields, EsType.organisation.name()); Map> orgInfoMap = - (Map>) - ElasticSearchHelper.getResponseFromFuture(orgInfoMapF); + (Map>) + ElasticSearchHelper.getResponseFromFuture(orgInfoMapF); for (Map userOrg : userOrgList) { Map esOrgMap = orgInfoMap.get(userOrg.get(JsonKey.ORGANISATION_ID)); @@ -1657,10 +1656,10 @@ public static List> getJobProfileDetails(String userId) { try { ProjectLogger.log("collecting user jobprofile user Id : " + userId); jobProfileResponse = - cassandraOperation.getRecordsByIndexedProperty( - jobProDbInfo.getKeySpace(), jobProDbInfo.getTableName(), JsonKey.USER_ID, userId); + cassandraOperation.getRecordsByIndexedProperty( + jobProDbInfo.getKeySpace(), jobProDbInfo.getTableName(), JsonKey.USER_ID, userId); userJobProfileList = - (List>) jobProfileResponse.getResult().get(JsonKey.RESPONSE); + (List>) jobProfileResponse.getResult().get(JsonKey.RESPONSE); ProjectLogger.log("collecting user jobprofile collection completed userId : " + userId); } catch (Exception e) { ProjectLogger.log(e.getMessage(), e); @@ -1681,8 +1680,8 @@ public static List> getUserEducationDetails(String userId) { Response eduResponse = null; try { eduResponse = - cassandraOperation.getRecordsByIndexedProperty( - eduDbInfo.getKeySpace(), eduDbInfo.getTableName(), JsonKey.USER_ID, userId); + cassandraOperation.getRecordsByIndexedProperty( + eduDbInfo.getKeySpace(), eduDbInfo.getTableName(), JsonKey.USER_ID, userId); userEducationList = (List>) eduResponse.getResult().get(JsonKey.RESPONSE); } catch (Exception e) { ProjectLogger.log(e.getMessage(), e); @@ -1706,12 +1705,12 @@ public static List> getAddressDetails(String userId, String ProjectLogger.log("collecting user address operation user Id : " + userId); String encUserId = encryptData(userId); addrResponse = - cassandraOperation.getRecordsByIndexedProperty( - addrDbInfo.getKeySpace(), addrDbInfo.getTableName(), JsonKey.USER_ID, encUserId); + cassandraOperation.getRecordsByIndexedProperty( + addrDbInfo.getKeySpace(), addrDbInfo.getTableName(), JsonKey.USER_ID, encUserId); } else { addrResponse = - cassandraOperation.getRecordById( - addrDbInfo.getKeySpace(), addrDbInfo.getTableName(), addressId); + cassandraOperation.getRecordById( + addrDbInfo.getKeySpace(), addrDbInfo.getTableName(), addressId); } userAddressList = (List>) addrResponse.getResult().get(JsonKey.RESPONSE); ProjectLogger.log("collecting user address operation completed user Id : " + userId); @@ -1723,24 +1722,24 @@ public static List> getAddressDetails(String userId, String public static void saveUserDataToES(Map userData) { boolean flag = - insertDataToElastic( - ProjectUtil.EsIndex.sunbird.getIndexName(), - ProjectUtil.EsType.user.getTypeName(), - (String) userData.get(JsonKey.USER_ID), - userData); + insertDataToElastic( + ProjectUtil.EsIndex.sunbird.getIndexName(), + ProjectUtil.EsType.user.getTypeName(), + (String) userData.get(JsonKey.USER_ID), + userData); if (flag) { ProjectLogger.log( - "Util:saveUserDataToES : ES save operation is successful for userId : " - + (String) userData.get(JsonKey.USER_ID)); + "Util:saveUserDataToES : ES save operation is successful for userId : " + + (String) userData.get(JsonKey.USER_ID)); } else { ProjectLogger.log( - "Util:saveUserDataToES : ES save operation is unsuccessful for userId : " - + (String) userData.get(JsonKey.USER_ID)); + "Util:saveUserDataToES : ES save operation is unsuccessful for userId : " + + (String) userData.get(JsonKey.USER_ID)); } } private static boolean insertDataToElastic( - String index, String type, String identifier, Map data) { + String index, String type, String identifier, Map data) { Future responseF = esService.save(type, identifier, data); String response = (String) ElasticSearchHelper.getResponseFromFuture(responseF); if (!StringUtils.isBlank(response)) { @@ -1748,7 +1747,7 @@ private static boolean insertDataToElastic( return true; } ProjectLogger.log( - "unbale to save the data inside ES with identifier " + identifier, LoggerEnum.INFO.name()); + "unbale to save the data inside ES with identifier " + identifier, LoggerEnum.INFO.name()); return false; } @@ -1766,24 +1765,24 @@ public static void checkPhoneUniqueness(Map userMap, String opTy } DbInfo userDb = dbInfoMap.get(JsonKey.USER_DB); Response result = - cassandraOperation.getRecordsByIndexedProperty( - userDb.getKeySpace(), userDb.getTableName(), (JsonKey.PHONE), phone); + cassandraOperation.getRecordsByIndexedProperty( + userDb.getKeySpace(), userDb.getTableName(), (JsonKey.PHONE), phone); List> userMapList = - (List>) result.get(JsonKey.RESPONSE); + (List>) result.get(JsonKey.RESPONSE); if (!userMapList.isEmpty()) { if (opType.equalsIgnoreCase(JsonKey.CREATE)) { throw new ProjectCommonException( - ResponseCode.PhoneNumberInUse.getErrorCode(), - ResponseCode.PhoneNumberInUse.getErrorMessage(), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.PhoneNumberInUse.getErrorCode(), + ResponseCode.PhoneNumberInUse.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); } else { Map user = userMapList.get(0); if (!(((String) user.get(JsonKey.ID)) - .equalsIgnoreCase((String) userMap.get(JsonKey.ID)))) { + .equalsIgnoreCase((String) userMap.get(JsonKey.ID)))) { throw new ProjectCommonException( - ResponseCode.PhoneNumberInUse.getErrorCode(), - ResponseCode.PhoneNumberInUse.getErrorMessage(), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.PhoneNumberInUse.getErrorCode(), + ResponseCode.PhoneNumberInUse.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); } } } @@ -1810,25 +1809,25 @@ public static void checkEmailUniqueness(Map userMap, String opTy map.put(JsonKey.FILTERS, filters); SearchDTO searchDto = Util.createSearchDto(map); Future> resultF = - esService.search(searchDto, ProjectUtil.EsType.user.getTypeName()); + esService.search(searchDto, ProjectUtil.EsType.user.getTypeName()); Map result = - (Map) ElasticSearchHelper.getResponseFromFuture(resultF); + (Map) ElasticSearchHelper.getResponseFromFuture(resultF); List> userMapList = - (List>) result.get(JsonKey.CONTENT); + (List>) result.get(JsonKey.CONTENT); if (!userMapList.isEmpty()) { if (opType.equalsIgnoreCase(JsonKey.CREATE)) { throw new ProjectCommonException( - ResponseCode.emailInUse.getErrorCode(), - ResponseCode.emailInUse.getErrorMessage(), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.emailInUse.getErrorCode(), + ResponseCode.emailInUse.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); } else { Map user = userMapList.get(0); if (!(((String) user.get(JsonKey.ID)) - .equalsIgnoreCase((String) userMap.get(JsonKey.ID)))) { + .equalsIgnoreCase((String) userMap.get(JsonKey.ID)))) { throw new ProjectCommonException( - ResponseCode.emailInUse.getErrorCode(), - ResponseCode.emailInUse.getErrorMessage(), - ResponseCode.CLIENT_ERROR.getResponseCode()); + ResponseCode.emailInUse.getErrorCode(), + ResponseCode.emailInUse.getErrorMessage(), + ResponseCode.CLIENT_ERROR.getResponseCode()); } } } @@ -1846,19 +1845,19 @@ public static Request sendOnboardingMail(Map emailTemplateMap) { reciptientsMail.add((String) emailTemplateMap.get(JsonKey.EMAIL)); emailTemplateMap.put(JsonKey.RECIPIENT_EMAILS, reciptientsMail); emailTemplateMap.put( - JsonKey.BODY, propertiesCache.getProperty(JsonKey.ONBOARDING_WELCOME_MAIL_BODY)); + JsonKey.BODY, propertiesCache.getProperty(JsonKey.ONBOARDING_WELCOME_MAIL_BODY)); emailTemplateMap.put(JsonKey.NOTE, propertiesCache.getProperty(JsonKey.MAIL_NOTE)); emailTemplateMap.put(JsonKey.ORG_NAME, envName); String welcomeMessage = propertiesCache.getProperty(JsonKey.ONBOARDING_MAIL_MESSAGE); emailTemplateMap.put( - JsonKey.WELCOME_MESSAGE, ProjectUtil.formatMessage(welcomeMessage, envName)); + JsonKey.WELCOME_MESSAGE, ProjectUtil.formatMessage(welcomeMessage, envName)); emailTemplateMap.put(JsonKey.EMAIL_TEMPLATE_TYPE, "welcome"); setRequiredActionLink(emailTemplateMap); if (StringUtils.isBlank((String) emailTemplateMap.get(JsonKey.SET_PASSWORD_LINK)) - && StringUtils.isBlank((String) emailTemplateMap.get(JsonKey.VERIFY_EMAIL_LINK))) { + && StringUtils.isBlank((String) emailTemplateMap.get(JsonKey.VERIFY_EMAIL_LINK))) { ProjectLogger.log( - "Util:sendOnboardingMail: Email not sent as generated link is empty", LoggerEnum.ERROR); + "Util:sendOnboardingMail: Email not sent as generated link is empty", LoggerEnum.ERROR); return null; } @@ -1884,27 +1883,27 @@ private static void setRequiredActionLink(Map templateMap) { public static void getUserRequiredActionLink(Map templateMap) { URLShortner urlShortner = new URLShortnerImpl(); String redirectUri = - StringUtils.isNotBlank((String) templateMap.get(JsonKey.REDIRECT_URI)) - ? ((String) templateMap.get(JsonKey.REDIRECT_URI)) - : null; + StringUtils.isNotBlank((String) templateMap.get(JsonKey.REDIRECT_URI)) + ? ((String) templateMap.get(JsonKey.REDIRECT_URI)) + : null; ProjectLogger.log( - "Util:getUserRequiredActionLink redirectURI = " + redirectUri, LoggerEnum.INFO.name()); + "Util:getUserRequiredActionLink redirectURI = " + redirectUri, LoggerEnum.INFO.name()); if (StringUtils.isBlank((String) templateMap.get(JsonKey.PASSWORD))) { templateMap.put( - JsonKey.SET_PASSWORD_LINK, - urlShortner.shortUrl( - KeycloakRequiredActionLinkUtil.getLink( - (String) templateMap.get(JsonKey.USERNAME), - redirectUri, - KeycloakRequiredActionLinkUtil.UPDATE_PASSWORD))); + JsonKey.SET_PASSWORD_LINK, + urlShortner.shortUrl( + KeycloakRequiredActionLinkUtil.getLink( + (String) templateMap.get(JsonKey.USERNAME), + redirectUri, + KeycloakRequiredActionLinkUtil.UPDATE_PASSWORD))); } else { templateMap.put( - JsonKey.VERIFY_EMAIL_LINK, - urlShortner.shortUrl( - KeycloakRequiredActionLinkUtil.getLink( - (String) templateMap.get(JsonKey.USERNAME), - redirectUri, - KeycloakRequiredActionLinkUtil.VERIFY_EMAIL))); + JsonKey.VERIFY_EMAIL_LINK, + urlShortner.shortUrl( + KeycloakRequiredActionLinkUtil.getLink( + (String) templateMap.get(JsonKey.USERNAME), + redirectUri, + KeycloakRequiredActionLinkUtil.VERIFY_EMAIL))); } } @@ -1913,9 +1912,9 @@ public static void sendSMS(Map userMap) { String envName = propertiesCache.getProperty(JsonKey.SUNBIRD_INSTALLATION_DISPLAY_NAME); setRequiredActionLink(userMap); if (StringUtils.isBlank((String) userMap.get(JsonKey.SET_PASSWORD_LINK)) - && StringUtils.isBlank((String) userMap.get(JsonKey.VERIFY_EMAIL_LINK))) { + && StringUtils.isBlank((String) userMap.get(JsonKey.VERIFY_EMAIL_LINK))) { ProjectLogger.log( - "Util:sendSMS: SMS not sent as generated link is empty", LoggerEnum.ERROR); + "Util:sendSMS: SMS not sent as generated link is empty", LoggerEnum.ERROR); return; } Map smsTemplate = new HashMap<>(); @@ -1930,30 +1929,30 @@ public static void sendSMS(Map userMap) { String countryCode = ""; if (StringUtils.isBlank((String) userMap.get(JsonKey.COUNTRY_CODE))) { countryCode = - PropertiesCache.getInstance().getProperty(JsonKey.SUNBIRD_DEFAULT_COUNTRY_CODE); + PropertiesCache.getInstance().getProperty(JsonKey.SUNBIRD_DEFAULT_COUNTRY_CODE); } else { countryCode = (String) userMap.get(JsonKey.COUNTRY_CODE); } ISmsProvider smsProvider = SMSFactory.getInstance("91SMS"); ProjectLogger.log( - "SMS text : " + sms + " with phone " + (String) userMap.get(JsonKey.PHONE), - LoggerEnum.INFO.name()); + "SMS text : " + sms + " with phone " + (String) userMap.get(JsonKey.PHONE), + LoggerEnum.INFO.name()); boolean response = smsProvider.send((String) userMap.get(JsonKey.PHONE), countryCode, sms); ProjectLogger.log("Response from smsProvider : " + response, LoggerEnum.INFO); if (response) { ProjectLogger.log( - "Welcome Message sent successfully to ." + (String) userMap.get(JsonKey.PHONE), - LoggerEnum.INFO.name()); + "Welcome Message sent successfully to ." + (String) userMap.get(JsonKey.PHONE), + LoggerEnum.INFO.name()); } else { ProjectLogger.log( - "Welcome Message failed for ." + (String) userMap.get(JsonKey.PHONE), - LoggerEnum.INFO.name()); + "Welcome Message failed for ." + (String) userMap.get(JsonKey.PHONE), + LoggerEnum.INFO.name()); } } } public static List> copyAndConvertExternalIdsToLower( - List> externalIds) { + List> externalIds) { List> list = new ArrayList<>(); if (CollectionUtils.isNotEmpty(externalIds)) { storeOriginalExternalIdsValue(externalIds); @@ -1968,14 +1967,14 @@ public static String getCustodianChannel(Map userMap, ActorRef a try { SystemSettingClient client = SystemSettingClientImpl.getInstance(); SystemSetting systemSetting = - client.getSystemSettingByField(actorRef, JsonKey.CUSTODIAN_ORG_CHANNEL); + client.getSystemSettingByField(actorRef, JsonKey.CUSTODIAN_ORG_CHANNEL); if (null != systemSetting && StringUtils.isNotBlank(systemSetting.getValue())) { channel = systemSetting.getValue(); } } catch (Exception ex) { ProjectLogger.log( - "Util:getCustodianChannel: Exception occurred while fetching custodian channel from system setting.", - ex); + "Util:getCustodianChannel: Exception occurred while fetching custodian channel from system setting.", + ex); } } if (StringUtils.isBlank(channel)) { @@ -1993,10 +1992,10 @@ public static String getCustodianChannel(Map userMap, ActorRef a */ public static Config getUserProfileConfig(ActorRef actorRef) { SystemSetting userProfileConfigSetting = - getSystemSettingByField(JsonKey.USER_PROFILE_CONFIG, actorRef); + getSystemSettingByField(JsonKey.USER_PROFILE_CONFIG, actorRef); String userProfileConfigString = userProfileConfigSetting.getValue(); Config userProfileConfig = - ConfigUtil.getConfigFromJsonString(userProfileConfigString, JsonKey.USER_PROFILE_CONFIG); + ConfigUtil.getConfigFromJsonString(userProfileConfigString, JsonKey.USER_PROFILE_CONFIG); validateUserProfileConfig(userProfileConfig); return userProfileConfig; } @@ -2004,8 +2003,8 @@ public static Config getUserProfileConfig(ActorRef actorRef) { private static void validateUserProfileConfig(Config userProfileConfig) { if (CollectionUtils.isEmpty(userProfileConfig.getStringList(JsonKey.FIELDS))) { ProjectLogger.log( - "Util:validateUserProfileConfig: User profile fields is not configured.", - LoggerEnum.ERROR.name()); + "Util:validateUserProfileConfig: User profile fields is not configured.", + LoggerEnum.ERROR.name()); ProjectCommonException.throwServerErrorException(ResponseCode.invaidConfiguration, ""); } List publicFields = null; @@ -2015,26 +2014,26 @@ private static void validateUserProfileConfig(Config userProfileConfig) { privateFields = userProfileConfig.getStringList(JsonKey.PRIVATE_FIELDS); } catch (Exception e) { ProjectLogger.log( - "Util:validateUserProfileConfig: Invalid configuration for public / private fields.", - LoggerEnum.ERROR.name()); + "Util:validateUserProfileConfig: Invalid configuration for public / private fields.", + LoggerEnum.ERROR.name()); } if (CollectionUtils.isNotEmpty(privateFields) && CollectionUtils.isNotEmpty(publicFields)) { for (String field : publicFields) { if (privateFields.contains(field)) { ProjectLogger.log( - "Field " - + field - + " in user configuration is conflicting in publicFields and privateFields.", - LoggerEnum.ERROR.name()); + "Field " + + field + + " in user configuration is conflicting in publicFields and privateFields.", + LoggerEnum.ERROR.name()); ProjectCommonException.throwServerErrorException( - ResponseCode.errorConflictingFieldConfiguration, - ProjectUtil.formatMessage( - ResponseCode.errorConflictingFieldConfiguration.getErrorMessage(), - field, - JsonKey.USER, - JsonKey.PUBLIC_FIELDS, - JsonKey.PRIVATE_FIELDS)); + ResponseCode.errorConflictingFieldConfiguration, + ProjectUtil.formatMessage( + ResponseCode.errorConflictingFieldConfiguration.getErrorMessage(), + field, + JsonKey.USER, + JsonKey.PUBLIC_FIELDS, + JsonKey.PRIVATE_FIELDS)); } } } @@ -2048,7 +2047,7 @@ private static void validateUserProfileConfig(Config userProfileConfig) { * @return system setting */ public static SystemSetting getSystemSettingByField( - String systemSettingField, ActorRef actorRef) { + String systemSettingField, ActorRef actorRef) { SystemSetting systemSetting = null; try { SystemSettingClient client = SystemSettingClientImpl.getInstance(); @@ -2058,13 +2057,13 @@ public static SystemSetting getSystemSettingByField( } } catch (Exception e) { ProjectLogger.log( - "Util:getSystemSettingByField: System setting not found for field - " - + systemSettingField, - e); + "Util:getSystemSettingByField: System setting not found for field - " + + systemSettingField, + e); ProjectCommonException.throwServerErrorException( - ResponseCode.errorSystemSettingNotFound, - ProjectUtil.formatMessage( - ResponseCode.errorSystemSettingNotFound.getErrorMessage(), systemSettingField)); + ResponseCode.errorSystemSettingNotFound, + ProjectUtil.formatMessage( + ResponseCode.errorSystemSettingNotFound.getErrorMessage(), systemSettingField)); } return systemSetting; } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/metrics/actors/CourseMetricsActor.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/metrics/actors/CourseMetricsActor.java index 85bf5642b6..86e17d620a 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/metrics/actors/CourseMetricsActor.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/metrics/actors/CourseMetricsActor.java @@ -1,5 +1,7 @@ package org.sunbird.metrics.actors; +import static org.sunbird.common.models.util.JsonKey.CONTENT; +import static org.sunbird.common.models.util.JsonKey.RESPONSE; import static org.sunbird.common.models.util.ProjectUtil.isNotNull; import static org.sunbird.common.models.util.ProjectUtil.isNull; @@ -202,7 +204,7 @@ private Map validateAndGetCourseBatch(String batchId) { } private void validateUserId(String requestedBy) { - Map requestedByInfo = userOrgService.getUserById(requestedBy); + Map requestedByInfo = userOrgService.getUserById(requestedBy); if (isNull(requestedByInfo) || StringUtils.isBlank((String) requestedByInfo.get(JsonKey.FIRST_NAME))) { throw new ProjectCommonException( @@ -220,7 +222,7 @@ private void courseProgressMetricsReport(Request actorMessage) { simpleDateFormat.setLenient(false); String requestedBy = (String) actorMessage.get(JsonKey.REQUESTED_BY); - Map requestedByInfo = userOrgService.getUserById(requestedBy); + Map requestedByInfo = userOrgService.getUserById(requestedBy); if (isNull(requestedByInfo) || StringUtils.isBlank((String) requestedByInfo.get(JsonKey.FIRST_NAME))) { throw new ProjectCommonException( @@ -283,6 +285,18 @@ private void courseProgressMetricsReport(Request actorMessage) { sender().tell(response, self()); } + private String getCourseNameFromBatch(Map courseBatchResult) { + + String courseName = null; + if (courseBatchResult.get(JsonKey.COURSE_ADDITIONAL_INFO) != null + && courseBatchResult.get(JsonKey.COURSE_ADDITIONAL_INFO) instanceof Map) { + Map map = + (Map) courseBatchResult.get(JsonKey.COURSE_ADDITIONAL_INFO); + courseName = map.get(JsonKey.COURSE_NAME); + } + return courseName; + } + @SuppressWarnings("unchecked") private void courseProgressMetrics(Request actorMessage) { ProjectLogger.log("CourseMetricsActor: courseProgressMetrics called.", LoggerEnum.INFO.name()); @@ -292,7 +306,7 @@ private void courseProgressMetrics(Request actorMessage) { String requestedBy = (String) actorMessage.get(JsonKey.REQUESTED_BY); - Map requestedByInfo = userOrgService.getUserById(requestedBy); + Map requestedByInfo = userOrgService.getUserById(requestedBy); if (isNull(requestedByInfo) || StringUtils.isBlank((String) requestedByInfo.get(JsonKey.FIRST_NAME))) { @@ -382,39 +396,40 @@ private void courseProgressMetrics(Request actorMessage) { userfields.add(JsonKey.ROOT_ORG_ID); userfields.add(JsonKey.FIRST_NAME); userfields.add(JsonKey.LAST_NAME); - List> useresContent = userOrgService.getUsersByIds(userIds); - Map> userInfoCache = new HashMap<>(); - Set orgSet = new HashSet<>(); - if (CollectionUtils.isNotEmpty(useresContent)) { - for (Map map : useresContent) { - String userId = (String) map.get(JsonKey.USER_ID); - map.put("user", userId); - map.put( - JsonKey.USERNAME, decryptionService.decryptData((String) map.get(JsonKey.USERNAME))); - String registerdOrgId = (String) map.get(JsonKey.ROOT_ORG_ID); - if (isNotNull(registerdOrgId)) { - orgSet.add(registerdOrgId); + List> useresContent= userOrgService.getUsersByIds(userIds); + Map> userInfoCache = new HashMap<>(); + Set orgSet = new HashSet<>(); + if(CollectionUtils.isNotEmpty(useresContent)) { + for (Map map : useresContent) { + String userId = (String) map.get(JsonKey.USER_ID); + map.put("user", userId); + map.put( + JsonKey.USERNAME, decryptionService.decryptData((String) map.get(JsonKey.USERNAME))); + String registerdOrgId = (String) map.get(JsonKey.ROOT_ORG_ID); + if (isNotNull(registerdOrgId)) { + orgSet.add(registerdOrgId); + } + userInfoCache.put(userId, new HashMap(map)); + // remove the org info from user content bcoz it is not desired in the user info + // result + map.remove(JsonKey.ROOT_ORG_ID); + map.remove(JsonKey.USER_ID); } - userInfoCache.put(userId, new HashMap(map)); - // remove the org info from user content bcoz it is not desired in the user info - // result - map.remove(JsonKey.ROOT_ORG_ID); - map.remove(JsonKey.USER_ID); } - } - List orgfields = orgSet.stream().collect(Collectors.toList()); + List orgfields=orgSet.stream().collect(Collectors.toList()); List> orgContent = userOrgService.getOrganisationsByIds(orgfields); - Map orgInfoCache = new HashMap<>(); + Map orgInfoCache = new HashMap<>(); - if (CollectionUtils.isNotEmpty(orgContent)) { - for (Map map : orgContent) { + if(CollectionUtils.isNotEmpty(orgContent)) { + for (Map map : orgContent) { - String regOrgId = (String) map.get(JsonKey.ID); - String regOrgName = (String) map.get(JsonKey.ORGANISATION_NAME); - orgInfoCache.put(regOrgId, regOrgName); + String regOrgId = (String) map.get(JsonKey.ID); + String regOrgName = (String) map.get(JsonKey.ORGANISATION_NAME); + orgInfoCache.put(regOrgId, regOrgName); + } } - } + Map batchFilter = new HashMap<>(); batchFilter.put(JsonKey.ID, batchId); @@ -525,7 +540,7 @@ private void courseConsumptionMetrics(Request actorMessage) { filterMap.put(CONTENT_ID, courseId); requestObject.put(JsonKey.FILTER, filterMap); - Map result = userOrgService.getUserById(requestedBy); + Map result= userOrgService.getUserById(requestedBy); if (null == result || result.isEmpty()) { ProjectCommonException exception = new ProjectCommonException( @@ -545,7 +560,7 @@ private void courseConsumptionMetrics(Request actorMessage) { ResponseCode.CLIENT_ERROR.getResponseCode()); sender().tell(exception, self()); } - Map rootOrgData = userOrgService.getOrganisationById(rootOrgId); + Map rootOrgData= userOrgService.getOrganisationById(rootOrgId); if (null == rootOrgData || rootOrgData.isEmpty()) { ProjectCommonException exception = new ProjectCommonException( diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/models/course/batch/CourseBatch.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/models/course/batch/CourseBatch.java index 8683fe313e..be47dc8f56 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/models/course/batch/CourseBatch.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/models/course/batch/CourseBatch.java @@ -3,8 +3,10 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import java.io.Serializable; +import java.util.HashMap; import java.util.List; import java.util.Map; +import org.sunbird.common.models.util.JsonKey; import org.sunbird.common.models.util.ProjectUtil; @JsonIgnoreProperties(ignoreUnknown = true) @@ -12,7 +14,12 @@ public class CourseBatch implements Serializable { private static final long serialVersionUID = 1L; - private String batchId; + private String id; + private String countDecrementDate; + private Boolean countDecrementStatus; + private String countIncrementDate; + private Boolean countIncrementStatus; + private Map courseAdditionalInfo; private String courseCreator; private String courseId; private String createdBy; @@ -28,10 +35,59 @@ public class CourseBatch implements Serializable { private String hashTagId; private List mentors; private String name; + private List participant; private String startDate; private Integer status; private String updatedDate; + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getCountDecrementDate() { + return countDecrementDate; + } + + public void setCountDecrementDate(String countDecrementDate) { + this.countDecrementDate = countDecrementDate; + } + + public boolean isCountDecrementStatus() { + return countDecrementStatus; + } + + public void setCountDecrementStatus(boolean countDecrementStatus) { + this.countDecrementStatus = countDecrementStatus; + } + + public String getCountIncrementDate() { + return countIncrementDate; + } + + public void setCountIncrementDate(String countIncrementDate) { + this.countIncrementDate = countIncrementDate; + } + + public boolean isCountIncrementStatus() { + return countIncrementStatus; + } + + public void setCountIncrementStatus(boolean countIncrementStatus) { + this.countIncrementStatus = countIncrementStatus; + } + + public Map getCourseAdditionalInfo() { + return courseAdditionalInfo; + } + + public void setCourseAdditionalInfo(Map courseAdditionalInfo) { + this.courseAdditionalInfo = courseAdditionalInfo; + } + public String getCourseCreator() { return courseCreator; } @@ -128,6 +184,14 @@ public void setName(String name) { this.name = name; } + public List getParticipant() { + return participant; + } + + public void setParticipant(List participant) { + this.participant = participant; + } + public String getStartDate() { return startDate; } @@ -152,16 +216,34 @@ public void setUpdatedDate(String updatedDate) { this.updatedDate = updatedDate; } + public void initCount() { + this.setCountDecrementStatus(false); + this.setCountIncrementStatus(false); + } + public void setContentDetails(Map contentDetails, String createdBy) { + this.setCourseCreator((String) contentDetails.get(JsonKey.CREATED_BY)); + this.setCourseAdditionalInfo(getAdditionalCourseInfo(contentDetails)); this.setCreatedBy(createdBy); this.setCreatedDate(ProjectUtil.getFormattedDate()); } - public String getBatchId() { - return batchId; + private Map getAdditionalCourseInfo(Map contentDetails) { + + Map courseMap = new HashMap<>(); + courseMap.put(JsonKey.COURSE_LOGO_URL, getContentAttribute(contentDetails, JsonKey.APP_ICON)); + courseMap.put(JsonKey.COURSE_NAME, getContentAttribute(contentDetails, JsonKey.NAME)); + courseMap.put(JsonKey.DESCRIPTION, getContentAttribute(contentDetails, JsonKey.DESCRIPTION)); + courseMap.put(JsonKey.TOC_URL, getContentAttribute(contentDetails, "toc_url")); + if (contentDetails.get(JsonKey.LEAF_NODE_COUNT) != null) { + courseMap.put( + JsonKey.LEAF_NODE_COUNT, (contentDetails.get(JsonKey.LEAF_NODE_COUNT)).toString()); + } + courseMap.put(JsonKey.STATUS, (String) contentDetails.getOrDefault(JsonKey.STATUS, "")); + return courseMap; } - public void setBatchId(String batchId) { - this.batchId = batchId; + private String getContentAttribute(Map contentDetails, String key) { + return (String) contentDetails.getOrDefault(key, ""); } } diff --git a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/models/user/courses/UserCourses.java b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/models/user/courses/UserCourses.java index 9481d9b03b..daa595d7c7 100644 --- a/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/models/user/courses/UserCourses.java +++ b/actors/sunbird-lms-mw/actors/common/src/main/java/org/sunbird/models/user/courses/UserCourses.java @@ -9,21 +9,35 @@ public class UserCourses implements Serializable { private static final long serialVersionUID = 1L; + private String id; private boolean active; private String addedBy; private String batchId; + private String contentId; private String courseId; + private String courseLogoUrl; + private String courseName; + private String timestamp; private String delta; + private String description; private String enrolledDate; private String grade; - private String datetime; private String lastReadContentId; - private String completedon; private int lastReadContentStatus; + private int leafNodesCount; private int progress; private int status; + private String tocUrl; private String userId; + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + public boolean isActive() { return active; } @@ -48,6 +62,14 @@ public void setBatchId(String batchId) { this.batchId = batchId; } + public String getContentId() { + return contentId; + } + + public void setContentId(String contentId) { + this.contentId = contentId; + } + public String getCourseId() { return courseId; } @@ -56,6 +78,30 @@ public void setCourseId(String courseId) { this.courseId = courseId; } + public String getCourseLogoUrl() { + return courseLogoUrl; + } + + public void setCourseLogoUrl(String courseLogoUrl) { + this.courseLogoUrl = courseLogoUrl; + } + + public String getCourseName() { + return courseName; + } + + public void setCourseName(String courseName) { + this.courseName = courseName; + } + + public String getTimestamp() { + return timestamp; + } + + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + public String getDelta() { return delta; } @@ -64,6 +110,14 @@ public void setDelta(String delta) { this.delta = delta; } + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + public String getEnrolledDate() { return enrolledDate; } @@ -96,20 +150,12 @@ public void setLastReadContentStatus(int lastReadContentStatus) { this.lastReadContentStatus = lastReadContentStatus; } - public String getCompletedon() { - return completedon; + public int getLeafNodesCount() { + return leafNodesCount; } - public void setCompletedon(String completedon) { - this.completedon = completedon; - } - - public String getDatetime() { - return datetime; - } - - public void setDatetime(String datetime) { - this.datetime = datetime; + public void setLeafNodesCount(int leafNodesCount) { + this.leafNodesCount = leafNodesCount; } public int getProgress() { @@ -128,6 +174,14 @@ public void setStatus(int status) { this.status = status; } + public String getTocUrl() { + return tocUrl; + } + + public void setTocUrl(String tocUrl) { + this.tocUrl = tocUrl; + } + public String getUserId() { return userId; } diff --git a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/SearchHandlerActorTest.java b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/SearchHandlerActorTest.java index dae3179ee2..8269fd8544 100644 --- a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/SearchHandlerActorTest.java +++ b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/SearchHandlerActorTest.java @@ -99,13 +99,44 @@ private static Map createResponseGet(boolean isResponseRequired) HashMap response = new HashMap<>(); List> content = new ArrayList<>(); HashMap innerMap = new HashMap<>(); - List> batchList = new ArrayList<>(); - innerMap.put(JsonKey.BATCHES, batchList); + List> orgList = new ArrayList<>(); + Map orgMap = new HashMap<>(); + orgMap.put(JsonKey.ORGANISATION_ID, "anyOrgId"); + + innerMap.put(JsonKey.ROOT_ORG_ID, "anyRootOrgId"); + innerMap.put(JsonKey.ORGANISATIONS, orgList); + innerMap.put(JsonKey.HASHTAGID, "HASHTAGID"); content.add(innerMap); response.put(JsonKey.CONTENT, content); return response; } + @Test + public void searchUser() { + TestKit probe = new TestKit(system); + ActorRef subject = system.actorOf(props); + + Request reqObj = new Request(); + reqObj.setOperation(ActorOperations.COMPOSITE_SEARCH.getValue()); + HashMap innerMap = new HashMap<>(); + innerMap.put(JsonKey.QUERY, ""); + Map filters = new HashMap<>(); + List objectType = new ArrayList(); + objectType.add("user"); + filters.put(JsonKey.OBJECT_TYPE, objectType); + filters.put(JsonKey.ROOT_ORG_ID, "ORG_001"); + innerMap.put(JsonKey.FILTERS, filters); + innerMap.put(JsonKey.LIMIT, 1); + + Map contextMap = new HashMap<>(); + contextMap.put(JsonKey.FIELDS, JsonKey.ORG_NAME); + reqObj.setContext(contextMap); + reqObj.setRequest(innerMap); + subject.tell(reqObj, probe.getRef()); + Response res = probe.expectMsgClass(duration("200 second"), Response.class); + Assert.assertTrue(null != res.get(JsonKey.RESPONSE)); + } + @Test public void searchCourse() { TestKit probe = new TestKit(system); @@ -117,8 +148,9 @@ public void searchCourse() { innerMap.put(JsonKey.QUERY, ""); Map filters = new HashMap<>(); List objectType = new ArrayList(); - objectType.add("course-batch"); + objectType.add("cbatch"); filters.put(JsonKey.OBJECT_TYPE, objectType); + filters.put(JsonKey.ROOT_ORG_ID, "ORG_001"); innerMap.put(JsonKey.FILTERS, filters); innerMap.put(JsonKey.LIMIT, 1); reqObj.setRequest(innerMap); diff --git a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/CourseEnrollmentActorTest.java b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/CourseEnrollmentActorTest.java index bbea6ba1d1..8e4957b909 100644 --- a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/CourseEnrollmentActorTest.java +++ b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/CourseEnrollmentActorTest.java @@ -238,6 +238,11 @@ private Response createGetCourseBatchSuccessResponse(int status) { userMap.put(JsonKey.STATUS, status); userMap.put(JsonKey.START_DATE, calculateDate(0)); userMap.put(JsonKey.END_DATE, calculateDate(4)); + Map courseInfo = new HashMap<>(); + courseInfo.put(JsonKey.NAME, courseName); + courseInfo.put(JsonKey.DESCRIPTION, courseDescription); + courseInfo.put(JsonKey.APP_ICON, courseAppIcon); + userMap.put(JsonKey.COURSE_ADDITIONAL_INFO, courseInfo); List> result = new ArrayList<>(); result.add(userMap); response.put(JsonKey.RESPONSE, result); diff --git a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/dao/CourseBatchDaoTest.java b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/dao/CourseBatchDaoTest.java index 4331fa359b..884ab8cbad 100644 --- a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/dao/CourseBatchDaoTest.java +++ b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/dao/CourseBatchDaoTest.java @@ -50,6 +50,9 @@ public void beforeEachTest() { public void createCourseBatchSuccess() { CourseBatch courseBatch = new CourseBatch(); + courseBatch.setId(JsonKey.ID); + courseBatch.setCountDecrementStatus(false); + courseBatch.setCountIncrementStatus(false); courseBatch.setStatus(ProjectUtil.ProgressStatus.STARTED.getValue()); when(cassandraOperation.insertRecord( Mockito.anyString(), Mockito.anyString(), Mockito.anyMap())) @@ -65,7 +68,7 @@ public void updateCourseBatchSuccess() { when(cassandraOperation.updateRecord( Mockito.anyString(), Mockito.anyString(), Mockito.anyMap())) .thenReturn(new Response()); - Response response = courseBatchDao.update(JsonKey.COURSE_ID, JsonKey.BATCH_ID, courseBatch); + Response response = courseBatchDao.update(courseBatch); Assert.assertNotEquals(null, response); } @@ -78,7 +81,7 @@ public void readCourseBatchSuccess() { when(cassandraOperation.getRecordById( Mockito.anyString(), Mockito.anyString(), Mockito.anyString())) .thenReturn(response); - CourseBatch courseBatch = courseBatchDao.readById(JsonKey.COURSE_ID, JsonKey.BATCH_ID); + CourseBatch courseBatch = courseBatchDao.readById(JsonKey.BATCH_ID); Assert.assertNotEquals(null, courseBatch); } @@ -90,7 +93,7 @@ public void readCourseBatchFailure() { Mockito.anyString(), Mockito.anyString(), Mockito.anyString())) .thenReturn(response); try { - courseBatchDao.readById(JsonKey.COURSE_ID, JsonKey.BATCH_ID); + courseBatchDao.readById(JsonKey.BATCH_ID); } catch (ProjectCommonException e) { Assert.assertEquals(ResponseCode.invalidCourseBatchId.getErrorCode(), e.getCode()); } diff --git a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/dao/UserCoursesDaoTest.java b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/dao/UserCoursesDaoTest.java index 36a9c4860c..c02a3840d3 100644 --- a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/dao/UserCoursesDaoTest.java +++ b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/dao/UserCoursesDaoTest.java @@ -50,7 +50,7 @@ public void readUserCoursesFailure() { when(cassandraOperation.getRecordById( Mockito.anyString(), Mockito.anyString(), Mockito.anyString())) .thenReturn(readResponse); - UserCourses response = userCoursesDao.read(JsonKey.BATCH_ID, JsonKey.USER_ID); + UserCourses response = userCoursesDao.read(JsonKey.ID); Assert.assertEquals(null, response); } @@ -61,7 +61,7 @@ public void readUserCoursesSuccess() { when(cassandraOperation.getRecordById( Mockito.anyString(), Mockito.anyString(), Mockito.anyString())) .thenReturn(readResponse); - UserCourses response = userCoursesDao.read(JsonKey.BATCH_ID, JsonKey.USER_ID); + UserCourses response = userCoursesDao.read(JsonKey.ID); Assert.assertNotEquals(null, response); } @@ -73,7 +73,7 @@ public void readUserCoursesExcpetionFailure() { when(cassandraOperation.getRecordById( Mockito.anyString(), Mockito.anyString(), Mockito.anyString())) .thenReturn(readResponse); - UserCourses response = userCoursesDao.read(JsonKey.BATCH_ID, JsonKey.USER_ID); + UserCourses response = userCoursesDao.read(JsonKey.ID); Assert.assertEquals(null, response); } @@ -93,7 +93,7 @@ public void updateUserCoursesSuccess() { when(cassandraOperation.updateRecord( Mockito.anyString(), Mockito.anyString(), Mockito.anyMap())) .thenReturn(new Response()); - Response response = userCoursesDao.update(JsonKey.BATCH_ID, JsonKey.USER_ID, userCourseMap); + Response response = userCoursesDao.update(userCourseMap); Assert.assertNotEquals(null, response); } @@ -110,7 +110,7 @@ public void batchInsertUserCoursesSuccess() { @Test public void getAllActiveUserWithoutParticipantsSuccess() { - when(cassandraOperation.getRecords( + when(cassandraOperation.getRecordsByProperties( Mockito.anyString(), Mockito.anyString(), Mockito.anyMap(), Mockito.anyList())) .thenReturn(new Response()); List participants = userCoursesDao.getAllActiveUserOfBatch(JsonKey.BATCH_ID); @@ -125,7 +125,7 @@ public void getAllActiveUserSuccess() { userCoursesMap.put(JsonKey.ACTIVE, true); readResponse.put(JsonKey.RESPONSE, Arrays.asList(userCoursesMap)); - when(cassandraOperation.getRecords( + when(cassandraOperation.getRecordsByProperties( Mockito.anyString(), Mockito.anyString(), Mockito.anyMap(), Mockito.anyList())) .thenReturn(readResponse); List participants = userCoursesDao.getAllActiveUserOfBatch(JsonKey.BATCH_ID); @@ -136,49 +136,4 @@ public void getAllActiveUserSuccess() { public void getInstanceTest() { Assert.assertNotEquals(null, UserCoursesDaoImpl.getInstance()); } - - @Test - public void getBatchParticipantsSuccess() { - Response readResponse = new Response(); - Map userCoursesMap = new HashMap<>(); - userCoursesMap.put(JsonKey.USER_ID, JsonKey.USER_ID); - userCoursesMap.put(JsonKey.ACTIVE, true); - - readResponse.put(JsonKey.RESPONSE, Arrays.asList(userCoursesMap)); - when(cassandraOperation.getRecords( - Mockito.anyString(), Mockito.anyString(), Mockito.anyMap(), Mockito.anyList())) - .thenReturn(readResponse); - List participants = userCoursesDao.getBatchParticipants(JsonKey.BATCH_ID, true); - Assert.assertEquals(1, participants.size()); - } - - @Test - public void getBatchParticipantsWithInactiveSuccess() { - Response readResponse = new Response(); - Map userCoursesMap = new HashMap<>(); - userCoursesMap.put(JsonKey.USER_ID, JsonKey.USER_ID); - userCoursesMap.put(JsonKey.ACTIVE, false); - - readResponse.put(JsonKey.RESPONSE, Arrays.asList(userCoursesMap)); - when(cassandraOperation.getRecords( - Mockito.anyString(), Mockito.anyString(), Mockito.anyMap(), Mockito.anyList())) - .thenReturn(readResponse); - List participants = userCoursesDao.getBatchParticipants(JsonKey.BATCH_ID, false); - Assert.assertEquals(1, participants.size()); - } - - @Test - public void getBatchParticipantsWithEmptySuccess() { - Response readResponse = new Response(); - Map userCoursesMap = new HashMap<>(); - userCoursesMap.put(JsonKey.USER_ID, JsonKey.USER_ID); - userCoursesMap.put(JsonKey.ACTIVE, false); - - readResponse.put(JsonKey.RESPONSE, Arrays.asList(userCoursesMap)); - when(cassandraOperation.getRecords( - Mockito.anyString(), Mockito.anyString(), Mockito.anyMap(), Mockito.anyList())) - .thenReturn(readResponse); - List participants = userCoursesDao.getBatchParticipants(JsonKey.BATCH_ID, true); - Assert.assertEquals(0, participants.size()); - } } diff --git a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/service/UserCourseServiceTest.java b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/service/UserCourseServiceTest.java index 0d3b74b6a5..bdb516a7ae 100644 --- a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/service/UserCourseServiceTest.java +++ b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursebatch/service/UserCourseServiceTest.java @@ -93,7 +93,7 @@ public void validateUserUnenrollAlreadyCompletedTest() { try { UserCourses userCourses = new UserCourses(); userCourses.setActive(true); - // userCourses.setLeafNodesCount(1); + userCourses.setLeafNodesCount(1); userCourses.setProgress(1); UserCoursesService.validateUserUnenroll(userCourses); } catch (ProjectCommonException e) { diff --git a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursemanagement/CourseBatchNotificationActorFailureTest.java b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursemanagement/CourseBatchNotificationActorFailureTest.java index 3185a67da7..2ac9f1f06c 100644 --- a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursemanagement/CourseBatchNotificationActorFailureTest.java +++ b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursemanagement/CourseBatchNotificationActorFailureTest.java @@ -83,7 +83,6 @@ public void beforeEachTest() { } @Test // Needs to test run - @Ignore public void testCourseBatchEnrollForLearnerFailure() { mockCassandraRequestForReadRecordById(); mockCassandraRequestForReadTemplate(); @@ -93,7 +92,6 @@ public void testCourseBatchEnrollForLearnerFailure() { } @Test - @Ignore public void testCourseBatchEnrollForMentorFailure() { mockCassandraRequestForReadRecordById(); mockCassandraRequestForReadTemplate(); @@ -189,7 +187,13 @@ private CourseBatch createCourseBatchObject() { mentors.add(USER_ID); participants.add(USER_ID); courseBatch.setMentors(mentors); + courseBatch.setCountDecrementStatus(false); + courseBatch.setCountIncrementStatus(false); + courseBatch.setParticipant(participants); courseBatch.setStatus(0); + Map courseAdditionalInfo = new HashMap<>(); + courseAdditionalInfo.put(JsonKey.ORG_NAME, orgName); + courseBatch.setCourseAdditionalInfo(courseAdditionalInfo); return courseBatch; } @@ -211,7 +215,13 @@ private CourseBatch createCourseBatchObject(boolean testType, String type) { } } courseBatch.setStatus(0); + courseBatch.setCountDecrementStatus(false); + courseBatch.setCountIncrementStatus(false); courseBatch.setMentors(mentors); + courseBatch.setParticipant(participants); + Map courseAdditionalInfo = new HashMap<>(); + courseAdditionalInfo.put(JsonKey.ORG_NAME, orgName); + courseBatch.setCourseAdditionalInfo(courseAdditionalInfo); return courseBatch; } diff --git a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursemanagement/CourseBatchNotificationActorSucessTest.java b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursemanagement/CourseBatchNotificationActorSucessTest.java index f69cb81df0..9a40f12b76 100644 --- a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursemanagement/CourseBatchNotificationActorSucessTest.java +++ b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/learner/actors/coursemanagement/CourseBatchNotificationActorSucessTest.java @@ -83,7 +83,6 @@ public void beforeEachTest() { } @Test - @Ignore public void testCourseBatchUpdateSucess() { mockCassandraRequestForReadRecordById(); mockCassandraRequestForReadTemplate(); @@ -93,7 +92,6 @@ public void testCourseBatchUpdateSucess() { } @Test - @Ignore public void testCourseBatchEnrollForLearnerSucess() { mockCassandraRequestForReadRecordById(); mockCassandraRequestForReadTemplate(); @@ -220,9 +218,13 @@ private CourseBatch createCourseBatchObject() { mentors.add(USER_ID); participants.add(USER_ID); courseBatch.setMentors(mentors); + courseBatch.setCountDecrementStatus(false); + courseBatch.setCountIncrementStatus(false); + courseBatch.setParticipant(participants); courseBatch.setStatus(0); Map courseAdditionalInfo = new HashMap<>(); courseAdditionalInfo.put(JsonKey.ORG_NAME, orgName); + courseBatch.setCourseAdditionalInfo(courseAdditionalInfo); return courseBatch; } @@ -244,9 +246,13 @@ private CourseBatch createCourseBatchObject(boolean testType, String type) { } } courseBatch.setStatus(0); + courseBatch.setCountDecrementStatus(false); + courseBatch.setCountIncrementStatus(false); courseBatch.setMentors(mentors); + courseBatch.setParticipant(participants); Map courseAdditionalInfo = new HashMap<>(); courseAdditionalInfo.put(JsonKey.ORG_NAME, orgName); + courseBatch.setCourseAdditionalInfo(courseAdditionalInfo); return courseBatch; } diff --git a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/metrics/actors/CourseMetricsActorTest.java b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/metrics/actors/CourseMetricsActorTest.java index d445320399..2228a85715 100644 --- a/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/metrics/actors/CourseMetricsActorTest.java +++ b/actors/sunbird-lms-mw/actors/common/src/test/java/org/sunbird/metrics/actors/CourseMetricsActorTest.java @@ -479,6 +479,9 @@ public Map getBatchData() { Map batchData = new HashMap<>(); batchData.put(JsonKey.START_DATE, "startDate"); batchData.put(JsonKey.END_DATE, "endDate"); + Map additionalInfo = new HashMap<>(); + additionalInfo.put(JsonKey.LEAF_NODE_COUNT, progress + ""); + batchData.put(JsonKey.COURSE_ADDITIONAL_INFO, additionalInfo); batchData.put(JsonKey.COMPLETED_COUNT, 1); return batchData; } diff --git a/actors/sunbird-lms-mw/service/src/main/java/org/sunbird/middleware/Application.java b/actors/sunbird-lms-mw/service/src/main/java/org/sunbird/middleware/Application.java index 6336e79b6b..19ddbbf013 100644 --- a/actors/sunbird-lms-mw/service/src/main/java/org/sunbird/middleware/Application.java +++ b/actors/sunbird-lms-mw/service/src/main/java/org/sunbird/middleware/Application.java @@ -16,7 +16,6 @@ public static void main(String[] args) { public static void checkCassandraConnection() { Util.checkCassandraDbConnections(JsonKey.SUNBIRD); Util.checkCassandraDbConnections(JsonKey.SUNBIRD_PLUGIN); - Util.checkCassandraDbConnections(Util.COURSE_KEY_SPACE_NAME); SchedulerManager.schedule(); // scheduler should start after few minutes so internally it is sleeping for 4 minute , so // putting in seperate thread . diff --git a/service/app/controllers/LearnerController.java b/service/app/controllers/LearnerController.java index 80d1b33e7b..2518731833 100644 --- a/service/app/controllers/LearnerController.java +++ b/service/app/controllers/LearnerController.java @@ -22,68 +22,68 @@ */ public class LearnerController extends BaseController { - private LearnerStateRequestValidator validator = new LearnerStateRequestValidator(); + private LearnerStateRequestValidator validator = new LearnerStateRequestValidator(); - /** - * This method will provide list of user content state. Content refer user activity {started,half - * completed ,completed} against TOC (table of content). - * - * @return Result - */ - public Promise getContentState() { - try { - JsonNode requestJson = request().body().asJson(); - Request request = createAndInitRequest(ActorOperations.GET_CONTENT.getValue(), requestJson); - validator.validateGetContentState(request); - request = transformUserId(request); - return actorResponseHandler(getActorRef(), request, timeout, JsonKey.CONTENT_LIST, request()); - } catch (Exception e) { - return Promise.pure(createCommonExceptionResponse(e, request())); - } + /** + * This method will provide list of user content state. Content refer user activity {started,half + * completed ,completed} against TOC (table of content). + * + * @return Result + */ + public Promise getContentState() { + try { + JsonNode requestJson = request().body().asJson(); + Request request = createAndInitRequest(ActorOperations.GET_CONTENT.getValue(), requestJson); + validator.validateGetContentState(request); + request = transformUserId(request); + return actorResponseHandler(getActorRef(), request, timeout, JsonKey.CONTENT_LIST, request()); + } catch (Exception e) { + return Promise.pure(createCommonExceptionResponse(e, request())); } + } - /** - * This method will update learner current state with last store state. - * - * @return Result - */ - public Promise updateContentState() { - try { - JsonNode requestData = request().body().asJson(); - ProjectLogger.log(" updateContentState request data=" + requestData, LoggerEnum.INFO.name()); - Request reqObj = (Request) mapper.RequestMapper.mapRequest(requestData, Request.class); - RequestValidator.validateUpdateContent(reqObj); - reqObj = transformUserId(reqObj); - reqObj.setOperation(ActorOperations.ADD_CONTENT.getValue()); - reqObj.setRequestId(ExecutionContext.getRequestId()); - reqObj.setEnv(getEnvironment()); - HashMap innerMap = new HashMap<>(); - innerMap.put(JsonKey.CONTENTS, reqObj.getRequest().get(JsonKey.CONTENTS)); - innerMap.put(JsonKey.REQUESTED_BY, ctx().flash().get(JsonKey.USER_ID)); - innerMap.put(JsonKey.USER_ID, reqObj.getRequest().get(JsonKey.USER_ID)); - reqObj.setRequest(innerMap); - return actorResponseHandler(getActorRef(), reqObj, timeout, null, request()); - } catch (Exception e) { - return Promise.pure(createCommonExceptionResponse(e, request())); - } + /** + * This method will update learner current state with last store state. + * + * @return Result + */ + public Promise updateContentState() { + try { + JsonNode requestData = request().body().asJson(); + ProjectLogger.log(" get content request data=" + requestData, LoggerEnum.INFO.name()); + Request reqObj = (Request) mapper.RequestMapper.mapRequest(requestData, Request.class); + RequestValidator.validateUpdateContent(reqObj); + reqObj = transformUserId(reqObj); + reqObj.setOperation(ActorOperations.ADD_CONTENT.getValue()); + reqObj.setRequestId(ExecutionContext.getRequestId()); + reqObj.setEnv(getEnvironment()); + HashMap innerMap = new HashMap<>(); + innerMap.put(JsonKey.CONTENTS, reqObj.getRequest().get(JsonKey.CONTENTS)); + innerMap.put(JsonKey.REQUESTED_BY, ctx().flash().get(JsonKey.USER_ID)); + innerMap.put(JsonKey.USER_ID, reqObj.getRequest().get(JsonKey.USER_ID)); + reqObj.setRequest(innerMap); + return actorResponseHandler(getActorRef(), reqObj, timeout, null, request()); + } catch (Exception e) { + return Promise.pure(createCommonExceptionResponse(e, request())); } + } - public Result getHealth() { - return Results.ok("ok"); - } + public Result getHealth() { + return Results.ok("ok"); + } - /** - * @param all - * @return - */ - public Result preflight(String all) { - response().setHeader("Access-Control-Allow-Origin", "*"); - response().setHeader("Allow", "*"); - response().setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS"); - response() - .setHeader( - "Access-Control-Allow-Headers", - "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent,X-Consumer-ID,cid,ts,X-Device-ID,X-Authenticated-Userid,X-msgid,id,X-Access-TokenId"); - return ok(); - } + /** + * @param all + * @return + */ + public Result preflight(String all) { + response().setHeader("Access-Control-Allow-Origin", "*"); + response().setHeader("Allow", "*"); + response().setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS"); + response() + .setHeader( + "Access-Control-Allow-Headers", + "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent,X-Consumer-ID,cid,ts,X-Device-ID,X-Authenticated-Userid,X-msgid,id,X-Access-TokenId"); + return ok(); + } } diff --git a/service/app/controllers/bulkapimanagement/BulkUploadController.java b/service/app/controllers/bulkapimanagement/BulkUploadController.java index 21729a609b..e3f7e1d9c9 100644 --- a/service/app/controllers/bulkapimanagement/BulkUploadController.java +++ b/service/app/controllers/bulkapimanagement/BulkUploadController.java @@ -1,6 +1,9 @@ package controllers.bulkapimanagement; +import java.util.Map; import org.sunbird.common.models.util.ActorOperations; +import org.sunbird.common.models.util.BulkUploadActorOperation; +import org.sunbird.common.models.util.GeoLocationJsonKey; import org.sunbird.common.models.util.JsonKey; import org.sunbird.common.request.BaseRequestValidator; import org.sunbird.common.request.Request; @@ -11,22 +14,46 @@ public class BulkUploadController extends BaseBulkUploadController { BaseRequestValidator baseRequestValidator = new BaseRequestValidator(); - public Promise batchEnrollmentBulkUpload() { + public Promise userBulkUpload() { + try { + Request request = + createAndInitBulkRequest( + BulkUploadActorOperation.USER_BULK_UPLOAD.getValue(), JsonKey.USER, true); + return actorResponseHandler(getActorRef(), request, timeout, null, request()); + } catch (Exception e) { + return Promise.pure(createCommonExceptionResponse(e, request())); + } + } + + public Promise orgBulkUpload() { try { Request request = createAndInitBulkRequest( - ActorOperations.BULK_UPLOAD.getValue(), JsonKey.BATCH_LEARNER_ENROL, false); + BulkUploadActorOperation.ORG_BULK_UPLOAD.getValue(), JsonKey.ORGANISATION, true); + return actorResponseHandler(getActorRef(), request, timeout, null, request()); + } catch (Exception e) { + return Promise.pure(createCommonExceptionResponse(e, request())); + } + } + + public Promise batchEnrollmentBulkUpload() { + try { + Request request = + createAndInitBulkRequest(ActorOperations.BULK_UPLOAD.getValue(), JsonKey.BATCH, false); return actorResponseHandler(getActorRef(), request, timeout, null, request()); } catch (Exception e) { return Promise.pure(createCommonExceptionResponse(e, request())); } } - public Promise batchUnEnrollmentBulkUpload() { + public Promise locationBulkUpload() { try { Request request = createAndInitBulkRequest( - ActorOperations.BULK_UPLOAD.getValue(), JsonKey.BATCH_LEARNER_UNENROL, false); + BulkUploadActorOperation.LOCATION_BULK_UPLOAD.getValue(), JsonKey.LOCATION, true); + baseRequestValidator.checkMandatoryFieldsPresent( + (Map) request.getRequest().get(JsonKey.DATA), + GeoLocationJsonKey.LOCATION_TYPE); return actorResponseHandler(getActorRef(), request, timeout, null, request()); } catch (Exception e) { return Promise.pure(createCommonExceptionResponse(e, request())); diff --git a/service/app/controllers/coursemanagement/CourseBatchController.java b/service/app/controllers/coursemanagement/CourseBatchController.java index 85c343b023..1e5be48ef8 100644 --- a/service/app/controllers/coursemanagement/CourseBatchController.java +++ b/service/app/controllers/coursemanagement/CourseBatchController.java @@ -57,18 +57,6 @@ public Promise addUserToCourseBatch(String batchId) { JsonKey.BATCH_ID); } - public Promise removeUserFromCourseBatch(String batchId) { - return handleRequest( - ActorOperations.REMOVE_USER_FROM_BATCH.getValue(), - request().body().asJson(), - (request) -> { - new CourseBatchRequestValidator().validateAddUserToCourseBatchRequest((Request) request); - return null; - }, - batchId, - JsonKey.BATCH_ID); - } - public Promise deleteBatch() { return handleRequest( ActorOperations.REMOVE_BATCH.getValue(), @@ -94,7 +82,7 @@ public Promise search() { String requestedField = request().getQueryString(JsonKey.FIELDS); reqObj.getContext().put(JsonKey.PARTICIPANTS, requestedField); List esObjectType = new ArrayList<>(); - esObjectType.add(EsType.courseBatch.getTypeName()); + esObjectType.add(EsType.course.getTypeName()); if (reqObj.getRequest().containsKey(JsonKey.FILTERS) && reqObj.getRequest().get(JsonKey.FILTERS) != null && reqObj.getRequest().get(JsonKey.FILTERS) instanceof Map) { @@ -110,15 +98,4 @@ public Promise search() { return Promise.pure(createCommonExceptionResponse(e, request())); } } - - public Promise getParticipants() { - return handleRequest( - ActorOperations.GET_PARTICIPANTS.getValue(), - request().body().asJson(), - (request) -> { - new CourseBatchRequestValidator().validateGetParticipantsRequest((Request) request); - return null; - }, - getAllRequestHeaders(request())); - } } diff --git a/service/app/controllers/coursemanagement/validator/CourseBatchRequestValidator.java b/service/app/controllers/coursemanagement/validator/CourseBatchRequestValidator.java index 06ce9717a3..feedb5ae45 100644 --- a/service/app/controllers/coursemanagement/validator/CourseBatchRequestValidator.java +++ b/service/app/controllers/coursemanagement/validator/CourseBatchRequestValidator.java @@ -1,13 +1,9 @@ package controllers.coursemanagement.validator; -import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; -import java.util.Map; - -import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.sunbird.common.exception.ProjectCommonException; import org.sunbird.common.models.util.JsonKey; @@ -42,10 +38,6 @@ public void validateCreateCourseBatchRequest(Request request) { } public void validateUpdateCourseBatchRequest(Request request) { - validateParam( - (String) request.getRequest().get(JsonKey.COURSE_ID), - ResponseCode.mandatoryParamsMissing, - JsonKey.COURSE_ID); if (null != request.getRequest().get(JsonKey.STATUS)) { boolean status = validateBatchStatus(request); if (!status) { @@ -345,17 +337,4 @@ private boolean checkProgressStatus(int status) { } return false; } - - public void validateGetParticipantsRequest(Request request) { - if(MapUtils.isEmpty((Map) request.getRequest().get(JsonKey.BATCH))){ - throw new ProjectCommonException( - ResponseCode.invalidRequestData.getErrorCode(), - MessageFormat.format(ResponseCode.invalidRequestData.getErrorMessage(), JsonKey.BATCH), - ResponseCode.CLIENT_ERROR.getResponseCode()); - } - validateParam( - (String) ((Map)request.getRequest().get(JsonKey.BATCH)).get(JsonKey.BATCH_ID), - ResponseCode.mandatoryParamsMissing, - JsonKey.BATCH_ID); - } } diff --git a/service/app/controllers/search/SearchController.java b/service/app/controllers/search/SearchController.java index 087f63bea0..63c2631a32 100644 --- a/service/app/controllers/search/SearchController.java +++ b/service/app/controllers/search/SearchController.java @@ -21,6 +21,28 @@ */ public class SearchController extends BaseController { + /** + * This method will do data search for user and organization. Search type will be decide based on + * request object type coming with filter if objectType key is not coming then we need to do the + * search for all the types. + * + * @return Promise + */ + public Promise compositeSearch() { + try { + JsonNode requestData = request().body().asJson(); + ProjectLogger.log("getting search request data = " + requestData, LoggerEnum.INFO.name()); + Request reqObj = (Request) mapper.RequestMapper.mapRequest(requestData, Request.class); + reqObj.setOperation(ActorOperations.COMPOSITE_SEARCH.getValue()); + reqObj.setRequestId(ExecutionContext.getRequestId()); + reqObj.getRequest().put(JsonKey.CREATED_BY, ctx().flash().get(JsonKey.USER_ID)); + reqObj.setEnv(getEnvironment()); + return actorResponseHandler(getActorRef(), reqObj, timeout, null, request()); + } catch (Exception e) { + return Promise.pure(createCommonExceptionResponse(e, request())); + } + } + /** * This method will do data Sync form Cassandra db to Elasticsearch. * diff --git a/service/app/util/Global.java b/service/app/util/Global.java index b25bda5c06..125277878e 100644 --- a/service/app/util/Global.java +++ b/service/app/util/Global.java @@ -366,7 +366,6 @@ private static void init() { Util.checkCassandraDbConnections(JsonKey.SUNBIRD); Util.checkCassandraDbConnections(JsonKey.SUNBIRD_PLUGIN); - Util.checkCassandraDbConnections(Util.COURSE_KEY_SPACE_NAME); SchedulerManager.schedule(); // Run quartz scheduler in a separate thread as it waits for 4 minutes diff --git a/service/conf/routes b/service/conf/routes index 63b42cd96d..65b532fb53 100644 --- a/service/conf/routes +++ b/service/conf/routes @@ -17,7 +17,6 @@ GET /v1/user/courses/list/:uid @controllers.courseenrollment.CourseEnro POST /v1/course/enroll @controllers.courseenrollment.CourseEnrollmentController.enrollCourse() POST /v1/course/unenroll @controllers.courseenrollment.CourseEnrollmentController.unenrollCourse() POST /v1/batch/bulk/enrollment @controllers.bulkapimanagement.BulkUploadController.batchEnrollmentBulkUpload() -POST /v1/batch/bulk/unenrollment @controllers.bulkapimanagement.BulkUploadController.batchUnEnrollmentBulkUpload() POST /v1/content/state/read @controllers.LearnerController.getContentState() PATCH /v1/user/content/state @controllers.LearnerController.updateContentState() PATCH /v1/content/state/update @controllers.LearnerController.updateContentState() @@ -50,8 +49,6 @@ PATCH /v1/course/batch/update @controllers.coursemanagement.CourseBatchCont GET /v1/course/batch/read/:batchId @controllers.coursemanagement.CourseBatchController.getBatch(batchId:String) POST /v1/course/batch/search @controllers.coursemanagement.CourseBatchController.search() POST /v1/course/batch/users/add/:batchId @controllers.coursemanagement.CourseBatchController.addUserToCourseBatch(batchId:String) -POST /v1/course/batch/users/remove/:batchId @controllers.coursemanagement.CourseBatchController.removeUserFromCourseBatch(batchId:String) -POST /v1/batch/participants/list @controllers.coursemanagement.CourseBatchController.getParticipants() # Textbook APIs POST /v1/textbook/toc/upload/:textbookId @controllers.textbook.TextbookController.uploadTOC(textbookId:String) diff --git a/service/pom.xml b/service/pom.xml index 4d025a31d1..2106d8f439 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -47,11 +47,6 @@ mw-service 1.0-SNAPSHOT - - org.sunbird - sunbird-commons - 1.0-SNAPSHOT -