diff --git a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/QuestionSetActorTest.scala b/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/QuestionSetActorTest.scala index 183591d87..6f17d13e6 100644 --- a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/QuestionSetActorTest.scala +++ b/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/QuestionSetActorTest.scala @@ -40,7 +40,7 @@ class QuestionSetActorTest extends BaseSpec with MockFactory { "navigationMode" -> "linear", "allowSkip" -> "Yes", "requiresSubmit" -> "No", - "shuffle" -> "Yes", + "shuffle" -> true.asInstanceOf[AnyRef], "showFeedback" -> "Yes", "showSolutions" -> "Yes", "showHints" -> "Yes", @@ -83,7 +83,7 @@ class QuestionSetActorTest extends BaseSpec with MockFactory { "navigationMode" -> "linear", "allowSkip" -> "Yes", "requiresSubmit" -> "No", - "shuffle" -> "Yes", + "shuffle" -> true.asInstanceOf[AnyRef], "showFeedback" -> "Yes", "showSolutions" -> "Yes", "showHints" -> "Yes", @@ -111,7 +111,7 @@ class QuestionSetActorTest extends BaseSpec with MockFactory { "navigationMode" -> "linear", "allowSkip" -> "Yes", "requiresSubmit" -> "No", - "shuffle" -> "Yes", + "shuffle" -> true.asInstanceOf[AnyRef], "showFeedback" -> "Yes", "showSolutions" -> "Yes", "showHints" -> "Yes", @@ -144,7 +144,7 @@ class QuestionSetActorTest extends BaseSpec with MockFactory { "navigationMode" -> "linear", "allowSkip" -> "Yes", "requiresSubmit" -> "No", - "shuffle" -> "Yes", + "shuffle" -> true.asInstanceOf[AnyRef], "showFeedback" -> "Yes", "showSolutions" -> "Yes", "showHints" -> "Yes", @@ -174,7 +174,7 @@ class QuestionSetActorTest extends BaseSpec with MockFactory { "navigationMode" -> "linear", "allowSkip" -> "Yes", "requiresSubmit" -> "No", - "shuffle" -> "Yes", + "shuffle" -> true.asInstanceOf[AnyRef], "showFeedback" -> "Yes", "showSolutions" -> "Yes", "showHints" -> "Yes", @@ -204,7 +204,7 @@ class QuestionSetActorTest extends BaseSpec with MockFactory { "navigationMode" -> "linear", "allowSkip" -> "Yes", "requiresSubmit" -> "No", - "shuffle" -> "Yes", + "shuffle" -> true.asInstanceOf[AnyRef], "showFeedback" -> "Yes", "showSolutions" -> "Yes", "showHints" -> "Yes", @@ -237,7 +237,7 @@ class QuestionSetActorTest extends BaseSpec with MockFactory { "navigationMode" -> "linear", "allowSkip" -> "Yes", "requiresSubmit" -> "No", - "shuffle" -> "Yes", + "shuffle" -> true.asInstanceOf[AnyRef], "showFeedback" -> "Yes", "showSolutions" -> "Yes", "showHints" -> "Yes", @@ -296,7 +296,7 @@ class QuestionSetActorTest extends BaseSpec with MockFactory { "navigationMode" -> "linear", "allowSkip" -> "Yes", "requiresSubmit" -> "No", - "shuffle" -> "Yes", + "shuffle" -> true.asInstanceOf[AnyRef], "showFeedback" -> "Yes", "showSolutions" -> "Yes", "status" -> "Review", @@ -381,7 +381,7 @@ class QuestionSetActorTest extends BaseSpec with MockFactory { } def getCassandraHierarchy(): Response = { - val hierarchyString: String = """{"children":[{"parent":"do_113165166851596288123","totalQuestions":0,"code":"QS_V_Parent_Old","allowSkip":"No","description":"QS-2_parent","language":["English"],"mimeType":"application/vnd.sunbird.questionset","showHints":"No","createdOn":"2020-12-04T15:31:45.948+0530","objectType":"QuestionSet","primaryCategory":"Practice Question Set","lastUpdatedOn":"2020-12-04T15:31:45.947+0530","showSolutions":"No","identifier":"do_11316516745992601613","lastStatusChangedOn":"2020-12-04T15:31:45.948+0530","requiresSubmit":"No","visibility":"Parent","maxQuestions":0,"index":1,"setType":"materialised","languageCode":["en"],"version":1,"versionKey":"1607076105948","showFeedback":"No","depth":1,"name":"QS_V_Parent_2","navigationMode":"non-linear","shuffle":"Yes","status":"Draft"},{"parent":"do_113165166851596288123","totalQuestions":0,"code":"QS_V_Parent_New","allowSkip":"No","description":"QS-1_parent","language":["English"],"mimeType":"application/vnd.sunbird.questionset","showHints":"No","createdOn":"2020-12-04T15:31:45.872+0530","objectType":"QuestionSet","primaryCategory":"Practice Question Set","children":[{"parent":"do_11316516745922969611","identifier":"do_11316399038283776016","lastStatusChangedOn":"2020-12-02T23:36:59.783+0530","code":"question.code","visibility":"Default","index":1,"language":["English"],"mimeType":"application/vnd.sunbird.question","languageCode":["en"],"createdOn":"2020-12-02T23:36:59.783+0530","version":1,"objectType":"Question","versionKey":"1606932419783","depth":2,"primaryCategory":"Practice Question Set","name":"question_1","lastUpdatedOn":"2020-12-02T23:36:59.783+0530","status":"Draft"}],"lastUpdatedOn":"2020-12-04T15:31:45.861+0530","showSolutions":"No","identifier":"do_11316516745922969611","lastStatusChangedOn":"2020-12-04T15:31:45.876+0530","requiresSubmit":"No","visibility":"Parent","maxQuestions":0,"index":2,"setType":"materialised","languageCode":["en"],"version":1,"versionKey":"1607076105872","showFeedback":"No","depth":1,"name":"QS_V_Parent_1","navigationMode":"non-linear","shuffle":"Yes","status":"Draft"},{"identifier":"do_11315445058114355211","parent":"do_113165166851596288123","lastStatusChangedOn":"2020-11-19T12:08:13.854+0530","code":"finemanfine","visibility":"Default","index":4,"language":["English"],"mimeType":"application/vnd.sunbird.question","languageCode":["en"],"createdOn":"2020-11-19T12:08:13.854+0530","version":1,"objectType":"Question","versionKey":"1605767893854","depth":1,"name":"question_1","lastUpdatedOn":"2020-11-19T12:08:13.854+0530","contentType":"Resource","status":"Draft"},{"identifier":"do_11315319237189632011","parent":"do_113165166851596288123","lastStatusChangedOn":"2020-11-17T17:28:23.277+0530","code":"finemanfine","visibility":"Default","index":3,"language":["English"],"mimeType":"application/vnd.sunbird.question","languageCode":["en"],"createdOn":"2020-11-17T17:28:23.277+0530","version":1,"objectType":"Question","versionKey":"1605614303277","depth":1,"name":"question_1","lastUpdatedOn":"2020-11-17T17:28:23.277+0530","contentType":"Resource","status":"Draft"}],"identifier":"do_113165166851596288123"}""" + val hierarchyString: String = """{"children":[{"parent":"do_113165166851596288123","totalQuestions":0,"code":"QS_V_Parent_Old","allowSkip":"No","description":"QS-2_parent","language":["English"],"mimeType":"application/vnd.sunbird.questionset","showHints":"No","createdOn":"2020-12-04T15:31:45.948+0530","objectType":"QuestionSet","primaryCategory":"Practice Question Set","lastUpdatedOn":"2020-12-04T15:31:45.947+0530","showSolutions":"No","identifier":"do_11316516745992601613","lastStatusChangedOn":"2020-12-04T15:31:45.948+0530","requiresSubmit":"No","visibility":"Parent","maxQuestions":0,"index":1,"setType":"materialised","languageCode":["en"],"version":1,"versionKey":"1607076105948","showFeedback":"No","depth":1,"name":"QS_V_Parent_2","navigationMode":"non-linear","shuffle":true,"status":"Draft"},{"parent":"do_113165166851596288123","totalQuestions":0,"code":"QS_V_Parent_New","allowSkip":"No","description":"QS-1_parent","language":["English"],"mimeType":"application/vnd.sunbird.questionset","showHints":"No","createdOn":"2020-12-04T15:31:45.872+0530","objectType":"QuestionSet","primaryCategory":"Practice Question Set","children":[{"parent":"do_11316516745922969611","identifier":"do_11316399038283776016","lastStatusChangedOn":"2020-12-02T23:36:59.783+0530","code":"question.code","visibility":"Default","index":1,"language":["English"],"mimeType":"application/vnd.sunbird.question","languageCode":["en"],"createdOn":"2020-12-02T23:36:59.783+0530","version":1,"objectType":"Question","versionKey":"1606932419783","depth":2,"primaryCategory":"Practice Question Set","name":"question_1","lastUpdatedOn":"2020-12-02T23:36:59.783+0530","status":"Draft"}],"lastUpdatedOn":"2020-12-04T15:31:45.861+0530","showSolutions":"No","identifier":"do_11316516745922969611","lastStatusChangedOn":"2020-12-04T15:31:45.876+0530","requiresSubmit":"No","visibility":"Parent","maxQuestions":0,"index":2,"setType":"materialised","languageCode":["en"],"version":1,"versionKey":"1607076105872","showFeedback":"No","depth":1,"name":"QS_V_Parent_1","navigationMode":"non-linear","shuffle":true,"status":"Draft"},{"identifier":"do_11315445058114355211","parent":"do_113165166851596288123","lastStatusChangedOn":"2020-11-19T12:08:13.854+0530","code":"finemanfine","visibility":"Default","index":4,"language":["English"],"mimeType":"application/vnd.sunbird.question","languageCode":["en"],"createdOn":"2020-11-19T12:08:13.854+0530","version":1,"objectType":"Question","versionKey":"1605767893854","depth":1,"name":"question_1","lastUpdatedOn":"2020-11-19T12:08:13.854+0530","contentType":"Resource","status":"Draft"},{"identifier":"do_11315319237189632011","parent":"do_113165166851596288123","lastStatusChangedOn":"2020-11-17T17:28:23.277+0530","code":"finemanfine","visibility":"Default","index":3,"language":["English"],"mimeType":"application/vnd.sunbird.question","languageCode":["en"],"createdOn":"2020-11-17T17:28:23.277+0530","version":1,"objectType":"Question","versionKey":"1605614303277","depth":1,"name":"question_1","lastUpdatedOn":"2020-11-17T17:28:23.277+0530","contentType":"Resource","status":"Draft"}],"identifier":"do_113165166851596288123"}""" val response = new Response response.put("hierarchy", hierarchyString) } @@ -443,7 +443,7 @@ class QuestionSetActorTest extends BaseSpec with MockFactory { "navigationMode" -> "linear", "allowSkip" -> "Yes", "requiresSubmit" -> "No", - "shuffle" -> "Yes", + "shuffle" -> true.asInstanceOf[AnyRef], "showFeedback" -> "Yes", "showSolutions" -> "Yes", "showHints" -> "Yes", diff --git a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/HierarchyManager.scala b/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/HierarchyManager.scala index 0632ec58d..6b3c8f8aa 100644 --- a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/HierarchyManager.scala +++ b/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/HierarchyManager.scala @@ -38,7 +38,7 @@ object HierarchyManager { else java.util.Arrays.asList("collections","children","usedByContent","item_sets","methods","libraries","editorState") } - + @throws[Exception] def addLeafNodesToHierarchy(request:Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { validateRequest(request) @@ -216,7 +216,8 @@ object HierarchyManager { @throws[Exception] def getPublishedHierarchy(request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Response] = { - val redisHierarchy = RedisCache.get(hierarchyPrefix + request.get("rootId")) + val redisHierarchy = if(Platform.getBoolean("questionset.cache.enable", false)) RedisCache.get(hierarchyPrefix + request.get("rootId")) else "" + val hierarchyFuture = if (StringUtils.isNotEmpty(redisHierarchy)) { Future(mapAsJavaMap(Map("questionSet" -> JsonUtils.deserialize(redisHierarchy, classOf[java.util.Map[String, AnyRef]])))) } else getCassandraHierarchy(request) @@ -428,8 +429,9 @@ object HierarchyManager { hierarchy.map(hierarchy => { if (!hierarchy.isEmpty) { if (StringUtils.isNotEmpty(hierarchy.getOrDefault("status", "").asInstanceOf[String]) && statusList.contains(hierarchy.getOrDefault("status", "").asInstanceOf[String])) { - rootHierarchy.put("questionSet", hierarchy) - RedisCache.set(hierarchyPrefix + request.get("rootId"), JsonUtils.serialize(hierarchy)) + val hierarchyMap = mapAsJavaMap(hierarchy) + rootHierarchy.put("questionSet", hierarchyMap) + RedisCache.set(hierarchyPrefix + request.get("rootId"), JsonUtils.serialize(hierarchyMap)) Future(rootHierarchy) } else { Future(new util.HashMap[String, AnyRef]()) diff --git a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala b/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala index cc4d9cd8f..8965a697d 100644 --- a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala +++ b/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala @@ -226,6 +226,7 @@ object UpdateHierarchyManager { private def createNewNode(nodeId: String, idMap: mutable.Map[String, String], metadata: java.util.HashMap[String, AnyRef], nodeList: List[Node], request: Request, setDefaultValue: Boolean = true)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[List[Node]] = { val objectType = metadata.getOrDefault("objectType", "").asInstanceOf[String] + metadata.remove("objectType") val identifier: String = Identifier.getIdentifier(HierarchyConstants.TAXONOMY_ID, Identifier.getUniqueIdFromTimestamp) idMap += (nodeId -> identifier) metadata.put(HierarchyConstants.IDENTIFIER, identifier) @@ -269,6 +270,7 @@ object UpdateHierarchyManager { if (neo4jCreateTypes.contains(objectType)) { createRequest.getContext.put(HierarchyConstants.IDENTIFIER, tempNode.getIdentifier) createRequest.getContext.put(HierarchyConstants.SCHEMA_NAME, "question") + createRequest.getContext.put(HierarchyConstants.OBJECT_TYPE, objectType) DataNode.update(createRequest).map(node => { idMap += (nodeId -> node.getIdentifier) updateNodeList(nodeList, node.getIdentifier, node.getMetadata) @@ -400,7 +402,8 @@ object UpdateHierarchyManager { } else { getQuestionNode(id, HierarchyConstants.TAXONOMY_ID).map(node => { populateHierarchyRelatedData(node, depth, index, parent) - node.getMetadata.put(HierarchyConstants.VISIBILITY, HierarchyConstants.DEFAULT) + //node.getMetadata.put(HierarchyConstants.VISIBILITY, HierarchyConstants.DEFAULT) + node.setObjectType(HierarchyConstants.QUESTION_OBJECT_TYPE) node.getMetadata.put(HierarchyConstants.OBJECT_TYPE, HierarchyConstants.QUESTION_OBJECT_TYPE) val nxtEnrichedNodeList = node :: enrichedNodeList if (MapUtils.isNotEmpty(hierarchyStructure.getOrDefault(id, Map[String, Int]()))) { diff --git a/build/assessment-service/Jenkinsfile b/build/assessment-service/Jenkinsfile index 481ee54ff..ebc9f1a63 100644 --- a/build/assessment-service/Jenkinsfile +++ b/build/assessment-service/Jenkinsfile @@ -15,19 +15,11 @@ node('build-slave') { } else println(ANSI_BOLD + ANSI_GREEN + "Found environment variable named hub_org with value as: " + hub_org + ANSI_NORMAL) } + cleanWs() - if (params.github_release_tag == "") { - checkout scm - commit_hash = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() - branch_name = sh(script: 'git name-rev --name-only HEAD | rev | cut -d "/" -f1| rev', returnStdout: true).trim() - build_tag = branch_name + "_" + commit_hash + "_" + env.BUILD_NUMBER - println(ANSI_BOLD + ANSI_YELLOW + "github_release_tag not specified, using the latest commit hash: " + commit_hash + ANSI_NORMAL) - } else { - def scmVars = checkout scm - checkout scm: [$class: 'GitSCM', branches: [[name: "refs/tags/$params.github_release_tag"]], userRemoteConfigs: [[url: scmVars.GIT_URL]]] - build_tag = params.github_release_tag + "_" + env.BUILD_NUMBER - println(ANSI_BOLD + ANSI_YELLOW + "github_release_tag specified, building from tag: " + params.github_release_tag + ANSI_NORMAL) - } + checkout scm + commit_hash = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() + build_tag = sh(script: "echo " + params.github_release_tag.split('/')[-1] + "_" + commit_hash + "_" + env.BUILD_NUMBER, returnStdout: true).trim() echo "build_tag: " + build_tag stage('Build') { diff --git a/build/content-service/Jenkinsfile b/build/content-service/Jenkinsfile index b65c06658..6909c139c 100644 --- a/build/content-service/Jenkinsfile +++ b/build/content-service/Jenkinsfile @@ -15,7 +15,7 @@ node('build-slave') { } else println(ANSI_BOLD + ANSI_GREEN + "Found environment variable named hub_org with value as: " + hub_org + ANSI_NORMAL) } - + cleanWs() checkout scm commit_hash = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() diff --git a/build/search-service/Jenkinsfile b/build/search-service/Jenkinsfile index 0e360103b..a565e7da3 100644 --- a/build/search-service/Jenkinsfile +++ b/build/search-service/Jenkinsfile @@ -15,19 +15,11 @@ node('build-slave') { } else println(ANSI_BOLD + ANSI_GREEN + "Found environment variable named hub_org with value as: " + hub_org + ANSI_NORMAL) } + cleanWs() - if (params.github_release_tag == "") { - checkout scm - commit_hash = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() - branch_name = sh(script: 'git name-rev --name-only HEAD | rev | cut -d "/" -f1| rev', returnStdout: true).trim() - build_tag = branch_name + "_" + commit_hash + "_" + env.BUILD_NUMBER - println(ANSI_BOLD + ANSI_YELLOW + "github_release_tag not specified, using the latest commit hash: " + commit_hash + ANSI_NORMAL) - } else { - def scmVars = checkout scm - checkout scm: [$class: 'GitSCM', branches: [[name: "refs/tags/$params.github_release_tag"]], userRemoteConfigs: [[url: scmVars.GIT_URL]]] - build_tag = params.github_release_tag + "_" + env.BUILD_NUMBER - println(ANSI_BOLD + ANSI_YELLOW + "github_release_tag specified, building from tag: " + params.github_release_tag + ANSI_NORMAL) - } + checkout scm + commit_hash = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() + build_tag = sh(script: "echo " + params.github_release_tag.split('/')[-1] + "_" + commit_hash + "_" + env.BUILD_NUMBER, returnStdout: true).trim() echo "build_tag: " + build_tag stage('Build') { diff --git a/build/taxonomy-service/Jenkinsfile b/build/taxonomy-service/Jenkinsfile index 06d92da1c..453a603f6 100644 --- a/build/taxonomy-service/Jenkinsfile +++ b/build/taxonomy-service/Jenkinsfile @@ -15,19 +15,11 @@ node('build-slave') { } else println(ANSI_BOLD + ANSI_GREEN + "Found environment variable named hub_org with value as: " + hub_org + ANSI_NORMAL) } + cleanWs() - if (params.github_release_tag == "") { - checkout scm - commit_hash = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() - branch_name = sh(script: 'git name-rev --name-only HEAD | rev | cut -d "/" -f1| rev', returnStdout: true).trim() - build_tag = branch_name + "_" + commit_hash + "_" + env.BUILD_NUMBER - println(ANSI_BOLD + ANSI_YELLOW + "github_release_tag not specified, using the latest commit hash: " + commit_hash + ANSI_NORMAL) - } else { - def scmVars = checkout scm - checkout scm: [$class: 'GitSCM', branches: [[name: "refs/tags/$params.github_release_tag"]], userRemoteConfigs: [[url: scmVars.GIT_URL]]] - build_tag = params.github_release_tag + "_" + env.BUILD_NUMBER - println(ANSI_BOLD + ANSI_YELLOW + "github_release_tag specified, building from tag: " + params.github_release_tag + ANSI_NORMAL) - } + checkout scm + commit_hash = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() + build_tag = sh(script: "echo " + params.github_release_tag.split('/')[-1] + "_" + commit_hash + "_" + env.BUILD_NUMBER, returnStdout: true).trim() echo "build_tag: " + build_tag stage('Build') { diff --git a/content-api/content-actors/src/main/scala/org/sunbird/channel/managers/ChannelManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/channel/managers/ChannelManager.scala index 4ffde63cf..41ebb50a0 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/channel/managers/ChannelManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/channel/managers/ChannelManager.scala @@ -2,14 +2,14 @@ package org.sunbird.channel.managers import java.util import java.util.Optional - import org.sunbird.common.dto.{Request, Response} -import org.sunbird.util.ChannelConstants +import org.sunbird.util.{ChannelConstants, HttpUtil} import org.sunbird.cache.impl.RedisCache import org.sunbird.common.exception.{ClientException, ServerException} import org.sunbird.common.Platform import com.mashape.unirest.http.HttpResponse import com.mashape.unirest.http.Unirest +import org.apache.commons.collections4.CollectionUtils import org.sunbird.common.JsonUtils import scala.collection.JavaConverters._ @@ -18,13 +18,13 @@ import scala.collection.mutable.ListBuffer object ChannelManager { - val CONTENT_PRIMARY_CATERGORIES: util.List[String] = Platform.getStringList("channel.content.primarycategories", new util.ArrayList[String]()) - val COLLECTION_PRIMARY_CATERGORIES: util.List[String] = Platform.getStringList("channel.collection.primarycategories", new util.ArrayList[String]()) - val ASSET_PRIMARY_CATERGORIES: util.List[String] = Platform.getStringList("channel.asset.primarycategories", new util.ArrayList[String]()) - val CONTENT_ADDITIONAL_CATERGORIES: util.List[String] = Platform.getStringList("channel.content.additionalcategories", new util.ArrayList[String]()) - val COLLECTION_ADDITIONAL_CATERGORIES: util.List[String] = Platform.getStringList("channel.collection.additionalcategories", new util.ArrayList[String]()) - val ASSET_ADDITIONAL_CATERGORIES: util.List[String] = Platform.getStringList("channel.asset.additionalcategories", new util.ArrayList[String]()) - + val CONTENT_PRIMARY_CATEGORIES: util.List[String] = Platform.getStringList("channel.content.primarycategories", new util.ArrayList[String]()) + val COLLECTION_PRIMARY_CATEGORIES: util.List[String] = Platform.getStringList("channel.collection.primarycategories", new util.ArrayList[String]()) + val ASSET_PRIMARY_CATEGORIES: util.List[String] = Platform.getStringList("channel.asset.primarycategories", new util.ArrayList[String]()) + val CONTENT_ADDITIONAL_CATEGORIES: util.List[String] = Platform.getStringList("channel.content.additionalcategories", new util.ArrayList[String]()) + val COLLECTION_ADDITIONAL_CATEGORIES: util.List[String] = Platform.getStringList("channel.collection.additionalcategories", new util.ArrayList[String]()) + val ASSET_ADDITIONAL_CATEGORIES: util.List[String] = Platform.getStringList("channel.asset.additionalcategories", new util.ArrayList[String]()) + implicit val httpUtil: HttpUtil = new HttpUtil def channelLicenseCache(request: Request, identifier: String): Unit = { if (request.getRequest.containsKey(ChannelConstants.DEFAULT_LICENSE)) @@ -32,7 +32,7 @@ object ChannelManager { } def getAllFrameworkList(): util.List[util.Map[String, AnyRef]] = { - val url: String = if (Platform.config.hasPath("composite.search.url")) Platform.config.getString("composite.search.url") else "https://dev.sunbirded.org/action/composite/v3/search" + val url: String = Platform.getString("composite.search.url", "https://dev.sunbirded.org/action/composite/v3/search") val httpResponse: HttpResponse[String] = Unirest.post(url).header("Content-Type", "application/json").body("""{"request":{"filters":{"objectType":"Framework","status":"Live"},"fields":["name","code","objectType","identifier"]}}""").asString if (200 != httpResponse.getStatus) throw new ServerException("ERR_FETCHING_FRAMEWORK", "Error while fetching framework.") @@ -44,7 +44,7 @@ object ChannelManager { val translations: util.Map[String, AnyRef] = Optional.ofNullable(request.get("translations").asInstanceOf[util.HashMap[String, AnyRef]]).orElse(new util.HashMap[String, AnyRef]()) if (translations.isEmpty) request.getRequest.remove("translations") else { - val languageCodes = if(Platform.config.hasPath("platform.language.codes")) Platform.config.getStringList("platform.language.codes") else new util.ArrayList[String]() + val languageCodes = Platform.getStringList("platform.language.codes", new util.ArrayList[String]()) if (translations.asScala.exists(entry => !languageCodes.contains(entry._1))) throw new ClientException("ERR_INVALID_LANGUAGE_CODE", "Please Provide Valid Language Code For translations. Valid Language Codes are : " + languageCodes) } @@ -89,27 +89,57 @@ object ChannelManager { } } -// def setPrimaryAndAdditionCategories(metadata: util.Map[String, AnyRef]): Unit = { -// val masterCategories = seqAsJavaList(getMasterCategoryList()) -// metadata.putIfAbsent(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, masterCategories) -// metadata.putIfAbsent(ChannelConstants.COLLECTION_PRIMARY_CATEGORIES, masterCategories) -// metadata.putIfAbsent(ChannelConstants.ASSET_PRIMARY_CATEGORIES, masterCategories) -// metadata.putIfAbsent(ChannelConstants.CONTENT_ADDITIONAL_CATEGORIES, masterCategories) -// metadata.putIfAbsent(ChannelConstants.COLLECTION_ADDITIONAL_CATEGORIES, masterCategories) -// metadata.putIfAbsent(ChannelConstants.ASSET_ADDITIONAL_CATEGORIES, masterCategories) -// } - def setPrimaryAndAdditionCategories(metadata: util.Map[String, AnyRef]): Unit = { - metadata.putIfAbsent(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, CONTENT_PRIMARY_CATERGORIES) - metadata.putIfAbsent(ChannelConstants.COLLECTION_PRIMARY_CATEGORIES, COLLECTION_PRIMARY_CATERGORIES) - metadata.putIfAbsent(ChannelConstants.ASSET_PRIMARY_CATEGORIES, ASSET_PRIMARY_CATERGORIES) - metadata.putIfAbsent(ChannelConstants.CONTENT_ADDITIONAL_CATEGORIES, CONTENT_ADDITIONAL_CATERGORIES) - metadata.putIfAbsent(ChannelConstants.COLLECTION_ADDITIONAL_CATEGORIES, COLLECTION_ADDITIONAL_CATERGORIES) - metadata.putIfAbsent(ChannelConstants.ASSET_ADDITIONAL_CATEGORIES, ASSET_ADDITIONAL_CATERGORIES) + metadata.putIfAbsent(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, CONTENT_PRIMARY_CATEGORIES) + metadata.putIfAbsent(ChannelConstants.COLLECTION_PRIMARY_CATEGORIES, COLLECTION_PRIMARY_CATEGORIES) + metadata.putIfAbsent(ChannelConstants.ASSET_PRIMARY_CATEGORIES, ASSET_PRIMARY_CATEGORIES) + metadata.putIfAbsent(ChannelConstants.CONTENT_ADDITIONAL_CATEGORIES, CONTENT_ADDITIONAL_CATEGORIES) + metadata.putIfAbsent(ChannelConstants.COLLECTION_ADDITIONAL_CATEGORIES, COLLECTION_ADDITIONAL_CATEGORIES) + metadata.putIfAbsent(ChannelConstants.ASSET_ADDITIONAL_CATEGORIES, ASSET_ADDITIONAL_CATEGORIES) + val primaryCategories = getChannelPrimaryCategories(metadata.get("identifier").asInstanceOf[String]) + metadata.put("primaryCategories", primaryCategories) + val additionalCategories = getAdditionalCategories() + metadata.put("additionalCategories", additionalCategories) + } + + def getAdditionalCategories()(implicit httpUtil: HttpUtil): java.util.List[String] = { + val body = """{"request":{"filters":{"objectType":"ObjectCategory"},"fields":["name","identifier"]}}""" + val url: String = Platform.getString("composite.search.url", "https://dev.sunbirded.org/action/composite/v3/search") + val httpResponse = httpUtil.post(url, body) + if (200 != httpResponse.status) throw new ServerException("ERR_FETCHING_OBJECT_CATEGORY", "Error while fetching object categories for additional category list.") + val response: Response = JsonUtils.deserialize(httpResponse.body, classOf[Response]) + val objectCategoryList: util.List[util.Map[String, AnyRef]] = response.getResult.getOrDefault(ChannelConstants.OBJECT_CATEGORY, new util.ArrayList[util.Map[String, AnyRef]]).asInstanceOf[util.ArrayList[util.Map[String, AnyRef]]] + objectCategoryList.asScala.map(cat => cat.get("name").asInstanceOf[String]).asJava + + } + + def getChannelPrimaryCategories(channel: String)(implicit httpUtil: HttpUtil): java.util.List[java.util.Map[String, AnyRef]] = { + val globalPCRequest = s"""{"request":{"filters":{"objectType":"ObjectCategoryDefinition"},"not_exists": "channel","fields":["name","identifier","targetObjectType"]}}""" + val globalPrimaryCategories = getPrimaryCategories(globalPCRequest) + val channelPCRequest = s"""{"request":{"filters":{"objectType":"ObjectCategoryDefinition", "channel": "$channel"},"fields":["name","identifier","targetObjectType"]}}""" + val channelPrimaryCategories = getPrimaryCategories(channelPCRequest) + if (CollectionUtils.isEmpty(channelPrimaryCategories)) + globalPrimaryCategories + else { + val idsToIgnore = channelPrimaryCategories.map(cat => cat.get("identifier").asInstanceOf[String]) + .map(id => id.replace("_"+channel, "_all")) + globalPrimaryCategories.filter(cat => { + !idsToIgnore.contains(cat.get("identifier").asInstanceOf[String]) + }) ++ channelPrimaryCategories + } + } + + private def getPrimaryCategories(body: String)(implicit httpUtil: HttpUtil): java.util.List[java.util.Map[String, AnyRef]] = { + val url: String = Platform.getString("composite.search.url", "https://dev.sunbirded.org/action/composite/v3/search") + val httpResponse = httpUtil.post(url, body) + if (200 != httpResponse.status) throw new ServerException("ERR_FETCHING_OBJECT_CATEGORY_DEFINITION", "Error while fetching primary categories.") + val response: Response = JsonUtils.deserialize(httpResponse.body, classOf[Response]) + val objectCategoryList: util.List[util.Map[String, AnyRef]] = response.getResult.getOrDefault(ChannelConstants.objectCategoryDefinitionKey, new util.ArrayList[util.Map[String, AnyRef]]).asInstanceOf[util.ArrayList[util.Map[String, AnyRef]]] + objectCategoryList.asScala.map(cat => (cat - "objectType").asJava).asJava } def getMasterCategoryList(): List[String] = { - val url: String = if (Platform.config.hasPath("composite.search.url")) Platform.config.getString("composite.search.url") else "https://dev.sunbirded.org/action/composite/v3/search" + val url: String = Platform.getString("composite.search.url", "https://dev.sunbirded.org/action/composite/v3/search") val httpResponse: HttpResponse[String] = Unirest.post(url).header("Content-Type", "application/json").body("""{"request":{"filters":{"objectType":"ObjectCategory"},"fields":["name"]}}""").asString if (200 != httpResponse.getStatus) throw new ServerException("ERR_FETCHING_OBJECT_CATEGORY", "Error while fetching object category.") diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/DiscardManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/DiscardManager.scala index e18c34531..12f924a1f 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/DiscardManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/DiscardManager.scala @@ -60,7 +60,7 @@ object DiscardManager { private def discardForCollection(node: Node, request: Request)(implicit executionContext: ExecutionContext, oec: OntologyEngineContext): Future[java.lang.Boolean] = { request.put(ContentConstants.IDENTIFIERS, if (node.getMetadata.containsKey(ContentConstants.PACKAGE_VERSION)) List(node.getIdentifier) else List(node.getIdentifier, node.getIdentifier + ContentConstants.IMAGE_SUFFIX)) request.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) - ExternalPropsManager.deleteProps(request).map(resp => DataNode.deleteNode(request)).flatMap(f => f) + oec.graphService.deleteExternalProps(request).map(resp => DataNode.deleteNode(request)).flatMap(f => f) } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/FlagManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/FlagManager.scala index 2eb08fc48..c42d4e48d 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/FlagManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/FlagManager.scala @@ -79,8 +79,8 @@ object FlagManager { }).flatMap(f => f) recoverWith { case e: CompletionException => throw e.getCause } } - private def fetchHierarchy(request: Request)(implicit ec: ExecutionContext): Future[Any] = { - ExternalPropsManager.fetchProps(request, List(HierarchyConstants.HIERARCHY)).map(resp => { + private def fetchHierarchy(request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Any] = { + oec.graphService.readExternalProps(request, List(HierarchyConstants.HIERARCHY)).map(resp => { resp.getResult.toMap.getOrElse(HierarchyConstants.HIERARCHY, "").asInstanceOf[String] }) recover { case e: ResourceNotFoundException => TelemetryManager.log("No hierarchy is present in cassandra for identifier:" + request.get(HierarchyConstants.IDENTIFIER)) } } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/RetireManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/RetireManager.scala index c2eb1c8c8..cbd8e4eba 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/RetireManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/RetireManager.scala @@ -69,7 +69,7 @@ object RetireManager { val req = new Request(request) req.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) req.put(ContentConstants.IDENTIFIER, request.get(ContentConstants.IDENTIFIER)) - ExternalPropsManager.fetchProps(req, List(HierarchyConstants.HIERARCHY)).flatMap(resp => { + oec.graphService.readExternalProps(req, List(HierarchyConstants.HIERARCHY)).flatMap(resp => { val hierarchyString = resp.getResult.toMap.getOrElse(HierarchyConstants.HIERARCHY, "").asInstanceOf[String] if (StringUtils.isNotBlank(hierarchyString)) { val hierarchyMap = JsonUtils.deserialize(hierarchyString, classOf[util.HashMap[String, AnyRef]]) @@ -81,7 +81,7 @@ object RetireManager { } hierarchyMap.putAll(updateMetadataMap) req.put(HierarchyConstants.HIERARCHY, ScalaJsonUtils.serialize(hierarchyMap)) - ExternalPropsManager.saveProps(req) + oec.graphService.saveExternalProps(req) } else Future(ResponseHandler.OK()) }) recover { case e: ResourceNotFoundException => TelemetryManager.log("No hierarchy is present in cassandra for identifier:" + node.getIdentifier) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/util/ChannelConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/util/ChannelConstants.scala index cc04f9c61..e49708593 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/util/ChannelConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/util/ChannelConstants.scala @@ -12,6 +12,7 @@ object ChannelConstants { val CONTENT: String = "content" val NAME: String = "name" val OBJECT_CATEGORY: String = "ObjectCategory" + val objectCategoryDefinitionKey = "ObjectCategoryDefinition" val ERR_VALIDATING_PRIMARY_CATEGORY: String = "ERR_VALIDATING_PRIMARY_CATEGORY" val CONTENT_ADDITIONAL_CATEGORIES: String = "contentAdditionalCategories" val COLLECTION_ADDITIONAL_CATEGORIES: String = "collectionAdditionalCategories" diff --git a/content-api/content-actors/src/main/scala/org/sunbird/util/HttpUtil.scala b/content-api/content-actors/src/main/scala/org/sunbird/util/HttpUtil.scala new file mode 100644 index 000000000..9284421ae --- /dev/null +++ b/content-api/content-actors/src/main/scala/org/sunbird/util/HttpUtil.scala @@ -0,0 +1,35 @@ +package org.sunbird.util + +import com.mashape.unirest.http.Unirest +import scala.collection.JavaConverters._ + +/** + * + * We need to move this class to platform-core. + */ + +case class HTTPResponse(status: Int, body: String) extends Serializable + +class HttpUtil extends Serializable { + + def get(url: String, headers: Map[String, String] = Map[String, String]("Content-Type"->"application/json")): HTTPResponse = { + val response = Unirest.get(url).headers(headers.asJava).asString() + HTTPResponse(response.getStatus, response.getBody) + } + + def post(url: String, requestBody: String, headers: Map[String, String] = Map[String, String]("Content-Type"->"application/json")): HTTPResponse = { + val response = Unirest.post(url).headers(headers.asJava).body(requestBody).asString() + HTTPResponse(response.getStatus, response.getBody) + } + + def put(url: String, requestBody: String, headers: Map[String, String] = Map[String, String]("Content-Type"->"application/json")): HTTPResponse = { + val response = Unirest.put(url).headers(headers.asJava).body(requestBody).asString() + HTTPResponse(response.getStatus, response.getBody) + } + + def patch(url: String, requestBody: String, headers: Map[String, String] = Map[String, String]("Content-Type"->"application/json")): HTTPResponse = { + val response = Unirest.patch(url).headers(headers.asJava).body(requestBody).asString() + HTTPResponse(response.getStatus, response.getBody) + } + +} \ No newline at end of file diff --git a/content-api/content-actors/src/test/scala/org/sunbird/channel/TestChannelManager.scala b/content-api/content-actors/src/test/scala/org/sunbird/channel/TestChannelManager.scala index 53b189651..4d58324f9 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/channel/TestChannelManager.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/channel/TestChannelManager.scala @@ -2,115 +2,131 @@ package org.sunbird.channel import org.scalatest.{AsyncFlatSpec, Matchers} import org.sunbird.common.dto.Request -import java.util +import java.util import org.apache.commons.collections.CollectionUtils import org.scalamock.scalatest.MockFactory import org.sunbird.cache.impl.RedisCache +import org.sunbird.util.{ChannelConstants, HTTPResponse, HttpUtil} import org.sunbird.channel.managers.ChannelManager -import org.sunbird.common.exception.ClientException -import org.sunbird.util.ChannelConstants -import org.sunbird.channel.managers.ChannelManager -import org.sunbird.common.exception.{ClientException, ResourceNotFoundException, ResponseCode} -import org.sunbird.graph.{GraphService, OntologyEngineContext} +import org.sunbird.common.exception.{ClientException} class TestChannelManager extends AsyncFlatSpec with Matchers with MockFactory { - "get All framework list" should "return a list of frameworks from search service" in { - val frameworkList = ChannelManager.getAllFrameworkList() - assert(CollectionUtils.isNotEmpty(frameworkList)) - } - - "validate translation map" should "throw exception if map contains invalid language translation" in { - val exception = intercept[ClientException] { - val request = new Request() - request.setRequest(new util.HashMap[String, AnyRef]() { - { - put("translations", new util.HashMap[String, AnyRef]() { - { - put("tyy", "dsk") - } - }) - } - }) - ChannelManager.validateTranslationMap(request) - } - exception.getMessage shouldEqual "Please Provide Valid Language Code For translations. Valid Language Codes are : [as, bn, en, gu, hi, hoc, jun, ka, mai, mr, unx, or, san, sat, ta, te, urd, pj]" - } - - def getRequest(): Request = { - val request = new Request() - request - } - - "store license in cache" should "store license in cache" in { - val request = new Request() - request.getRequest.put("defaultLicense","license1234") - ChannelManager.channelLicenseCache(request, "channel_test") - assert(null != RedisCache.get("channel_channel_test_license")) - } - - it should "return success for valid objectCategory" in { - val request = new Request() - request.setRequest(new util.HashMap[String, AnyRef]() {{ - put(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("Learning Resource")}}) - put(ChannelConstants.COLLECTION_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("Learning Resource")}}) - put(ChannelConstants.ASSET_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("Learning Resource")}}) - }}) - ChannelManager.validateObjectCategory(request) - assert(true) - } - - it should "throw exception for invalid objectCategory" in { - val exception = intercept[ClientException] { - val request = new Request() - request.setRequest(new util.HashMap[String, AnyRef]() {{ - put(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("xyz")}}) - put(ChannelConstants.COLLECTION_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("xyz")}}) - put(ChannelConstants.ASSET_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("xyz")}}) - }}) - ChannelManager.validateObjectCategory(request) - } - exception.getMessage shouldEqual "Please provide valid : [contentPrimaryCategories,collectionPrimaryCategories,assetPrimaryCategories]" - } - - it should "throw exception for empty objectCategory" in { - val exception = intercept[ClientException] { - val request = new Request() - request.setRequest(new util.HashMap[String, AnyRef]() {{ - put(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, new util.ArrayList[String]()) - }}) - ChannelManager.validateObjectCategory(request) - } - exception.getMessage shouldEqual "Empty list not allowed for contentPrimaryCategories" - } - - it should "throw exception for invalid dataType for objectCategory" in { - val exception = intercept[ClientException] { - val request = new Request() - request.setRequest(new util.HashMap[String, AnyRef]() {{ - put(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, "test-string") - }}) - ChannelManager.validateObjectCategory(request) - } - exception.getMessage shouldEqual "Please provide valid list for contentPrimaryCategories" - } - - it should "add objectCategory into channel read response" in { - val metaDataMap: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef]() - ChannelManager.setPrimaryAndAdditionCategories(metaDataMap) - assert(metaDataMap.containsKey(ChannelConstants.CONTENT_PRIMARY_CATEGORIES)) - assert(CollectionUtils.isNotEmpty(metaDataMap.get(ChannelConstants.CONTENT_PRIMARY_CATEGORIES).asInstanceOf[util.List[String]])) - } - - it should "not change objectCategory into channel read response" in { - val metaDataMap: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ - put(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("Learning Resource")}}) - }} - ChannelManager.setPrimaryAndAdditionCategories(metaDataMap) - assert(metaDataMap.containsKey(ChannelConstants.CONTENT_PRIMARY_CATEGORIES)) - assert(CollectionUtils.isEqualCollection(metaDataMap.get(ChannelConstants.CONTENT_PRIMARY_CATEGORIES).asInstanceOf[util.List[String]], - new util.ArrayList[String]() {{add("Learning Resource")}})) - } + implicit val httpUtil: HttpUtil = mock[HttpUtil] + + "ChannelManager" should "return a list of frameworks from search service" in { + val frameworkList = ChannelManager.getAllFrameworkList() + assert(CollectionUtils.isNotEmpty(frameworkList)) + } + + it should "throw exception if map contains invalid language translation" in { + val exception = intercept[ClientException] { + val request = new Request() + request.setRequest(new util.HashMap[String, AnyRef]() { + { + put("translations", new util.HashMap[String, AnyRef]() { + { + put("tyy", "dsk") + } + }) + } + }) + ChannelManager.validateTranslationMap(request) + } + exception.getMessage shouldEqual "Please Provide Valid Language Code For translations. Valid Language Codes are : [as, bn, en, gu, hi, hoc, jun, ka, mai, mr, unx, or, san, sat, ta, te, urd, pj]" + } + + def getRequest(): Request = { + val request = new Request() + request + } + + it should "store license in cache" in { + val request = new Request() + request.getRequest.put("defaultLicense","license1234") + ChannelManager.channelLicenseCache(request, "channel_test") + assert(null != RedisCache.get("channel_channel_test_license")) + } + + it should "return success for valid objectCategory" in { + val request = new Request() + request.setRequest(new util.HashMap[String, AnyRef]() {{ + put(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("Learning Resource")}}) + put(ChannelConstants.COLLECTION_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("Learning Resource")}}) + put(ChannelConstants.ASSET_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("Learning Resource")}}) + }}) + ChannelManager.validateObjectCategory(request) + assert(true) + } + + it should "throw exception for invalid objectCategory" in { + val exception = intercept[ClientException] { + val request = new Request() + request.setRequest(new util.HashMap[String, AnyRef]() {{ + put(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("xyz")}}) + put(ChannelConstants.COLLECTION_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("xyz")}}) + put(ChannelConstants.ASSET_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("xyz")}}) + }}) + ChannelManager.validateObjectCategory(request) + } + exception.getMessage shouldEqual "Please provide valid : [contentPrimaryCategories,collectionPrimaryCategories,assetPrimaryCategories]" + } + + it should "throw exception for empty objectCategory" in { + val exception = intercept[ClientException] { + val request = new Request() + request.setRequest(new util.HashMap[String, AnyRef]() {{ + put(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, new util.ArrayList[String]()) + }}) + ChannelManager.validateObjectCategory(request) + } + exception.getMessage shouldEqual "Empty list not allowed for contentPrimaryCategories" + } + + it should "throw exception for invalid dataType for objectCategory" in { + val exception = intercept[ClientException] { + val request = new Request() + request.setRequest(new util.HashMap[String, AnyRef]() {{ + put(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, "test-string") + }}) + ChannelManager.validateObjectCategory(request) + } + exception.getMessage shouldEqual "Please provide valid list for contentPrimaryCategories" + } + + it should "add objectCategory into channel read response" in { + val metaDataMap: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef]() + ChannelManager.setPrimaryAndAdditionCategories(metaDataMap) + assert(metaDataMap.containsKey(ChannelConstants.CONTENT_PRIMARY_CATEGORIES)) + assert(CollectionUtils.isNotEmpty(metaDataMap.get(ChannelConstants.CONTENT_PRIMARY_CATEGORIES).asInstanceOf[util.List[String]])) + } + + it should "not change objectCategory into channel read response" in { + val metaDataMap: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ + put(ChannelConstants.CONTENT_PRIMARY_CATEGORIES, new util.ArrayList[String]() {{add("Learning Resource")}}) + }} + ChannelManager.setPrimaryAndAdditionCategories(metaDataMap) + assert(metaDataMap.containsKey(ChannelConstants.CONTENT_PRIMARY_CATEGORIES)) + assert(CollectionUtils.isEqualCollection(metaDataMap.get(ChannelConstants.CONTENT_PRIMARY_CATEGORIES).asInstanceOf[util.List[String]], + new util.ArrayList[String]() {{add("Learning Resource")}})) + } + + it should "return primary categories of a channel" in { + (httpUtil.post _).expects(*, """{"request":{"filters":{"objectType":"ObjectCategoryDefinition"},"not_exists":"channel","fields":["name","identifier","targetObjectType"]}}""", *) + .returning(HTTPResponse(200, """{"id":"api.v1.search","ver":"1.0","ts":"2021-02-15T05:25:54.939Z","params":{"resmsgid":"46b5e4b0-6f4e-11eb-90b0-bb9ae961ede2","msgid":"46b4d340-6f4e-11eb-90b0-bb9ae961ede2","status":"successful","err":null,"errmsg":null},"responseCode":"OK","result":{"count":24,"ObjectCategoryDefinition":[{"identifier":"obj-cat:asset_asset_all","name":"Asset","targetObjectType":"Asset","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:certasset_asset_all","name":"CertAsset","targetObjectType":"Asset","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:certificate-template_asset_all","name":"Certificate Template","targetObjectType":"Asset","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:content-playlist_content_all","name":"Content Playlist","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:content-playlist_collection_all","name":"Content Playlist","targetObjectType":"Collection","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:course_content_all","name":"Course","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:course_collection_all","name":"Course","targetObjectType":"Collection","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:course-assessment_content_all","name":"Course Assessment","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:course-unit_content_all","name":"Course Unit","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:course-unit_collection_all","name":"Course Unit","targetObjectType":"Collection","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:digital-textbook_content_all","name":"Digital Textbook","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:digital-textbook_collection_all","name":"Digital Textbook","targetObjectType":"Collection","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:etextbook_content_all","name":"eTextbook","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:explanation-content_content_all","name":"Explanation Content","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:explanation-content_collection_all","name":"Explanation Content","targetObjectType":"Collection","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:learning-resource_content_all","name":"Learning Resource","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:lesson-plan-unit_content_all","name":"Lesson Plan Unit","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:lesson-plan-unit_collection_all","name":"Lesson Plan Unit","targetObjectType":"Collection","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:plugin_content_all","name":"Plugin","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:practice-question-set_content_all","name":"Practice Question Set","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:teacher-resource_content_all","name":"Teacher Resource","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:template_content_all","name":"Template","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:textbook-unit_collection_all","name":"Textbook Unit","targetObjectType":"Collection","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:textbook-unit_content_all","name":"Textbook Unit","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"}]}}""")) + (httpUtil.post _).expects(*, """{"request":{"filters":{"objectType":"ObjectCategoryDefinition", "channel": "01309282781705830427"},"fields":["name","identifier","targetObjectType"]}}""", *) + .returning(HTTPResponse(200, """{"id":"api.v1.search","ver":"1.0","ts":"2021-02-15T05:31:41.939Z","params":{"resmsgid":"1589e430-6f4f-11eb-a956-2bb50a66d58f","msgid":"1588abb0-6f4f-11eb-a956-2bb50a66d58f","status":"successful","err":null,"errmsg":null},"responseCode":"OK","result":{"count":3,"ObjectCategoryDefinition":[{"identifier":"obj-cat:course_collection_01309282781705830427","name":"Course","targetObjectType":"Collection","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:exam-question_content_01309282781705830427","name":"Exam Question","targetObjectType":"Content","objectType":"ObjectCategoryDefinition"},{"identifier":"obj-cat:question-paper_collection_01309282781705830427","name":"Question Paper","targetObjectType":"Collection","objectType":"ObjectCategoryDefinition"}]}}""")) + + val primaryCategories = ChannelManager.getChannelPrimaryCategories("01309282781705830427") + assert(primaryCategories.size() > 0) + } + + it should "return additional categories" in { + (httpUtil.post _).expects(*, """{"request":{"filters":{"objectType":"ObjectCategory"},"fields":["name","identifier"]}}""", *) + .returning(HTTPResponse(200, """{"id":"api.v1.search","ver":"1.0","ts":"2021-02-15T08:06:20.058Z","params":{"resmsgid":"afba7fa0-6f64-11eb-a956-2bb50a66d58f","msgid":"afb8aae0-6f64-11eb-a956-2bb50a66d58f","status":"successful","err":null,"errmsg":null},"responseCode":"OK","result":{"ObjectCategory":[{"identifier":"obj-cat:asset","name":"Asset","objectType":"ObjectCategory"},{"identifier":"obj-cat:certificate-template","name":"Certificate Template","objectType":"ObjectCategory"},{"identifier":"obj-cat:classroom-teaching-video","name":"Classroom Teaching Video","objectType":"ObjectCategory"},{"identifier":"obj-cat:content-playlist","name":"Content Playlist","objectType":"ObjectCategory"},{"identifier":"obj-cat:course","name":"Course","objectType":"ObjectCategory"},{"identifier":"obj-cat:course-assessment","name":"Course Assessment","objectType":"ObjectCategory"}],"count":6}}""")) + val additionalCategories = ChannelManager.getAdditionalCategories() + assert(additionalCategories.size() > 0) + } } diff --git a/content-api/content-service/app/controllers/BaseController.scala b/content-api/content-service/app/controllers/BaseController.scala index 49ea240b5..4374015b5 100644 --- a/content-api/content-service/app/controllers/BaseController.scala +++ b/content-api/content-service/app/controllers/BaseController.scala @@ -159,14 +159,31 @@ abstract class BaseController(protected val cc: ControllerComponents)(implicit e case (x: String, y: String) => (x, y) case ("Resource", y) => (contentType, getCategoryForResource(input.getOrDefault("mimeType", "").asInstanceOf[String], input.getOrDefault("resourceType", "").asInstanceOf[String])) - case (x: String, y) => (x, categoryMap.get(x).asInstanceOf[String]) - case (x, y: String) => (categoryMap.asScala.filter(entry => StringUtils.equalsIgnoreCase(entry._2.asInstanceOf[String], y)).keys.headOption.getOrElse(""), y) + case (x: String, y) => (x, getPrimeryCategory(x)) + case (x, y: String) => (getContentType(y), y) case _ => (contentType, primaryCategory) } - input.put("contentType", updatedContentType) + input.put("contentType", if (StringUtils.isBlank(updatedContentType)) "Resource" else updatedContentType) input.put("primaryCategory", updatedPrimaryCategory) } + private def getPrimeryCategory(contentType: String): String ={ + val primaryCategory = categoryMap.get(contentType) + if(primaryCategory.isInstanceOf[String]) + primaryCategory.asInstanceOf[String] + else + primaryCategory.asInstanceOf[util.List[String]].asScala.headOption.getOrElse("Learning Resource") + + } + + private def getContentType(primaryCategory: String): String ={ + categoryMap.asScala.filter(entry => (entry._2 match{ + case xs: util.List[_] => xs.asInstanceOf[util.List[String]].contains(primaryCategory) + case _ => StringUtils.equalsIgnoreCase(entry._2.asInstanceOf[String], primaryCategory) + + })).keys.headOption.getOrElse("Resource") + } + private def getCategoryForResource(mimeType: String, resourceType: String): String = (mimeType, resourceType) match { case ("", "") => "Learning Resource" case (x: String, "") => categoryMapForMimeType.get(x).asInstanceOf[util.List[String]].asScala.headOption.getOrElse("Learning Resource") diff --git a/content-api/content-service/conf/application.conf b/content-api/content-service/conf/application.conf index a4898e344..a9583f0d1 100644 --- a/content-api/content-service/conf/application.conf +++ b/content-api/content-service/conf/application.conf @@ -593,7 +593,7 @@ content.import.topic_name="local.auto.creation.job.request" contentTypeToPrimaryCategory { ClassroomTeachingVideo: "Explanation Content" ConceptMap: "Learning Resource" - Course: "Course" + Course: ["Course", "Curriculum Course", "Professional Development Course"] CuriosityQuestionSet: "Practice Question Set" eTextBook: "eTextbook" ExperientialResource: "Learning Resource" diff --git a/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/HierarchyManager.scala b/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/HierarchyManager.scala index aedcaf68f..97f64dbed 100644 --- a/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/HierarchyManager.scala +++ b/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/HierarchyManager.scala @@ -181,7 +181,7 @@ object HierarchyManager { } @throws[Exception] - def getPublishedHierarchy(request: Request)(implicit ec: ExecutionContext): Future[Response] = { + def getPublishedHierarchy(request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Response] = { val redisHierarchy = RedisCache.get(hierarchyPrefix + request.get("rootId")) val hierarchyFuture = if (StringUtils.isNotEmpty(redisHierarchy)) { Future(mapAsJavaMap(Map("content" -> JsonUtils.deserialize(redisHierarchy, classOf[java.util.Map[String, AnyRef]])))) @@ -322,7 +322,7 @@ object HierarchyManager { val req = new Request(request) req.put("hierarchy", ScalaJsonUtils.serialize(updatedHierarchy)) req.put("identifier", rootNode.getIdentifier) - ExternalPropsManager.saveProps(req) + oec.graphService.saveExternalProps(req) } def restructureUnit(childList: java.util.List[java.util.Map[String, AnyRef]], leafNodes: java.util.List[java.util.Map[String, AnyRef]], leafNodeIds: java.util.List[String], depth: Integer, parent: String): java.util.List[java.util.Map[String, AnyRef]] = { @@ -357,10 +357,10 @@ object HierarchyManager { filteredLeafNodes } - def fetchHierarchy(request: Request, identifier: String)(implicit ec: ExecutionContext): Future[Map[String, AnyRef]] = { + def fetchHierarchy(request: Request, identifier: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Map[String, AnyRef]] = { val req = new Request(request) req.put("identifier", identifier) - val responseFuture = ExternalPropsManager.fetchProps(req, List("hierarchy")) + val responseFuture = oec.graphService.readExternalProps(req, List("hierarchy")) responseFuture.map(response => { if (!ResponseHandler.checkError(response)) { val hierarchyString = response.getResult.toMap.getOrDefault("hierarchy", "").asInstanceOf[String] @@ -370,7 +370,7 @@ object HierarchyManager { Future(Map[String, AnyRef]()) } else if (ResponseHandler.checkError(response) && response.getResponseCode.code() == 404 && Platform.config.hasPath("collection.image.migration.enabled") && Platform.config.getBoolean("collection.image.migration.enabled")) { req.put("identifier", identifier.replaceAll(".img", "") + ".img") - val responseFuture = ExternalPropsManager.fetchProps(req, List("hierarchy")) + val responseFuture = oec.graphService.readExternalProps(req, List("hierarchy")) responseFuture.map(response => { if (!ResponseHandler.checkError(response)) { val hierarchyString = response.getResult.toMap.getOrDefault("hierarchy", "").asInstanceOf[String] @@ -390,7 +390,7 @@ object HierarchyManager { }).flatMap(f => f) recoverWith { case e: CompletionException => throw e.getCause } } - def getCassandraHierarchy(request: Request)(implicit ec: ExecutionContext): Future[util.Map[String, AnyRef]] = { + def getCassandraHierarchy(request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[util.Map[String, AnyRef]] = { val rootHierarchy: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef]() val hierarchy = fetchHierarchy(request, request.getRequest.get("rootId").asInstanceOf[String]) hierarchy.map(hierarchy => { @@ -493,7 +493,7 @@ object HierarchyManager { } } - def getUnpublishedBookmarkHierarchy(request: Request, identifier: String)(implicit ec: ExecutionContext): Future[util.Map[String, AnyRef]] = { + def getUnpublishedBookmarkHierarchy(request: Request, identifier: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[util.Map[String, AnyRef]] = { if (StringUtils.isNotEmpty(identifier)) { val parentHierarchy = fetchHierarchy(request, identifier + imgSuffix) parentHierarchy.map(hierarchy => { diff --git a/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala b/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala index 8fcd6d896..0dc9e2308 100644 --- a/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala +++ b/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala @@ -113,7 +113,7 @@ object UpdateHierarchyManager { }) } - private def getExistingHierarchy(request: Request, rootNode: Node)(implicit ec: ExecutionContext): Future[java.util.HashMap[String, AnyRef]] = { + private def getExistingHierarchy(request: Request, rootNode: Node)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[java.util.HashMap[String, AnyRef]] = { fetchHierarchy(request, rootNode).map(hierarchyString => { if (!hierarchyString.asInstanceOf[String].isEmpty) { JsonUtils.deserialize(hierarchyString.asInstanceOf[String], classOf[java.util.HashMap[String, AnyRef]]) @@ -121,10 +121,10 @@ object UpdateHierarchyManager { }) } - private def fetchHierarchy(request: Request, rootNode: Node)(implicit ec: ExecutionContext): Future[Any] = { + private def fetchHierarchy(request: Request, rootNode: Node)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Any] = { val req = new Request(request) req.put(HierarchyConstants.IDENTIFIER, rootNode.getIdentifier) - ExternalPropsManager.fetchProps(req, List(HierarchyConstants.HIERARCHY)).map(response => { + oec.graphService.readExternalProps(req, List(HierarchyConstants.HIERARCHY)).map(response => { if (ResponseHandler.checkError(response) && ResponseHandler.isResponseNotFoundError(response)) { if (CollectionUtils.containsAny(HierarchyConstants.HIERARCHY_LIVE_STATUS, rootNode.getMetadata.get("status").asInstanceOf[String])) throw new ServerException(HierarchyErrorCodes.ERR_HIERARCHY_NOT_FOUND, "No hierarchy is present in cassandra for identifier:" + rootNode.getIdentifier) @@ -136,7 +136,7 @@ object UpdateHierarchyManager { request.getContext.put("shouldImageDelete", shouldImageBeDeleted(rootNode).asInstanceOf[AnyRef]) req.put(HierarchyConstants.IDENTIFIER, if (!rootNode.getIdentifier.endsWith(HierarchyConstants.IMAGE_SUFFIX)) rootNode.getIdentifier + HierarchyConstants.IMAGE_SUFFIX else rootNode.getIdentifier) } - ExternalPropsManager.fetchProps(req, List(HierarchyConstants.HIERARCHY)).map(resp => { + oec.graphService.readExternalProps(req, List(HierarchyConstants.HIERARCHY)).map(resp => { resp.getResult.toMap.getOrElse(HierarchyConstants.HIERARCHY, "").asInstanceOf[String] }) recover { case e: ResourceNotFoundException => TelemetryManager.log("No hierarchy is present in cassandra for identifier:" + rootNode.getIdentifier) } } @@ -492,11 +492,11 @@ object UpdateHierarchyManager { } - def deleteHierarchy(request: Request)(implicit ec: ExecutionContext): Future[Response] = { + def deleteHierarchy(request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Response] = { val req = new Request(request) val rootId = request.getContext.get(HierarchyConstants.ROOT_ID).asInstanceOf[String] req.put(HierarchyConstants.IDENTIFIERS, if (rootId.contains(HierarchyConstants.IMAGE_SUFFIX)) List(rootId) else List(rootId + HierarchyConstants.IMAGE_SUFFIX)) - ExternalPropsManager.deleteProps(req) + oec.graphService.deleteExternalProps(req) } } diff --git a/ontology-engine/graph-core_2.11/src/main/scala/org/sunbird/graph/GraphService.scala b/ontology-engine/graph-core_2.11/src/main/scala/org/sunbird/graph/GraphService.scala index b2b97f0ba..f7986ffbc 100644 --- a/ontology-engine/graph-core_2.11/src/main/scala/org/sunbird/graph/GraphService.scala +++ b/ontology-engine/graph-core_2.11/src/main/scala/org/sunbird/graph/GraphService.scala @@ -56,6 +56,9 @@ class GraphService { ExternalPropsManager.update(request) } + def deleteExternalProps(request: Request): Future[Response] = { + ExternalPropsManager.deleteProps(request) + } def checkCyclicLoop(graphId:String, endNodeId: String, startNodeId: String, relationType: String) = { Neo4JBoltSearchOperations.checkCyclicLoop(graphId, endNodeId, relationType, startNodeId) } @@ -67,6 +70,5 @@ class GraphService { def createRelation(graphId: String, relationMap: util.List[util.Map[String, AnyRef]]) = { GraphAsyncOperations.createRelation(graphId, relationMap) } - } diff --git a/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/external/ExternalPropsManager.scala b/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/external/ExternalPropsManager.scala deleted file mode 100644 index aef8d7cdd..000000000 --- a/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/external/ExternalPropsManager.scala +++ /dev/null @@ -1,57 +0,0 @@ - -package org.sunbird.graph.external - -import java.util - -import org.sunbird.common.dto.{Request, Response} -import org.sunbird.graph.external.store.ExternalStoreFactory -import org.sunbird.schema.SchemaValidatorFactory - -import scala.concurrent.{ExecutionContext, Future} -import scala.collection.JavaConverters._ - -object ExternalPropsManager { - def saveProps(request: Request)(implicit ec: ExecutionContext): Future[Response] = { - val objectType: String = request.getObjectType - val schemaName: String = request.getContext.get("schemaName").asInstanceOf[String] - val version: String = request.getContext.get("version").asInstanceOf[String] - val primaryKey: util.List[String] = SchemaValidatorFactory.getExternalPrimaryKey(schemaName, version) - val store = ExternalStoreFactory.getExternalStore(SchemaValidatorFactory.getExternalStoreName(schemaName, version), primaryKey) - store.insert(request.getRequest, getPropsDataType(schemaName, version)) - } - - def fetchProps(request: Request, fields: List[String])(implicit ec: ExecutionContext): Future[Response] = { - val schemaName: String = request.getContext.get("schemaName").asInstanceOf[String] - val version: String = request.getContext.get("version").asInstanceOf[String] - val primaryKey: util.List[String] = SchemaValidatorFactory.getExternalPrimaryKey(schemaName, version) - val store = ExternalStoreFactory.getExternalStore(SchemaValidatorFactory.getExternalStoreName(schemaName, version), primaryKey) - store.read(request.get("identifier").asInstanceOf[String], fields, getPropsDataType(schemaName, version)) - } - - def deleteProps(request: Request)(implicit ec: ExecutionContext): Future[Response] = { - val schemaName: String = request.getContext.get("schemaName").asInstanceOf[String] - val version: String = request.getContext.get("version").asInstanceOf[String] - val primaryKey: util.List[String] = SchemaValidatorFactory.getExternalPrimaryKey(schemaName, version) - val store = ExternalStoreFactory.getExternalStore(SchemaValidatorFactory.getExternalStoreName(schemaName, version), primaryKey) - store.delete(request.get("identifiers").asInstanceOf[List[String]]) - } - - def update(request: Request)(implicit ec: ExecutionContext): Future[Response] = { - val schemaName: String = request.getContext.get("schemaName").asInstanceOf[String] - val version: String = request.getContext.get("version").asInstanceOf[String] - val primaryKey: util.List[String] = SchemaValidatorFactory.getExternalPrimaryKey(schemaName, version) - val store = ExternalStoreFactory.getExternalStore(SchemaValidatorFactory.getExternalStoreName(schemaName, version), primaryKey) - store.update(request.get("identifier").asInstanceOf[String], request.get("fields").asInstanceOf[List[String]], - request.get("values").asInstanceOf[List[java.util.Map[String, AnyRef]]], getPropsDataType(schemaName, version)) - } - - def getPropsDataType(schemaName: String, version: String) = { - val propTypes: Map[String, String] = SchemaValidatorFactory.getInstance(schemaName, version).getConfig.getAnyRef("external.properties") - .asInstanceOf[java.util.HashMap[String, AnyRef]].asScala - .map{ ele => - ele._1 -> ele._2.asInstanceOf[java.util.HashMap[String, AnyRef]].asScala.getOrElse("type", "").asInstanceOf[String] - }.toMap - propTypes - } - -} \ No newline at end of file diff --git a/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/external/store/ExternalStoreFactory.scala b/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/external/store/ExternalStoreFactory.scala deleted file mode 100644 index 6369a4563..000000000 --- a/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/external/store/ExternalStoreFactory.scala +++ /dev/null @@ -1,25 +0,0 @@ -package org.sunbird.graph.external.store - -import java.util -import java.util.{Arrays, List} - -object ExternalStoreFactory { - - private val PRIMARY_KEY = util.Arrays.asList("content_id") - var externalStores: Map[String, ExternalStore] = Map() - - def getExternalStore(externalStoreName: String, primaryKey: util.List[String]): ExternalStore = { - val keySpace = externalStoreName.split("\\.")(0); - val table = externalStoreName.split("\\.")(1); - val key = getKey(keySpace,table) - val store = externalStores.getOrElse(key, new ExternalStore(keySpace, table, primaryKey)) - if(!externalStores.contains(key)) - externalStores += (key -> store) - store - } - - private def getKey(keySpace: String, table: String) = { - "store-" + keySpace + "-" + table - } - -} diff --git a/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/schema/validator/FrameworkValidator.scala b/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/schema/validator/FrameworkValidator.scala index f501fc37c..af1da9317 100644 --- a/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/schema/validator/FrameworkValidator.scala +++ b/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/schema/validator/FrameworkValidator.scala @@ -60,21 +60,16 @@ trait FrameworkValidator extends IDefinition { private def validateAndSetMultiFrameworks(node: Node, orgFwTerms: List[String], targetFwTerms: List[String])(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Map[String, AnyRef]] = { getValidatedTerms(node, orgFwTerms).map(orgTermMap => { - val boardIds = getList("boardIds", node) - if (CollectionUtils.isNotEmpty(boardIds)) - node.getMetadata.putIfAbsent("board", orgTermMap(boardIds.get(0))) - val mediumIds = getList("mediumIds", node) - if (CollectionUtils.isNotEmpty(mediumIds)) - node.getMetadata.putIfAbsent("medium", mediumIds.asScala.map(id => orgTermMap(id)).toList.asJava) - val subjectIds = getList("subjectIds", node) - if (CollectionUtils.isNotEmpty(subjectIds)) - node.getMetadata.putIfAbsent("subject", subjectIds.asScala.map(id => orgTermMap(id)).toList.asJava) - val gradeIds = getList("gradeLevelIds", node) - if (CollectionUtils.isNotEmpty(gradeIds)) - node.getMetadata.putIfAbsent("gradeLevel", gradeIds.asScala.map(id => orgTermMap(id)).toList.asJava) - val topicIds = getList("topicsIds", node) - if (CollectionUtils.isNotEmpty(topicIds)) - node.getMetadata.putIfAbsent("topics", topicIds.asScala.map(id => orgTermMap(id)).toList.asJava) + val boards = fetchValidatedList(getList("boardIds", node), orgTermMap) + if (CollectionUtils.isNotEmpty(boards)) node.getMetadata.putIfAbsent("board", boards.get(0)) + val mediums = fetchValidatedList(getList("mediumIds", node), orgTermMap) + if (CollectionUtils.isNotEmpty(mediums)) node.getMetadata.putIfAbsent("medium", mediums) + val subjects = fetchValidatedList(getList("subjectIds", node), orgTermMap) + if (CollectionUtils.isNotEmpty(subjects)) node.getMetadata.putIfAbsent("subject", subjects) + val grades = fetchValidatedList(getList("gradeLevelIds", node), orgTermMap) + if (CollectionUtils.isNotEmpty(grades)) node.getMetadata.putIfAbsent("gradeLevel", grades) + val topics = fetchValidatedList(getList("topicsIds", node), orgTermMap) + if (CollectionUtils.isNotEmpty(topics)) node.getMetadata.putIfAbsent("topics", topics) getValidatedTerms(node, targetFwTerms) }).flatMap(f => f) } @@ -136,4 +131,12 @@ trait FrameworkValidator extends IDefinition { }) } + def fetchValidatedList(itemList: util.List[String], orgTermMap: Map[String, AnyRef]): util.List[String] = { + if (CollectionUtils.isNotEmpty(itemList)) { + itemList.asScala.map(id => orgTermMap.getOrElse(id, "").asInstanceOf[String]) + .filter(medium => medium.nonEmpty) + .toList.asJava + } else List().asJava + } + } diff --git a/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/schema/validator/VersioningNode.scala b/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/schema/validator/VersioningNode.scala index 9595dc9f7..abcd8b5c2 100644 --- a/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/schema/validator/VersioningNode.scala +++ b/ontology-engine/graph-engine_2.11/src/main/scala/org/sunbird/graph/schema/validator/VersioningNode.scala @@ -113,7 +113,7 @@ trait VersioningNode extends IDefinition { put("graph_id", graphId) }}) request.put("identifier", identifier) - ExternalPropsManager.fetchProps(request, getExternalPropsList(graphId, schemaName, getSchemaVersion())) + oec.graphService.readExternalProps(request, getExternalPropsList(graphId, schemaName, getSchemaVersion())) } private def getExternalPropsList(graphId: String, schemaName: String, version: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): List[String] ={ diff --git a/ontology-engine/graph-engine_2.11/src/test/scala/org/sunbird/graph/BaseSpec.scala b/ontology-engine/graph-engine_2.11/src/test/scala/org/sunbird/graph/BaseSpec.scala index e893b96e4..08b164065 100644 --- a/ontology-engine/graph-engine_2.11/src/test/scala/org/sunbird/graph/BaseSpec.scala +++ b/ontology-engine/graph-engine_2.11/src/test/scala/org/sunbird/graph/BaseSpec.scala @@ -89,6 +89,10 @@ class BaseSpec extends AsyncFlatSpec with Matchers with BeforeAndAfterAll { setUpEmbeddedCassandra() executeNeo4jQuery("UNWIND [{identifier:\"obj-cat:course_collection_all\",name:\"LearningResource\",description:\"Learning resource\",categoryId:\"obj-cat:course\",targetObjectType:\"Collection\",status:\"Live\",objectMetadata:\"{\\\"config\\\":{},\\\"schema\\\":{\\\"properties\\\":{\\\"trackable\\\":{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{\\\"enabled\\\":{\\\"type\\\":\\\"string\\\",\\\"enum\\\":[\\\"Yes\\\",\\\"No\\\"],\\\"default\\\":\\\"Yes\\\"},\\\"autoBatch\\\":{\\\"type\\\":\\\"string\\\",\\\"enum\\\":[\\\"Yes\\\",\\\"No\\\"],\\\"default\\\":\\\"Yes\\\"}},\\\"default\\\":{\\\"enabled\\\":\\\"Yes\\\",\\\"autoBatch\\\":\\\"Yes\\\"},\\\"additionalProperties\\\":false}}}}\",IL_SYS_NODE_TYPE:\"DATA_NODE\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",IL_UNIQUE_ID:\"obj-cat:course_collection_all\"},{identifier:\"obj-cat:learning-resource_content_all\",name:\"LearningResource\",description:\"Learning resource\",categoryId:\"obj-cat:learningresource\",targetObjectType:\"Content\",status:\"Live\",objectMetadata:\"{\\\"config\\\":{},\\\"schema\\\":{\\\"properties\\\":{\\\"trackable\\\":{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{\\\"enabled\\\":{\\\"type\\\":\\\"string\\\",\\\"enum\\\":[\\\"Yes\\\",\\\"No\\\"],\\\"default\\\":\\\"Yes\\\"},\\\"autoBatch\\\":{\\\"type\\\":\\\"string\\\",\\\"enum\\\":[\\\"Yes\\\",\\\"No\\\"],\\\"default\\\":\\\"Yes\\\"}},\\\"default\\\":{\\\"enabled\\\":\\\"Yes\\\",\\\"autoBatch\\\":\\\"Yes\\\"},\\\"additionalProperties\\\":false}}}}\",IL_SYS_NODE_TYPE:\"DATA_NODE\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",IL_UNIQUE_ID:\"obj-cat:learning-resource_content_all\"},{identifier:\"obj-cat:learning-resource_content_all\",name:\"LearningResource\",description:\"Learning resource\",categoryId:\"obj-cat:learningresource\",targetObjectType:\"Collection\",status:\"Live\",objectMetadata:\"{\\\"config\\\":{},\\\"schema\\\":{\\\"properties\\\":{\\\"trackable\\\":{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{\\\"enabled\\\":{\\\"type\\\":\\\"string\\\",\\\"enum\\\":[\\\"Yes\\\",\\\"No\\\"],\\\"default\\\":\\\"Yes\\\"},\\\"autoBatch\\\":{\\\"type\\\":\\\"string\\\",\\\"enum\\\":[\\\"Yes\\\",\\\"No\\\"],\\\"default\\\":\\\"Yes\\\"}},\\\"default\\\":{\\\"enabled\\\":\\\"Yes\\\",\\\"autoBatch\\\":\\\"Yes\\\"},\\\"additionalProperties\\\":false}}}}\",IL_SYS_NODE_TYPE:\"DATA_NODE\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",IL_UNIQUE_ID:\"obj-cat:learning-resource_collection_all\"}" + ",{owner:\"in.ekstep\",code:\"NCF\",IL_SYS_NODE_TYPE:\"DATA_NODE\",apoc_json:\"{\\\"batch\\\": true}\",consumerId:\"9393568c-3a56-47dd-a9a3-34da3c821638\",channel:\"in.ekstep\",description:\"NCF \",type:\"K-12\",createdOn:\"2018-01-23T09:53:50.189+0000\",versionKey:\"1545195552163\",apoc_text:\"APOC\",appId:\"dev.sunbird.portal\",IL_FUNC_OBJECT_TYPE:\"Framework\",name:\"State (Uttar Pradesh)\",lastUpdatedOn:\"2018-12-19T04:59:12.163+0000\",IL_UNIQUE_ID:\"NCF\",status:\"Live\",apoc_num:1}" + + ",{code:\"cbse\",IL_SYS_NODE_TYPE:\"DATA_NODE\",IL_FUNC_OBJECT_TYPE:\"Term\",name:\"CBSE\",IL_UNIQUE_ID:\"ncf_board_cbse\",status:\"Live\"}" + + ",{code:\"english\",IL_SYS_NODE_TYPE:\"DATA_NODE\",IL_FUNC_OBJECT_TYPE:\"Term\",name:\"English\",IL_UNIQUE_ID:\"ncf_medium_english\",status:\"Live\"}" + + ",{code:\"english\",IL_SYS_NODE_TYPE:\"DATA_NODE\",IL_FUNC_OBJECT_TYPE:\"Term\",name:\"English\",IL_UNIQUE_ID:\"ncf_subject_cbse\",status:\"Live\"}" + + ",{code:\"grade1\",IL_SYS_NODE_TYPE:\"DATA_NODE\",IL_FUNC_OBJECT_TYPE:\"Term\",name:\"Class 1\",IL_UNIQUE_ID:\"ncf_gradelevel_grade1\",status:\"Live\"}" + ",{owner:\"in.ekstep\",code:\"tpd\",IL_SYS_NODE_TYPE:\"DATA_NODE\",apoc_json:\"{\\\"batch\\\": true}\",consumerId:\"9393568c-3a56-47dd-a9a3-34da3c821638\",channel:\"in.ekstep\",description:\"NCF \",type:\"K-12\",createdOn:\"2018-01-23T09:53:50.189+0000\",versionKey:\"1545195552163\",apoc_text:\"APOC\",appId:\"dev.sunbird.portal\",IL_FUNC_OBJECT_TYPE:\"Framework\",name:\"State (Uttar Pradesh)\",lastUpdatedOn:\"2018-12-19T04:59:12.163+0000\",IL_UNIQUE_ID:\"tpd\",status:\"Live\",apoc_num:1}] as row CREATE (n:domain) SET n += row;") executeCassandraQuery(script_1, script_2, script_3, script_4, script_5, script_6, script_7, script_8, script_9, script_10, script_11, script_12) } diff --git a/ontology-engine/graph-engine_2.11/src/test/scala/org/sunbird/graph/schema/validator/TestSchemaValidator.scala b/ontology-engine/graph-engine_2.11/src/test/scala/org/sunbird/graph/schema/validator/TestSchemaValidator.scala index 4fda5a151..d63a3f395 100644 --- a/ontology-engine/graph-engine_2.11/src/test/scala/org/sunbird/graph/schema/validator/TestSchemaValidator.scala +++ b/ontology-engine/graph-engine_2.11/src/test/scala/org/sunbird/graph/schema/validator/TestSchemaValidator.scala @@ -34,6 +34,10 @@ class TestSchemaValidator extends BaseSpec { put("channel", "in.ekstep") put("contentCredits", a) put("primaryCategory", "Learning Resource") + put("boardIds", Array("ncf_board_cbse")) + put("mediumIds", Array("ncf_medium_english")) + put("subjectIds", Array("ncf_subject_cbse")) + put("gradeLevelIds", Array("ncf_gradelevel_grade1")) }} @@ -42,8 +46,6 @@ class TestSchemaValidator extends BaseSpec { node.setMetadata(metaData) val future: Future[Node] = definition.validate(node, "create") - future map { node => { - assert(null != node) - } - } - }} + future map { node => assert(null != node) } + } +} diff --git a/platform-core/kafka-client/src/main/scala/org/sunbird/kafka/client/KafkaClient.scala b/platform-core/kafka-client/src/main/scala/org/sunbird/kafka/client/KafkaClient.scala index ecdd8f38d..60f659c57 100644 --- a/platform-core/kafka-client/src/main/scala/org/sunbird/kafka/client/KafkaClient.scala +++ b/platform-core/kafka-client/src/main/scala/org/sunbird/kafka/client/KafkaClient.scala @@ -56,5 +56,4 @@ class KafkaClient { } }) } - } diff --git a/platform-core/pom.xml b/platform-core/pom.xml index 840cbe426..915ae188d 100755 --- a/platform-core/pom.xml +++ b/platform-core/pom.xml @@ -26,11 +26,10 @@ commons-lang3 3.9 - junit junit - 4.4 + 4.13.1 test diff --git a/platform-modules/pom.xml b/platform-modules/pom.xml index 95c97c943..b2bdd0a80 100644 --- a/platform-modules/pom.xml +++ b/platform-modules/pom.xml @@ -24,7 +24,7 @@ junit junit - 4.12 + 4.13.1 test diff --git a/schemas/asset/1.0/schema.json b/schemas/asset/1.0/schema.json index 9298e5d59..ae73ccda4 100644 --- a/schemas/asset/1.0/schema.json +++ b/schemas/asset/1.0/schema.json @@ -1073,12 +1073,7 @@ "type": "string" }, "primaryCategory": { - "type": "string", - "enum": [ - "Asset", - "Certificate Template", - "CertAsset" - ] + "type": "string" }, "additionalCategories": { "type": "array", diff --git a/schemas/question/1.0/schema.json b/schemas/question/1.0/schema.json index ecfdbf4b0..eea9f246f 100644 --- a/schemas/question/1.0/schema.json +++ b/schemas/question/1.0/schema.json @@ -27,12 +27,7 @@ ] }, "primaryCategory": { - "type": "string", - "enum": [ - "Multiple Choice Question", - "Subjective Question", - "FTB Question" - ] + "type": "string" }, "additionalCategories": { "type": "array", @@ -130,6 +125,9 @@ "prevState": { "type": "string" }, + "prevStatus": { + "type": "string" + }, "lastStatusChangedOn": { "type": "string" }, @@ -362,7 +360,7 @@ ] }, "qumlVersion": { - "type": "string" + "type": "number" }, "timeLimit": { "type": "number" diff --git a/schemas/questionset/1.0/schema.json b/schemas/questionset/1.0/schema.json index c4add38a2..bb6c52513 100644 --- a/schemas/questionset/1.0/schema.json +++ b/schemas/questionset/1.0/schema.json @@ -27,10 +27,7 @@ ] }, "primaryCategory": { - "type": "string", - "enum": [ - "Practice Question Set" - ] + "type": "string" }, "additionalCategories": { "type": "array", @@ -125,6 +122,17 @@ "type": "string", "format": "url" }, + "previewUrl": { + "type": "string", + "format": "url" + }, + "pdfUrl": { + "type": "string", + "format": "url" + }, + "variants": { + "type": "object" + }, "size": { "type": "number" }, @@ -144,6 +152,9 @@ "prevState": { "type": "string" }, + "prevStatus": { + "type": "string" + }, "lastStatusChangedOn": { "type": "string" }, @@ -370,14 +381,11 @@ ] }, "qumlVersion": { - "type": "string" + "type": "number" }, "timeLimits": { "type": "object" }, - "maxScore": { - "type": "number" - }, "showTimer": { "type": "string", "enum": [ @@ -459,12 +467,8 @@ ] }, "shuffle": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "Yes" + "type": "boolean", + "default": true }, "totalQuestions": { "type": "number" diff --git a/search-api/search-actors/pom.xml b/search-api/search-actors/pom.xml index 0ce887026..9059b66c8 100644 --- a/search-api/search-actors/pom.xml +++ b/search-api/search-actors/pom.xml @@ -43,7 +43,7 @@ junit junit - 4.12 + 4.13.1 test diff --git a/search-api/search-core/pom.xml b/search-api/search-core/pom.xml index 2db32be97..a68a641e4 100644 --- a/search-api/search-core/pom.xml +++ b/search-api/search-core/pom.xml @@ -77,7 +77,7 @@ junit junit - 4.12 + 4.13.1 test