diff --git a/assessment-api/assessment-actors/pom.xml b/assessment-api/assessment-actors/pom.xml deleted file mode 100644 index 5e5418207..000000000 --- a/assessment-api/assessment-actors/pom.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - assessment-api - org.sunbird - 1.0-SNAPSHOT - - 4.0.0 - assessment-actors - - - - org.scala-lang - scala-library - ${scala.version} - - - javax.inject - javax.inject - 1 - - - org.sunbird - actor-core - 1.0-SNAPSHOT - - - org.sunbird - graph-engine_2.12 - 1.0-SNAPSHOT - jar - - - org.sunbird - qs-hierarchy-manager - 1.0-SNAPSHOT - - - org.sunbird - import-manager - 1.0-SNAPSHOT - jar - - - org.scalatest - scalatest_${scala.maj.version} - ${scalatest.version} - test - - - org.scalamock - scalamock_${scala.maj.version} - 4.4.0 - test - - - com.typesafe.akka - akka-testkit_${scala.maj.version} - 2.5.22 - test - - - - - src/main/scala - src/test/scala - - - net.alchim31.maven - scala-maven-plugin - 4.4.0 - - ${scala.version} - false - - - - scala-compile-first - process-resources - - add-source - compile - - - - scala-test-compile - process-test-resources - - testCompile - - - - - - org.scalatest - scalatest-maven-plugin - 2.0.0 - - - test - test - - test - - - - - - org.scoverage - scoverage-maven-plugin - ${scoverage.plugin.version} - - ${scala.version} - true - true - - - - - - \ No newline at end of file diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/HealthActor.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/HealthActor.scala deleted file mode 100644 index 3072bb928..000000000 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/HealthActor.scala +++ /dev/null @@ -1,20 +0,0 @@ -package org.sunbird.actors - -import javax.inject.Inject -import org.sunbird.actor.core.BaseActor -import org.sunbird.common.dto.{Request, Response} -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.graph.health.HealthCheckManager - -import scala.concurrent.{ExecutionContext, Future} - - -class HealthActor @Inject() (implicit oec: OntologyEngineContext) extends BaseActor { - - implicit val ec: ExecutionContext = getContext().dispatcher - - @throws[Throwable] - override def onReceive(request: Request): Future[Response] = { - HealthCheckManager.checkAllSystemHealth() - } -} diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/ItemSetActor.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/ItemSetActor.scala deleted file mode 100644 index ba6d39993..000000000 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/ItemSetActor.scala +++ /dev/null @@ -1,98 +0,0 @@ -package org.sunbird.actors - -import java.util - -import javax.inject.Inject -import org.apache.commons.collections4.CollectionUtils -import org.apache.commons.lang3.StringUtils -import org.sunbird.actor.core.BaseActor -import org.sunbird.common.dto.{Request, Response, ResponseHandler} -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.graph.dac.model.Relation -import org.sunbird.graph.nodes.DataNode -import org.sunbird.graph.utils.NodeUtil -import org.sunbird.parseq.Task - -import scala.collection.convert.ImplicitConversions._ -import scala.collection.JavaConverters.seqAsJavaListConverter -import scala.concurrent.{ExecutionContext, Future} - -class ItemSetActor @Inject() (implicit oec: OntologyEngineContext) extends BaseActor { - - implicit val ec: ExecutionContext = getContext().dispatcher - - override def onReceive(request: Request): Future[Response] = request.getOperation match { - case "createItemSet" => create(request) - case "readItemSet" => read(request) - case "updateItemSet" => update(request) - case "reviewItemSet" => review(request) - case "retireItemSet" => retire(request) - case _ => ERROR(request.getOperation) - } - - - def create(request: Request): Future[Response] = DataNode.create(request).map(node => { - ResponseHandler.OK.put("identifier", node.getIdentifier) - }) - - def read(request: Request): Future[Response] = { - val fields = request.getRequest.getOrDefault("fields", "").asInstanceOf[String] - .split(",").filter((field: String) => StringUtils.isNotBlank(field) && !StringUtils.equalsIgnoreCase(field, "null")).toList.asJava - request.getRequest.put("fields", fields) - DataNode.read(request).map(node => { - val metadata = NodeUtil.serialize(node, fields, request.getContext.get("schemaName").asInstanceOf[String], request.getContext.get("version").asInstanceOf[String]) - metadata.remove("versionKey") - ResponseHandler.OK.put("itemset", metadata) - }) - } - - def update(request: Request): Future[Response] = DataNode.update(request).map(node => { - ResponseHandler.OK.put("identifier", node.getIdentifier) - }) - - def review(request: Request): Future[Response] = { - val identifier = request.getContext.get("identifier").asInstanceOf[String] - var flag = false - val readReq = new Request(); - val reqContext = request.getContext - readReq.setContext(reqContext) - readReq.put("identifier", identifier) - readReq.put("fields", new util.ArrayList[String]) - val updateReq = new Request() - updateReq.setContext(reqContext) - DataNode.read(readReq).map(node => { - if (CollectionUtils.isNotEmpty(node.getOutRelations)) { - //process relations with AssessmentItem - val itemRels: util.List[Relation] = node.getOutRelations.filter((rel: Relation) => StringUtils.equalsAnyIgnoreCase("AssessmentItem", rel.getEndNodeObjectType)).filterNot((reln: Relation) => StringUtils.equalsAnyIgnoreCase("Retired", reln.getEndNodeMetadata.get("status").toString)) - val draftRelIds: List[String] = itemRels.filter((rel: Relation) => StringUtils.equalsAnyIgnoreCase("Draft", rel.getEndNodeMetadata.get("status").toString)).map(rel => rel.getEndNodeId).toList - if (CollectionUtils.isNotEmpty(draftRelIds)) { - updateReq.put("identifiers", draftRelIds.asJava) - updateReq.put("metadata", new util.HashMap[String, AnyRef]() {{put("status", "Review")}}) - flag = true - } - val newRels: util.List[util.HashMap[String, AnyRef]] = itemRels.sortBy((rel: Relation) => rel.getMetadata.get("IL_SEQUENCE_INDEX").asInstanceOf[Long])(Ordering.Long).map(rel => { - new util.HashMap[String, AnyRef]() {{put("identifier", rel.getEndNodeId);}}}).toList - request.put("items", newRels); - } - request.put("status", "Review") - val func = flag match { - case true => DataNode.bulkUpdate(updateReq).map(f => ResponseHandler.OK()) - case false => Future(ResponseHandler.OK()) - } - val futureList = Task.parallel[Response](func, - DataNode.update(request).map(node => { - ResponseHandler.OK.put("identifier", node.getIdentifier) - })) - futureList - }).flatMap(f => f).map(f => f.get(1)) - } - - def retire(request: Request): Future[Response] = { - request.put("status", "Retired") - DataNode.update(request).map(node => { - ResponseHandler.OK.put("identifier", node.getIdentifier) - }) - } - - -} diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionActor.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionActor.scala deleted file mode 100644 index 5e1eb12ca..000000000 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionActor.scala +++ /dev/null @@ -1,140 +0,0 @@ -package org.sunbird.actors - -import org.apache.commons.lang3.StringUtils -import org.sunbird.`object`.importer.{ImportConfig, ImportManager} -import org.sunbird.actor.core.BaseActor -import org.sunbird.common.dto.{Request, Response, ResponseHandler} -import org.sunbird.common.{DateUtils, Platform} -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.graph.nodes.DataNode -import org.sunbird.graph.utils.NodeUtil -import org.sunbird.managers.{AssessmentManager, CopyManager} -import org.sunbird.utils.RequestUtil - -import java.util -import javax.inject.Inject -import scala.collection.JavaConverters -import scala.collection.JavaConverters._ -import scala.concurrent.{ExecutionContext, Future} - -class QuestionActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor { - - implicit val ec: ExecutionContext = getContext().dispatcher - - private lazy val importConfig = getImportConfig() - private lazy val importMgr = new ImportManager(importConfig) - - override def onReceive(request: Request): Future[Response] = request.getOperation match { - case "createQuestion" => AssessmentManager.create(request, "ERR_QUESTION_CREATE") - case "readQuestion" => AssessmentManager.read(request, "question") - case "readPrivateQuestion" => AssessmentManager.privateRead(request, "question") - case "updateQuestion" => update(request) - case "reviewQuestion" => review(request) - case "publishQuestion" => publish(request) - case "retireQuestion" => retire(request) - case "importQuestion" => importQuestion(request) - case "systemUpdateQuestion" => systemUpdate(request) - case "listQuestions" => listQuestions(request) - case "rejectQuestion" => reject(request) - case "copyQuestion" => copy(request) - case _ => ERROR(request.getOperation) - } - - def update(request: Request): Future[Response] = { - RequestUtil.restrictProperties(request) - request.getRequest.put("identifier", request.getContext.get("identifier")) - request.getRequest.put("artifactUrl",null) - AssessmentManager.getValidatedNodeForUpdate(request, "ERR_QUESTION_UPDATE").flatMap(_ => AssessmentManager.updateNode(request)) - } - - def review(request: Request): Future[Response] = { - request.getRequest.put("identifier", request.getContext.get("identifier")) - AssessmentManager.getValidatedNodeForReview(request, "ERR_QUESTION_REVIEW").flatMap(node => { - val updateRequest = new Request(request) - updateRequest.getContext.put("identifier", request.get("identifier")) - updateRequest.putAll(Map("versionKey" -> node.getMetadata.get("versionKey"), "prevStatus" -> "Draft", "status" -> "Review", "lastStatusChangedOn" -> DateUtils.formatCurrentDate).asJava) - AssessmentManager.updateNode(updateRequest) - }) - } - - def publish(request: Request): Future[Response] = { - val lastPublishedBy: String = request.getRequest.getOrDefault("lastPublishedBy", "").asInstanceOf[String] - request.getRequest.put("identifier", request.getContext.get("identifier")) - AssessmentManager.getValidatedNodeForPublish(request, "ERR_QUESTION_PUBLISH").map(node => { - if(StringUtils.isNotBlank(lastPublishedBy)) - node.getMetadata.put("lastPublishedBy", lastPublishedBy) - AssessmentManager.pushInstructionEvent(node.getIdentifier, node) - ResponseHandler.OK.putAll(Map[String, AnyRef]("identifier" -> node.getIdentifier.replace(".img", ""), "message" -> "Question is successfully sent for Publish").asJava) - }) - } - - def retire(request: Request): Future[Response] = { - request.getRequest.put("identifier", request.getContext.get("identifier")) - AssessmentManager.getValidatedNodeForRetire(request, "ERR_QUESTION_RETIRE").flatMap(node => { - val updateRequest = new Request(request) - updateRequest.put("identifiers", java.util.Arrays.asList(request.get("identifier").asInstanceOf[String], request.get("identifier").asInstanceOf[String] + ".img")) - val updateMetadata: util.Map[String, AnyRef] = Map[String, AnyRef]("status" -> "Retired", "lastStatusChangedOn" -> DateUtils.formatCurrentDate).asJava - updateRequest.put("metadata", updateMetadata) - DataNode.bulkUpdate(updateRequest).map(_ => { - ResponseHandler.OK.putAll(Map("identifier" -> node.getIdentifier.replace(".img", ""), "versionKey" -> node.getMetadata.get("versionKey")).asJava) - }) - }) - } - - def importQuestion(request: Request): Future[Response] = importMgr.importObject(request) - - def getImportConfig(): ImportConfig = { - val requiredProps = Platform.getStringList("import.required_props.question", java.util.Arrays.asList("name", "code", "mimeType", "framework")).asScala.toList - val validStages = Platform.getStringList("import.valid_stages.question", java.util.Arrays.asList("create", "upload", "review", "publish")).asScala.toList - val propsToRemove = Platform.getStringList("import.remove_props.question", java.util.Arrays.asList()).asScala.toList - val topicName = Platform.config.getString("import.output_topic_name") - val reqLimit = Platform.getInteger("import.request_size_limit", 200) - val validSourceStatus = Platform.getStringList("import.valid_source_status", java.util.Arrays.asList("Live", "Unlisted")).asScala.toList - ImportConfig(topicName, reqLimit, requiredProps, validStages, propsToRemove, validSourceStatus) - } - - def systemUpdate(request: Request): Future[Response] = { - val identifier = request.getContext.get("identifier").asInstanceOf[String] - RequestUtil.validateRequest(request) - val readReq = new Request(request) - val identifiers = new util.ArrayList[String](){{ - add(identifier) - if (!identifier.endsWith(".img")) - add(identifier.concat(".img")) - }} - readReq.put("identifiers", identifiers) - DataNode.list(readReq).flatMap(response => { - DataNode.systemUpdate(request, response,"", None) - }).map(node => ResponseHandler.OK.put("identifier", identifier).put("status", "success")) - } - - def listQuestions(request: Request): Future[Response] = { - RequestUtil.validateListRequest(request) - val fields: util.List[String] = JavaConverters.seqAsJavaListConverter(request.get("fields").asInstanceOf[String].split(",").filter(field => StringUtils.isNotBlank(field) && !StringUtils.equalsIgnoreCase(field, "null"))).asJava - request.getRequest.put("fields", fields) - DataNode.search(request).map(nodeList => { - val questionList = nodeList.map(node => { - NodeUtil.serialize(node, fields, node.getObjectType.toLowerCase.replace("Image", ""), request.getContext.get("version").asInstanceOf[String]) - }).asJava - ResponseHandler.OK.put("questions", questionList).put("count", questionList.size) - }) - } - - def reject(request: Request): Future[Response] = { - request.getRequest.put("identifier", request.getContext.get("identifier")) - AssessmentManager.getValidateNodeForReject(request, "ERR_QUESTION_REJECT").flatMap(node => { - val updateRequest = new Request(request) - val date = DateUtils.formatCurrentDate - updateRequest.getContext.put("identifier", request.getContext.get("identifier")) - if(request.getRequest.containsKey("rejectComment")) - updateRequest.put("rejectComment", request.get("rejectComment").asInstanceOf[String]) - updateRequest.putAll(Map("versionKey" -> node.getMetadata.get("versionKey"), "status" -> "Draft", "prevStatus" -> node.getMetadata.get("status"), "lastStatusChangedOn" -> date, "lastUpdatedOn" -> date).asJava) - AssessmentManager.updateNode(updateRequest) - }) - } - - def copy(request: Request): Future[Response] ={ - RequestUtil.restrictProperties(request) - CopyManager.copy(request) - } -} diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionSetActor.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionSetActor.scala deleted file mode 100644 index 797b684d9..000000000 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionSetActor.scala +++ /dev/null @@ -1,169 +0,0 @@ -package org.sunbird.actors - -import java.util - -import javax.inject.Inject -import org.apache.commons.collections4.CollectionUtils -import org.apache.commons.lang3.StringUtils -import org.sunbird.`object`.importer.{ImportConfig, ImportManager} -import org.sunbird.actor.core.BaseActor -import org.sunbird.cache.impl.RedisCache -import org.sunbird.common.{DateUtils, Platform} -import org.sunbird.common.dto.{Request, Response, ResponseHandler} -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.graph.nodes.DataNode -import org.sunbird.graph.dac.model.Node -import org.sunbird.managers.HierarchyManager.hierarchyPrefix -import org.sunbird.managers.{AssessmentManager, CopyManager, HierarchyManager, UpdateHierarchyManager} -import org.sunbird.utils.RequestUtil - -import scala.collection.JavaConverters._ -import scala.concurrent.{ExecutionContext, Future} - -class QuestionSetActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor { - - implicit val ec: ExecutionContext = getContext().dispatcher - private lazy val importConfig = getImportConfig() - private lazy val importMgr = new ImportManager(importConfig) - - override def onReceive(request: Request): Future[Response] = request.getOperation match { - case "createQuestionSet" => AssessmentManager.create(request, "ERR_QUESTION_SET_CREATE") - case "readQuestionSet" => AssessmentManager.read(request, "questionset") - case "readPrivateQuestionSet" => AssessmentManager.privateRead(request, "questionset") - case "updateQuestionSet" => update(request) - case "reviewQuestionSet" => review(request) - case "publishQuestionSet" => publish(request) - case "retireQuestionSet" => retire(request) - case "addQuestion" => HierarchyManager.addLeafNodesToHierarchy(request) - case "removeQuestion" => HierarchyManager.removeLeafNodesFromHierarchy(request) - case "updateHierarchy" => UpdateHierarchyManager.updateHierarchy(request) - case "getHierarchy" => HierarchyManager.getHierarchy(request) - case "rejectQuestionSet" => reject(request) - case "importQuestionSet" => importQuestionSet(request) - case "systemUpdateQuestionSet" => systemUpdate(request) - case "copyQuestionSet" => copy(request) - case _ => ERROR(request.getOperation) - } - - def update(request: Request): Future[Response] = { - RequestUtil.restrictProperties(request) - request.getRequest.put("identifier", request.getContext.get("identifier")) - AssessmentManager.getValidatedNodeForUpdate(request, "ERR_QUESTION_SET_UPDATE").flatMap(_ => AssessmentManager.updateNode(request)) - } - - def review(request: Request): Future[Response] = { - request.getRequest.put("identifier", request.getContext.get("identifier")) - request.getRequest.put("mode", "edit") - AssessmentManager.getValidatedNodeForReview(request, "ERR_QUESTION_SET_REVIEW").flatMap(node => { - AssessmentManager.getQuestionSetHierarchy(request, node).flatMap(hierarchyString => { - AssessmentManager.validateQuestionSetHierarchy(hierarchyString.asInstanceOf[String], node.getMetadata.getOrDefault("createdBy", "").asInstanceOf[String]) - val (updatedHierarchy, nodeIds) = AssessmentManager.updateHierarchy(hierarchyString.asInstanceOf[String], "Review", node.getMetadata.getOrDefault("createdBy", "").asInstanceOf[String]) - val updateReq = new Request(request) - val date = DateUtils.formatCurrentDate - updateReq.putAll(Map("identifiers" -> nodeIds, "metadata" -> Map("status" -> "Review", "prevStatus" -> node.getMetadata.get("status"), "lastStatusChangedOn" -> date, "lastUpdatedOn" -> date).asJava).asJava) - updateHierarchyNodes(updateReq, node, Map("status" -> "Review", "hierarchy" -> updatedHierarchy), nodeIds) - }) - }) - } - - def publish(request: Request): Future[Response] = { - val lastPublishedBy: String = request.getRequest.getOrDefault("lastPublishedBy", "").asInstanceOf[String] - request.getRequest.put("identifier", request.getContext.get("identifier")) - request.put("mode", "edit") - AssessmentManager.getValidatedNodeForPublish(request, "ERR_QUESTION_SET_PUBLISH").flatMap(node => { - AssessmentManager.getQuestionSetHierarchy(request, node).map(hierarchyString => { - AssessmentManager.validateQuestionSetHierarchy(hierarchyString.asInstanceOf[String], node.getMetadata.getOrDefault("createdBy", "").asInstanceOf[String]) - if(StringUtils.isNotBlank(lastPublishedBy)) - node.getMetadata.put("lastPublishedBy", lastPublishedBy) - AssessmentManager.pushInstructionEvent(node.getIdentifier, node) - ResponseHandler.OK.putAll(Map[String, AnyRef]("identifier" -> node.getIdentifier.replace(".img", ""), "message" -> "QuestionSet is successfully sent for Publish").asJava) - }) - }) - } - - def retire(request: Request): Future[Response] = { - request.getRequest.put("identifier", request.getContext.get("identifier")) - AssessmentManager.getValidatedNodeForRetire(request, "ERR_QUESTION_SET_RETIRE").flatMap(node => { - val updateRequest = new Request(request) - updateRequest.put("identifiers", java.util.Arrays.asList(request.get("identifier").asInstanceOf[String], request.get("identifier").asInstanceOf[String] + ".img")) - val updateMetadata: util.Map[String, AnyRef] = Map("prevStatus" -> node.getMetadata.get("status"), "status" -> "Retired", "lastStatusChangedOn" -> DateUtils.formatCurrentDate, "lastUpdatedOn" -> DateUtils.formatCurrentDate).asJava - updateRequest.put("metadata", updateMetadata) - DataNode.bulkUpdate(updateRequest).map(_ => { - ResponseHandler.OK.putAll(Map("identifier" -> node.getIdentifier.replace(".img", ""), "versionKey" -> node.getMetadata.get("versionKey")).asJava) - }) - }) - } - - def reject(request: Request): Future[Response] = { - request.getRequest.put("identifier", request.getContext.get("identifier")) - request.getRequest.put("mode", "edit") - AssessmentManager.getValidateNodeForReject(request, "ERR_QUESTION_SET_REJECT").flatMap(node => { - AssessmentManager.getQuestionSetHierarchy(request, node).flatMap(hierarchyString => { - AssessmentManager.validateQuestionSetHierarchy(hierarchyString.asInstanceOf[String], node.getMetadata.getOrDefault("createdBy", "").asInstanceOf[String]) - val (updatedHierarchy, nodeIds) = AssessmentManager.updateHierarchy(hierarchyString.asInstanceOf[String], "Draft", node.getMetadata.getOrDefault("createdBy", "").asInstanceOf[String]) - val updateReq = new Request(request) - val date = DateUtils.formatCurrentDate - updateReq.putAll(Map("identifiers" -> nodeIds, "metadata" -> Map("status" -> "Draft", "prevStatus" -> node.getMetadata.get("status"), "lastStatusChangedOn" -> date, "lastUpdatedOn" -> date).asJava).asJava) - val metadata: Map[String, AnyRef] = Map("status" -> "Draft", "hierarchy" -> updatedHierarchy) - val updatedMetadata = if(request.getRequest.containsKey("rejectComment")) (metadata ++ Map("rejectComment" -> request.get("rejectComment").asInstanceOf[String])) else metadata - updateHierarchyNodes(updateReq, node, updatedMetadata, nodeIds) - }) - }) - } - - def updateHierarchyNodes(request: Request, node: Node, metadata: Map[String, AnyRef], nodeIds: util.List[String]): Future[Response] = { - if (CollectionUtils.isNotEmpty(nodeIds)) { - DataNode.bulkUpdate(request).flatMap(_ => { - updateNode(request, node, metadata) - }) - } else { - updateNode(request, node, metadata) - } - } - - def updateNode(request: Request, node: Node, metadata: Map[String, AnyRef]): Future[Response] = { - val updateRequest = new Request(request) - val date = DateUtils.formatCurrentDate - val fMeta: Map[String, AnyRef] = Map("versionKey" -> node.getMetadata.get("versionKey"), "prevStatus" -> node.getMetadata.get("status"), "lastStatusChangedOn" -> date, "lastUpdatedOn" -> date) ++ metadata - updateRequest.getContext.put("identifier", request.getContext.get("identifier")) - updateRequest.putAll(fMeta.asJava) - DataNode.update(updateRequest).map(_ => { - ResponseHandler.OK.putAll(Map("identifier" -> node.getIdentifier.replace(".img", ""), "versionKey" -> node.getMetadata.get("versionKey")).asJava) - }) - } - - def importQuestionSet(request: Request): Future[Response] = importMgr.importObject(request) - - def getImportConfig(): ImportConfig = { - val requiredProps = Platform.getStringList("import.required_props.questionset", java.util.Arrays.asList("name", "code", "mimeType", "framework")).asScala.toList - val validStages = Platform.getStringList("import.valid_stages.questionset", java.util.Arrays.asList("create", "upload", "review", "publish")).asScala.toList - val propsToRemove = Platform.getStringList("import.remove_props.questionset", java.util.Arrays.asList()).asScala.toList - val topicName = Platform.config.getString("import.output_topic_name") - val reqLimit = Platform.getInteger("import.request_size_limit", 200) - val validSourceStatus = Platform.getStringList("import.valid_source_status", java.util.Arrays.asList("Live", "Unlisted")).asScala.toList - ImportConfig(topicName, reqLimit, requiredProps, validStages, propsToRemove, validSourceStatus) - } - - def systemUpdate(request: Request): Future[Response] = { - val identifier = request.getContext.get("identifier").asInstanceOf[String] - RequestUtil.validateRequest(request) - if(Platform.getBoolean("questionset.cache.enable", false)) - RedisCache.delete(hierarchyPrefix + identifier) - - val readReq = new Request(request) - val identifiers = new util.ArrayList[String](){{ - add(identifier) - if (!identifier.endsWith(".img")) - add(identifier.concat(".img")) - }} - readReq.put("identifiers", identifiers) - DataNode.list(readReq).flatMap(response => { - DataNode.systemUpdate(request, response,"questionSet", Some(HierarchyManager.getHierarchy)) - }).map(node => ResponseHandler.OK.put("identifier", identifier).put("status", "success")) - } - - def copy(request: Request): Future[Response] ={ - RequestUtil.restrictProperties(request) - CopyManager.copy(request) - } -} diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/managers/AssessmentManager.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/managers/AssessmentManager.scala deleted file mode 100644 index e81fe6c9d..000000000 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/managers/AssessmentManager.scala +++ /dev/null @@ -1,224 +0,0 @@ -package org.sunbird.managers - -import java.util - -import org.apache.commons.lang3.StringUtils -import org.sunbird.common.{DateUtils, JsonUtils, Platform} -import org.sunbird.common.dto.{Request, Response, ResponseHandler} -import org.sunbird.common.exception.{ClientException, ResourceNotFoundException, ServerException} -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.graph.dac.model.{Node, Relation} -import org.sunbird.graph.nodes.DataNode -import org.sunbird.graph.utils.NodeUtil -import org.sunbird.telemetry.logger.TelemetryManager -import org.sunbird.telemetry.util.LogTelemetryEventUtil -import org.sunbird.utils.RequestUtil - -import scala.concurrent.{ExecutionContext, Future} -import scala.collection.convert.ImplicitConversions._ -import scala.collection.JavaConverters -import scala.collection.JavaConverters._ - -object AssessmentManager { - - val skipValidation: Boolean = Platform.getBoolean("assessment.skip.validation", false) - val validStatus = List("Draft", "Review") - - def create(request: Request, errCode: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - val visibility: String = request.getRequest.getOrDefault("visibility", "").asInstanceOf[String] - if (StringUtils.isNotBlank(visibility) && StringUtils.equalsIgnoreCase(visibility, "Parent")) - throw new ClientException(errCode, "Visibility cannot be Parent!") - RequestUtil.restrictProperties(request) - DataNode.create(request).map(node => { - val response = ResponseHandler.OK - response.putAll(Map("identifier" -> node.getIdentifier, "versionKey" -> node.getMetadata.get("versionKey")).asJava) - response - }) - } - - def read(request: Request, resName: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - val fields: util.List[String] = JavaConverters.seqAsJavaListConverter(request.get("fields").asInstanceOf[String].split(",").filter(field => StringUtils.isNotBlank(field) && !StringUtils.equalsIgnoreCase(field, "null"))).asJava - request.getRequest.put("fields", fields) - DataNode.read(request).map(node => { - val metadata: util.Map[String, AnyRef] = NodeUtil.serialize(node, fields, node.getObjectType.toLowerCase.replace("Image", ""), request.getContext.get("version").asInstanceOf[String]) - metadata.put("identifier", node.getIdentifier.replace(".img", "")) - if(!StringUtils.equalsIgnoreCase(metadata.get("visibility").asInstanceOf[String],"Private")) { - ResponseHandler.OK.put(resName, metadata) - } - else { - throw new ClientException("ERR_ACCESS_DENIED", s"$resName visibility is private, hence access denied") - } - }) - } - - def privateRead(request: Request, resName: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - val fields: util.List[String] = JavaConverters.seqAsJavaListConverter(request.get("fields").asInstanceOf[String].split(",").filter(field => StringUtils.isNotBlank(field) && !StringUtils.equalsIgnoreCase(field, "null"))).asJava - request.getRequest.put("fields", fields) - if (StringUtils.isBlank(request.getRequest.getOrDefault("channel", "").asInstanceOf[String])) throw new ClientException("ERR_INVALID_CHANNEL", "Please Provide Channel!") - DataNode.read(request).map(node => { - val metadata: util.Map[String, AnyRef] = NodeUtil.serialize(node, fields, node.getObjectType.toLowerCase.replace("Image", ""), request.getContext.get("version").asInstanceOf[String]) - metadata.put("identifier", node.getIdentifier.replace(".img", "")) - if (StringUtils.equalsIgnoreCase(metadata.getOrDefault("channel", "").asInstanceOf[String],request.getRequest.getOrDefault("channel", "").asInstanceOf[String])) { - ResponseHandler.OK.put(resName, metadata) - } - else { - throw new ClientException("ERR_ACCESS_DENIED", "Channel id is not matched") - } - }) - } - - def updateNode(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - DataNode.update(request).map(node => { - ResponseHandler.OK.putAll(Map("identifier" -> node.getIdentifier.replace(".img", ""), "versionKey" -> node.getMetadata.get("versionKey")).asJava) - }) - } - - def getValidatedNodeForUpdate(request: Request, errCode: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Node] = { - DataNode.read(request).map(node => { - if (StringUtils.equalsIgnoreCase(node.getMetadata.getOrDefault("visibility", "").asInstanceOf[String], "Parent")) - throw new ClientException(errCode, node.getMetadata.getOrDefault("objectType", "").asInstanceOf[String].replace("Image", "") + " with visibility Parent, can't be updated individually.") - node - }) - } - - def getValidatedNodeForReview(request: Request, errCode: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Node] = { - request.put("mode", "edit") - DataNode.read(request).map(node => { - if (StringUtils.equalsIgnoreCase(node.getMetadata.getOrDefault("visibility", "").asInstanceOf[String], "Parent")) - throw new ClientException(errCode, s"${node.getObjectType.replace("Image", "")} with visibility Parent, can't be sent for review individually.") - if (!StringUtils.equalsAnyIgnoreCase(node.getMetadata.getOrDefault("status", "").asInstanceOf[String], "Draft")) - throw new ClientException(errCode, s"${node.getObjectType.replace("Image", "")} with status other than Draft can't be sent for review.") - node - }) - } - - def getValidatedNodeForPublish(request: Request, errCode: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Node] = { - request.put("mode", "edit") - DataNode.read(request).map(node => { - if (StringUtils.equalsIgnoreCase(node.getMetadata.getOrDefault("visibility", "").asInstanceOf[String], "Parent")) - throw new ClientException(errCode, s"${node.getObjectType.replace("Image", "")} with visibility Parent, can't be sent for publish individually.") - if (StringUtils.equalsAnyIgnoreCase(node.getMetadata.getOrDefault("status", "").asInstanceOf[String], "Processing")) - throw new ClientException(errCode, s"${node.getObjectType.replace("Image", "")} having Processing status can't be sent for publish.") - node - }) - } - - def getValidatedNodeForRetire(request: Request, errCode: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Node] = { - DataNode.read(request).map(node => { - if (StringUtils.equalsIgnoreCase("Retired", node.getMetadata.get("status").asInstanceOf[String])) - throw new ClientException(errCode, s"${node.getObjectType.replace("Image", "")} with identifier : ${node.getIdentifier} is already Retired.") - node - }) - } - - def getValidateNodeForReject(request: Request, errCode: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Node] = { - request.put("mode", "edit") - DataNode.read(request).map(node => { - if (StringUtils.equalsIgnoreCase(node.getMetadata.getOrDefault("visibility", "").asInstanceOf[String], "Parent")) - throw new ClientException(errCode, s"${node.getObjectType.replace("Image", "")} with visibility Parent, can't be sent for reject individually.") - if (!StringUtils.equalsIgnoreCase("Review", node.getMetadata.get("status").asInstanceOf[String])) - throw new ClientException(errCode, s"${node.getObjectType.replace("Image", "")} is not in 'Review' state for identifier: " + node.getIdentifier) - node - }) - } - - def getValidatedQuestionSet(request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Node] = { - request.put("mode", "edit") - DataNode.read(request).map(node => { - if (!StringUtils.equalsIgnoreCase("QuestionSet", node.getObjectType)) - throw new ClientException("ERR_QUESTION_SET_ADD", "Node with Identifier " + node.getIdentifier + " is not a Question Set") - node - }) - } - - def validateQuestionSetHierarchy(hierarchyString: String, rootUserId: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Unit = { - if (!skipValidation) { - val hierarchy = if (!hierarchyString.asInstanceOf[String].isEmpty) { - JsonUtils.deserialize(hierarchyString.asInstanceOf[String], classOf[java.util.Map[String, AnyRef]]) - } else - new java.util.HashMap[String, AnyRef]() - val children = hierarchy.getOrDefault("children", new util.ArrayList[java.util.Map[String, AnyRef]]).asInstanceOf[util.List[java.util.Map[String, AnyRef]]] - validateChildrenRecursive(children, rootUserId) - } - } - - def getQuestionSetHierarchy(request: Request, rootNode: Node)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Any] = { - request.put("rootId", request.get("identifier").asInstanceOf[String]) - HierarchyManager.getUnPublishedHierarchy(request).map(resp => { - if (!ResponseHandler.checkError(resp) && resp.getResponseCode.code() == 200) { - val hierarchy = resp.getResult.get("questionSet").asInstanceOf[util.Map[String, AnyRef]] - JsonUtils.serialize(hierarchy) - } else throw new ServerException("ERR_QUESTION_SET_HIERARCHY", "No hierarchy is present in cassandra for identifier:" + rootNode.getIdentifier) - }) - } - - private def validateChildrenRecursive(children: util.List[util.Map[String, AnyRef]], rootUserId: String): Unit = { - children.toList.foreach(content => { - if ((StringUtils.equalsAnyIgnoreCase(content.getOrDefault("visibility", "").asInstanceOf[String], "Default") - && !StringUtils.equals(rootUserId, content.getOrDefault("createdBy", "").asInstanceOf[String])) - && !StringUtils.equalsIgnoreCase(content.getOrDefault("status", "").asInstanceOf[String], "Live")) - throw new ClientException("ERR_QUESTION_SET", "Object with identifier: " + content.get("identifier") + " is not Live. Please Publish it.") - validateChildrenRecursive(content.getOrDefault("children", new util.ArrayList[Map[String, AnyRef]]).asInstanceOf[util.List[util.Map[String, AnyRef]]], rootUserId) - }) - } - - def getChildIdsFromRelation(node: Node): (List[String], List[String]) = { - val outRelations: List[Relation] = if (node.getOutRelations != null) node.getOutRelations.asScala.toList else List[Relation]() - val visibilityIdMap: Map[String, List[String]] = outRelations - .groupBy(_.getEndNodeMetadata.get("visibility").asInstanceOf[String]) - .mapValues(_.map(_.getEndNodeId).toList) - (visibilityIdMap.getOrDefault("Default", List()), visibilityIdMap.getOrDefault("Parent", List())) - } - - def updateHierarchy(hierarchyString: String, status: String, rootUserId: String): (java.util.Map[String, AnyRef], java.util.List[String]) = { - val hierarchy: java.util.Map[String, AnyRef] = if (!hierarchyString.asInstanceOf[String].isEmpty) { - JsonUtils.deserialize(hierarchyString.asInstanceOf[String], classOf[java.util.Map[String, AnyRef]]) - } else - new java.util.HashMap[String, AnyRef]() - val keys = List("identifier", "children").asJava - hierarchy.keySet().retainAll(keys) - val children = hierarchy.getOrDefault("children", new util.ArrayList[java.util.Map[String, AnyRef]]).asInstanceOf[util.List[java.util.Map[String, AnyRef]]] - val childrenToUpdate: List[String] = updateChildrenRecursive(children, status, List(), rootUserId) - (hierarchy, childrenToUpdate.asJava) - } - - private def updateChildrenRecursive(children: util.List[util.Map[String, AnyRef]], status: String, idList: List[String], rootUserId: String): List[String] = { - children.toList.flatMap(content => { - val objectType = content.getOrDefault("objectType", "").asInstanceOf[String] - val updatedIdList: List[String] = - if (StringUtils.equalsAnyIgnoreCase(content.getOrDefault("visibility", "").asInstanceOf[String], "Parent") || (StringUtils.equalsIgnoreCase( objectType, "Question") && StringUtils.equalsAnyIgnoreCase(content.getOrDefault("visibility", "").asInstanceOf[String], "Default") && validStatus.contains(content.getOrDefault("status", "").asInstanceOf[String]) && StringUtils.equals(rootUserId, content.getOrDefault("createdBy", "").asInstanceOf[String]))) { - content.put("lastStatusChangedOn", DateUtils.formatCurrentDate) - content.put("prevStatus", content.getOrDefault("status", "Draft")) - content.put("status", status) - content.put("lastUpdatedOn", DateUtils.formatCurrentDate) - if(StringUtils.equalsAnyIgnoreCase(objectType, "Question")) content.get("identifier").asInstanceOf[String] :: idList else idList - } else idList - val list = updateChildrenRecursive(content.getOrDefault("children", new util.ArrayList[Map[String, AnyRef]]).asInstanceOf[util.List[util.Map[String, AnyRef]]], status, updatedIdList, rootUserId) - list ++ updatedIdList - }) - } - - @throws[Exception] - def pushInstructionEvent(identifier: String, node: Node)(implicit oec: OntologyEngineContext): Unit = { - val (actor, context, objData, eData) = generateInstructionEventMetadata(identifier.replace(".img", ""), node) - val beJobRequestEvent: String = LogTelemetryEventUtil.logInstructionEvent(actor.asJava, context.asJava, objData.asJava, eData) - val topic: String = Platform.getString("kafka.topics.instruction", "sunbirddev.learning.job.request") - if (StringUtils.isBlank(beJobRequestEvent)) throw new ClientException("BE_JOB_REQUEST_EXCEPTION", "Event is not generated properly.") - oec.kafkaClient.send(beJobRequestEvent, topic) - } - - def generateInstructionEventMetadata(identifier: String, node: Node): (Map[String, AnyRef], Map[String, AnyRef], Map[String, AnyRef], util.Map[String, AnyRef]) = { - val metadata: util.Map[String, AnyRef] = node.getMetadata - val publishType = if (StringUtils.equalsIgnoreCase(metadata.getOrDefault("status", "").asInstanceOf[String], "Unlisted")) "unlisted" else "public" - val eventMetadata = Map("identifier" -> identifier, "mimeType" -> metadata.getOrDefault("mimeType", ""), "objectType" -> node.getObjectType.replace("Image", ""), "pkgVersion" -> metadata.getOrDefault("pkgVersion", 0.asInstanceOf[AnyRef]), "lastPublishedBy" -> metadata.getOrDefault("lastPublishedBy", "")) - val actor = Map("id" -> s"${node.getObjectType.toLowerCase().replace("image", "")}-publish", "type" -> "System".asInstanceOf[AnyRef]) - val context = Map("channel" -> metadata.getOrDefault("channel", ""), "pdata" -> Map("id" -> "org.sunbird.platform", "ver" -> "1.0").asJava, "env" -> Platform.getString("cloud_storage.env", "dev")) - val objData = Map("id" -> identifier, "ver" -> metadata.getOrDefault("versionKey", "")) - val eData: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef] {{ - put("action", "publish") - put("publish_type", publishType) - put("metadata", eventMetadata.asJava) - }} - (actor, context, objData, eData) - } -} diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/managers/CopyManager.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/managers/CopyManager.scala deleted file mode 100644 index 22aefc8f0..000000000 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/managers/CopyManager.scala +++ /dev/null @@ -1,293 +0,0 @@ -package org.sunbird.managers - -import org.apache.commons.collections4.CollectionUtils -import org.apache.commons.collections4.MapUtils -import org.sunbird.common.{JsonUtils, Platform} -import org.sunbird.common.dto.{Request, Response, ResponseHandler} -import org.sunbird.common.exception.{ClientException, ServerException} -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.graph.common.Identifier -import org.sunbird.graph.dac.model.Node -import org.sunbird.graph.nodes.DataNode -import org.sunbird.graph.schema.DefinitionNode -import org.sunbird.graph.utils.{NodeUtil, ScalaJsonUtils} -import org.sunbird.telemetry.logger.TelemetryManager -import org.sunbird.utils.{AssessmentConstants, BranchingUtil, HierarchyConstants} -import java.util -import java.util.concurrent.CompletionException -import java.util.{Optional, UUID} - -import org.apache.commons.lang3.StringUtils - -import scala.collection.JavaConversions.mapAsScalaMap -import scala.collection.JavaConverters._ -import scala.concurrent.{ExecutionContext, Future} - -object CopyManager { - - private val originMetadataKeys: util.List[String] = Platform.getStringList("assessment.copy.origin_data", new util.ArrayList[String]()) - private val internalHierarchyProps = List("identifier", "parent", "index", "depth") - private val metadataNotTobeCopied = Platform.config.getStringList("assessment.copy.props_to_remove") - - def copy(request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Response] = { - validateRequest(request) - DataNode.read(request).map(node => { - validateExistingNode(request, node) - val copiedNodeFuture: Future[Node] = node.getMetadata.get(AssessmentConstants.MIME_TYPE) match { - case AssessmentConstants.QUESTIONSET_MIME_TYPE => - node.setInRelations(null) - node.setOutRelations(null) - validateShallowCopyReq(node, request) - copyQuestionSet(node, request) - case AssessmentConstants.QUESTION_MIME_TYPE => - node.setInRelations(null) - copyNode(node, request) - } - copiedNodeFuture.map(copiedNode => { - val response = ResponseHandler.OK() - response.put("node_id", new util.HashMap[String, AnyRef]() { - { - put(node.getIdentifier, copiedNode.getIdentifier) - } - }) - response.put(AssessmentConstants.VERSION_KEY, copiedNode.getMetadata.get(AssessmentConstants.VERSION_KEY)) - response - }) - }).flatMap(f => f) recoverWith { case e: CompletionException => throw e.getCause } - } - - def validateExistingNode(request: Request, node: Node) = { - val requestObjectType = request.getObjectType - val nodeObjectType = node.getObjectType - if (!StringUtils.equalsIgnoreCase(requestObjectType, nodeObjectType)) throw new ClientException(AssessmentConstants.ERR_INVALID_OBJECT_TYPE, s"Please Provide Valid ${requestObjectType} Identifier") - if (StringUtils.equalsIgnoreCase(node.getObjectType, AssessmentConstants.QUESTION) && StringUtils.equalsIgnoreCase(node.getMetadata.getOrDefault(AssessmentConstants.VISIBILITY, AssessmentConstants.VISIBILITY_PARENT).asInstanceOf[String], AssessmentConstants.VISIBILITY_PARENT)) - throw new ClientException(AssessmentConstants.ERR_INVALID_REQUEST, "Question With Visibility Parent Cannot Be Copied Individually!") - } - - def copyQuestionSet(originNode: Node, request: Request)(implicit ex: ExecutionContext, oec: OntologyEngineContext): Future[Node] = { - val copyType = request.getRequest.get(AssessmentConstants.COPY_TYPE).asInstanceOf[String] - copyNode(originNode, request).map(node => { - val req = new Request(request) - req.put(AssessmentConstants.ROOT_ID, request.get(AssessmentConstants.IDENTIFIER)) - req.put(AssessmentConstants.MODE, request.get(AssessmentConstants.MODE)) - HierarchyManager.getHierarchy(req).map(response => { - val originHierarchy = response.getResult.getOrDefault(AssessmentConstants.QUESTIONSET, new util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - copyType match { - case AssessmentConstants.COPY_TYPE_SHALLOW => updateShallowHierarchy(request, node, originNode, originHierarchy) - case _ => updateHierarchy(request, node, originNode, originHierarchy, copyType) - } - }).flatMap(f => f) - }).flatMap(f => f) recoverWith { case e: CompletionException => throw e.getCause } - } - - - def copyNode(node: Node, request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Node] = { - val copyCreateReq: Future[Request] = getCopyRequest(node, request) - copyCreateReq.map(req => { - DataNode.create(req).map(copiedNode => { - Future(copiedNode) - }).flatMap(f => f) - }).flatMap(f => f) - } - - def updateHierarchy(request: Request, node: Node, originNode: Node, originHierarchy: util.Map[String, AnyRef], copyType: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Node] = { - prepareHierarchyRequest(originHierarchy, originNode, node, copyType, request).map(req => { - val hierarchyRequest = new Request(request) - hierarchyRequest.putAll(req) - val nodesModified: java.util.HashMap[String, AnyRef] = hierarchyRequest.getRequest.get(HierarchyConstants.NODES_MODIFIED).asInstanceOf[java.util.HashMap[String, AnyRef]] - val branchingRecord = BranchingUtil.generateBranchingRecord(nodesModified) - val originalRequest = JsonUtils.deserialize(ScalaJsonUtils.serialize(hierarchyRequest), classOf[Request]) - val BLExists = branchingRecord.exists(BLRecord => BLRecord._2.asInstanceOf[util.HashMap[String, AnyRef]].get(AssessmentConstants.CONTAINS_BL) == true) - val (updateHierarchyReq, branchingUpdateReq) = if (BLExists) (hierarchyRequest, JsonUtils.deserialize(ScalaJsonUtils.serialize(hierarchyRequest), classOf[Request])) else (originalRequest, new Request()) - UpdateHierarchyManager.updateHierarchy(updateHierarchyReq).map(response => { - if (!ResponseHandler.checkError(response)) response - else { - TelemetryManager.info(s"Update Hierarchy Failed For Copy Question Set Having Identifier: ${node.getIdentifier} | Response is: " + response) - throw new ServerException("ERR_QUESTIONSET_COPY", "Something Went Wrong, Please Try Again") - } - }).map(response => { - if (BLExists) { - BranchingUtil.hierarchyRequestModifier(branchingUpdateReq, branchingRecord, response.getResult.get(AssessmentConstants.IDENTIFIERS).asInstanceOf[util.Map[String, String]]) - UpdateHierarchyManager.updateHierarchy(branchingUpdateReq).map(response_ => { - if (!ResponseHandler.checkError(response_)) node - else { - TelemetryManager.info(s"Update Hierarchy Failed For Copy Question Set Having Identifier: ${node.getIdentifier} | Response is: " + response) - throw new ServerException("ERR_QUESTIONSET_COPY", "Something Went Wrong, Please Try Again") - } - }) - } else Future(node) - }).flatMap(f => f) - }).flatMap(f => f) - } - - def prepareHierarchyRequest(originHierarchy: util.Map[String, AnyRef], originNode: Node, node: Node, copyType: String, request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[util.Map[String, AnyRef]] = { - val children: util.List[util.Map[String, AnyRef]] = originHierarchy.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]] - if (null != children && !children.isEmpty) { - val nodesModified = new util.HashMap[String, AnyRef]() - val hierarchy = new util.HashMap[String, AnyRef]() - val idMap = new util.HashMap[String, String]() - hierarchy.put(node.getIdentifier, new util.HashMap[String, AnyRef]() { - { - put(AssessmentConstants.CHILDREN, new util.ArrayList[String]()) - put(AssessmentConstants.ROOT, true.asInstanceOf[AnyRef]) - put(AssessmentConstants.PRIMARY_CATEGORY, node.getMetadata.get(AssessmentConstants.PRIMARY_CATEGORY)) - } - }) - populateHierarchyRequest(children, nodesModified, hierarchy, node.getIdentifier, copyType, request, idMap) - getExternalData(idMap.keySet().asScala.toList, request).map(exData => { - idMap.asScala.toMap.foreach(entry => { - nodesModified.get(entry._2).asInstanceOf[java.util.Map[String, AnyRef]].get("metadata").asInstanceOf[util.Map[String, AnyRef]].putAll(exData.getOrDefault(entry._1, new util.HashMap[String, AnyRef]()).asInstanceOf[util.Map[String, AnyRef]]) - }) - new util.HashMap[String, AnyRef]() { - { - put(AssessmentConstants.NODES_MODIFIED, nodesModified) - put(AssessmentConstants.HIERARCHY, hierarchy) - } - } - }) - - } else Future(new util.HashMap[String, AnyRef]()) - } - - def getExternalData(identifiers: List[String], request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[util.Map[String, AnyRef]] = { - val req = new Request(request) - req.getContext().putAll(Map("objectType" -> "Question", "schemaName" -> "question").asJava) - req.put("identifiers", identifiers) - val result = new util.HashMap[String, AnyRef]() - val externalProps = DefinitionNode.getExternalProps(req.getContext.getOrDefault("graph_id", "domain").asInstanceOf[String], req.getContext.getOrDefault("version", "1.0").asInstanceOf[String], req.getContext.getOrDefault("schemaName", "question").asInstanceOf[String]) - val externalPropsResponse = oec.graphService.readExternalProps(req, externalProps) - externalPropsResponse.map(response => { - identifiers.map(id => { - val externalData = Optional.ofNullable(response.get(id).asInstanceOf[util.Map[String, AnyRef]]).orElse(new util.HashMap[String, AnyRef]()) - result.put(id, externalData) - }) - result - }) - } - - def populateHierarchyRequest(children: util.List[util.Map[String, AnyRef]], nodesModified: util.HashMap[String, AnyRef], hierarchy: util.HashMap[String, AnyRef], parentId: String, copyType: String, request: Request, idMap: java.util.Map[String, String])(implicit ec: ExecutionContext, oec: OntologyEngineContext): Unit = { - if (null != children && !children.isEmpty) { - children.asScala.toList.foreach(child => { - val id = if ("Parent".equalsIgnoreCase(child.get(AssessmentConstants.VISIBILITY).asInstanceOf[String])) { - val identifier = UUID.randomUUID().toString - nodesModified.put(identifier, new util.HashMap[String, AnyRef]() { - { - put(AssessmentConstants.METADATA, cleanUpCopiedData(new util.HashMap[String, AnyRef]() { - { - putAll(child) - put(AssessmentConstants.COPY_OF, child.getOrDefault(AssessmentConstants.IDENTIFIER,"")) - put(AssessmentConstants.CHILDREN, new util.ArrayList()) - internalHierarchyProps.map(key => remove(key)) - } - }, copyType)) - put(AssessmentConstants.ROOT, false.asInstanceOf[AnyRef]) - put(AssessmentConstants.OBJECT_TYPE, child.getOrDefault(AssessmentConstants.OBJECT_TYPE, "")) - put("isNew", true.asInstanceOf[AnyRef]) - put("setDefaultValue", false.asInstanceOf[AnyRef]) - } - }) - if (StringUtils.equalsIgnoreCase(AssessmentConstants.QUESTION_MIME_TYPE, child.getOrDefault("mimeType", "").asInstanceOf[String])) - idMap.put(child.getOrDefault("identifier", "").asInstanceOf[String], identifier) - identifier - } else - child.get(AssessmentConstants.IDENTIFIER).asInstanceOf[String] - if (StringUtils.equalsIgnoreCase(child.getOrDefault(AssessmentConstants.MIME_TYPE, "").asInstanceOf[String], AssessmentConstants.QUESTIONSET_MIME_TYPE)) - hierarchy.put(id, new util.HashMap[String, AnyRef]() { - { - put(AssessmentConstants.CHILDREN, new util.ArrayList[String]()) - put(AssessmentConstants.ROOT, false.asInstanceOf[AnyRef]) - put(AssessmentConstants.PRIMARY_CATEGORY, child.get(AssessmentConstants.PRIMARY_CATEGORY)) - } - }) - hierarchy.get(parentId).asInstanceOf[util.Map[String, AnyRef]].get(AssessmentConstants.CHILDREN).asInstanceOf[util.List[String]].add(id) - populateHierarchyRequest(child.get(AssessmentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]], nodesModified, hierarchy, id, copyType, request, idMap) - }) - } - } - - def updateShallowHierarchy(request: Request, node: Node, originNode: Node, originHierarchy: util.Map[String, AnyRef])(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Node] = { - val childrenHierarchy = originHierarchy.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]] - val req = new Request(request) - req.getContext.put(AssessmentConstants.SCHEMA_NAME, request.getContext.getOrDefault(AssessmentConstants.SCHEMA_NAME, AssessmentConstants.QUESTIONSET_SCHEMA_NAME)) - req.getContext.put(AssessmentConstants.VERSION, request.getContext.getOrDefault(AssessmentConstants.VERSION, AssessmentConstants.SCHEMA_VERSION)) - req.getContext.put(AssessmentConstants.IDENTIFIER, node.getIdentifier) - req.put(AssessmentConstants.HIERARCHY, ScalaJsonUtils.serialize(new java.util.HashMap[String, AnyRef]() { - { - put(AssessmentConstants.IDENTIFIER, node.getIdentifier) - put(AssessmentConstants.CHILDREN, childrenHierarchy) - } - })) - DataNode.update(req).map(node => node) - } - - def getCopyRequest(node: Node, request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Request] = { - val metadata: util.Map[String, AnyRef] = NodeUtil.serialize(node, new util.ArrayList(), node.getObjectType.toLowerCase.replace("image", ""), request.getContext.getOrDefault(AssessmentConstants.VERSION, "").asInstanceOf[String]) - val requestMap = request.getRequest - requestMap.remove(AssessmentConstants.MODE) - requestMap.remove(AssessmentConstants.COPY_SCHEME).asInstanceOf[String] - val copyType = requestMap.remove(AssessmentConstants.COPY_TYPE).asInstanceOf[String] - val originData: java.util.Map[String, AnyRef] = getOriginData(metadata, copyType) - cleanUpCopiedData(metadata, copyType) - metadata.putAll(requestMap) - metadata.put(AssessmentConstants.STATUS, "Draft") - metadata.put(AssessmentConstants.ORIGIN, node.getIdentifier) - metadata.put(AssessmentConstants.IDENTIFIER, Identifier.getIdentifier(request.getContext.get("graph_id").asInstanceOf[String], Identifier.getUniqueIdFromTimestamp)) - if (MapUtils.isNotEmpty(originData)) - metadata.put(AssessmentConstants.ORIGIN_DATA, originData) - request.getContext().put(AssessmentConstants.SCHEMA_NAME, node.getObjectType.toLowerCase.replace("image", "")) - val req = new Request(request) - req.setRequest(metadata) - val graphId = request.getContext.getOrDefault("graph_id", "").asInstanceOf[String] - val version = request.getContext.getOrDefault("version", "").asInstanceOf[String] - val externalProps = if (StringUtils.equalsIgnoreCase(AssessmentConstants.QUESTIONSET_MIME_TYPE, node.getMetadata.getOrDefault("mimeType", "").asInstanceOf[String])) { - DefinitionNode.getExternalProps(graphId, version, AssessmentConstants.QUESTIONSET_SCHEMA_NAME).diff(List("hierarchy")) - } else { - DefinitionNode.getExternalProps(graphId, version, AssessmentConstants.QUESTION_SCHEMA_NAME) - } - val readReq = new Request() - readReq.setContext(request.getContext) - readReq.put("identifier", node.getIdentifier) - readReq.put("fields", externalProps.asJava) - DataNode.read(readReq).map(node => { - val metadata: util.Map[String, AnyRef] = NodeUtil.serialize(node, externalProps.asJava, node.getObjectType.toLowerCase.replace - ("image", ""), request.getContext.get("version").asInstanceOf[String]) - externalProps.foreach(prop => { - val propValue = metadata.get(prop) - if (metadata.containsKey(prop) && propValue != null) { - req.put(prop, propValue) - } - }) - Future(req) - }).flatMap(f=>f) - } - - def getOriginData(metadata: util.Map[String, AnyRef], copyType: String): java.util.Map[String, AnyRef] = (Map(AssessmentConstants.COPY_TYPE -> copyType) ++ originMetadataKeys.asScala.filter(key => metadata.containsKey(key)).map(key => key -> metadata.get(key)).toMap).asJava - - def validateRequest(request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Unit = { - val keysNotPresent = AssessmentConstants.REQUIRED_KEYS.filter(key => emptyCheckFilter(request.getRequest.getOrDefault(key, ""))) - if (keysNotPresent.nonEmpty) - throw new ClientException(AssessmentConstants.ERR_INVALID_REQUEST, "Please provide valid value for " + keysNotPresent) - } - - def validateShallowCopyReq(node: Node, request: Request) = { - val copyType: String = request.getRequest.get("copyType").asInstanceOf[String] - if (StringUtils.equalsIgnoreCase("shallow", copyType) && !StringUtils.equalsIgnoreCase("Live", node.getMetadata.get("status").asInstanceOf[String])) - throw new ClientException(AssessmentConstants.ERR_INVALID_REQUEST, "QuestionSet With Status " + node.getMetadata.get(AssessmentConstants.STATUS).asInstanceOf[String].toLowerCase + " Cannot Be Partially (Shallow) Copied.") - if(StringUtils.equalsIgnoreCase("shallow", copyType) && StringUtils.equalsIgnoreCase(request.get(AssessmentConstants.MODE).asInstanceOf[String], "edit")) - request.getRequest.remove(AssessmentConstants.MODE) - } - - def emptyCheckFilter(key: AnyRef): Boolean = key match { - case k: String => k.asInstanceOf[String].isEmpty - case k: util.Map[String, AnyRef] => MapUtils.isEmpty(k.asInstanceOf[util.Map[String, AnyRef]]) - case k: util.List[String] => CollectionUtils.isEmpty(k.asInstanceOf[util.List[String]]) - case _ => true - } - - def cleanUpCopiedData(metadata: util.Map[String, AnyRef], copyType: String): util.Map[String, AnyRef] = { - if (StringUtils.equalsIgnoreCase(AssessmentConstants.COPY_TYPE_SHALLOW, copyType)) { - metadata.keySet().removeAll(metadataNotTobeCopied.asScala.toList.filter(str => !str.contains("dial")).asJava) - } else metadata.keySet().removeAll(metadataNotTobeCopied) - metadata - } -} \ No newline at end of file diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/AssessmentContants.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/AssessmentContants.scala deleted file mode 100644 index 16e47ccde..000000000 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/AssessmentContants.scala +++ /dev/null @@ -1,48 +0,0 @@ -package org.sunbird.utils - -object AssessmentConstants { - val REQUIRED_KEYS: List[String] = List("createdBy", "createdFor") - val ERR_INVALID_REQUEST: String = "ERR_INVALID_REQUEST" - val ERR_INVALID_OBJECT_TYPE: String = "ERR_INVALID_OBJECT_TYPE" - val COPY_SCHEME: String = "copyScheme" - val MIME_TYPE: String = "mimeType" - val QUESTIONSET_MIME_TYPE: String = "application/vnd.sunbird.questionset" - val STATUS: String = "status" - val COPY_TYPE: String = "copyType" - val SCHEMA_NAME: String = "schemaName" - val VERSION: String = "version" - val ROOT_ID: String = "rootId" - val MODE: String = "mode" - val COPY_TYPE_SHALLOW: String = "shallow" - val QUESTIONSET_SCHEMA_NAME: String = "questionset" - val SCHEMA_VERSION: String = "1.0" - val IDENTIFIER: String = "identifier" - val QUESTION: String = "question" - val HIERARCHY: String = "hierarchy" - val CHILDREN: String = "children" - val ORIGIN: String = "origin" - val ORIGIN_DATA: String = "originData" - val CONTENT_TYPE: String = "contentType" - val ROOT: String = "root" - val NODES_MODIFIED: String = "nodesModified" - val VISIBILITY: String = "visibility" - val METADATA: String = "metadata" - val VERSION_KEY: String = "versionKey" - val PRIMARY_CATEGORY : String = "primaryCategory" - val QUESTIONSET : String = "questionSet" - val OBJECT_TYPE : String = "objectType" - val COPY_TYPE_DEEP: String = "deep" - val QUESTION_MIME_TYPE: String = "application/vnd.sunbird.question" - val QUESTION_SCHEMA_NAME: String = "question" - val VISIBILITY_PARENT: String = "Parent" - val VISIBILITY_DEFAULT: String = "Default" - val BRANCHING_LOGIC: String = "branchingLogic" - val COPY_OF: String = "copyOf" - val CONTAINS_BL: String = "containsBL" - val IDENTIFIERS: String = "identifiers" - val IS_NEW: String = "isNew" - val TARGET: String = "target" - val PRE_CONDITION: String = "preCondition" - val SOURCE: String = "source" - val PRE_CONDITION_VAR : String = "var" -} diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/BranchingUtil.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/BranchingUtil.scala deleted file mode 100644 index 791079d42..000000000 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/BranchingUtil.scala +++ /dev/null @@ -1,121 +0,0 @@ -package org.sunbird.utils - -import org.apache.commons.lang3.StringUtils -import org.sunbird.common.dto.Request - -import java.util -import scala.collection.JavaConverters._ -import scala.collection.JavaConversions.{asScalaBuffer} - -object BranchingUtil { - - def generateBranchingRecord(nodesModified: util.HashMap[String, AnyRef]): util.HashMap[String, AnyRef] = { - val idSet = nodesModified.keySet().asScala.toList - val branchingRecord = new util.HashMap[String, AnyRef]() - idSet.map(id => { - val nodeMetaData = nodesModified.getOrDefault(id, new util.HashMap()).asInstanceOf[util.Map[String, AnyRef]].getOrDefault(AssessmentConstants.METADATA, new util.HashMap()).asInstanceOf[util.Map[String, AnyRef]] - val containsBL = nodeMetaData.containsKey(AssessmentConstants.BRANCHING_LOGIC) - branchingRecord.put(id, new util.HashMap[String, AnyRef]() { - { - if (containsBL) { - put(AssessmentConstants.BRANCHING_LOGIC, nodeMetaData.get(AssessmentConstants.BRANCHING_LOGIC)) - nodeMetaData.remove(AssessmentConstants.BRANCHING_LOGIC) - } - put(AssessmentConstants.CONTAINS_BL, containsBL.asInstanceOf[AnyRef]) - put(AssessmentConstants.COPY_OF, nodeMetaData.get(AssessmentConstants.COPY_OF).asInstanceOf[String]) - } - }) - nodeMetaData.remove(AssessmentConstants.COPY_OF) - }) - branchingRecord - } - - def hierarchyRequestModifier(request: Request, branchingRecord: util.HashMap[String, AnyRef], identifiers: util.Map[String, String]) = { - val nodesModified: java.util.HashMap[String, AnyRef] = request.getRequest.get(HierarchyConstants.NODES_MODIFIED).asInstanceOf[java.util.HashMap[String, AnyRef]] - val hierarchy: java.util.HashMap[String, AnyRef] = request.getRequest.get(HierarchyConstants.HIERARCHY).asInstanceOf[java.util.HashMap[String, AnyRef]] - val oldToNewIdMap = getIdentifierMapping(branchingRecord, identifiers) - branchingRecord.keySet().asScala.toList.map(id => { - val nodeInfo = branchingRecord.get(id).asInstanceOf[util.HashMap[String, AnyRef]] - val node = nodesModified.get(id).asInstanceOf[util.HashMap[String, AnyRef]] - val nodeMetaData = node.get(AssessmentConstants.METADATA).asInstanceOf[util.HashMap[String, AnyRef]] - val newId = identifiers.get(id) - if (nodeInfo.get(AssessmentConstants.CONTAINS_BL).asInstanceOf[Boolean]) { - val branchingLogic = nodeInfo.get(AssessmentConstants.BRANCHING_LOGIC).asInstanceOf[util.HashMap[String, AnyRef]] - branchingLogicModifier(branchingLogic, oldToNewIdMap) - nodeMetaData.put(AssessmentConstants.BRANCHING_LOGIC, branchingLogic) - } - node.put(AssessmentConstants.IS_NEW, false.asInstanceOf[AnyRef]) - nodesModified.remove(id) - nodesModified.put(newId, node) - }) - hierarchy.keySet().asScala.toList.map(id => { - val nodeHierarchy = hierarchy.get(id).asInstanceOf[util.HashMap[String, AnyRef]] - val children = nodeHierarchy.get(AssessmentConstants.CHILDREN).asInstanceOf[util.ArrayList[String]] - val newChildrenList = new util.ArrayList[String] - children.map(identifier => { - if (identifiers.containsKey(identifier)) newChildrenList.add(identifiers.get(identifier)) else newChildrenList.add(identifier) - }) - nodeHierarchy.put(AssessmentConstants.CHILDREN, newChildrenList) - if (identifiers.containsKey(id)) { - hierarchy.remove(id) - hierarchy.put(identifiers.get(id), nodeHierarchy) - } - }) - request - } - - def branchingLogicModifier(branchingLogic: util.HashMap[String, AnyRef], oldToNewIdMap: util.Map[String, String]): Unit = { - branchingLogic.keySet().asScala.toList.map(identifier => { - val nodeBL = branchingLogic.get(identifier).asInstanceOf[util.HashMap[String, AnyRef]] - nodeBL.keySet().asScala.toList.map(key => { - if (StringUtils.equalsIgnoreCase(key, AssessmentConstants.TARGET)) branchingLogicArrayHandler(nodeBL, AssessmentConstants.TARGET, oldToNewIdMap) - else if (StringUtils.equalsIgnoreCase(key, AssessmentConstants.PRE_CONDITION)) preConditionHandler(nodeBL, oldToNewIdMap) - else if (StringUtils.equalsIgnoreCase(key, AssessmentConstants.SOURCE)) branchingLogicArrayHandler(nodeBL, AssessmentConstants.SOURCE, oldToNewIdMap) - }) - if (oldToNewIdMap.containsKey(identifier)) { - branchingLogic.put(oldToNewIdMap.get(identifier), nodeBL) - branchingLogic.remove(identifier) - } - }) - } - - def getIdentifierMapping(branchingRecord: util.HashMap[String, AnyRef], identifiers: util.Map[String, String]): util.Map[String, String] = { - val oldToNewIdMap = new util.HashMap[String, String]() - branchingRecord.keySet().asScala.toList.map(id => { - val nodeInfo = branchingRecord.get(id).asInstanceOf[util.HashMap[String, AnyRef]] - val newId = identifiers.get(id) - val oldId = nodeInfo.get(AssessmentConstants.COPY_OF).asInstanceOf[String] - oldToNewIdMap.put(oldId, newId) - }) - oldToNewIdMap - } - - def branchingLogicArrayHandler(nodeBL: util.HashMap[String, AnyRef], name: String, oldToNewIdMap: util.Map[String, String]) = { - val branchingLogicArray = nodeBL.getOrDefault(name, new util.ArrayList[String]).asInstanceOf[util.ArrayList[String]] - val newBranchingLogicArray = new util.ArrayList[String]() - branchingLogicArray.map(id => { - if (oldToNewIdMap.containsKey(id)) { - newBranchingLogicArray.add(oldToNewIdMap.get(id)) - } else newBranchingLogicArray.add(id) - }) - nodeBL.put(name, newBranchingLogicArray) - } - - def preConditionHandler(nodeBL: util.HashMap[String, AnyRef], oldToNewIdMap: util.Map[String, String]): Unit = { - val preCondition = nodeBL.get(AssessmentConstants.PRE_CONDITION).asInstanceOf[util.HashMap[String, AnyRef]] - preCondition.keySet().asScala.toList.map(key => { - val conjunctionArray = preCondition.get(key).asInstanceOf[util.ArrayList[String]] - val condition = conjunctionArray.get(0).asInstanceOf[util.HashMap[String, AnyRef]] - condition.keySet().asScala.toList.map(logicOp => { - val conditionArray = condition.get(logicOp).asInstanceOf[util.ArrayList[String]] - val sourceQuestionRecord = conditionArray.get(0).asInstanceOf[util.HashMap[String, AnyRef]] - val preConditionVar = sourceQuestionRecord.get(AssessmentConstants.PRE_CONDITION_VAR).asInstanceOf[String] - val stringArray = preConditionVar.split("\\.") - if (oldToNewIdMap.containsKey(stringArray(0))) { - val newString = oldToNewIdMap.get(stringArray(0)) + "." + stringArray.drop(1).mkString(".") - sourceQuestionRecord.put(AssessmentConstants.PRE_CONDITION_VAR, newString) - } - }) - }) - } -} diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/RequestUtil.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/RequestUtil.scala deleted file mode 100644 index c96e218b0..000000000 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/RequestUtil.scala +++ /dev/null @@ -1,43 +0,0 @@ -package org.sunbird.utils - -import org.sunbird.common.Platform -import org.sunbird.common.dto.Request -import org.sunbird.common.exception.{ClientException, ErrorCodes} -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.graph.schema.DefinitionNode - -import scala.concurrent.ExecutionContext -import scala.collection.convert.ImplicitConversions._ - -object RequestUtil { - - private val SYSTEM_UPDATE_ALLOWED_CONTENT_STATUS = List("Live", "Unlisted") - val questionListLimit = if (Platform.config.hasPath("question.list.limit")) Platform.config.getInt("question.list.limit") else 20 - - def restrictProperties(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Unit = { - val graphId = request.getContext.getOrDefault("graph_id","").asInstanceOf[String] - val version = request.getContext.getOrDefault("version","").asInstanceOf[String] - val objectType = request.getContext.getOrDefault("objectType", "").asInstanceOf[String] - val schemaName = request.getContext.getOrDefault("schemaName","").asInstanceOf[String] - val operation = request.getOperation.toLowerCase.replace(objectType.toLowerCase, "") - val restrictedProps =DefinitionNode.getRestrictedProperties(graphId, version, operation, schemaName) - if (restrictedProps.exists(prop => request.getRequest.containsKey(prop))) throw new ClientException("ERROR_RESTRICTED_PROP", "Properties in list " + restrictedProps.mkString("[", ", ", "]") + " are not allowed in request") - } - - def validateRequest(request: Request): Unit = { - if (request.getRequest.isEmpty) - throw new ClientException(ErrorCodes.ERR_BAD_REQUEST.name(), s"Request Body cannot be Empty.") - - if (request.get("status") != null && SYSTEM_UPDATE_ALLOWED_CONTENT_STATUS.contains(request.get("status").asInstanceOf[String])) - throw new ClientException(ErrorCodes.ERR_BAD_REQUEST.name(), s"Cannot update content status to : ${SYSTEM_UPDATE_ALLOWED_CONTENT_STATUS.mkString("[", ", ", "]")}.") - - } - - def validateListRequest(request: Request): Unit = { - if (request.get("identifiers") == null || request.get("identifiers").asInstanceOf[java.util.List[String]].isEmpty) - throw new ClientException(ErrorCodes.ERR_BAD_REQUEST.name(), "Required field identifier is missing or empty.") - - if (request.get("identifiers").asInstanceOf[java.util.List[String]].length > questionListLimit) - throw new ClientException(ErrorCodes.ERR_BAD_REQUEST.name(), "Request contains more than the permissible limit of identifier: 20.") - } -} diff --git a/assessment-api/assessment-actors/src/test/resources/application.conf b/assessment-api/assessment-actors/src/test/resources/application.conf deleted file mode 100644 index b9ad82663..000000000 --- a/assessment-api/assessment-actors/src/test/resources/application.conf +++ /dev/null @@ -1,426 +0,0 @@ -# This is the main configuration file for the application. -# https://www.playframework.com/documentation/latest/ConfigFile -# ~~~~~ -# Play uses HOCON as its configuration file format. HOCON has a number -# of advantages over other config formats, but there are two things that -# can be used when modifying settings. -# -# You can include other configuration files in this main application.conf file: -#include "extra-config.conf" -# -# You can declare variables and substitute for them: -#mykey = ${some.value} -# -# And if an environment variable exists when there is no other substitution, then -# HOCON will fall back to substituting environment variable: -#mykey = ${JAVA_HOME} - -## Akka -# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration -# https://www.playframework.com/documentation/latest/JavaAkka#Configuration -# ~~~~~ -# Play uses Akka internally and exposes Akka Streams and actors in Websockets and -# other streaming HTTP responses. -akka { - # "akka.log-config-on-start" is extraordinarly useful because it log the complete - # configuration at INFO level, including defaults and overrides, so it s worth - # putting at the very top. - # - # Put the following in your conf/logback.xml file: - # - # - # - # And then uncomment this line to debug the configuration. - # - #log-config-on-start = true -} - -## Secret key -# http://www.playframework.com/documentation/latest/ApplicationSecret -# ~~~~~ -# The secret key is used to sign Play's session cookie. -# This must be changed for production, but we don't recommend you change it in this file. -play.http.secret.key = a-long-secret-to-calm-the-rage-of-the-entropy-gods - -## Modules -# https://www.playframework.com/documentation/latest/Modules -# ~~~~~ -# Control which modules are loaded when Play starts. Note that modules are -# the replacement for "GlobalSettings", which are deprecated in 2.5.x. -# Please see https://www.playframework.com/documentation/latest/GlobalSettings -# for more information. -# -# You can also extend Play functionality by using one of the publically available -# Play modules: https://playframework.com/documentation/latest/ModuleDirectory -play.modules { - # By default, Play will load any class called Module that is defined - # in the root package (the "app" directory), or you can define them - # explicitly below. - # If there are any built-in modules that you want to enable, you can list them here. - #enabled += my.application.Module - - # If there are any built-in modules that you want to disable, you can list them here. - #disabled += "" -} - -## IDE -# https://www.playframework.com/documentation/latest/IDE -# ~~~~~ -# Depending on your IDE, you can add a hyperlink for errors that will jump you -# directly to the code location in the IDE in dev mode. The following line makes -# use of the IntelliJ IDEA REST interface: -#play.editor="http://localhost:63342/api/file/?file=%s&line=%s" - -## Internationalisation -# https://www.playframework.com/documentation/latest/JavaI18N -# https://www.playframework.com/documentation/latest/ScalaI18N -# ~~~~~ -# Play comes with its own i18n settings, which allow the user's preferred language -# to map through to internal messages, or allow the language to be stored in a cookie. -play.i18n { - # The application languages - langs = [ "en" ] - - # Whether the language cookie should be secure or not - #langCookieSecure = true - - # Whether the HTTP only attribute of the cookie should be set to true - #langCookieHttpOnly = true -} - -## Play HTTP settings -# ~~~~~ -play.http { - ## Router - # https://www.playframework.com/documentation/latest/JavaRouting - # https://www.playframework.com/documentation/latest/ScalaRouting - # ~~~~~ - # Define the Router object to use for this application. - # This router will be looked up first when the application is starting up, - # so make sure this is the entry point. - # Furthermore, it's assumed your route file is named properly. - # So for an application router like `my.application.Router`, - # you may need to define a router file `conf/my.application.routes`. - # Default to Routes in the root package (aka "apps" folder) (and conf/routes) - #router = my.application.Router - - ## Action Creator - # https://www.playframework.com/documentation/latest/JavaActionCreator - # ~~~~~ - #actionCreator = null - - ## ErrorHandler - # https://www.playframework.com/documentation/latest/JavaRouting - # https://www.playframework.com/documentation/latest/ScalaRouting - # ~~~~~ - # If null, will attempt to load a class called ErrorHandler in the root package, - #errorHandler = null - - ## Session & Flash - # https://www.playframework.com/documentation/latest/JavaSessionFlash - # https://www.playframework.com/documentation/latest/ScalaSessionFlash - # ~~~~~ - session { - # Sets the cookie to be sent only over HTTPS. - #secure = true - - # Sets the cookie to be accessed only by the server. - #httpOnly = true - - # Sets the max-age field of the cookie to 5 minutes. - # NOTE: this only sets when the browser will discard the cookie. Play will consider any - # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout, - # you need to put a timestamp in the session and check it at regular intervals to possibly expire it. - #maxAge = 300 - - # Sets the domain on the session cookie. - #domain = "example.com" - } - - flash { - # Sets the cookie to be sent only over HTTPS. - #secure = true - - # Sets the cookie to be accessed only by the server. - #httpOnly = true - } -} - -## Netty Provider -# https://www.playframework.com/documentation/latest/SettingsNetty -# ~~~~~ -play.server.netty { - # Whether the Netty wire should be logged - log.wire = true - - # If you run Play on Linux, you can use Netty's native socket transport - # for higher performance with less garbage. - transport = "native" -} - -## WS (HTTP Client) -# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS -# ~~~~~ -# The HTTP client primarily used for REST APIs. The default client can be -# configured directly, but you can also create different client instances -# with customized settings. You must enable this by adding to build.sbt: -# -# libraryDependencies += ws // or javaWs if using java -# -play.ws { - # Sets HTTP requests not to follow 302 requests - #followRedirects = false - - # Sets the maximum number of open HTTP connections for the client. - #ahc.maxConnectionsTotal = 50 - - ## WS SSL - # https://www.playframework.com/documentation/latest/WsSSL - # ~~~~~ - ssl { - # Configuring HTTPS with Play WS does not require programming. You can - # set up both trustManager and keyManager for mutual authentication, and - # turn on JSSE debugging in development with a reload. - #debug.handshake = true - #trustManager = { - # stores = [ - # { type = "JKS", path = "exampletrust.jks" } - # ] - #} - } -} - -## Cache -# https://www.playframework.com/documentation/latest/JavaCache -# https://www.playframework.com/documentation/latest/ScalaCache -# ~~~~~ -# Play comes with an integrated cache API that can reduce the operational -# overhead of repeated requests. You must enable this by adding to build.sbt: -# -# libraryDependencies += cache -# -play.cache { - # If you want to bind several caches, you can bind the individually - #bindCaches = ["db-cache", "user-cache", "session-cache"] -} - -## Filter Configuration -# https://www.playframework.com/documentation/latest/Filters -# ~~~~~ -# There are a number of built-in filters that can be enabled and configured -# to give Play greater security. -# -play.filters { - - # Enabled filters are run automatically against Play. - # CSRFFilter, AllowedHostFilters, and SecurityHeadersFilters are enabled by default. - enabled = [] - - # Disabled filters remove elements from the enabled list. - # disabled += filters.CSRFFilter - - - ## CORS filter configuration - # https://www.playframework.com/documentation/latest/CorsFilter - # ~~~~~ - # CORS is a protocol that allows web applications to make requests from the browser - # across different domains. - # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has - # dependencies on CORS settings. - cors { - # Filter paths by a whitelist of path prefixes - #pathPrefixes = ["/some/path", ...] - - # The allowed origins. If null, all origins are allowed. - #allowedOrigins = ["http://www.example.com"] - - # The allowed HTTP methods. If null, all methods are allowed - #allowedHttpMethods = ["GET", "POST"] - } - - ## Security headers filter configuration - # https://www.playframework.com/documentation/latest/SecurityHeaders - # ~~~~~ - # Defines security headers that prevent XSS attacks. - # If enabled, then all options are set to the below configuration by default: - headers { - # The X-Frame-Options header. If null, the header is not set. - #frameOptions = "DENY" - - # The X-XSS-Protection header. If null, the header is not set. - #xssProtection = "1; mode=block" - - # The X-Content-Type-Options header. If null, the header is not set. - #contentTypeOptions = "nosniff" - - # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set. - #permittedCrossDomainPolicies = "master-only" - - # The Content-Security-Policy header. If null, the header is not set. - #contentSecurityPolicy = "default-src 'self'" - } - - ## Allowed hosts filter configuration - # https://www.playframework.com/documentation/latest/AllowedHostsFilter - # ~~~~~ - # Play provides a filter that lets you configure which hosts can access your application. - # This is useful to prevent cache poisoning attacks. - hosts { - # Allow requests to example.com, its subdomains, and localhost:9000. - #allowed = [".example.com", "localhost:9000"] - } -} - -# Learning-Service Configuration -content.metadata.visibility.parent=["textbookunit", "courseunit", "lessonplanunit"] - -# Cassandra Configuration -content.keyspace.name=content_store -content.keyspace.table=content_data -#TODO: Add Configuration for assessment. e.g: question_data -orchestrator.keyspace.name=script_store -orchestrator.keyspace.table=script_data -cassandra.lp.connection="127.0.0.1:9042,127.0.0.2:9042,127.0.0.3:9042" -cassandra.lpa.connection="127.0.0.1:9042,127.0.0.2:9042,127.0.0.3:9042" - -# Redis Configuration -redis.host=localhost -redis.port=6379 -redis.maxConnections=128 - -#Condition to enable publish locally -content.publish_task.enabled=true - -#directory location where store unzip file -dist.directory=/data/tmp/dist/ -output.zipfile=/data/tmp/story.zip -source.folder=/data/tmp/temp2/ -save.directory=/data/tmp/temp/ - -# Content 2 vec analytics URL -CONTENT_TO_VEC_URL="http://172.31.27.233:9000/content-to-vec" - -# FOR CONTENT WORKFLOW PIPELINE (CWP) - -#--Content Workflow Pipeline Mode -OPERATION_MODE=TEST - -#--Maximum Content Package File Size Limit in Bytes (50 MB) -MAX_CONTENT_PACKAGE_FILE_SIZE_LIMIT=52428800 - -#--Maximum Asset File Size Limit in Bytes (20 MB) -MAX_ASSET_FILE_SIZE_LIMIT=20971520 - -#--No of Retry While File Download Fails -RETRY_ASSET_DOWNLOAD_COUNT=1 - -#Google-vision-API -google.vision.tagging.enabled = false - -#Orchestrator env properties -env="https://dev.ekstep.in/api/learning" - -#Current environment -cloud_storage.env=dev - - -#Folder configuration -cloud_storage.content.folder=content -cloud_storage.asset.folder=assets -cloud_storage.artefact.folder=artifact -cloud_storage.bundle.folder=bundle -cloud_storage.media.folder=media -cloud_storage.ecar.folder=ecar_files - -# Media download configuration -content.media.base.url="https://dev.open-sunbird.org" -plugin.media.base.url="https://dev.open-sunbird.org" - -# Configuration -graph.dir=/data/testingGraphDB -akka.request_timeout=30 -environment.id=10000000 -graph.ids=["domain"] -graph.passport.key.base=31b6fd1c4d64e745c867e61a45edc34a -route.domain="bolt://localhost:7687" -route.bolt.write.domain="bolt://localhost:7687" -route.bolt.read.domain="bolt://localhost:7687" -route.bolt.comment.domain="bolt://localhost:7687" -route.all="bolt://localhost:7687" -route.bolt.write.all="bolt://localhost:7687" -route.bolt.read.all="bolt://localhost:7687" -route.bolt.comment.all="bolt://localhost:7687" - -shard.id=1 -platform.auth.check.enabled=false -platform.cache.ttl=3600000 - - -framework.max_term_creation_limit=200 - -# Enable Suggested Framework in Get Channel API. -channel.fetch.suggested_frameworks=true - - -#Top N Config for Search Telemetry -telemetry_env=dev -telemetry.search.topn=5 - -installation.id=ekstep - - -channel.default="in.ekstep" - - -# Language-Code Configuration -platform.language.codes=["as","bn","en","gu","hi","hoc","jun","ka","mai","mr","unx","or","san","sat","ta","te","urd", "pj"] - - -framework.categories_cached=["subject", "medium", "gradeLevel", "board"] -framework.cache.ttl=86400 -framework.cache.read=false - - -# Max size(width/height) of thumbnail in pixels -max.thumbnail.size.pixels=150 - -schema.base_path="../../schemas/" - -assessment.skip.validation=true -uestion.keyspace="dev_question_store" -questionset.keyspace="dev_hierarchy_store" -cassandra { - lp { - connection: "127.0.0.1:9042,127.0.0.1:9042,127.0.0.1:9042" - } - lpa { - connection: "127.0.0.1:9042" - } -} -questionset.keyspace = "dev_hierarchy_store" - -import { - request_size_limit = 200 - output_topic_name = "local.auto.creation.job.request" - required_props { - question = ["name", "code", "mimeType", "framework", "channel"] - questionset = ["name", "code", "mimeType", "framework", "channel"] - } - remove_props { - question = [] - questionset = [] - } -} - -assessment.copy.origin_data=["name", "author", "license", "organisation"] -assessment.copy.props_to_remove=["downloadUrl", "artifactUrl", "variants", - "createdOn", "collections", "children", "lastUpdatedOn", "SYS_INTERNAL_LAST_UPDATED_ON", - "versionKey", "s3Key", "status", "pkgVersion", "toc_url", "mimeTypesCount", - "contentTypesCount", "leafNodesCount", "childNodes", "prevState", "lastPublishedOn", - "flagReasons", "compatibilityLevel", "size", "publishChecklist", "publishComment", - "LastPublishedBy", "rejectReasons", "rejectComment", "gradeLevel", "subject", - "medium", "board", "topic", "purpose", "subtopic", "contentCredits", - "owner", "collaborators", "creators", "contributors", "badgeAssertions", "dialcodes", - "concepts", "keywords", "reservedDialcodes", "dialcodeRequired", "leafNodes", "sYS_INTERNAL_LAST_UPDATED_ON", "prevStatus", "lastPublishedBy", "streamingUrl"] - - diff --git a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/BaseSpec.scala b/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/BaseSpec.scala deleted file mode 100644 index b1abb5a29..000000000 --- a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/BaseSpec.scala +++ /dev/null @@ -1,78 +0,0 @@ -package org.sunbird.actors - -import java.util -import java.util.concurrent.TimeUnit - -import akka.actor.{ActorSystem, Props} -import akka.testkit.TestKit -import org.scalatest.{FlatSpec, Matchers} -import org.sunbird.common.dto.{Request, Response} -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.graph.dac.model.Node - -import scala.concurrent.duration.FiniteDuration - -class BaseSpec extends FlatSpec with Matchers { - val system = ActorSystem.create("system") - - def testUnknownOperation(props: Props, request: Request)(implicit oec: OntologyEngineContext) = { - request.setOperation("unknown") - val response = callActor(request, props) - assert("failed".equals(response.getParams.getStatus)) - } - - def callActor(request: Request, props: Props): Response = { - val probe = new TestKit(system) - val actorRef = system.actorOf(props) - actorRef.tell(request, probe.testActor) - probe.expectMsgType[Response](FiniteDuration.apply(100, TimeUnit.SECONDS)) - } - - def getNode(objectType: String, metadata: Option[util.Map[String, AnyRef]]): Node = { - val node = new Node("domain", "DATA_NODE", objectType) - node.setGraphId("domain") - val nodeMetadata = metadata.getOrElse(new util.HashMap[String, AnyRef]() {{ - put("name", "Sunbird Node") - put("code", "sunbird-node") - put("status", "Draft") - }}) - node.setNodeType("DATA_NODE") - node.setMetadata(nodeMetadata) - node.setObjectType(objectType) - node.setIdentifier("test_id") - node - } - def getCategoryNode(): util.List[Node] = { - val node = new Node() - node.setIdentifier("board") - node.setNodeType("DATA_NODE") - node.setObjectType("Category") - node.setMetadata(new util.HashMap[String, AnyRef]() { - { - put("code", "board") - put("orgIdFieldName", "boardIds") - put("targetIdFieldName", "targetBoardIds") - put("searchIdFieldName", "se_boardIds") - put("searchLabelFieldName", "se_boards") - put("status", "Live") - } - }) - util.Arrays.asList(node) - } - - def getNode(identifier: String, objectType: String, metadata: Option[util.Map[String, AnyRef]]): Node = { - val node = new Node("domain", "DATA_NODE", objectType) - node.setGraphId("domain") - val nodeMetadata = metadata.getOrElse(new util.HashMap[String, AnyRef]() {{ - put("name", "Question 1") - put("code", "ques.1") - put("status", "Draft") - put("primaryCategory", "Multiple Choice Question") - }}) - node.setNodeType("DATA_NODE") - node.setMetadata(nodeMetadata) - node.setObjectType(objectType) - node.setIdentifier(identifier) - node - } -} diff --git a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/CopySpec.scala b/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/CopySpec.scala deleted file mode 100644 index b5cbd725e..000000000 --- a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/CopySpec.scala +++ /dev/null @@ -1,380 +0,0 @@ -package org.sunbird.actors - -import org.apache.commons.lang3.StringUtils -import org.sunbird.common.dto.{Request, Response, ResponseParams} -import org.sunbird.graph.dac.model.Node -import org.sunbird.utils.AssessmentConstants -import org.sunbird.common.exception.ResponseCode - -import java.util -import scala.collection.JavaConversions.mapAsJavaMap -import scala.collection.JavaConverters.asJavaIterableConverter -import scala.collection.mutable - -object CopySpec { - - private def getQuestionSetRequest(): Request = { - val request = new Request() - request.setContext(new java.util.HashMap[String, AnyRef]() { - { - put("graph_id", "domain") - put("version", "1.0") - put("objectType", "QuestionSet") - put("schemaName", "questionset") - } - }) - request.setObjectType("QuestionSet") - request - } - - def getQuestionSetCopyRequest(): Request = { - val request = getQuestionSetRequest() - request.putAll(new util.HashMap[String, AnyRef]() { - { - put("createdBy", "Shikshalokam") - put("createdFor", new util.ArrayList[String]() { - { - add("Shikshalokam") - } - }) - put("name", "NewRootNode") - } - }) - request - } - - def getInvalidQuestionSetCopyRequest(): Request = { - val request = getQuestionSetRequest() - request.putAll(new util.HashMap[String, AnyRef]() { - { - put("name", "NewRootNode") - } - }) - request - } - - def getInvalidQuestionCopyRequest(): Request = { - val request = getQuestionRequest() - request.putAll(new util.HashMap[String, AnyRef]() { - { - put("name", "NewQuestion") - } - }) - request - } - - private def getQuestionRequest(): Request = { - val request = new Request() - request.setContext(new java.util.HashMap[String, AnyRef]() { - { - put("graph_id", "domain") - put("version", "1.0") - put("objectType", "Question") - put("schemaName", "question") - } - }) - request.setObjectType("Question") - request - } - - def getQuestionCopyRequest(): Request = { - val request = getQuestionRequest() - request.putAll(new util.HashMap[String, AnyRef]() { - { - put("createdBy", "Shikshalokam") - put("createdFor", new util.ArrayList[String]() { - { - add("Shikshalokam") - } - }) - put("name", "NewQuestion") - } - }) - request - } - - private def getNode(objectType: String, identifier: String, primaryCategory: String, visibility: String, name: String, id: Long, - status: String): Node = { - val node = new Node("domain", "DATA_NODE", objectType) - node.setGraphId("domain") - node.setIdentifier(identifier) - node.setId(id) - node.setNodeType("DATA_NODE") - node.setObjectType(objectType) - node.setMetadata(new util.HashMap[String, AnyRef]() { - { - put("code", "xyz") - put("mimeType", { - if (StringUtils.endsWithIgnoreCase(objectType, AssessmentConstants.QUESTIONSET_SCHEMA_NAME)) { - AssessmentConstants.QUESTIONSET_MIME_TYPE - } else { - AssessmentConstants.QUESTION_MIME_TYPE - } - }) - put("createdOn", "2022-03-16T14:35:11.040+0530") - put("objectType", objectType) - put("primaryCategory", primaryCategory) - put("contentDisposition", "inline") - put("contentEncoding", "gzip") - put("lastUpdatedOn", "2022-03-16T14:38:51.287+0530") - put("showSolutions", "No") - put("allowAnonymousAccess", "Yes") - put("identifier", identifier) - put("lastStatusChangedOn", "2022-03-16T14:35:11.040+0530") - put("visibility", visibility) - put("showTimer", "No") - put("version", 1.asInstanceOf[Number]) - put("showFeedback", "No") - put("versionKey", "1234") - put("license", "CC BY 4.0") - put("compatibilityLevel", 5.asInstanceOf[Number]) - put("name", name) - put("status", status) - } - }) - node - } - - def getExistingRootNode(): Node = { - val node = getNode("QuestionSet", "do_1234", "Observation", AssessmentConstants.VISIBILITY_DEFAULT, "ExistingRootNode", 1234, - "Live") - node.getMetadata.put("childNodes", Array("do_5678")) - node - } - - def getNewRootNode(): Node = { - val node = getNode("QuestionSet", "do_9876", "Observation", AssessmentConstants.VISIBILITY_DEFAULT, "NewRootNode", 0, "Draft") - node.getMetadata.put("origin", "do_1234") - node.getMetadata.put("originData", "{\"name\":\"ExistingRootNode\",\"copyType\":\"deep\"}") - node.getMetadata.put("createdFor", Array("ShikshaLokam")) - node.getMetadata.put("createdBy", "ShikshaLokam") - node.setExternalData(new util.HashMap[String, AnyRef]() { - { - put("instructions", "This is the instruction.") - put("outcomeDeclaration", "This is outcomeDeclaration.") - } - }) - node - } - - def getExistingQuestionNode(): Node = { - val node = getNode("Question", "do_1234", "Slider", AssessmentConstants.VISIBILITY_DEFAULT, "ExistingQuestionNode", 1234, - "Live") - node - } - - def getQuestionNode(): Node = { - val node = getNode("Question", "do_5678", "Slider", AssessmentConstants.VISIBILITY_PARENT, "Question1", 0, "Draft") - node.setExternalData(new util.HashMap[String, AnyRef]() { - { - put("answer", "This is Answer.") - put("body", "This is Body.") - } - }) - node - } - - def getNewQuestionNode(): Node = { - val node = getNode("Question", "do_5678", "Slider", AssessmentConstants.VISIBILITY_DEFAULT, "NewQuestion", 0, "Draft") - node.setExternalData(new util.HashMap[String, AnyRef]() { - { - put("answer", "This is Answer.") - put("body", "This is Body.") - } - }) - node.getMetadata.put("origin", "do_1234") - node.getMetadata.put("originData", "{\\\"name\\\":\\\"Q2\\\",\\\"copyType\\\":\\\"deep\\\",\\\"license\\\":\\\"CC BY 4.0\\\"}") - node.getMetadata.put("createdFor", Array("ShikshaLokam")) - node.getMetadata.put("createdBy", "ShikshaLokam") - node - } - - def getSuccessfulResponse(): Response = { - val response = new Response - response.setVer("3.0") - val responseParams = new ResponseParams - responseParams.setStatus("successful") - response.setParams(responseParams) - response.setResponseCode(ResponseCode.OK) - response - } - - def getExternalPropsRequest(): Request = { - val request = getQuestionSetRequest() - request.putAll(new util.HashMap[String, AnyRef]() { - { - put("instructions", "This is the instruction.") - put("outcomeDeclaration", "This is outcomeDeclaration.") - } - }) - request - } - - def getExternalPropsResponseWithData(): Response = { - val response = getSuccessfulResponse() - response.put("instructions", "This is the instruction for this QuestionSet") - response.put("outcomeDeclaration", "This is the outcomeDeclaration for this QuestionSet") - response.put("hierarchy", "{\"code\":\"ExistingRootNode\",\"allowSkip\":\"Yes\",\"containsUserData\":\"No\"," + - "\"channel\":\"{{all}}\",\"language\":[\"English\"],\"showHints\":\"No\",\"mimeType\":\"application/vnd" + "" + ".sunbird" + "" - + ".questionset\",\"createdOn\":\"2022-03-16T14:35:11.040+0530\",\"objectType\":\"QuestionSet\"," + - "\"primaryCategory\":\"Observation\",\"contentDisposition\":\"inline\",\"contentEncoding\":\"gzip\"," + - "\"lastUpdatedOn\":\"2022-03-16T14:38:51.287+0530\",\"generateDIALCodes\":\"No\",\"showSolutions\":\"No\"," + - "\"allowAnonymousAccess\":\"Yes\",\"identifier\":\"do_1234\"," + "\"lastStatusChangedOn\":\"2022-03-16T14:35:11.040+0530\"," + - "\"requiresSubmit\":\"No\",\"visibility\":\"Default\"," + "" + "" + "\"IL_SYS_NODE_TYPE\":\"DATA_NODE\",\"showTimer\":\"No\"," + - "\"childNodes\":[\"do_113495678820704256110\"]," + "\"setType\":\"materialised\",\"version\":1," + "\"showFeedback\":\"No\"," + - "\"versionKey\":\"1647421731287\"," + "\"license\":\"CC BY 4.0\",\"depth\":0," + "\"compatibilityLevel\":5," + - "\"IL_FUNC_OBJECT_TYPE\":\"QuestionSet\"," + "\"allowBranching\":\"No\"," + "\"navigationMode\":\"non-linear\"," + - "\"name\":\"CopyQuestionSet\",\"shuffle\":true," + "\"IL_UNIQUE_ID\":\"do_11349567701798912019\",\"status\":\"Live\"," + - "\"children\":[{\"parent\":\"do_11349567701798912019\",\"code\":\"Q1\",\"channel\":\"{{channel_id}}\"," + - "\"language\":[\"English\"],\"mimeType\":\"application/vnd.sunbird.question\"," + - "\"createdOn\":\"2022-03-16T14:38:51.043+0530\",\"objectType\":\"Question\",\"primaryCategory\":\"Slider\"," + - "\"contentDisposition\":\"inline\",\"lastUpdatedOn\":\"2022-03-16T14:38:51.042+0530\"," + "\"contentEncoding\":\"gzip\"," + - "\"showSolutions\":\"No\",\"allowAnonymousAccess\":\"Yes\"," + "\"identifier\":\"do_113495678820704256110\"," + - "\"lastStatusChangedOn\":\"2022-03-16T14:38:51.043+0530\"," + "\"visibility\":\"Parent\",\"showTimer\":\"No\",\"index\":1," + - "\"languageCode\":[\"en\"],\"version\":1," + "\"versionKey\":\"1647421731066\",\"showFeedback\":\"No\",\"license\":\"CC BY " + - "4.0\",\"depth\":1," + "\"compatibilityLevel\":4,\"name\":\"Q1\",\"status\":\"Live\"}]}") - response.put("body", "This is Body") - response.put("answer", "This is Answer") - response - } - - def getReadPropsResponseForQuestion(): Response = { - val response = getSuccessfulResponse() - response.put("answer", "This is Answer 2") - response.put("body", "This is Body 2") - response - } - - def getUpsertNode(): Node = { - val node = getNewRootNode() - node.setExternalData(new util.HashMap[String, AnyRef]() { - { - put("hierarchy", "{\\\"identifier\\\":\\\"do_9876\\\"," + "\\\"children\\\":[{\\\"parent\\\":\\\"do_9876\\\"," + - "\\\"code\\\":\\\"b65f36d1-a243-4043-9df7-da14a2dd83b9\\\",\\\"channel\\\":\\\"{{channel_id}}\\\"," + - "\\\"language\\\":[\\\"English\\\"],\\\"mimeType\\\":\\\"application/vnd.sunbird.question\\\"," + - "\\\"createdOn\\\":\\\"2022-03-23T15:45:28.620+0530\\\",\\\"objectType\\\":\\\"Question\\\"," + - "\\\"primaryCategory\\\":\\\"Slider\\\",\\\"contentDisposition\\\":\\\"inline\\\"," + - "\\\"lastUpdatedOn\\\":\\\"2022-03-23T15:45:28.616+0530\\\",\\\"contentEncoding\\\":\\\"gzip\\\"," + - "\\\"showSolutions\\\":\\\"No\\\",\\\"allowAnonymousAccess\\\":\\\"Yes\\\"," + - "\\\"identifier\\\":\\\"do_11350066609045504013\\\",\\\"lastStatusChangedOn\\\":\\\"2022-03-23T15:45:28.621+0530\\\"," + - "\\\"visibility\\\":\\\"Parent\\\",\\\"showTimer\\\":\\\"No\\\",\\\"index\\\":1,\\\"languageCode\\\":[\\\"en\\\"]," + - "\\\"version\\\":1,\\\"versionKey\\\":\\\"1648030746815\\\",\\\"showFeedback\\\":\\\"No\\\",\\\"license\\\":\\\"CC BY " - + "4.0\\\",\\\"depth\\\":1,\\\"compatibilityLevel\\\":4,\\\"name\\\":\\\"Q1\\\",\\\"status\\\":\\\"Draft\\\"}]}") - } - }) - node - } - - private def generateStaticBranchingLogic(): util.HashMap[String, AnyRef] = { - new util.HashMap[String, AnyRef]() { - { - put("do_11351041198373273619", new util.HashMap[String, AnyRef]() { - put("target", new util.ArrayList[String]() { - { - add("do_113510411984044032111") - } - }) - put("preCondition", new util.HashMap[String, AnyRef]()) - put("source", new util.ArrayList[String]()) - }) - put("do_113510411984044032111", new util.HashMap[String, AnyRef]() { - put("target", new util.ArrayList[String]()) - put("preCondition", new util.HashMap[String, AnyRef]() { - { - put("and", new util.ArrayList[util.HashMap[String, AnyRef]]() { - add(new util.HashMap[String, AnyRef]() { - put("eq", new util.ArrayList[AnyRef]() { - { - add(new util.HashMap[String, String]() { - put("var", "do_11351041198373273619" + ".response1.value") - put("type", "responseDeclaration") - }) - add("0") - } - }) - }) - }) - } - }) - put("source", new util.ArrayList[String]() { - { - add("do_11351041198373273619") - } - }) - }) - } - } - } - - def generateNodesModified(identifier: String, withBranchingLogic: Boolean): util.HashMap[String, AnyRef] = { - val nodesModified = new util.HashMap[String, AnyRef]() - nodesModified.put(identifier, new util.HashMap[String, AnyRef]() { - { - put("setDefaultValue", false.asInstanceOf[AnyRef]) - put("metadata", new util.HashMap[String, AnyRef]() { - { - putAll((getNode("QuestionSet", "do_5678", "Observation", AssessmentConstants.VISIBILITY_PARENT, "Observation", 0, - "Draft").getMetadata)) - put("copyOf", "do_113510411984478208113") - if (withBranchingLogic) put("branchingLogic", generateStaticBranchingLogic) - } - }) - put("root", false.asInstanceOf[AnyRef]) - put("isNew", (!withBranchingLogic).asInstanceOf[AnyRef]) - put("objectType", "QuestionSet") - } - }) - nodesModified - } - - def generateBranchingRecord(): util.HashMap[String, AnyRef] = { - val nodeBLRecord = new util.HashMap[String, AnyRef]() - nodeBLRecord.put("afa2bef1-b5db-45d9-b0d7-aeea757906c3", new util.HashMap[String, AnyRef]() { - { - put("containsBL", true.asInstanceOf[AnyRef]) - put("branchingLogic", generateStaticBranchingLogic()) - put("copyOf", "do_113510411984478208113") - } - }) - nodeBLRecord - } - - def generateIdentifiers(): util.Map[String, String] = { - val idMap: mutable.Map[String, String] = mutable.Map() - idMap += ("afa2bef1-b5db-45d9-b0d7-aeea757906c3" -> "do_11351201604857856013") - mapAsJavaMap(idMap) - } - - def generateUpdateRequest(withBranchingLogic: Boolean, identifier: String): Request = { - val request = getQuestionSetRequest() - request.put(AssessmentConstants.NODES_MODIFIED, generateNodesModified(identifier, withBranchingLogic)) - request.put(AssessmentConstants.HIERARCHY, new util.HashMap[String, AnyRef]() { - { - put("do_11351201402236108811", new util.HashMap[String, AnyRef]() { - { - put(AssessmentConstants.CHILDREN, new util.ArrayList[String]() { - { - add(identifier) - } - }) - put(AssessmentConstants.PRIMARY_CATEGORY, "Observation") - put(AssessmentConstants.ROOT, true.asInstanceOf[AnyRef]) - } - }) - put(identifier, new util.HashMap[String, AnyRef]() { - { - put(AssessmentConstants.CHILDREN, new util.ArrayList[String]() { - { - add("do_11351041198373273619") - add("do_113510411984044032111") - } - }) - put(AssessmentConstants.PRIMARY_CATEGORY, "Observation") - put(AssessmentConstants.ROOT, false.asInstanceOf[AnyRef]) - } - }) - } - }) - request - } -} diff --git a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/QuestionActorTest.scala b/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/QuestionActorTest.scala deleted file mode 100644 index a6ded4683..000000000 --- a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/QuestionActorTest.scala +++ /dev/null @@ -1,381 +0,0 @@ -package org.sunbird.actors -import java.util -import akka.actor.Props -import org.scalamock.scalatest.MockFactory -import org.sunbird.common.HttpUtil -import org.sunbird.common.dto.ResponseHandler -import org.sunbird.common.dto.{Property, Request, Response} -import org.sunbird.common.exception.ResponseCode -import org.sunbird.graph.dac.model.{Node, SearchCriteria} -import org.sunbird.graph.utils.ScalaJsonUtils -import org.sunbird.graph.{GraphService, OntologyEngineContext} -import org.sunbird.kafka.client.KafkaClient - -import scala.collection.convert.ImplicitConversions._ -import scala.collection.JavaConverters._ -import scala.concurrent.Future -import scala.concurrent.ExecutionContext.Implicits.global - -class QuestionActorTest extends BaseSpec with MockFactory { - - "questionActor" should "return failed response for 'unknown' operation" in { - implicit val oec: OntologyEngineContext = new OntologyEngineContext - testUnknownOperation(Props(new QuestionActor()), getQuestionRequest()) - } - - it should "return success response for 'createQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("Question", None) - (graphDB.addNode(_: String, _: Node)).expects(*, *).returns(Future(node)) - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getQuestionRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("channel"-> "in.ekstep","name" -> "New Content", "code" -> "1234", "mimeType"-> "application/vnd.sunbird.question", "primaryCategory" -> "Multiple Choice Question", "visibility" -> "Default"))) - request.setOperation("createQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'readQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB) - val node = getNode("Question", None) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)) - val request = getQuestionRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "fields" -> ""))) - request.setOperation("readQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'readPrivateQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB) - val node = getNode("Question", Some(new util.HashMap[String, AnyRef]() { - { - put("name", "Question") - put("visibility","Private") - put("channel","abc-123") - } - })) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)) - val request = getQuestionRequest() - request.getContext.put("identifier","do1234") - request.getRequest.put("channel", "abc-123") - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "fields" -> ""))) - request.setOperation("readPrivateQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return client error for 'readPrivateQuestion' if channel is 'blank'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - val request = getQuestionRequest() - request.getContext.put("identifier","do1234") - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "fields" -> ""))) - request.setOperation("readPrivateQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert(response.getResponseCode == ResponseCode.CLIENT_ERROR) - assert(response.getParams.getErr == "ERR_INVALID_CHANNEL") - assert(response.getParams.getErrmsg == "Please Provide Channel!") - } - - it should "return client error for 'readPrivateQuestion' if channel is mismatched" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB) - val node = getNode("Question", Some(new util.HashMap[String, AnyRef]() { - { - put("name", "Question") - put("visibility","Private") - put("channel","abc-123") - } - })) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() - val request = getQuestionRequest() - request.getContext.put("identifier","do1234") - request.getRequest.put("channel", "abc") - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "fields" -> ""))) - request.setOperation("readPrivateQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert(response.getResponseCode == ResponseCode.CLIENT_ERROR) - assert(response.getParams.getErr == "ERR_ACCESS_DENIED") - assert(response.getParams.getErrmsg == "Channel id is not matched") - } - - it should "return client error response for 'readQuestion' if visibility is 'Private'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB) - val node = getNode("Question", Some(new util.HashMap[String, AnyRef]() { - { - put("name", "Question") - put("visibility","Private") - } - })) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)) - val request = getQuestionRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "fields" -> ""))) - request.setOperation("readQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert(response.getResponseCode == ResponseCode.CLIENT_ERROR) - } - - it should "return success response for 'updateQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("Question", None) - node.getMetadata.putAll(Map("versionKey" -> "1234", "primaryCategory" -> "Multiple Choice Question", "name" -> "Updated New Content", "code" -> "1234", "mimeType"-> "application/vnd.sunbird.question").asJava) - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getQuestionRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map( "versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("updateQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'reviewQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("Question", None) - node.getMetadata.putAll(Map("versionKey" -> "1234", "primaryCategory" -> "Multiple Choice Question", "name" -> "Updated New Content", "code" -> "1234", "mimeType"-> "application/vnd.sunbird.question").asJava) - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getQuestionRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map( "versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("reviewQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'retireQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("Question", None) - node.getMetadata.putAll(Map("versionKey" -> "1234", "primaryCategory" -> "Practice Question Set", "name" -> "Updated New Content", "code" -> "1234", "mimeType"-> "application/vnd.sunbird.question").asJava) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.updateNodes(_: String, _: util.List[String], _: util.HashMap[String, AnyRef])).expects(*, *, *).returns(Future(new util.HashMap[String, Node])) - val request = getQuestionRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map( "versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("retireQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'publishQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - val kfClient = mock[KafkaClient] - (oec.kafkaClient _).expects().returns(kfClient).anyNumberOfTimes() - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("Question", None) - node.getMetadata.putAll(Map("versionKey" -> "1234", "primaryCategory" -> "Practice Question Set", "name" -> "Updated New Content", "code" -> "1234", "mimeType"-> "application/vnd.sunbird.question").asJava) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (kfClient.send(_:String, _:String)).expects(*,*).once() - val request = getQuestionRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map( "versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("publishQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "send events to kafka topic" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val kfClient = mock[KafkaClient] - val hUtil = mock[HttpUtil] - (oec.httpUtil _).expects().returns(hUtil) - val resp :Response = ResponseHandler.OK() - resp.put("question", new util.HashMap[String, AnyRef](){{ - put("framework", "NCF") - put("channel", "test") - put("status", "Live") - }}) - (hUtil.get(_: String, _: String, _: util.Map[String, String])).expects(*, *, *).returns(resp) - (oec.kafkaClient _).expects().returns(kfClient) - (kfClient.send(_: String, _: String)).expects(*, *).returns(None) - val request = getQuestionRequest() - request.getRequest.put("question", new util.HashMap[String, AnyRef](){{ - put("source", "https://dock.sunbirded.org/api/question/v1/read/do_113486481122729984143") - put("metadata", new util.HashMap[String, AnyRef](){{ - put("name", "Test Question") - put("description", "Test Question") - put("mimeType", "application/vnd.sunbird.question") - put("code", "test.ques.1") - put("primaryCategory", "Learning Resource") - }}) - }}) - request.setOperation("importQuestion") - request.setObjectType("Question") - val response = callActor(request, Props(new QuestionActor())) - assert(response.get("processId") != null) - } - - it should "return success response for 'systemUpdateQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("Question", None) - node.getMetadata.putAll(Map("versionKey" -> "1234", "primaryCategory" -> "Multiple Choice Question", "name" -> "Updated New Content", "code" -> "1234", "mimeType" -> "application/vnd.sunbird.question").asJava) - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)).anyNumberOfTimes() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(List(node))).once() - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) - val request = getQuestionRequest() - request.getContext.put("identifier", "test_id") - request.putAll(mapAsJavaMap(Map("versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("systemUpdateQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'listQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("Question", None) - node.getMetadata.putAll(Map("versionKey" -> "1234", "primaryCategory" -> "Multiple Choice Question", "name" -> "Updated New Content", "code" -> "1234", "mimeType" -> "application/vnd.sunbird.question").asJava) - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(List(node))).once() - val request = getQuestionRequest() - request.put("identifiers", util.Arrays.asList( "test_id")) - request.put("identifier", util.Arrays.asList( "test_id")) - request.put("fields", "") - request.setOperation("listQuestions") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "throw exception for 'listQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val request = getQuestionRequest() - request.put("identifier", null) - request.put("fields", "") - request.setOperation("listQuestions") - val response = callActor(request, Props(new QuestionActor())) - assert(response.getResponseCode.code == 400) - } - - it should "throw client exception for 'listQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val request = getQuestionRequest() - request.put("identifiers", util.Arrays.asList( "test_id_1","test_id_2","test_id_3","test_id_4","test_id_5","test_id_6","test_id_7","test_id_8","test_id_9","test_id_10","test_id_11","test_id_12","test_id_13","test_id_14","test_id_15","test_id_16","test_id_17","test_id_18","test_id_19","test_id_20","test_id_21")) - request.setOperation("listQuestions") - request.put("fields", "") - val response = callActor(request, Props(new QuestionActor())) - assert(response.getResponseCode.code == 400) - } - - it should "return success response for 'rejectQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("Question", None) - node.getMetadata.putAll(Map("versionKey" -> "1234", "primaryCategory" -> "Multiple Choice Question", "name" -> "Updated New Content", "code" -> "1234", "mimeType"-> "application/vnd.sunbird.question","status" -> "Review").asJava) - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getQuestionRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map( "versionKey" -> "1234", "description" -> "updated description","rejectComment" -> "Rejected for testing"))) - request.setOperation("rejectQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'copyQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects("domain", "do_1234", false, *).returns(Future(CopySpec.getExistingQuestionNode())).anyNumberOfTimes() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, List("objectMetadata")).returns(Future(CopySpec.getSuccessfulResponse())).anyNumberOfTimes() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(CopySpec.getReadPropsResponseForQuestion())).anyNumberOfTimes() - (graphDB.addNode(_: String, _: Node)).expects(*, *).returns(Future(CopySpec.getNewQuestionNode())) - (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(CopySpec.getSuccessfulResponse())).anyNumberOfTimes - val request = CopySpec.getQuestionCopyRequest() - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "mode" -> "", "copyType"-> "deep"))) - request.setOperation("copyQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return error response for 'copyQuestion' when createdFor & createdBy is missing" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val request = CopySpec.getInvalidQuestionSetCopyRequest() - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "mode" -> "", "copyType"-> "deep"))) - request.setOperation("copyQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("failed".equals(response.getParams.getStatus)) - } - - it should "return error response for 'copyQuestion' when visibility is Parent" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val request = CopySpec.getQuestionCopyRequest() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects("domain", "do_1234", false, *).returns(Future(CopySpec.getQuestionNode())).anyNumberOfTimes() - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "mode" -> "", "copyType"-> "deep"))) - request.setOperation("copyQuestion") - val response = callActor(request, Props(new QuestionActor())) - assert("failed".equals(response.getParams.getStatus)) - } - - private def getQuestionRequest(): Request = { - val request = new Request() - request.setContext(new java.util.HashMap[String, AnyRef]() { - { - put("graph_id", "domain") - put("version", "1.0") - put("objectType", "Question") - put("schemaName", "question") - } - }) - request.setObjectType("Question") - request - } - - def getDefinitionNode(): Node = { - val node = new Node() - node.setIdentifier("obj-cat:practice-question-set_question_all") - node.setNodeType("DATA_NODE") - node.setObjectType("ObjectCategoryDefinition") - node.setGraphId("domain") - node.setMetadata(mapAsJavaMap( - ScalaJsonUtils.deserialize[Map[String,AnyRef]]("{\n \"objectCategoryDefinition\": {\n \"name\": \"Learning Resource\",\n \"description\": \"Content Playlist\",\n \"categoryId\": \"obj-cat:practice_question_set\",\n \"targetObjectType\": \"Content\",\n \"objectMetadata\": {\n \"config\": {},\n \"schema\": {\n \"required\": [\n \"author\",\n \"copyright\",\n \"license\",\n \"audience\"\n ],\n \"properties\": {\n \"audience\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"Student\",\n \"Teacher\"\n ]\n },\n \"default\": [\n \"Student\"\n ]\n },\n \"mimeType\": {\n \"type\": \"string\",\n \"enum\": [\n \"application/pdf\"\n ]\n }\n }\n }\n }\n }\n }"))) - node - } -} 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 deleted file mode 100644 index dbd30c7e5..000000000 --- a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/QuestionSetActorTest.scala +++ /dev/null @@ -1,766 +0,0 @@ -package org.sunbird.actors - -import java.util -import akka.actor.Props -import org.scalamock.scalatest.MockFactory -import org.sunbird.common.HttpUtil -import org.sunbird.common.dto.{Property, Request, Response, ResponseHandler} -import org.sunbird.common.exception.ResponseCode -import org.sunbird.graph.dac.model.{Node, Relation, SearchCriteria} -import org.sunbird.graph.nodes.DataNode.getRelationMap -import org.sunbird.graph.utils.ScalaJsonUtils -import org.sunbird.graph.{GraphService, OntologyEngineContext} -import org.sunbird.kafka.client.KafkaClient -import org.sunbird.managers.CopyManager -import org.sunbird.utils.{AssessmentConstants, BranchingUtil, JavaJsonUtils} - -import java.util -import scala.collection.convert.ImplicitConversions._ -import scala.collection.JavaConverters._ -import scala.concurrent.ExecutionContext.Implicits.global -import scala.concurrent.Future - -class QuestionSetActorTest extends BaseSpec with MockFactory { - - "questionSetActor" should "return failed response for 'unknown' operation" in { - implicit val oec: OntologyEngineContext = new OntologyEngineContext - testUnknownOperation(Props(new QuestionSetActor()), getQuestionSetRequest()) - } - - it should "return success response for 'createQuestionSet'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("QuestionSet", None) - (graphDB.addNode(_: String, _: Node)).expects(*, *).returns(Future(node)) - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getQuestionSetRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - request.setOperation("createQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'readQuestionSet'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("QuestionSet", Some(new util.HashMap[String, AnyRef]() { - { - put("name", "QuestionSet") - put("description", "Updated question Set") - } - })) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)) - val request = getQuestionSetRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "fields" -> ""))) - request.setOperation("readQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - - it should "return client error response for 'readQuestionSet' if visibility is 'Private'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("QuestionSet", Some(new util.HashMap[String, AnyRef]() { - { - put("name", "QuestionSet") - put("description", "Updated question Set") - put("visibility","Private") - } - })) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)) - val request = getQuestionSetRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "fields" -> ""))) - request.setOperation("readQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert(response.getResponseCode == ResponseCode.CLIENT_ERROR) - } - - it should "return success response for 'readPrivateQuestionSet'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB) - val node = getNode("QuestionSet", Some(new util.HashMap[String, AnyRef]() { - { - put("name", "QuestionSet") - put("visibility","Private") - put("channel","abc-123") - } - })) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)) - val request = getQuestionSetRequest() - request.getContext.put("identifier","do1234") - request.getRequest.put("channel", "abc-123") - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "fields" -> ""))) - request.setOperation("readPrivateQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return client error for 'readPrivateQuestionSet' if channel is 'blank'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - val request = getQuestionSetRequest() - request.getContext.put("identifier","do1234") - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "fields" -> ""))) - request.setOperation("readPrivateQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert(response.getResponseCode == ResponseCode.CLIENT_ERROR) - assert(response.getParams.getErr == "ERR_INVALID_CHANNEL") - assert(response.getParams.getErrmsg == "Please Provide Channel!") - } - - it should "return client error for 'readPrivateQuestionSet' if channel is mismatched" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB) - val node = getNode("QuestionSet", Some(new util.HashMap[String, AnyRef]() { - { - put("name", "QuestionSet") - put("visibility","Private") - put("channel","abc-123") - } - })) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() - val request = getQuestionSetRequest() - request.getContext.put("identifier","do1234") - request.getRequest.put("channel", "abc") - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "fields" -> ""))) - request.setOperation("readPrivateQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert(response.getResponseCode == ResponseCode.CLIENT_ERROR) - assert(response.getParams.getErr == "ERR_ACCESS_DENIED") - assert(response.getParams.getErrmsg == "Channel id is not matched") - } - - it should "return success response for 'updateQuestionSet'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val node = getNode("QuestionSet", None) - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "description" -> "Updated description", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - val request = getQuestionSetRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("updateQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'reviewQuestionSet'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val node = getNode("QuestionSet", None) - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "versionKey" -> "1234", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes - (graphDB.updateExternalProps(_: Request)).expects(*).returns(Future(new Response())).anyNumberOfTimes - (graphDB.updateNodes(_:String, _:util.List[String], _: util.Map[String, AnyRef])).expects(*, *, *).returns(Future(Map[String, Node]().asJava)).anyNumberOfTimes - val request = getQuestionSetRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("reviewQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'retireQuestionSet" + - "'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("QuestionSet", None) - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.updateNodes(_: String, _: util.List[String], _: util.HashMap[String, AnyRef])).expects(*, *, *).returns(Future(new util.HashMap[String, Node])) - val request = getQuestionSetRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("retireQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'publishQuestionSet" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - val kfClient = mock[KafkaClient] - (oec.kafkaClient _).expects().returns(kfClient).anyNumberOfTimes() - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("do_11348469558523494411","QuestionSet", None) - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "mimeType" -> "application/vnd.sunbird.questionset", - "createdBy" -> "g-001", - "primaryCategory" -> "Practice Question Set"))) - val nodeList = new util.ArrayList[Node]() {{ - add(getNode("do_11348469662446387212","Question", Some(Map("visibility"-> "Parent", "createdBy"-> "g-001")))) - add(getNode("do_11348469662607769614","Question", Some(Map("visibility"-> "Default", "createdBy"-> "g-002")))) - }} - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.getNodeByUniqueIds(_ :String, _: SearchCriteria)).expects(*, *).returns(Future(nodeList)).atLeastOnce() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getDraftCassandraHierarchy)).anyNumberOfTimes - (kfClient.send(_: String, _: String)).expects(*, *).once() - val request = getQuestionSetRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("publishQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'addQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("QuestionSet", None) - node.setIdentifier("do_1234") - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "versionKey" -> "1234", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(List(node).asJava)).anyNumberOfTimes() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes - (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())).anyNumberOfTimes - val request = getQuestionSetRequest() - request.getContext.put("identifier", "do1234") - request.putAll((Map("children" -> List("do_749").asJava.asInstanceOf[AnyRef], "rootId" -> "do1234")).asJava) - request.setOperation("addQuestion") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'removeQuestion'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("QuestionSet", None) - node.setIdentifier("do_1234") - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "versionKey" -> "1234", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(List(node).asJava)).anyNumberOfTimes() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes - (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())).anyNumberOfTimes - val request = getQuestionSetRequest() - request.getContext.put("identifier", "do1234") - request.putAll((Map("children" -> List("do_914").asJava.asInstanceOf[AnyRef], "rootId" -> "do1234")).asJava) - request.setOperation("removeQuestion") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return error response for 'updateHierarchyQuestionSet'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val request = getInvalidUpdateHierarchyReq() - request.getContext.put("rootId", "do_123") - request.setOperation("updateHierarchy") - val response = callActor(request, Props(new QuestionSetActor())) - assert("failed".equals(response.getParams.getStatus)) - } - - - it should "return success response for 'updateHierarchyQuestionSet'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val rootNode = getRootNode() - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(rootNode)) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(rootNode)).anyNumberOfTimes() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getEmptyCassandraHierarchy())).anyNumberOfTimes - (graphDB.updateExternalProps(_: Request)).expects(*).returns(Future(new Response())).anyNumberOfTimes - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getUpdateHierarchyReq() - request.getContext.put("rootId", "do_1234") - request.setOperation("updateHierarchy") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - - it should "return success response for 'rejectQuestionSet'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("QuestionSet", None) - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "showSolutions" -> "Yes", - "status" -> "Review", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "versionKey" -> "1234", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes - (graphDB.updateExternalProps(_: Request)).expects(*).returns(Future(new Response())).anyNumberOfTimes - (graphDB.updateNodes(_:String, _:util.List[String], _: util.Map[String, AnyRef])).expects(*, *, *).returns(Future(Map[String, Node]().asJava)).anyNumberOfTimes - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getQuestionSetRequest() - request.getContext.put("identifier", "do1234") - request.putAll(mapAsJavaMap(Map("versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("rejectQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "send events to kafka topic" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val kfClient = mock[KafkaClient] - val hUtil = mock[HttpUtil] - (oec.httpUtil _).expects().returns(hUtil) - val resp :Response = ResponseHandler.OK() - resp.put("questionset", new util.HashMap[String, AnyRef](){{ - put("framework", "NCF") - put("channel", "test") - put("status", "Live") - }}) - (hUtil.get(_: String, _: String, _: util.Map[String, String])).expects(*, *, *).returns(resp) - (oec.kafkaClient _).expects().returns(kfClient) - (kfClient.send(_: String, _: String)).expects(*, *).returns(None) - val request = getQuestionSetRequest() - request.getRequest.put("questionset", new util.HashMap[String, AnyRef](){{ - put("source", "https://dock.sunbirded.org/api/questionset/v1/read/do_113486480153952256140") - put("metadata", new util.HashMap[String, AnyRef](){{ - put("name", "Test QuestionSet") - put("description", "Test QuestionSet") - put("mimeType", "application/vnd.sunbird.questionset") - put("code", "test.ques.1") - put("primaryCategory", "Learning Resource") - }}) - }}) - request.setOperation("importQuestionSet") - request.setObjectType("QuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert(response.get("processId") != null) - } - - it should "return success response for 'systemUpdateQuestionSet'" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("QuestionSet", None) - node.setIdentifier("test_id") - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "description" -> "Updated description", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "status" -> "Draft", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(List(node))).once() - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).noMoreThanOnce() - - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes - val request = getQuestionSetRequest() - request.getContext.put("identifier", "test_id") - request.putAll(mapAsJavaMap(Map("versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("systemUpdateQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'systemUpdateQuestionSet' with image Node" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getNode("QuestionSet", None) - val imageNode = getNode("QuestionSet", None) - node.setIdentifier("test_id") - imageNode.setIdentifier("test_id.img") - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "description" -> "Updated description", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "status" -> "Live", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - imageNode.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "description" -> "Updated description", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "status" -> "Draft", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).atLeastOnce() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(List(node, imageNode))).once() - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes - (graphDB.updateExternalProps(_: Request)).expects(*).returns(Future(new Response())).anyNumberOfTimes - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)).anyNumberOfTimes() - val request = getQuestionSetRequest() - request.getContext.put("identifier", "test_id") - request.putAll(mapAsJavaMap(Map("versionKey" -> "1234", "description" -> "updated desc"))) - request.setOperation("systemUpdateQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'copyQuestionSet' (Deep)" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects("domain", "do_1234", false, *).returns(Future(CopySpec.getExistingRootNode())).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects("domain", "do_9876", false, *).returns(Future(CopySpec.getNewRootNode())).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects("domain", "do_9876.img", false, *).returns(Future(CopySpec.getNewRootNode())).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects("domain", *, false, *).returns(Future(CopySpec.getQuestionNode())).anyNumberOfTimes() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, List("objectMetadata")).returns(Future(CopySpec.getSuccessfulResponse())).anyNumberOfTimes() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(CopySpec.getExternalPropsResponseWithData())).anyNumberOfTimes() - (graphDB.updateExternalProps(_: Request)).expects(*).returns(Future(CopySpec.getSuccessfulResponse())).anyNumberOfTimes - (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(CopySpec.getSuccessfulResponse())).anyNumberOfTimes - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(CopySpec.getUpsertNode())).anyNumberOfTimes() - inSequence { - (graphDB.addNode(_: String, _: Node)).expects(*, *).returns(Future(CopySpec.getNewRootNode())) - (graphDB.addNode(_: String, _: Node)).expects(*, *).returns(Future(CopySpec.getQuestionNode())) - } - val request = CopySpec.getQuestionSetCopyRequest() - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "mode" -> "", "copyType"-> "deep"))) - request.setOperation("copyQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return success response for 'copyQuestionSet' (Shallow)" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects("domain", "do_1234", false, *).returns(Future(CopySpec.getExistingRootNode())).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects("domain", "do_5678", false, *).returns(Future(CopySpec.getNewRootNode())).anyNumberOfTimes() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, List("objectMetadata")).returns(Future(CopySpec.getSuccessfulResponse())).anyNumberOfTimes() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(CopySpec.getExternalPropsResponseWithData())).anyNumberOfTimes() - (graphDB.addNode(_: String, _: Node)).expects(*, *).returns(Future(CopySpec.getQuestionNode())) - (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(CopySpec.getSuccessfulResponse())).anyNumberOfTimes - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(CopySpec.getUpsertNode())).anyNumberOfTimes() - (graphDB.updateExternalProps(_: Request)).expects(*).returns(Future(CopySpec.getSuccessfulResponse())).anyNumberOfTimes - val request = CopySpec.getQuestionSetCopyRequest() - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "mode" -> "", "copyType"-> "shallow"))) - request.setOperation("copyQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("successful".equals(response.getParams.getStatus)) - } - - it should "return error response for 'copyQuestionSet' when createdFor & createdBy is missing" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val request = CopySpec.getInvalidQuestionCopyRequest() - request.putAll(mapAsJavaMap(Map("identifier" -> "do_1234", "mode" -> "", "copyType"-> "deep"))) - request.setOperation("copyQuestionSet") - val response = callActor(request, Props(new QuestionSetActor())) - assert("failed".equals(response.getParams.getStatus)) - } - - it should "return expected result for 'generateBranchingRecord'" in { - val result = BranchingUtil.generateBranchingRecord(CopySpec.generateNodesModified("afa2bef1-b5db-45d9-b0d7-aeea757906c3", true)) - assert(result == CopySpec.generateBranchingRecord) - } - - it should "return expected result for 'hierarchyRequestModifier'" in { - val result = BranchingUtil.hierarchyRequestModifier(CopySpec.generateUpdateRequest(false, "afa2bef1-b5db-45d9-b0d7-aeea757906c3"), CopySpec.generateBranchingRecord(), CopySpec.generateIdentifiers()) - val expectedResult = CopySpec.generateUpdateRequest(true, "do_11351201604857856013") - assert(result.getRequest.get(AssessmentConstants.NODES_MODIFIED) == expectedResult.getRequest.get(AssessmentConstants.NODES_MODIFIED)) - assert(result.getRequest.get(AssessmentConstants.HIERARCHY) == expectedResult.getRequest.get(AssessmentConstants.HIERARCHY)) - } - - private def getQuestionSetRequest(): Request = { - val request = new Request() - request.setContext(new java.util.HashMap[String, AnyRef]() { - { - put("graph_id", "domain") - put("version", "1.0") - put("objectType", "QuestionSet") - put("schemaName", "questionset") - } - }) - request.setObjectType("QuestionSet") - request - } - - - private def getRelationNode(): Node = { - val node = new Node() - node.setGraphId("domain") - node.setIdentifier("do_749") - node.setMetadata(new util.HashMap[String, AnyRef]() { - { - put("identifier", "do_749") - put("mimeType", "application/vnd.sunbird.question") - put("visibility", "Default") - put("status", "Draft") - put("primaryCategory", "Practice Question Set") - } - }) - node.setObjectType("Question") - node.setNodeType("DATA_NODE") - node - } - - private def getRelationNode_1(): Node = { - val node = new Node() - node.setGraphId("domain") - node.setIdentifier("do_914") - node.setMetadata(new util.HashMap[String, AnyRef]() { - { - put("identifier", "do_914") - put("visibility", "Default") - put("mimeType", "application/vnd.sunbird.question") - put("status", "Draft") - put("primaryCategory", "Practice Question Set") - } - }) - node.setObjectType("Question") - node.setNodeType("DATA_NODE") - node - } - - def getDefinitionNode(): Node = { - val node = new Node() - node.setIdentifier("obj-cat:practice-question-set_question-set_all") - node.setNodeType("DATA_NODE") - node.setObjectType("ObjectCategoryDefinition") - node.setGraphId("domain") - node.setMetadata(mapAsJavaMap( - ScalaJsonUtils.deserialize[Map[String, AnyRef]]("{\n \"objectCategoryDefinition\": {\n \"name\": \"Learning Resource\",\n \"description\": \"Content Playlist\",\n \"categoryId\": \"obj-cat:practice_question_set\",\n \"targetObjectType\": \"Content\",\n \"objectMetadata\": {\n \"config\": {},\n \"schema\": {\n \"required\": [\n \"author\",\n \"copyright\",\n \"license\",\n \"audience\"\n ],\n \"properties\": {\n \"audience\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"Student\",\n \"Teacher\"\n ]\n },\n \"default\": [\n \"Student\"\n ]\n },\n \"mimeType\": {\n \"type\": \"string\",\n \"enum\": [\n \"application/pdf\"\n ]\n }\n }\n }\n }\n }\n }"))) - node - } - - def getCassandraHierarchy(): Response = { - val hierarchyString: String = """{"status":"Live","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) - } - - def getDraftCassandraHierarchy(): Response = { - val hierarchyString: String = """{"identifier":"do_11348469558523494411","children":[{"parent":"do_11348469558523494411","code":"Q1","description":"Q1","language":["English"],"mimeType":"application/vnd.sunbird.question","createdOn":"2022-03-01T02:15:30.917+0530","objectType":"Question","primaryCategory":"Multiple Choice question","contentDisposition":"inline","lastUpdatedOn":"2022-03-01T02:15:30.915+0530","contentEncoding":"gzip","showSolutions":"No","allowAnonymousAccess":"Yes","identifier":"do_11348469662446387212","lastStatusChangedOn":"2022-03-01T02:15:30.917+0530","visibility":"Parent","showTimer":"No","index":1,"languageCode":["en"],"version":1,"versionKey":"1646081131087","showFeedback":"No","license":"CC BY 4.0","depth":1,"createdBy":"g-001","compatibilityLevel":4,"name":"Q1","status":"Draft"},{"parent":"do_11348469558523494411","code":"Q2","description":"Q2","language":["English"],"mimeType":"application/vnd.sunbird.question","createdOn":"2022-03-01T02:15:31.113+0530","objectType":"Question","primaryCategory":"Multiple Choice question","contentDisposition":"inline","lastUpdatedOn":"2022-03-01T02:15:31.126+0530","contentEncoding":"gzip","showSolutions":"No","allowAnonymousAccess":"Yes","identifier":"do_11348469662607769614","lastStatusChangedOn":"2022-03-01T02:15:31.113+0530","visibility":"Default","showTimer":"No","index":2,"languageCode":["en"],"version":1,"versionKey":"1646081131126","showFeedback":"No","license":"CC BY 4.0","depth":1,"createdBy":"g-002","compatibilityLevel":4,"name":"Q2","status":"Draft"}]}""" - val response = new Response - response.put("hierarchy", hierarchyString) - } - - def getEmptyCassandraHierarchy(): Response = { - val response = new Response - response.put("hierarchy", "{}") - } - - def getInvalidUpdateHierarchyReq() = { - val nodesModified = "{\n \"do_1234\": {\n \"metadata\": {\n \"code\": \"updated_code_of_root\"\n },\n \"root\": true,\n \"isNew\": false\n },\n \"QS_V_Parent_New\": {\n \"metadata\": {\n \"code\": \"QS_V_Parent\",\n \"name\": \"QS_V_Parent_1\",\n \"description\": \"QS-1_parent\",\n \"mimeType\": \"application/vnd.sunbird.questionset\",\n \"visibility\": \"Parent\",\n \"primaryCategory\": \"Practice Question Set\"\n },\n \"root\": false,\n \"objectType\": \"QuestionSet\",\n \"isNew\": true\n },\n \"QS_V_Parent_Old\": {\n \"metadata\": {\n \"code\": \"QS_V_Parent\",\n \"name\": \"QS_V_Parent_2\",\n \"description\": \"QS-2_parent\",\n \"mimeType\": \"application/vnd.sunbird.questionset\",\n \"visibility\": \"Parent\",\n \"primaryCategory\": \"Practice Question Set\"\n },\n \"root\": false,\n \"objectType\": \"QuestionSet\",\n \"isNew\": true\n },\n \"do_113178560758022144113\": {\n \"metadata\": {\n \"code\": \"Q_NEW_PARENT\",\n \"name\": \"Q_NEW_PARENT\",\n \"description\": \"Q_NEW_PARENT\",\n \"mimeType\": \"application/vnd.sunbird.question\",\n \"visibility\": \"Parent\",\n \"primaryCategory\": \"Practice Question Set\"\n },\n \"root\": false,\n \"objectType\": \"Question\",\n \"isNew\": true\n }\n }" - val hierarchy = "{\n \"do_1234\": {\n \"children\": [\n \"QS_V_Parent_Old\",\n \"QS_V_Parent_New\"\n ],\n \"root\": true\n },\n \"QS_V_Parent_Old\": {\n \"children\": [],\n \"root\": false\n },\n \"QS_V_Parent_New\": {\n \"children\": [\n \"do_113178560758022144113\"\n ],\n \"root\": false\n },\n \"do_113178560758022144113\": {\n\n }\n }" - val request = getQuestionSetRequest() - request.put("nodesModified", JavaJsonUtils.deserialize[java.util.Map[String, AnyRef]](nodesModified)) - request.put("hierarchy", JavaJsonUtils.deserialize[java.util.Map[String, AnyRef]](hierarchy)) - request - } - - def getUpdateHierarchyReq() = { - val nodesModified = - """ - |{ - | "UUID": { - | "metadata": { - | "mimeType": "application/vnd.sunbird.questionset", - | "name": "Subjective", - | "primaryCategory": "Practice Question Set", - | "code": "questionset" - | }, - | "objectType": "QuestionSet", - | "root": false, - | "isNew": true - | } - | } - """.stripMargin - val hierarchy = - """ - |{ - | "do_1234": { - | "children": [ - | "UUID" - | ], - | "root": true - | } - | } - """.stripMargin - val request = getQuestionSetRequest() - request.put("nodesModified", JavaJsonUtils.deserialize[java.util.Map[String, AnyRef]](nodesModified)) - request.put("hierarchy", JavaJsonUtils.deserialize[java.util.Map[String, AnyRef]](hierarchy)) - request - } - - def getRootNode(): Node = { - val node = getNode("QuestionSet", None) - node.setIdentifier("do_1234") - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "navigationMode" -> "linear", - "allowSkip" -> "Yes", - "requiresSubmit" -> "No", - "shuffle" -> true.asInstanceOf[AnyRef], - "showFeedback" -> "Yes", - "showSolutions" -> "Yes", - "showHints" -> "Yes", - "summaryType" -> "Complete", - "versionKey" -> "1234", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set", - "channel" -> "in.ekstep" - ))) - node - } - - def getQuestionSetNode(identifier:String): Node = { - val node = getNode("QuestionSet", None) - node.setIdentifier(identifier) - node.getMetadata.putAll(mapAsJavaMap(Map("name" -> "question_1", - "visibility" -> "Default", - "code" -> "finemanfine", - "versionKey" -> "1234", - "mimeType" -> "application/vnd.sunbird.questionset", - "primaryCategory" -> "Practice Question Set"))) - node - } -} diff --git a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/TestItemSetActor.scala b/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/TestItemSetActor.scala deleted file mode 100644 index d84f19cf1..000000000 --- a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/TestItemSetActor.scala +++ /dev/null @@ -1,143 +0,0 @@ -package org.sunbird.actors - -import java.util - -import akka.actor.Props -import org.scalamock.scalatest.MockFactory -import org.sunbird.common.dto.Request -import org.sunbird.graph.dac.model.{Node, SearchCriteria} -import org.sunbird.graph.{GraphService, OntologyEngineContext} - -import scala.collection.JavaConversions.mapAsJavaMap -import scala.concurrent.Future -import scala.concurrent.ExecutionContext.Implicits.global - -class TestItemSetActor extends BaseSpec with MockFactory { - - "ItemSetActor" should "return failed response for 'unknown' operation" in { - implicit val oec: OntologyEngineContext = new OntologyEngineContext - testUnknownOperation(Props(new ItemSetActor()), getItemSetRequest()) - } - - it should "create a itemSetNode and store it in neo4j" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - (graphDB.addNode(_: String, _: Node)).expects(*, *).returns(Future(getValidNode())) - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getItemSetRequest() - request.setRequest(mapAsJavaMap(Map("name" -> "test-itemset", "code" -> "1234"))) - request.setOperation("createItemSet") - val response = callActor(request, Props(new ItemSetActor())) - assert(response.get("identifier") != null) - assert(response.get("identifier").equals("1234")) - } - - it should "return success response for updateItemSet" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getValidNode() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getItemSetRequest() - request.getContext.put("identifier", "1234") - request.put("name", "test") - request.put("code", "1234") - request.putAll(mapAsJavaMap(Map("description" -> "test desc"))) - request.setOperation("updateItemSet") - val response = callActor(request, Props(new ItemSetActor())) - assert("successful".equals(response.getParams.getStatus)) - assert(response.get("identifier").equals("1234")) - } - - - it should "return success response for readItemSet" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).repeated(1) - val node = getValidNode() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() - val request = getItemSetRequest() - request.getContext.put("identifier", "1234") - request.putAll(mapAsJavaMap(Map("fields" -> ""))) - request.setOperation("readItemSet") - val response = callActor(request, Props(new ItemSetActor())) - assert("successful".equals(response.getParams.getStatus)) - assert(response.get("itemset").asInstanceOf[util.Map[String, AnyRef]].get("identifier").equals("1234")) - } - - it should "return success response for reviewItemSet" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getValidNode() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getItemSetRequest() - request.getContext.put("identifier","do_1234") - request.put("name", "test") - request.put("code", "1234") - request.setOperation("reviewItemSet") - val response = callActor(request, Props(new ItemSetActor())) - assert("successful".equals(response.getParams.getStatus)) - assert(response.get("identifier").equals("1234")) - } - - it should "return success response for retireItemSet" in { - implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - val node = getValidNode() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(node)) - val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - val request = getItemSetRequest() - request.getContext.put("identifier","do_1234") - request.put("name", "test") - request.put("code", "1234") - request.setOperation("retireItemSet") - val response = callActor(request, Props(new ItemSetActor())) - assert("successful".equals(response.getParams.getStatus)) - assert(response.get("identifier").equals("1234")) - } - - private def getItemSetRequest(): Request = { - val request = new Request() - request.setContext(new util.HashMap[String, AnyRef]() { - { - put("graph_id", "domain") - put("version", "2.0") - put("objectType", "ItemSet") - put("schemaName", "itemset") - } - }) - request.setObjectType("ItemSet") - request - } - - private def getValidNode(): Node = { - val node = new Node() - node.setIdentifier("1234") - node.setNodeType("DATA_NODE") - node.setMetadata(new util.HashMap[String, AnyRef]() { - { - put("identifier", "1234") - put("objectType", "ItemSet") - put("name", "test-itemset") - } - }) - node.setObjectType("ItemSet") - node - } -} diff --git a/assessment-api/assessment-service/app/controllers/BaseController.scala b/assessment-api/assessment-service/app/controllers/BaseController.scala deleted file mode 100644 index d388c4a31..000000000 --- a/assessment-api/assessment-service/app/controllers/BaseController.scala +++ /dev/null @@ -1,73 +0,0 @@ -package controllers - -import java.util.UUID - -import akka.actor.ActorRef -import akka.pattern.Patterns -import org.sunbird.common.DateUtils -import org.sunbird.common.dto.{Response, ResponseHandler} -import org.sunbird.common.exception.ResponseCode -import play.api.mvc._ -import utils.JavaJsonUtils - -import collection.JavaConverters._ -import scala.concurrent.{ExecutionContext, Future} - -abstract class BaseController(protected val cc: ControllerComponents)(implicit exec: ExecutionContext) extends AbstractController(cc) { - - def requestBody()(implicit request: Request[AnyContent]) = { - val body = request.body.asJson.getOrElse("{}").toString - JavaJsonUtils.deserialize[java.util.Map[String, Object]](body).getOrDefault("request", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]] - } - - def commonHeaders()(implicit request: Request[AnyContent]): java.util.Map[String, Object] = { - val customHeaders = Map("x-channel-id" -> "channel", "X-Consumer-ID" -> "consumerId", "X-App-Id" -> "appId") - customHeaders.map(ch => { - val value = request.headers.get(ch._1) - if (value.isDefined && !value.isEmpty) { - collection.mutable.HashMap[String, Object](ch._2 -> value.get).asJava - } else { - collection.mutable.HashMap[String, Object]().asJava - } - }).reduce((a, b) => { - a.putAll(b) - return a - }) - } - - def getRequest(input: java.util.Map[String, AnyRef], context: java.util.Map[String, AnyRef], operation: String): org.sunbird.common.dto.Request = { - new org.sunbird.common.dto.Request(context, input, operation, null); - } - - def getResult(apiId: String, actor: ActorRef, request: org.sunbird.common.dto.Request) : Future[Result] = { - val future = Patterns.ask(actor, request, 30000) recoverWith {case e: Exception => Future(ResponseHandler.getErrorResponse(e))} - future.map(f => { - val result = f.asInstanceOf[Response] - result.setId(apiId) - setResponseEnvelope(result) - val response = JavaJsonUtils.serialize(result); - result.getResponseCode match { - case ResponseCode.OK => Ok(response).as("application/json") - case ResponseCode.CLIENT_ERROR => BadRequest(response).as("application/json") - case ResponseCode.RESOURCE_NOT_FOUND => NotFound(response).as("application/json") - case _ => play.api.mvc.Results.InternalServerError(response).as("application/json") - } - }) - } - - def setResponseEnvelope(response: Response) = { - response.setTs(DateUtils.formatCurrentDate("yyyy-MM-dd'T'HH:mm:ss'Z'XXX")) - response.getParams.setResmsgid(UUID.randomUUID().toString) - } - - def setRequestContext(request:org.sunbird.common.dto.Request, version: String, objectType: String, schemaName: String): Unit = { - var contextMap: java.util.Map[String, AnyRef] = new java.util.HashMap[String, AnyRef](){{ - put("graph_id", "domain") - put("version" , version) - put("objectType" , objectType) - put("schemaName", schemaName) - }}; - request.setObjectType(objectType); - request.getContext().putAll(contextMap) - } -} diff --git a/assessment-api/assessment-service/app/controllers/HealthController.scala b/assessment-api/assessment-service/app/controllers/HealthController.scala deleted file mode 100644 index d278b7681..000000000 --- a/assessment-api/assessment-service/app/controllers/HealthController.scala +++ /dev/null @@ -1,31 +0,0 @@ -package controllers - -import akka.actor.{ActorRef, ActorSystem} -import handlers.SignalHandler -import javax.inject._ -import org.sunbird.common.JsonUtils -import org.sunbird.common.dto.ResponseHandler -import play.api.mvc._ -import utils.{ActorNames, ApiId} - -import scala.concurrent.{ExecutionContext, Future} - -class HealthController @Inject()(@Named(ActorNames.HEALTH_ACTOR) healthActor: ActorRef, cc: ControllerComponents, actorSystem: ActorSystem, signalHandler: SignalHandler)(implicit exec: ExecutionContext) extends BaseController(cc) { - - def health() = Action.async { implicit request => - if (signalHandler.isShuttingDown) { - Future { ServiceUnavailable } - } else { - getResult(ApiId.APPLICATION_HEALTH, healthActor, new org.sunbird.common.dto.Request()) - } - } - - def serviceHealth() = Action.async { implicit request => - if (signalHandler.isShuttingDown) - Future { ServiceUnavailable } - else { - val response = ResponseHandler.OK().setId(ApiId.APPLICATION_SERVICE_HEALTH).put("healthy", true) - Future { Ok(JsonUtils.serialize(response)).as("application/json") } - } - } -} diff --git a/assessment-api/assessment-service/app/controllers/v3/ItemSetController.scala b/assessment-api/assessment-service/app/controllers/v3/ItemSetController.scala deleted file mode 100644 index 4786424a7..000000000 --- a/assessment-api/assessment-service/app/controllers/v3/ItemSetController.scala +++ /dev/null @@ -1,71 +0,0 @@ -package controllers.v3 - -import akka.actor.{ActorRef, ActorSystem} -import com.google.inject.Singleton -import controllers.BaseController -import javax.inject.{Inject, Named} -import play.api.mvc.ControllerComponents -import utils.{ActorNames, ApiId, ItemSetOperations} - -import scala.collection.JavaConverters._ -import scala.concurrent.ExecutionContext - -@Singleton -class ItemSetController @Inject()(@Named(ActorNames.ITEM_SET_ACTOR) itemSetActor: ActorRef, cc: ControllerComponents, actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends BaseController(cc) { - - val objectType = "ItemSet" - val schemaName: String = "itemset" - val version = "2.0" - - def create() = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val itemset = body.getOrDefault("itemset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, AnyRef]] - itemset.putAll(headers) - val itemSetRequest = getRequest(itemset, headers, ItemSetOperations.createItemSet.toString) - setRequestContext(itemSetRequest, version, objectType, schemaName) - getResult(ApiId.CREATE_ITEM_SET, itemSetActor, itemSetRequest) - } - - def read(identifier: String, fields: Option[String]) = Action.async { implicit request => - val headers = commonHeaders() - val itemset = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]] - itemset.putAll(headers) - itemset.putAll(Map("identifier" -> identifier, "fields" -> fields.getOrElse("")).asJava) - val itemSetRequest = getRequest(itemset, headers, ItemSetOperations.readItemSet.toString) - setRequestContext(itemSetRequest, version, objectType, schemaName) - getResult(ApiId.READ_ITEM_SET, itemSetActor, itemSetRequest) - } - - def update(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val itemset = body.getOrDefault("itemset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - itemset.putAll(headers) - val itemSetRequest = getRequest(itemset, headers, ItemSetOperations.updateItemSet.toString) - setRequestContext(itemSetRequest, version, objectType, schemaName) - itemSetRequest.getContext.put("identifier", identifier); - getResult(ApiId.UPDATE_ITEM_SET, itemSetActor, itemSetRequest) - } - - def review(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val itemset = body.getOrDefault("itemset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - itemset.putAll(headers) - val itemSetRequest = getRequest(itemset, headers, ItemSetOperations.reviewItemSet.toString) - setRequestContext(itemSetRequest, version, objectType, schemaName) - itemSetRequest.getContext.put("identifier", identifier); - getResult(ApiId.REVIEW_ITEM_SET, itemSetActor, itemSetRequest) - } - - def retire(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val itemset = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]] - itemset.putAll(headers) - val itemSetRequest = getRequest(itemset, headers, ItemSetOperations.retireItemSet.toString) - setRequestContext(itemSetRequest, version, objectType, schemaName) - itemSetRequest.getContext.put("identifier", identifier) - getResult(ApiId.RETIRE_ITEM_SET, itemSetActor, itemSetRequest) - } -} diff --git a/assessment-api/assessment-service/app/controllers/v4/QuestionController.scala b/assessment-api/assessment-service/app/controllers/v4/QuestionController.scala deleted file mode 100644 index d929bb272..000000000 --- a/assessment-api/assessment-service/app/controllers/v4/QuestionController.scala +++ /dev/null @@ -1,146 +0,0 @@ -package controllers.v4 - -import akka.actor.{ActorRef, ActorSystem} -import controllers.BaseController -import org.sunbird.utils.AssessmentConstants - -import javax.inject.{Inject, Named} -import play.api.mvc.ControllerComponents -import utils.{ActorNames, ApiId, QuestionOperations} - -import scala.collection.JavaConverters._ -import scala.concurrent.ExecutionContext - -class QuestionController @Inject()(@Named(ActorNames.QUESTION_ACTOR) questionActor: ActorRef, cc: ControllerComponents, actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends BaseController(cc) { - - val objectType = "Question" - val schemaName: String = "question" - val version = "1.0" - - def create() = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val question = body.getOrDefault("question", new java.util.HashMap()).asInstanceOf[java.util.Map[String, AnyRef]] - question.putAll(headers) - val questionRequest = getRequest(question, headers, QuestionOperations.createQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - getResult(ApiId.CREATE_QUESTION, questionActor, questionRequest) - } - - def read(identifier: String, mode: Option[String], fields: Option[String]) = Action.async { implicit request => - val headers = commonHeaders() - val question = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]] - question.putAll(headers) - question.putAll(Map("identifier" -> identifier, "fields" -> fields.getOrElse(""), "mode" -> mode.getOrElse("read")).asJava) - val questionRequest = getRequest(question, headers, QuestionOperations.readQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - getResult(ApiId.READ_QUESTION, questionActor, questionRequest) - } - - def privateRead(identifier: String, mode: Option[String], fields: Option[String]) = Action.async { implicit request => - val headers = commonHeaders() - val question = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]] - question.putAll(headers) - question.putAll(Map("identifier" -> identifier, "fields" -> fields.getOrElse(""), "mode" -> mode.getOrElse("read")).asJava) - val questionRequest = getRequest(question, headers, QuestionOperations.readPrivateQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - getResult(ApiId.READ_PRIVATE_QUESTION, questionActor, questionRequest) - } - - def update(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val question = body.getOrDefault("question", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - question.putAll(headers) - val questionRequest = getRequest(question, headers, QuestionOperations.updateQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - questionRequest.getContext.put("identifier", identifier) - getResult(ApiId.UPDATE_QUESTION, questionActor, questionRequest) - } - - def review(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val question = body.getOrDefault("question", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - question.putAll(headers) - val questionRequest = getRequest(question, headers, QuestionOperations.reviewQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - questionRequest.getContext.put("identifier", identifier) - getResult(ApiId.REVIEW_QUESTION, questionActor, questionRequest) - } - - def publish(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val question = body.getOrDefault("question", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - question.putAll(headers) - val questionRequest = getRequest(question, headers, QuestionOperations.publishQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - questionRequest.getContext.put("identifier", identifier) - getResult(ApiId.PUBLISH_QUESTION, questionActor, questionRequest) - } - - def retire(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val question = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]] - question.putAll(headers) - val questionRequest = getRequest(question, headers, QuestionOperations.retireQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - questionRequest.getContext.put("identifier", identifier) - getResult(ApiId.RETIRE_QUESTION, questionActor, questionRequest) - } - - def importQuestion() = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - body.putAll(headers) - val questionRequest = getRequest(body, headers, QuestionOperations.importQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - getResult(ApiId.IMPORT_QUESTION, questionActor, questionRequest) - } - - def systemUpdate(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val content = body.getOrDefault(schemaName, new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - content.putAll(headers) - val questionRequest = getRequest(content, headers, QuestionOperations.systemUpdateQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - questionRequest.getContext.put("identifier", identifier); - getResult(ApiId.SYSTEM_UPDATE_QUESTION, questionActor, questionRequest) - } - - def list(fields: Option[String]) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val question = body.getOrDefault("search", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - question.putAll(headers) - question.put("fields", fields.getOrElse("")) - val questionRequest = getRequest(question, headers, QuestionOperations.listQuestions.toString) - questionRequest.put("identifiers", questionRequest.get("identifier")) - setRequestContext(questionRequest, version, objectType, schemaName) - getResult(ApiId.LIST_QUESTIONS, questionActor, questionRequest) - } - - def reject(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val question = body.getOrDefault(schemaName, new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - question.putAll(headers) - val questionRequest = getRequest(question, headers, QuestionOperations.rejectQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - questionRequest.getContext.put("identifier", identifier) - getResult(ApiId.REJECT_QUESTION, questionActor, questionRequest) - } - - def copy(identifier: String, mode: Option[String]) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val question = body.getOrDefault("question", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - question.putAll(headers) - question.putAll(Map("identifier" -> identifier, "mode" -> mode.getOrElse(""), "copyType" -> AssessmentConstants.COPY_TYPE_DEEP).asJava) - val questionRequest = getRequest(question, headers, QuestionOperations.copyQuestion.toString) - setRequestContext(questionRequest, version, objectType, schemaName) - getResult(ApiId.COPY_QUESTION, questionActor, questionRequest) - } -} diff --git a/assessment-api/assessment-service/app/controllers/v4/QuestionSetController.scala b/assessment-api/assessment-service/app/controllers/v4/QuestionSetController.scala deleted file mode 100644 index f2fa9cdce..000000000 --- a/assessment-api/assessment-service/app/controllers/v4/QuestionSetController.scala +++ /dev/null @@ -1,172 +0,0 @@ -package controllers.v4 - -import akka.actor.{ActorRef, ActorSystem} -import controllers.BaseController -import javax.inject.{Inject, Named} -import play.api.mvc.ControllerComponents -import utils.{ActorNames, ApiId, QuestionSetOperations} - -import scala.collection.JavaConverters._ -import scala.concurrent.ExecutionContext - -class QuestionSetController @Inject()(@Named(ActorNames.QUESTION_SET_ACTOR) questionSetActor: ActorRef, cc: ControllerComponents, actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends BaseController(cc) { - - val objectType = "QuestionSet" - val schemaName: String = "questionset" - val version = "1.0" - - def create() = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val questionSet = body.getOrDefault("questionset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, AnyRef]] - questionSet.putAll(headers) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.createQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - getResult(ApiId.CREATE_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def read(identifier: String, mode: Option[String], fields: Option[String]) = Action.async { implicit request => - val headers = commonHeaders() - val questionSet = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]] - questionSet.putAll(headers) - questionSet.putAll(Map("identifier" -> identifier, "fields" -> fields.getOrElse(""), "mode" -> mode.getOrElse("read")).asJava) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.readQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - getResult(ApiId.READ_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def privateRead(identifier: String, mode: Option[String], fields: Option[String]) = Action.async { implicit request => - val headers = commonHeaders() - val questionSet = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]] - questionSet.putAll(headers) - questionSet.putAll(Map("identifier" -> identifier, "fields" -> fields.getOrElse(""), "mode" -> mode.getOrElse("read")).asJava) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.readPrivateQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - getResult(ApiId.READ_PRIVATE_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def update(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val questionSet = body.getOrDefault("questionset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - questionSet.putAll(headers) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.updateQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - questionSetRequest.getContext.put("identifier", identifier) - getResult(ApiId.UPDATE_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def review(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val questionSet = body.getOrDefault("questionset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - questionSet.putAll(headers) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.reviewQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - questionSetRequest.getContext.put("identifier", identifier) - getResult(ApiId.REVIEW_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def publish(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val questionSet = body.getOrDefault("questionset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - questionSet.putAll(headers) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.publishQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - questionSetRequest.getContext.put("identifier", identifier) - getResult(ApiId.PUBLISH_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def retire(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val questionSet = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]] - questionSet.putAll(headers) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.retireQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - questionSetRequest.getContext.put("identifier", identifier) - getResult(ApiId.RETIRE_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def add() = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val questionSet = body.getOrDefault("questionset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]] - questionSet.putAll(headers) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.addQuestion.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - getResult(ApiId.ADD_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def remove() = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val questionSet = body.getOrDefault("questionset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]] - questionSet.putAll(headers) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.removeQuestion.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - getResult(ApiId.REMOVE_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def updateHierarchy() = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val data = body.getOrDefault("data", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]] - data.putAll(headers) - val questionSetRequest = getRequest(data, headers, "updateHierarchy") - setRequestContext(questionSetRequest, version, objectType, schemaName) - getResult(ApiId.UPDATE_HIERARCHY, questionSetActor, questionSetRequest) - } - - def getHierarchy(identifier: String, mode: Option[String]) = Action.async { implicit request => - val headers = commonHeaders() - val questionSet = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]] - questionSet.putAll(headers) - questionSet.putAll(Map("rootId" -> identifier, "mode" -> mode.getOrElse("")).asJava) - val readRequest = getRequest(questionSet, headers, "getHierarchy") - setRequestContext(readRequest, version, objectType, schemaName) - getResult(ApiId.GET_HIERARCHY, questionSetActor, readRequest) - } - - def reject(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val questionSet = body.getOrDefault("questionset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - questionSet.putAll(headers) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.rejectQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - questionSetRequest.getContext.put("identifier", identifier) - getResult(ApiId.REJECT_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def importQuestionSet() = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - body.putAll(headers) - val questionSetRequest = getRequest(body, headers, QuestionSetOperations.importQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - getResult(ApiId.IMPORT_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def systemUpdate(identifier: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val questionSet = body.getOrDefault("questionset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - questionSet.putAll(headers) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.systemUpdateQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - questionSetRequest.getContext.put("identifier", identifier); - getResult(ApiId.SYSTEM_UPDATE_QUESTION_SET, questionSetActor, questionSetRequest) - } - - def copy(identifier: String, mode: Option[String], copyType: String) = Action.async { implicit request => - val headers = commonHeaders() - val body = requestBody() - val questionSet = body.getOrDefault("questionset", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; - questionSet.putAll(headers) - questionSet.putAll(Map("identifier" -> identifier, "mode" -> mode.getOrElse(""), "copyType" -> copyType).asJava) - val questionSetRequest = getRequest(questionSet, headers, QuestionSetOperations.copyQuestionSet.toString) - setRequestContext(questionSetRequest, version, objectType, schemaName) - getResult(ApiId.COPY_QUESTION_SET, questionSetActor, questionSetRequest) - } -} diff --git a/assessment-api/assessment-service/app/filters/AccessLogFilter.scala b/assessment-api/assessment-service/app/filters/AccessLogFilter.scala deleted file mode 100644 index aad9f8419..000000000 --- a/assessment-api/assessment-service/app/filters/AccessLogFilter.scala +++ /dev/null @@ -1,45 +0,0 @@ -package filters - -import akka.util.ByteString -import javax.inject.Inject -import org.sunbird.telemetry.util.TelemetryAccessEventUtil -import play.api.Logging -import play.api.libs.streams.Accumulator -import play.api.mvc._ - -import scala.concurrent.ExecutionContext -import scala.collection.JavaConverters._ - -class AccessLogFilter @Inject() (implicit ec: ExecutionContext) extends EssentialFilter with Logging { - - val xHeaderNames = Map("x-session-id" -> "X-Session-ID", "X-Consumer-ID" -> "x-consumer-id", "x-device-id" -> "X-Device-ID", "x-app-id" -> "APP_ID", "x-authenticated-userid" -> "X-Authenticated-Userid", "x-channel-id" -> "X-Channel-Id") - - def apply(nextFilter: EssentialAction) = new EssentialAction { - def apply(requestHeader: RequestHeader) = { - - val startTime = System.currentTimeMillis - - val accumulator: Accumulator[ByteString, Result] = nextFilter(requestHeader) - - accumulator.map { result => - val endTime = System.currentTimeMillis - val requestTime = endTime - startTime - - val path = requestHeader.uri - if(!path.contains("/health")){ - val headers = requestHeader.headers.headers.groupBy(_._1).mapValues(_.map(_._2)) - val appHeaders = headers.filter(header => xHeaderNames.keySet.contains(header._1.toLowerCase)) - .map(entry => (xHeaderNames.get(entry._1.toLowerCase()).get, entry._2.head)) - val otherDetails = Map[String, Any]("StartTime" -> startTime, "env" -> "assessment", - "RemoteAddress" -> requestHeader.remoteAddress, - "ContentLength" -> result.body.contentLength.getOrElse(0), - "Status" -> result.header.status, "Protocol" -> "http", - "path" -> path, - "Method" -> requestHeader.method.toString) - TelemetryAccessEventUtil.writeTelemetryEventLog((otherDetails ++ appHeaders).asInstanceOf[Map[String, AnyRef]].asJava) - } - result.withHeaders("Request-Time" -> requestTime.toString) - } - } - } - } \ No newline at end of file diff --git a/assessment-api/assessment-service/app/handlers/SignalHandler.scala b/assessment-api/assessment-service/app/handlers/SignalHandler.scala deleted file mode 100644 index 4cad301c1..000000000 --- a/assessment-api/assessment-service/app/handlers/SignalHandler.scala +++ /dev/null @@ -1,33 +0,0 @@ -package handlers - -import java.util.concurrent.TimeUnit - -import akka.actor.ActorSystem -import javax.inject.{Inject, Singleton} -import org.slf4j.LoggerFactory -import play.api.inject.DefaultApplicationLifecycle -import sun.misc.Signal - -import scala.concurrent.duration.Duration - -@Singleton -class SignalHandler @Inject()(implicit actorSystem: ActorSystem, lifecycle: DefaultApplicationLifecycle) { - val LOG = LoggerFactory.getLogger(classOf[SignalHandler]) - val STOP_DELAY = Duration.create(30, TimeUnit.SECONDS) - var isShuttingDown = false - - println("Initializing SignalHandler...") - Signal.handle(new Signal("TERM"), new sun.misc.SignalHandler() { - override def handle(signal: Signal): Unit = { - // $COVERAGE-OFF$ Disabling scoverage as this code is impossible to test - isShuttingDown = true - println("Termination required, swallowing SIGTERM to allow current requests to finish. : " + System.currentTimeMillis()) - actorSystem.scheduler.scheduleOnce(STOP_DELAY)(() => { - println("ApplicationLifecycle stop triggered... : " + System.currentTimeMillis()) - lifecycle.stop() - })(actorSystem.dispatcher) - // $COVERAGE-ON - } - }) -} - diff --git a/assessment-api/assessment-service/app/modules/AssessmentModule.scala b/assessment-api/assessment-service/app/modules/AssessmentModule.scala deleted file mode 100644 index b73f02536..000000000 --- a/assessment-api/assessment-service/app/modules/AssessmentModule.scala +++ /dev/null @@ -1,18 +0,0 @@ -package modules - -import com.google.inject.AbstractModule -import org.sunbird.actors.{HealthActor, ItemSetActor, QuestionActor, QuestionSetActor} -import play.libs.akka.AkkaGuiceSupport -import utils.ActorNames - -class AssessmentModule extends AbstractModule with AkkaGuiceSupport { - - override def configure() = { -// super.configure() - bindActor(classOf[HealthActor], ActorNames.HEALTH_ACTOR) - bindActor(classOf[ItemSetActor], ActorNames.ITEM_SET_ACTOR) - bindActor(classOf[QuestionActor], ActorNames.QUESTION_ACTOR) - bindActor(classOf[QuestionSetActor], ActorNames.QUESTION_SET_ACTOR) - println("Initialized application actors for assessment-service") - } -} diff --git a/assessment-api/assessment-service/app/utils/ActorNames.scala b/assessment-api/assessment-service/app/utils/ActorNames.scala deleted file mode 100644 index 16a5cb726..000000000 --- a/assessment-api/assessment-service/app/utils/ActorNames.scala +++ /dev/null @@ -1,10 +0,0 @@ -package utils - -object ActorNames { - - final val HEALTH_ACTOR = "healthActor" - final val ITEM_SET_ACTOR = "itemSetActor" - final val QUESTION_ACTOR = "questionActor" - final val QUESTION_SET_ACTOR = "questionSetActor" - -} diff --git a/assessment-api/assessment-service/app/utils/ApiId.scala b/assessment-api/assessment-service/app/utils/ApiId.scala deleted file mode 100644 index 062340338..000000000 --- a/assessment-api/assessment-service/app/utils/ApiId.scala +++ /dev/null @@ -1,45 +0,0 @@ -package utils - -object ApiId { - - final val APPLICATION_HEALTH = "api.assessment.health" - final val APPLICATION_SERVICE_HEALTH = "api.assessment.service.health" - - //ItemSet APIs - val CREATE_ITEM_SET = "api.itemset.create" - val READ_ITEM_SET = "api.itemset.read" - val UPDATE_ITEM_SET = "api.itemset.update" - val REVIEW_ITEM_SET = "api.itemset.review" - val RETIRE_ITEM_SET = "api.itemset.retire" - - //Question APIs - val CREATE_QUESTION = "api.question.create" - val READ_QUESTION = "api.question.read" - val READ_PRIVATE_QUESTION = "api.question.private.read" - val UPDATE_QUESTION = "api.question.update" - val REVIEW_QUESTION = "api.question.review" - val PUBLISH_QUESTION = "api.question.publish" - val RETIRE_QUESTION = "api.question.retire" - val IMPORT_QUESTION = "api.question.import" - val SYSTEM_UPDATE_QUESTION = "api.question.system.update" - val LIST_QUESTIONS = "api.questions.list" - val REJECT_QUESTION = "api.question.reject" - val COPY_QUESTION = "api.question.copy" - - //QuestionSet APIs - val CREATE_QUESTION_SET = "api.questionset.create" - val READ_QUESTION_SET = "api.questionset.read" - val READ_PRIVATE_QUESTION_SET = "api.questionset.private.read" - val UPDATE_QUESTION_SET = "api.questionset.update" - val REVIEW_QUESTION_SET = "api.questionset.review" - val PUBLISH_QUESTION_SET = "api.questionset.publish" - val RETIRE_QUESTION_SET = "api.questionset.retire" - val ADD_QUESTION_SET = "api.questionset.add" - val REMOVE_QUESTION_SET = "api.questionset.remove" - val UPDATE_HIERARCHY = "api.questionset.hierarchy.update" - val GET_HIERARCHY = "api.questionset.hierarchy.get" - val REJECT_QUESTION_SET = "api.questionset.reject" - val IMPORT_QUESTION_SET = "api.questionset.import" - val SYSTEM_UPDATE_QUESTION_SET = "api.questionset.system.update" - val COPY_QUESTION_SET = "api.questionset.copy" -} diff --git a/assessment-api/assessment-service/app/utils/ItemSetOperations.scala b/assessment-api/assessment-service/app/utils/ItemSetOperations.scala deleted file mode 100644 index 4f3fcaa5b..000000000 --- a/assessment-api/assessment-service/app/utils/ItemSetOperations.scala +++ /dev/null @@ -1,5 +0,0 @@ -package utils - -object ItemSetOperations extends Enumeration { - val createItemSet, readItemSet, updateItemSet, reviewItemSet, retireItemSet = Value -} diff --git a/assessment-api/assessment-service/app/utils/JavaJsonUtils.scala b/assessment-api/assessment-service/app/utils/JavaJsonUtils.scala deleted file mode 100644 index 2093c2e33..000000000 --- a/assessment-api/assessment-service/app/utils/JavaJsonUtils.scala +++ /dev/null @@ -1,38 +0,0 @@ -package utils - -import java.lang.reflect.{ParameterizedType, Type} - -import com.fasterxml.jackson.core.`type`.TypeReference -import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper} - -object JavaJsonUtils { - - @transient val mapper = new ObjectMapper(); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); -// mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false); -// mapper.setSerializationInclusion(Include.NON_NULL); - - @throws(classOf[Exception]) - def serialize(obj: AnyRef): String = { - mapper.writeValueAsString(obj); - } - - @throws(classOf[Exception]) - def deserialize[T: Manifest](value: String): T = mapper.readValue(value, typeReference[T]); - - private[this] def typeReference[T: Manifest] = new TypeReference[T] { - override def getType = typeFromManifest(manifest[T]) - } - - - private[this] def typeFromManifest(m: Manifest[_]): Type = { - if (m.typeArguments.isEmpty) { m.runtimeClass } - // $COVERAGE-OFF$Disabling scoverage as this code is impossible to test - else new ParameterizedType { - def getRawType = m.runtimeClass - def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray - def getOwnerType = null - } - // $COVERAGE-ON$ - } -} diff --git a/assessment-api/assessment-service/app/utils/QuestionOperations.scala b/assessment-api/assessment-service/app/utils/QuestionOperations.scala deleted file mode 100644 index 8d71d88e1..000000000 --- a/assessment-api/assessment-service/app/utils/QuestionOperations.scala +++ /dev/null @@ -1,5 +0,0 @@ -package utils - -object QuestionOperations extends Enumeration { - val createQuestion, readQuestion, readPrivateQuestion, updateQuestion, reviewQuestion, publishQuestion, retireQuestion, importQuestion, systemUpdateQuestion, listQuestions, rejectQuestion, copyQuestion = Value -} diff --git a/assessment-api/assessment-service/app/utils/QuestionSetOperations.scala b/assessment-api/assessment-service/app/utils/QuestionSetOperations.scala deleted file mode 100644 index 43f0266b1..000000000 --- a/assessment-api/assessment-service/app/utils/QuestionSetOperations.scala +++ /dev/null @@ -1,7 +0,0 @@ -package utils - -object QuestionSetOperations extends Enumeration { - val createQuestionSet, readQuestionSet, readPrivateQuestionSet, updateQuestionSet, reviewQuestionSet, publishQuestionSet, - retireQuestionSet, addQuestion, removeQuestion, updateHierarchyQuestion, readHierarchyQuestion, - rejectQuestionSet, importQuestionSet, systemUpdateQuestionSet, copyQuestionSet = Value -} diff --git a/assessment-api/assessment-service/conf/application.conf b/assessment-api/assessment-service/conf/application.conf deleted file mode 100644 index 5e82dfa27..000000000 --- a/assessment-api/assessment-service/conf/application.conf +++ /dev/null @@ -1,433 +0,0 @@ -# This is the main configuration file for the application. -# https://www.playframework.com/documentation/latest/ConfigFile -# ~~~~~ -# Play uses HOCON as its configuration file format. HOCON has a number -# of advantages over other config formats, but there are two things that -# can be used when modifying settings. -# -# You can include other configuration files in this main application.conf file: -#include "extra-config.conf" -# -# You can declare variables and substitute for them: -#mykey = ${some.value} -# -# And if an environment variable exists when there is no other substitution, then -# HOCON will fall back to substituting environment variable: -#mykey = ${JAVA_HOME} - -## Akka -# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration -# https://www.playframework.com/documentation/latest/JavaAkka#Configuration -# ~~~~~ -# Play uses Akka internally and exposes Akka Streams and actors in Websockets and -# other streaming HTTP responses. -akka { - # "akka.log-config-on-start" is extraordinarly useful because it log the complete - # configuration at INFO level, including defaults and overrides, so it s worth - # putting at the very top. - # - # Put the following in your conf/logback.xml file: - # - # - # - # And then uncomment this line to debug the configuration. - # - #log-config-on-start = true - default-dispatcher { - # This will be used if you have set "executor = "fork-join-executor"" - fork-join-executor { - # Min number of threads to cap factor-based parallelism number to - parallelism-min = 8 - - # The parallelism factor is used to determine thread pool size using the - # following formula: ceil(available processors * factor). Resulting size - # is then bounded by the parallelism-min and parallelism-max values. - parallelism-factor = 32.0 - - # Max number of threads to cap factor-based parallelism number to - parallelism-max = 64 - - # Setting to "FIFO" to use queue like peeking mode which "poll" or "LIFO" to use stack - # like peeking mode which "pop". - task-peeking-mode = "FIFO" - } - } - actors-dispatcher { - type = "Dispatcher" - executor = "fork-join-executor" - fork-join-executor { - parallelism-min = 8 - parallelism-factor = 32.0 - parallelism-max = 64 - } - # Throughput for default Dispatcher, set to 1 for as fair as possible - throughput = 1 - } - actor { - deployment { - /healthActor - { - router = smallest-mailbox-pool - nr-of-instances = 5 - dispatcher = actors-dispatcher - } - /itemSetActor - { - router = smallest-mailbox-pool - nr-of-instances = 2 - dispatcher = actors-dispatcher - } - /questionActor - { - router = smallest-mailbox-pool - nr-of-instances = 5 - dispatcher = actors-dispatcher - } - /questionSetActor - { - router = smallest-mailbox-pool - nr-of-instances = 5 - dispatcher = actors-dispatcher - } - } - } -} - -## Secret key -# http://www.playframework.com/documentation/latest/ApplicationSecret -# ~~~~~ -# The secret key is used to sign Play's session cookie. -# This must be changed for production, but we don't recommend you change it in this file. -play.http.secret.key= a-long-secret-to-calm-the-rage-of-the-entropy-gods - -## Modules -# https://www.playframework.com/documentation/latest/Modules -# ~~~~~ -# Control which modules are loaded when Play starts. Note that modules are -# the replacement for "GlobalSettings", which are deprecated in 2.5.x. -# Please see https://www.playframework.com/documentation/latest/GlobalSettings -# for more information. -# -# You can also extend Play functionality by using one of the publically available -# Play modules: https://playframework.com/documentation/latest/ModuleDirectory -play.modules { - # By default, Play will load any class called Module that is defined - # in the root package (the "app" directory), or you can define them - # explicitly below. - # If there are any built-in modules that you want to enable, you can list them here. - #enabled += my.application.Module - - # If there are any built-in modules that you want to disable, you can list them here. - #disabled += "" - enabled += modules.AssessmentModule -} - -## IDE -# https://www.playframework.com/documentation/latest/IDE -# ~~~~~ -# Depending on your IDE, you can add a hyperlink for errors that will jump you -# directly to the code location in the IDE in dev mode. The following line makes -# use of the IntelliJ IDEA REST interface: -#play.editor="http://localhost:63342/api/file/?file=%s&line=%s" - -## Internationalisation -# https://www.playframework.com/documentation/latest/JavaI18N -# https://www.playframework.com/documentation/latest/ScalaI18N -# ~~~~~ -# Play comes with its own i18n settings, which allow the user's preferred language -# to map through to internal messages, or allow the language to be stored in a cookie. -play.i18n { - # The application languages - langs = [ "en" ] - - # Whether the language cookie should be secure or not - #langCookieSecure = true - - # Whether the HTTP only attribute of the cookie should be set to true - #langCookieHttpOnly = true -} - -## Play HTTP settings -# ~~~~~ -play.http { - ## Router - # https://www.playframework.com/documentation/latest/JavaRouting - # https://www.playframework.com/documentation/latest/ScalaRouting - # ~~~~~ - # Define the Router object to use for this application. - # This router will be looked up first when the application is starting up, - # so make sure this is the entry point. - # Furthermore, it's assumed your route file is named properly. - # So for an application router like `my.application.Router`, - # you may need to define a router file `conf/my.application.routes`. - # Default to Routes in the root package (aka "apps" folder) (and conf/routes) - #router = my.application.Router - - ## Action Creator - # https://www.playframework.com/documentation/latest/JavaActionCreator - # ~~~~~ - #actionCreator = null - - ## ErrorHandler - # https://www.playframework.com/documentation/latest/JavaRouting - # https://www.playframework.com/documentation/latest/ScalaRouting - # ~~~~~ - # If null, will attempt to load a class called ErrorHandler in the root package, - #errorHandler = null - - ## Session & Flash - # https://www.playframework.com/documentation/latest/JavaSessionFlash - # https://www.playframework.com/documentation/latest/ScalaSessionFlash - # ~~~~~ - session { - # Sets the cookie to be sent only over HTTPS. - #secure = true - - # Sets the cookie to be accessed only by the server. - #httpOnly = true - - # Sets the max-age field of the cookie to 5 minutes. - # NOTE: this only sets when the browser will discard the cookie. Play will consider any - # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout, - # you need to put a timestamp in the session and check it at regular intervals to possibly expire it. - #maxAge = 300 - - # Sets the domain on the session cookie. - #domain = "example.com" - } - - flash { - # Sets the cookie to be sent only over HTTPS. - #secure = true - - # Sets the cookie to be accessed only by the server. - #httpOnly = true - } -} - -play.server.http.idleTimeout = 60s -play.http.parser.maxDiskBuffer = 10MB -parsers.anyContent.maxLength = 10MB - -## Netty Provider -# https://www.playframework.com/documentation/latest/SettingsNetty -# ~~~~~ -play.server.netty { - # Whether the Netty wire should be logged - log.wire = true - - # If you run Play on Linux, you can use Netty's native socket transport - # for higher performance with less garbage. - transport = "native" -} - -## WS (HTTP Client) -# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS -# ~~~~~ -# The HTTP client primarily used for REST APIs. The default client can be -# configured directly, but you can also create different client instances -# with customized settings. You must enable this by adding to build.sbt: -# -# libraryDependencies += ws // or javaWs if using java -# -play.ws { - # Sets HTTP requests not to follow 302 requests - #followRedirects = false - - # Sets the maximum number of open HTTP connections for the client. - #ahc.maxConnectionsTotal = 50 - - ## WS SSL - # https://www.playframework.com/documentation/latest/WsSSL - # ~~~~~ - ssl { - # Configuring HTTPS with Play WS does not require programming. You can - # set up both trustManager and keyManager for mutual authentication, and - # turn on JSSE debugging in development with a reload. - #debug.handshake = true - #trustManager = { - # stores = [ - # { type = "JKS", path = "exampletrust.jks" } - # ] - #} - } -} - -## Cache -# https://www.playframework.com/documentation/latest/JavaCache -# https://www.playframework.com/documentation/latest/ScalaCache -# ~~~~~ -# Play comes with an integrated cache API that can reduce the operational -# overhead of repeated requests. You must enable this by adding to build.sbt: -# -# libraryDependencies += cache -# -play.cache { - # If you want to bind several caches, you can bind the individually - #bindCaches = ["db-cache", "user-cache", "session-cache"] -} - -## Filter Configuration -# https://www.playframework.com/documentation/latest/Filters -# ~~~~~ -# There are a number of built-in filters that can be enabled and configured -# to give Play greater security. -# -play.filters { - - # Enabled filters are run automatically against Play. - # CSRFFilter, AllowedHostFilters, and SecurityHeadersFilters are enabled by default. - enabled = [filters.AccessLogFilter] - - # Disabled filters remove elements from the enabled list. - # disabled += filters.CSRFFilter - - - ## CORS filter configuration - # https://www.playframework.com/documentation/latest/CorsFilter - # ~~~~~ - # CORS is a protocol that allows web applications to make requests from the browser - # across different domains. - # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has - # dependencies on CORS settings. - cors { - # Filter paths by a whitelist of path prefixes - #pathPrefixes = ["/some/path", ...] - - # The allowed origins. If null, all origins are allowed. - #allowedOrigins = ["http://www.example.com"] - - # The allowed HTTP methods. If null, all methods are allowed - #allowedHttpMethods = ["GET", "POST"] - } - - ## Security headers filter configuration - # https://www.playframework.com/documentation/latest/SecurityHeaders - # ~~~~~ - # Defines security headers that prevent XSS attacks. - # If enabled, then all options are set to the below configuration by default: - headers { - # The X-Frame-Options header. If null, the header is not set. - #frameOptions = "DENY" - - # The X-XSS-Protection header. If null, the header is not set. - #xssProtection = "1; mode=block" - - # The X-Content-Type-Options header. If null, the header is not set. - #contentTypeOptions = "nosniff" - - # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set. - #permittedCrossDomainPolicies = "master-only" - - # The Content-Security-Policy header. If null, the header is not set. - #contentSecurityPolicy = "default-src 'self'" - } - - ## Allowed hosts filter configuration - # https://www.playframework.com/documentation/latest/AllowedHostsFilter - # ~~~~~ - # Play provides a filter that lets you configure which hosts can access your application. - # This is useful to prevent cache poisoning attacks. - hosts { - # Allow requests to example.com, its subdomains, and localhost:9000. - #allowed = [".example.com", "localhost:9000"] - } -} - -play.http.parser.maxMemoryBuffer = 50MB -akka.http.parsing.max-content-length = 50MB -schema.base_path="../../schemas/" - -# Cassandra Configuration -cassandra.lp.connection="127.0.0.1:9042" -content.keyspace = "content_store" - -# Redis Configuration -redis.host="localhost" -redis.port=6379 -redis.maxConnections=128 - -# Graph Configuration -graph.dir=/data/testingGraphDB -akka.request_timeout=30 -environment.id=10000000 -graph.ids=["domain"] -graph.passport.key.base=31b6fd1c4d64e745c867e61a45edc34a -route.domain="bolt://localhost:7687" -route.bolt.write.domain="bolt://localhost:7687" -route.bolt.read.domain="bolt://localhost:7687" -route.bolt.comment.domain="bolt://localhost:7687" -route.all="bolt://localhost:7687" -route.bolt.write.all="bolt://localhost:7687" -route.bolt.read.all="bolt://localhost:7687" -route.bolt.comment.all="bolt://localhost:7687" - -shard.id=1 -platform.auth.check.enabled=false -platform.cache.ttl=3600000 - -#Top N Config for Search Telemetry -telemetry_env=dev - -installation.id=ekstep - - -languageCode { - assamese : "as" - bengali : "bn" - english : "en" - gujarati : "gu" - hindi : "hi" - kannada : "ka" - marathi : "mr" - odia : "or" - tamil : "ta" - telugu : "te" -} - -kafka { - urls : "localhost:9092" - topic.send.enable : true - topics.instruction : "sunbirddev.assessment.publish.request" -} -objectcategorydefinition.keyspace="category_store" -question { - keyspace = "question_store" - list.limit=20 -} -questionset.keyspace="hierarchy_store" - -cassandra { - lp { - connection: "localhost:9042" - } - lpa { - connection: "localhost:9042" - } -} -neo4j_objecttypes_enabled=["Question"] - -import { - request_size_limit = 200 - output_topic_name = "local.auto.creation.job.request" - required_props { - question = ["name", "code", "mimeType", "framework", "channel"] - questionset = ["name", "code", "mimeType", "framework", "channel"] - } - remove_props { - question = [] - questionset = [] - } -} - -root_node_visibility=["Default","Private"] -assessment.copy.origin_data=["name", "author", "license", "organisation"] -assessment.copy.props_to_remove=["downloadUrl", "artifactUrl", "variants", - "createdOn", "collections", "children", "lastUpdatedOn", "SYS_INTERNAL_LAST_UPDATED_ON", - "versionKey", "s3Key", "status", "pkgVersion", "toc_url", "mimeTypesCount", - "contentTypesCount", "leafNodesCount", "childNodes", "prevState", "lastPublishedOn", - "flagReasons", "compatibilityLevel", "size", "publishChecklist", "publishComment", - "LastPublishedBy", "rejectReasons", "rejectComment", "gradeLevel", "subject", - "medium", "board", "topic", "purpose", "subtopic", "contentCredits", - "owner", "collaborators", "creators", "contributors", "badgeAssertions", "dialcodes", - "concepts", "keywords", "reservedDialcodes", "dialcodeRequired", "leafNodes", "sYS_INTERNAL_LAST_UPDATED_ON", "prevStatus", "lastPublishedBy", "streamingUrl"] \ No newline at end of file diff --git a/assessment-api/assessment-service/conf/logback.xml b/assessment-api/assessment-service/conf/logback.xml deleted file mode 100644 index 73529d622..000000000 --- a/assessment-api/assessment-service/conf/logback.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - %d %msg%n - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assessment-api/assessment-service/conf/routes b/assessment-api/assessment-service/conf/routes deleted file mode 100644 index b76bb70a9..000000000 --- a/assessment-api/assessment-service/conf/routes +++ /dev/null @@ -1,43 +0,0 @@ -# Routes -# This file defines all application routes (Higher priority routes first) -# ~~~~ -GET /health controllers.HealthController.health -GET /service/health controllers.HealthController.serviceHealth - -# ItemSet API's -POST /itemset/v3/create controllers.v3.ItemSetController.create -GET /itemset/v3/read/:identifier controllers.v3.ItemSetController.read(identifier:String, fields:Option[String]) -PATCH /itemset/v3/update/:identifier controllers.v3.ItemSetController.update(identifier:String) -POST /itemset/v3/review/:identifier controllers.v3.ItemSetController.review(identifier:String) -DELETE /itemset/v3/retire/:identifier controllers.v3.ItemSetController.retire(identifier:String) - -# Question API's -POST /question/v4/create controllers.v4.QuestionController.create -GET /question/v4/read/:identifier controllers.v4.QuestionController.read(identifier:String, mode:Option[String], fields:Option[String]) -GET /question/v4/private/read/:identifier controllers.v4.QuestionController.privateRead(identifier:String, mode:Option[String], fields:Option[String]) -PATCH /question/v4/update/:identifier controllers.v4.QuestionController.update(identifier:String) -POST /question/v4/review/:identifier controllers.v4.QuestionController.review(identifier:String) -POST /question/v4/publish/:identifier controllers.v4.QuestionController.publish(identifier:String) -DELETE /question/v4/retire/:identifier controllers.v4.QuestionController.retire(identifier:String) -POST /question/v4/import controllers.v4.QuestionController.importQuestion() -PATCH /question/v4/system/update/:identifier controllers.v4.QuestionController.systemUpdate(identifier:String) -POST /question/v4/list controllers.v4.QuestionController.list(fields:Option[String]) -POST /question/v4/reject/:identifier controllers.v4.QuestionController.reject(identifier:String) -POST /question/v4/copy/:identifier controllers.v4.QuestionController.copy(identifier:String, mode:Option[String]) - -# QuestionSet API's -POST /questionset/v4/create controllers.v4.QuestionSetController.create -GET /questionset/v4/read/:identifier controllers.v4.QuestionSetController.read(identifier:String, mode:Option[String], fields:Option[String]) -GET /questionset/v4/private/read/:identifier controllers.v4.QuestionSetController.privateRead(identifier:String, mode:Option[String], fields:Option[String]) -PATCH /questionset/v4/update/:identifier controllers.v4.QuestionSetController.update(identifier:String) -POST /questionset/v4/review/:identifier controllers.v4.QuestionSetController.review(identifier:String) -POST /questionset/v4/publish/:identifier controllers.v4.QuestionSetController.publish(identifier:String) -DELETE /questionset/v4/retire/:identifier controllers.v4.QuestionSetController.retire(identifier:String) -PATCH /questionset/v4/add controllers.v4.QuestionSetController.add -DELETE /questionset/v4/remove controllers.v4.QuestionSetController.remove -PATCH /questionset/v4/hierarchy/update controllers.v4.QuestionSetController.updateHierarchy -GET /questionset/v4/hierarchy/:identifier controllers.v4.QuestionSetController.getHierarchy(identifier:String, mode:Option[String]) -POST /questionset/v4/reject/:identifier controllers.v4.QuestionSetController.reject(identifier:String) -POST /questionset/v4/import controllers.v4.QuestionSetController.importQuestionSet() -PATCH /questionset/v4/system/update/:identifier controllers.v4.QuestionSetController.systemUpdate(identifier:String) -POST /questionset/v4/copy/:identifier controllers.v4.QuestionSetController.copy(identifier:String, mode:Option[String], type:String?="deep") \ No newline at end of file diff --git a/assessment-api/assessment-service/pom.xml b/assessment-api/assessment-service/pom.xml deleted file mode 100644 index b60eabf21..000000000 --- a/assessment-api/assessment-service/pom.xml +++ /dev/null @@ -1,188 +0,0 @@ - - - - assessment-api - org.sunbird - 1.0-SNAPSHOT - - 4.0.0 - assessment-service - play2 - - - - scalaz-bintray - Scalaz Bintray - releases - https://dl.bintray.com/scalaz/releases/ - - false - - - - - - typesafe-releases-plugins - https://repo.typesafe.com/typesafe/releases/ - - false - - - - - 2.7.2 - 1.0.0-rc5 - 1.0.0 - - - - - com.google.guava - guava - 18.0 - - - com.google.inject - guice - 3.0 - - - com.google.inject.extensions - guice-assistedinject - 3.0 - - - com.typesafe.play - play_${scala.major.version} - ${play2.version} - - - guava - com.google.guava - - - - - com.typesafe.play - play-guice_${scala.major.version} - ${play2.version} - - - guava - com.google.guava - - - - - com.typesafe.play - filters-helpers_${scala.major.version} - ${play2.version} - - - com.typesafe.play - play-logback_${scala.major.version} - ${play2.version} - runtime - - - com.typesafe.play - play-netty-server_${scala.major.version} - ${play2.version} - runtime - - - org.scala-lang - scala-library - ${scala.version} - - - org.sunbird - assessment-actors - 1.0-SNAPSHOT - jar - - - slf4j-log4j12 - org.slf4j - - - - - org.scalatest - scalatest_${scala.maj.version} - 3.1.2 - test - - - com.typesafe.play - play-specs2_${scala.maj.version} - ${play2.version} - test - - - guava - com.google.guava - - - - - org.joda - joda-convert - 2.2.1 - - - com.github.danielwegener - logback-kafka-appender - 0.2.0-RC2 - - - - ${basedir}/app - ${basedir}/test - - - ${basedir}/conf - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M4 - - - **/*Spec.java - **/*Test.java - - - - - com.google.code.play2-maven-plugin - play2-maven-plugin - ${play2.plugin.version} - true - - - com.google.code.sbt-compiler-maven-plugin - sbt-compiler-maven-plugin - ${sbt-compiler.plugin.version} - - -feature -deprecation -Xfatal-warnings - - - - org.scoverage - scoverage-maven-plugin - ${scoverage.plugin.version} - - ${scala.version} - true - true - .*RoutesPrefix.*;.*Routes.*;.*javascript.* - - - - - - \ No newline at end of file diff --git a/assessment-api/assessment-service/test/controllers/base/BaseSpec.scala b/assessment-api/assessment-service/test/controllers/base/BaseSpec.scala deleted file mode 100644 index 883693c86..000000000 --- a/assessment-api/assessment-service/test/controllers/base/BaseSpec.scala +++ /dev/null @@ -1,38 +0,0 @@ -package controllers.base - -import com.typesafe.config.ConfigFactory -import modules.TestModule -import org.specs2.mutable.Specification -import play.api.inject.guice.GuiceApplicationBuilder -import play.api.libs.json.Json -import play.api.mvc.Result -import play.api.test.Helpers.{POST, contentAsString, contentType, defaultAwaitTimeout, route, status, _} -import play.api.test.{FakeHeaders, FakeRequest} - -import scala.concurrent.Future - -class BaseSpec extends Specification { - implicit val app = new GuiceApplicationBuilder() - .disable(classOf[modules.AssessmentModule]) - .bindings(new TestModule) - .build - implicit val config = ConfigFactory.load() - - def post(apiURL: String, request: String, h: FakeHeaders = FakeHeaders(Seq())) - : Future[Result] = { - val headers = h.add(("content-type", "application/json")) - route(app, FakeRequest(POST, apiURL, headers, Json.toJson(Json.parse(request)))).get - } - - def isOK(response: Future[Result]) { - status(response) must equalTo(OK) - contentType(response) must beSome.which(_ == "application/json") - contentAsString(response) must contain(""""status":"successful"""") - } - - def hasClientError(response: Future[Result]) { - status(response) must equalTo(BAD_REQUEST) - contentType(response) must beSome.which(_ == "application/json") - contentAsString(response) must contain(""""err":"CLIENT_ERROR","status":"failed"""") - } -} diff --git a/assessment-api/assessment-service/test/controllers/v3/HealthControllerSpec.scala b/assessment-api/assessment-service/test/controllers/v3/HealthControllerSpec.scala deleted file mode 100644 index 49f351a62..000000000 --- a/assessment-api/assessment-service/test/controllers/v3/HealthControllerSpec.scala +++ /dev/null @@ -1,18 +0,0 @@ -package controllers.v3 - -import controllers.base.BaseSpec -import org.junit.runner.RunWith -import org.specs2.runner.JUnitRunner -import play.api.test.{FakeRequest, Helpers} -import play.api.test.Helpers.{OK, status} - -@RunWith(classOf[JUnitRunner]) -class HealthControllerSpec extends BaseSpec { - - "return api health status report - successful response" in { - val controller = app.injector.instanceOf[controllers.HealthController] - val result = controller.health()(FakeRequest()) - isOK(result) - status(result)(Helpers.defaultAwaitTimeout) must equalTo(OK) - } -} diff --git a/assessment-api/assessment-service/test/controllers/v3/ItemSetControllerSpec.scala b/assessment-api/assessment-service/test/controllers/v3/ItemSetControllerSpec.scala deleted file mode 100644 index c0a7cd546..000000000 --- a/assessment-api/assessment-service/test/controllers/v3/ItemSetControllerSpec.scala +++ /dev/null @@ -1,43 +0,0 @@ -package controllers.v3 - -import controllers.base.BaseSpec -import org.junit.runner.RunWith -import org.specs2.runner.JUnitRunner -import play.api.test.FakeRequest -import play.api.test.Helpers.{OK, defaultAwaitTimeout, status} - -@RunWith(classOf[JUnitRunner]) -class ItemSetControllerSpec extends BaseSpec { - - val controller = app.injector.instanceOf[controllers.v3.ItemSetController] - - "create should create an itemset successfully for given valid request" in { - val result = controller.create()(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "read should return an itemset successfully for given valid identifier" in { - val result = controller.read("do_123", None)(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "update should update the itemset successfully for given valid identifier" in { - val result = controller.update("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "review should update the itemset status to Review successfully for given valid identifier" in { - val result = controller.review("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "retire should update the itemset status to Retired successfully for given valid identifier" in { - val result = controller.retire("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } -} diff --git a/assessment-api/assessment-service/test/controllers/v4/QuestionControllerSpec.scala b/assessment-api/assessment-service/test/controllers/v4/QuestionControllerSpec.scala deleted file mode 100644 index fff589e98..000000000 --- a/assessment-api/assessment-service/test/controllers/v4/QuestionControllerSpec.scala +++ /dev/null @@ -1,79 +0,0 @@ -package controllers.v4 - -import controllers.base.BaseSpec -import org.junit.runner.RunWith -import org.specs2.runner.JUnitRunner -import play.api.test.FakeRequest -import play.api.test.Helpers.{OK, defaultAwaitTimeout, status} - -@RunWith(classOf[JUnitRunner]) -class QuestionControllerSpec extends BaseSpec { - - val controller = app.injector.instanceOf[controllers.v4.QuestionController] - - "create should create an question successfully for given valid request" in { - val result = controller.create()(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "read should return an question successfully for given valid identifier" in { - val result = controller.read("do_123", None, None)(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "private read should return an question successfully for given valid identifier" in { - val result = controller.privateRead("do_123", None, None)(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "update should update the question successfully for given valid identifier" in { - val result = controller.update("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "review should update the question status to Review successfully for given valid identifier" in { - val result = controller.review("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "publish should update the question status to Live successfully for given valid identifier" in { - val result = controller.publish("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "retire should update the question status to Retired successfully for given valid identifier" in { - val result = controller.retire("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "import should create a question successfully for given valid request" in { - val result = controller.importQuestion()(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "systemUpdate should update an question successfully for given valid request" in { - val result = controller.systemUpdate("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "list should list all the questions for given list of ids in the request" in { - val result = controller.list(None)(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "reject should update the question status to Draft successfully for given valid identifier" in { - val result = controller.reject("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } -} diff --git a/assessment-api/assessment-service/test/controllers/v4/QuestionSetControllerSpec.scala b/assessment-api/assessment-service/test/controllers/v4/QuestionSetControllerSpec.scala deleted file mode 100644 index 136d2ca5d..000000000 --- a/assessment-api/assessment-service/test/controllers/v4/QuestionSetControllerSpec.scala +++ /dev/null @@ -1,99 +0,0 @@ -package controllers.v4 - -import controllers.base.BaseSpec -import org.junit.runner.RunWith -import org.specs2.runner.JUnitRunner -import play.api.test.FakeRequest -import play.api.test.Helpers.{OK, defaultAwaitTimeout, status} - -@RunWith(classOf[JUnitRunner]) -class QuestionSetControllerSpec extends BaseSpec { - - val controller = app.injector.instanceOf[controllers.v4.QuestionSetController] - - "create should create an questionSet successfully for given valid request" in { - val result = controller.create()(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "read should return an questionSet successfully for given valid identifier" in { - val result = controller.read("do_123", None, None)(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "private read should return an questionSet successfully for given valid identifier" in { - val result = controller.privateRead("do_123", None, None)(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "update should update the questionSet successfully for given valid identifier" in { - val result = controller.update("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "review should update the questionSet status to Review successfully for given valid identifier" in { - val result = controller.review("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "publish should update the questionSet status to Live successfully for given valid identifier" in { - val result = controller.publish("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "retire should update the questionSet status to Retired successfully for given valid identifier" in { - val result = controller.retire("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "update Hierarchy should update hierarchy successfully for given valid identifier" in { - val result = controller.updateHierarchy()(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "read Hierarchy should read Hierarchy successfully for given valid identifier" in { - val result = controller.getHierarchy("do_123", None)(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - - "add question should update the questionSet status to Add question successfully for given valid identifier" in { - val result = controller.add()(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - - "remove question should update the questionSet status to remove question successfully for given valid identifier" in { - val result = controller.remove()(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "review should update the questionSet status to Reject successfully for given valid identifier" in { - val result = controller.reject("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "import should create an questionSet successfully for given valid request" in { - val result = controller.importQuestionSet()(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } - - "systemUpdate should update an questionSet successfully for given valid request" in { - val result = controller.systemUpdate("do_123")(FakeRequest()) - isOK(result) - status(result)(defaultAwaitTimeout) must equalTo(OK) - } -} diff --git a/assessment-api/assessment-service/test/modules/TestModule.scala b/assessment-api/assessment-service/test/modules/TestModule.scala deleted file mode 100644 index 8867e7cbc..000000000 --- a/assessment-api/assessment-service/test/modules/TestModule.scala +++ /dev/null @@ -1,28 +0,0 @@ -package modules - -import com.google.inject.AbstractModule -import org.sunbird.actor.core.BaseActor -import org.sunbird.common.dto.{Request, Response, ResponseHandler} -import play.libs.akka.AkkaGuiceSupport -import utils.ActorNames - -import scala.concurrent.{ExecutionContext, Future} - -class TestModule extends AbstractModule with AkkaGuiceSupport { - override def configure(): Unit = { - bindActor(classOf[TestActor], ActorNames.HEALTH_ACTOR) - bindActor(classOf[TestActor], ActorNames.ITEM_SET_ACTOR) - bindActor(classOf[TestActor], ActorNames.QUESTION_ACTOR) - bindActor(classOf[TestActor], ActorNames.QUESTION_SET_ACTOR) - println("Test Module is initialized...") - } -} - -class TestActor extends BaseActor { - - implicit val ec: ExecutionContext = getContext().dispatcher - - override def onReceive(request: Request): Future[Response] = { - Future(ResponseHandler.OK) - } -} diff --git a/assessment-api/pom.xml b/assessment-api/pom.xml deleted file mode 100644 index 7c55ee4d4..000000000 --- a/assessment-api/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - knowledge-platform - org.sunbird - 1.0-SNAPSHOT - - 4.0.0 - assessment-api - pom - assessment-api - - assessment-actors - assessment-service - qs-hierarchy-manager - - - - UTF-8 - UTF-8 - 2.12 - - - - - - - maven-assembly-plugin - 3.3.0 - - - src/assembly/bin.xml - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 11 - - - - org.scoverage - scoverage-maven-plugin - - ${scala.version} - true - true - - - - - - - \ No newline at end of file diff --git a/assessment-api/qs-hierarchy-manager/pom.xml b/assessment-api/qs-hierarchy-manager/pom.xml deleted file mode 100644 index 8431814a0..000000000 --- a/assessment-api/qs-hierarchy-manager/pom.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - - assessment-api - org.sunbird - 1.0-SNAPSHOT - - 4.0.0 - qs-hierarchy-manager - 1.0-SNAPSHOT - - - - org.sunbird - graph-engine_2.12 - 1.0-SNAPSHOT - jar - - - org.sunbird - platform-common - 1.0-SNAPSHOT - - - org.scala-lang - scala-library - ${scala.version} - - - org.scalatest - scalatest_${scala.maj.version} - 3.1.2 - test - - - org.neo4j - neo4j-bolt - 3.5.0 - test - - - org.neo4j - neo4j-graphdb-api - 3.5.0 - test - - - org.neo4j - neo4j - 3.5.0 - test - - - org.cassandraunit - cassandra-unit - 3.11.2.0 - test - - - httpcore - org.apache.httpcomponents - - - httpclient - org.apache.httpcomponents - - - - - com.mashape.unirest - unirest-java - 1.4.9 - - - - - - src/main/scala - src/test/scala - - - net.alchim31.maven - scala-maven-plugin - 4.4.0 - - ${scala.version} - false - - - - scala-compile-first - process-resources - - add-source - compile - - - - scala-test-compile - process-test-resources - - testCompile - - - - - - org.scalatest - scalatest-maven-plugin - 2.0.0 - - - test - test - - test - - - - - - org.scoverage - scoverage-maven-plugin - ${scoverage.plugin.version} - - ${scala.version} - true - true - - - - - - \ No newline at end of file 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 deleted file mode 100644 index 906d838a7..000000000 --- a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/HierarchyManager.scala +++ /dev/null @@ -1,726 +0,0 @@ -package org.sunbird.managers - -import java.util -import java.util.concurrent.CompletionException - -import com.fasterxml.jackson.databind.ObjectMapper -import org.apache.commons.lang3.StringUtils -import org.sunbird.cache.impl.RedisCache -import org.sunbird.common.dto.{Request, Response, ResponseHandler} -import org.sunbird.common.exception.{ClientException, ErrorCodes, ResourceNotFoundException, ResponseCode, ServerException} -import org.sunbird.common.{JsonUtils, Platform} -import org.sunbird.graph.dac.model.Node -import org.sunbird.graph.nodes.DataNode -import org.sunbird.graph.utils.{NodeUtil, ScalaJsonUtils} - -import scala.collection.convert.ImplicitConversions._ -import scala.collection.JavaConverters._ -import scala.collection.JavaConverters -import scala.concurrent.{ExecutionContext, Future} -import com.mashape.unirest.http.HttpResponse -import com.mashape.unirest.http.Unirest -import org.apache.commons.collections4.{CollectionUtils, MapUtils} -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.telemetry.logger.TelemetryManager -import org.sunbird.utils.HierarchyConstants - -object HierarchyManager { - - val schemaName: String = "questionset" - val schemaVersion: String = "1.0" - val imgSuffix: String = ".img" - val hierarchyPrefix: String = "qs_hierarchy_" - val statusList = List("Live", "Unlisted", "Flagged") - val ASSESSMENT_OBJECT_TYPES = List("Question", "QuestionSet") - - val keyTobeRemoved = { - if(Platform.config.hasPath("content.hierarchy.removed_props_for_leafNodes")) - Platform.config.getStringList("content.hierarchy.removed_props_for_leafNodes") - else - java.util.Arrays.asList("collections","children","usedByContent","item_sets","methods","libraries","editorState") - } - - val externalKeys: java.util.List[String] = if(Platform.config.hasPath("questionset.hierarchy.remove_external_props")) Platform.config.getStringList("questionset.hierarchy.remove_external_props") - else List("hierarchy","outcomeDeclaration").asJava - - @throws[Exception] - def addLeafNodesToHierarchy(request:Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - validateRequest(request, "add") - val rootNodeFuture = getRootNode(request) - rootNodeFuture.map(rootNode => { - val unitId = request.getRequest.getOrDefault("collectionId", "").asInstanceOf[String] - if (StringUtils.isBlank(unitId)) attachLeafToRootNode(request, rootNode, "add") else { - val rootNodeMap = NodeUtil.serialize(rootNode, java.util.Arrays.asList("childNodes", "originData"), schemaName, schemaVersion) - if(!rootNodeMap.get("childNodes").asInstanceOf[Array[String]].toList.contains(unitId)) { - Future{ResponseHandler.ERROR(ResponseCode.RESOURCE_NOT_FOUND, ResponseCode.RESOURCE_NOT_FOUND.name(), "collectionId " + unitId + " does not exist")} - }else { - val hierarchyFuture = fetchHierarchy(request, rootNode.getIdentifier) - hierarchyFuture.map(hierarchy => { - if(hierarchy.isEmpty){ - Future{ResponseHandler.ERROR(ResponseCode.SERVER_ERROR, ResponseCode.SERVER_ERROR.name(), "hierarchy is empty")} - } else { - val leafNodesFuture = fetchLeafNodes(request) - leafNodesFuture.map(leafNodes => updateHierarchyData(unitId, hierarchy, leafNodes, rootNode, request, "add").map(node => ResponseHandler.OK.put("rootId", node.getIdentifier.replaceAll(imgSuffix, "")))).flatMap(f => f) - } - }).flatMap(f => f) - } - } - }).flatMap(f => f) recoverWith {case e: CompletionException => throw e.getCause} - } - - @throws[Exception] - def removeLeafNodesFromHierarchy(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - validateRequest(request, "remove") - val rootNodeFuture = getRootNode(request) - rootNodeFuture.map(rootNode => { - val unitId = request.getRequest.getOrDefault("collectionId", "").asInstanceOf[String] - if (StringUtils.isBlank(unitId)) attachLeafToRootNode(request, rootNode, "remove") else { - val rootNodeMap = NodeUtil.serialize(rootNode, java.util.Arrays.asList("childNodes", "originData"), schemaName, schemaVersion) - if(!rootNodeMap.get("childNodes").asInstanceOf[Array[String]].toList.contains(unitId)) { - Future{ResponseHandler.ERROR(ResponseCode.RESOURCE_NOT_FOUND, ResponseCode.RESOURCE_NOT_FOUND.name(), "collectionId " + unitId + " does not exist")} - }else { - val hierarchyFuture = fetchHierarchy(request, rootNode.getIdentifier) - hierarchyFuture.map(hierarchy => { - if(hierarchy.isEmpty){ - Future{ResponseHandler.ERROR(ResponseCode.SERVER_ERROR, ResponseCode.SERVER_ERROR.name(), "hierarchy is empty")} - } else updateHierarchyData(unitId, hierarchy, null, rootNode, request, "remove").map(node => ResponseHandler.OK.put("rootId", node.getIdentifier.replaceAll(imgSuffix, ""))) - }).flatMap(f => f) - } - } - }).flatMap(f => f) recoverWith {case e: CompletionException => throw e.getCause} - } - - def attachLeafToRootNode(request: Request, rootNode: Node, operation: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - fetchHierarchy(request, rootNode.getIdentifier).map(hierarchy => { - if (hierarchy.isEmpty) { - Future(ResponseHandler.ERROR(ResponseCode.SERVER_ERROR, ResponseCode.SERVER_ERROR.name(), "hierarchy is empty")) - } else { - fetchLeafNodes(request).map(leafNodes => { - val rootNodeMap = NodeUtil.serialize(rootNode, java.util.Arrays.asList(HierarchyConstants.BRANCHING_LOGIC, HierarchyConstants.ALLOW_BRANCHING, HierarchyConstants.CHILD_NODES), schemaName, schemaVersion) - if (isBranchingEnabled(rootNodeMap, request, operation)) { - val branchingLogic = rootNodeMap.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - TelemetryManager.info(s"Branching Found For ${rootNode.getIdentifier}. Branching Rules are : ${branchingLogic}") - leafNodes.foreach(leafNode => { - val updatedBranching = operation match { - case "remove" => removeBranching(leafNode.getIdentifier, branchingLogic) - case "add" => addBranching(leafNode.getIdentifier, branchingLogic, request, rootNode.getMetadata.getOrDefault("childNodes", Array[String]()).asInstanceOf[Array[String]].toList) - } - if (MapUtils.isNotEmpty(updatedBranching)) { - rootNode.getMetadata.put(HierarchyConstants.BRANCHING_LOGIC, updatedBranching) - request.put(HierarchyConstants.BRANCHING_LOGIC, updatedBranching) - } - }) - TelemetryManager.info("updated branchingLogic for node " + rootNode.getIdentifier + " is : " + rootNode.getMetadata.get(HierarchyConstants.BRANCHING_LOGIC)) - } else if (StringUtils.equalsIgnoreCase("add", operation) && request.getRequest.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new util.HashMap[String, AnyRef]()).asInstanceOf[util.Map[String, AnyRef]].nonEmpty) - throw new ClientException("ERR_BRANCHING_LOGIC", s"Branching Is Not Enabled For ${rootNode.getIdentifier}. Please Enable Branching Or Remove branchingLogic from Request.") - updateRootNode(rootNode, request, operation).map(node => { - updateRootHierarchy(hierarchy, leafNodes, node, request, operation).map(response => { - if (!ResponseHandler.checkError(response)) { - ResponseHandler.OK - .put("rootId", node.getIdentifier.replaceAll(imgSuffix, "")) - .put("children", request.get("children")) - } else response - }) - }).flatMap(f => f) - }).flatMap(f => f) - } - }).flatMap(f => f) - } - - def updateRootHierarchy(hierarchy: java.util.Map[String, AnyRef], leafNodes: List[Node], rootNode: Node, request: Request, operation: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext) = { - val leafNodeIds = request.get("children").asInstanceOf[util.List[String]] - val req = new Request(request) - if ("add".equalsIgnoreCase(operation)) { - val updatedChildren = restructureUnit(hierarchy.get("children").asInstanceOf[java.util.List[java.util.Map[String, AnyRef]]], - convertNodeToMap(leafNodes), leafNodeIds, 1, rootNode.getIdentifier.replace(imgSuffix, "")) - val updatedHierarchy = Map("children" -> updatedChildren, "identifier" -> rootNode.getIdentifier.replace(imgSuffix, "")).asJava - req.put("hierarchy", ScalaJsonUtils.serialize(updatedHierarchy)) - } - if ("remove".equalsIgnoreCase(operation)) { - val filteredChildren = hierarchy.get("children") - .asInstanceOf[java.util.List[java.util.Map[String, AnyRef]]].asScala - .filter(child => !leafNodeIds.contains(child.get("identifier"))) - filteredChildren.sortBy(_.get("index").asInstanceOf[Integer]) - .zipWithIndex.foreach(zippedChild => zippedChild._1.put("index", (zippedChild._2.asInstanceOf[Integer] + 1).asInstanceOf[Object])) - val updatedHierarchy = Map("children" -> filteredChildren, "identifier" -> rootNode.getIdentifier.replace(imgSuffix, "")).asJava - req.put("hierarchy", ScalaJsonUtils.serialize(updatedHierarchy)) - } - req.put("identifier", rootNode.getIdentifier) - oec.graphService.saveExternalProps(req) - } - - @throws[Exception] - def getHierarchy(request : Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - val mode = request.get("mode").asInstanceOf[String] - if(StringUtils.isNotEmpty(mode) && mode.equals("edit")) - getUnPublishedHierarchy(request) - else - getPublishedHierarchy(request) - } - - @throws[Exception] - def getUnPublishedHierarchy(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - val rootNodeFuture = getRootNode(request) - rootNodeFuture.map(rootNode => { - if (StringUtils.equalsIgnoreCase("Retired", rootNode.getMetadata.getOrDefault("status", "").asInstanceOf[String])) { - Future(ResponseHandler.ERROR(ResponseCode.RESOURCE_NOT_FOUND, ResponseCode.RESOURCE_NOT_FOUND.name(), "rootId " + request.get("rootId") + " does not exist")) - } - val bookmarkId = request.get("bookmarkId").asInstanceOf[String] - var metadata: util.Map[String, AnyRef] = NodeUtil.serialize(rootNode, new util.ArrayList[String](), request.getContext.get("schemaName").asInstanceOf[String], request.getContext.get("version").asInstanceOf[String]) - val hierarchy = fetchHierarchy(request, rootNode.getIdentifier) - hierarchy.map(hierarchy => { - val children = hierarchy.getOrDefault("children", new util.ArrayList[java.util.Map[String, AnyRef]]).asInstanceOf[util.ArrayList[java.util.Map[String, AnyRef]]] - val leafNodeIds = new util.ArrayList[String]() - fetchAllLeafNodes(children, leafNodeIds) - getLatestLeafNodes(leafNodeIds).map(leafNodesMap => { - updateLatestLeafNodes(children, leafNodesMap) - metadata.put("children", children) - metadata.put("identifier", request.get("rootId")) - if(StringUtils.isNotEmpty(bookmarkId)) - metadata = filterBookmarkHierarchy(metadata.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]], bookmarkId) - if (MapUtils.isEmpty(metadata)) { - ResponseHandler.ERROR(ResponseCode.RESOURCE_NOT_FOUND, ResponseCode.RESOURCE_NOT_FOUND.name(), "bookmarkId " + bookmarkId + " does not exist") - } else { - ResponseHandler.OK.put("questionSet", metadata) - } - }) - }).flatMap(f => f) - }).flatMap(f => f) recoverWith { case e: ResourceNotFoundException => { - val searchResponse = searchRootIdInElasticSearch(request.get("rootId").asInstanceOf[String]) - searchResponse.map(rootHierarchy => { - if(!rootHierarchy.isEmpty && StringUtils.isNotEmpty(rootHierarchy.asInstanceOf[util.HashMap[String, AnyRef]].get("identifier").asInstanceOf[String])){ - val unPublishedBookmarkHierarchy = getUnpublishedBookmarkHierarchy(request, rootHierarchy.asInstanceOf[util.HashMap[String, AnyRef]].get("identifier").asInstanceOf[String]) - unPublishedBookmarkHierarchy.map(hierarchy => { - if (!hierarchy.isEmpty) { - val children = hierarchy.getOrDefault("children", new util.ArrayList[java.util.Map[String, AnyRef]]).asInstanceOf[util.ArrayList[java.util.Map[String, AnyRef]]] - val leafNodeIds = new util.ArrayList[String]() - fetchAllLeafNodes(children, leafNodeIds) - getLatestLeafNodes(leafNodeIds).map(leafNodesMap => { - updateLatestLeafNodes(children, leafNodesMap) - hierarchy.put("children", children) - }) - ResponseHandler.OK.put("questionSet", hierarchy) - } else - ResponseHandler.ERROR(ResponseCode.RESOURCE_NOT_FOUND, ResponseCode.RESOURCE_NOT_FOUND.name(), "rootId " + request.get("rootId") + " does not exist") - }) - } else { - Future(ResponseHandler.ERROR(ResponseCode.RESOURCE_NOT_FOUND, ResponseCode.RESOURCE_NOT_FOUND.name(), "rootId " + request.get("rootId") + " does not exist")) - } - }).flatMap(f => f) - } - } - } - - @throws[Exception] - def getPublishedHierarchy(request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Response] = { - 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) - hierarchyFuture.map(result => { - if (!result.isEmpty) { - val bookmarkId = request.get("bookmarkId").asInstanceOf[String] - val rootHierarchy = result.get("questionSet").asInstanceOf[util.Map[String, AnyRef]] - if (StringUtils.isEmpty(bookmarkId)) { - ResponseHandler.OK.put("questionSet", rootHierarchy) - } else { - val children = rootHierarchy.getOrElse("children", new util.ArrayList[util.Map[String, AnyRef]]()).asInstanceOf[util.List[util.Map[String, AnyRef]]] - val bookmarkHierarchy = filterBookmarkHierarchy(children, bookmarkId) - if (MapUtils.isEmpty(bookmarkHierarchy)) { - ResponseHandler.ERROR(ResponseCode.RESOURCE_NOT_FOUND, ResponseCode.RESOURCE_NOT_FOUND.name(), "bookmarkId " + bookmarkId + " does not exist") - } else { - ResponseHandler.OK.put("questionSet", bookmarkHierarchy) - } - } - } else - ResponseHandler.ERROR(ResponseCode.RESOURCE_NOT_FOUND, ResponseCode.RESOURCE_NOT_FOUND.name(), "rootId " + request.get("rootId") + " does not exist") - }) - } - - def validateRequest(request: Request, operation: String)(implicit ec: ExecutionContext) = { - val rootId = request.get("rootId").asInstanceOf[String] - val children = request.get("children").asInstanceOf[java.util.List[String]] - val branchingLogic = request.getRequest.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - if (StringUtils.isBlank(rootId)) { - throw new ClientException(ErrorCodes.ERR_BAD_REQUEST.name(), "rootId is mandatory") - } - if (null == children || children.isEmpty) { - throw new ClientException(ErrorCodes.ERR_BAD_REQUEST.name(), "children are mandatory") - } - if(StringUtils.equalsAnyIgnoreCase(operation, "add") && MapUtils.isNotEmpty(branchingLogic)) { - if(!children.containsAll(branchingLogic.keySet())) - throw new ClientException(ErrorCodes.ERR_BAD_REQUEST.name(), "Branch Rule Found For The Node Which Is Not A Children Having Identifier : "+branchingLogic.keySet().toList.diff(children.toList).asJava) - } - } - - private def getRootNode(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Node] = { - val req = new Request(request) - req.put("identifier", request.get("rootId").asInstanceOf[String]) - req.put("mode", request.get("mode").asInstanceOf[String]) - req.put("fields",request.get("fields").asInstanceOf[java.util.List[String]]) - DataNode.read(req) - } - - def fetchLeafNodes(request: Request)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[List[Node]] = { - val leafNodes = request.get("children").asInstanceOf[java.util.List[String]] - val req = new Request(request) - req.put("identifiers", leafNodes) - DataNode.list(req).map(nodes => { - if(nodes.size() != leafNodes.size()) { - val filteredList = leafNodes.toList.filter(id => !nodes.contains(id)) - throw new ClientException(ErrorCodes.ERR_BAD_REQUEST.name(), "Children which are not available are: " + filteredList) - } else { - val invalidNodes = nodes.filterNot(node => ASSESSMENT_OBJECT_TYPES.contains(node.getObjectType)) - if (CollectionUtils.isNotEmpty(invalidNodes)) - throw new ClientException(ErrorCodes.ERR_BAD_REQUEST.name(), s"Children must be of types $ASSESSMENT_OBJECT_TYPES for ids: ${invalidNodes.map(_.getIdentifier)}") - else nodes.toList - } - }) - } - - def convertNodeToMap(leafNodes: List[Node])(implicit oec: OntologyEngineContext, ec: ExecutionContext): java.util.List[java.util.Map[String, AnyRef]] = { - leafNodes.map(node => { - val updatedNode: Node = if (node.getObjectType.equalsIgnoreCase("QuestionSet") - && node.getMetadata.getOrDefault("visibility", "Parent").asInstanceOf[String].equalsIgnoreCase("Parent")) { - val extData = if (null != node.getExternalData) node.getExternalData.filter(entry => !externalKeys.contains(entry._1)).asJava else Map().asJava - node.getMetadata.putAll(extData) - node - } else node - val nodeMap:java.util.Map[String,AnyRef] = NodeUtil.serialize(updatedNode, null, updatedNode.getObjectType.toLowerCase().replace("image", ""), schemaVersion) - nodeMap.keySet().removeAll(keyTobeRemoved) - nodeMap - }) - } - - def addChildrenToUnit(children: java.util.List[java.util.Map[String,AnyRef]], unitId:String, leafNodes: java.util.List[java.util.Map[String, AnyRef]], leafNodeIds: java.util.List[String], request: Request): Unit = { - val childNodes = children.filter(child => ("Parent".equalsIgnoreCase(child.get("visibility").asInstanceOf[String]) && unitId.equalsIgnoreCase(child.get("identifier").asInstanceOf[String]))).toList - if(null != childNodes && !childNodes.isEmpty){ - val child = childNodes.get(0) - if (isBranchingEnabled(child, request, "add")) { - TelemetryManager.info(s"Branching Found for ${child.get("identifier")}. Branching Rules Are : ${child.get(HierarchyConstants.BRANCHING_LOGIC)}") - val childrenIds: List[String] = child.getOrDefault(HierarchyConstants.CHILDREN, new util.ArrayList[java.util.Map[String, AnyRef]]()).asInstanceOf[util.ArrayList[java.util.Map[String, AnyRef]]].toList.map(child => child.get("identifier").asInstanceOf[String]) - leafNodeIds.foreach(nodeId => { - val updatedBranching = addBranching(nodeId, child.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new util.HashMap()).asInstanceOf[java.util.Map[String, AnyRef]], request, childrenIds) - if (MapUtils.isNotEmpty(updatedBranching)) { - child.put(HierarchyConstants.BRANCHING_LOGIC, updatedBranching) - } - }) - TelemetryManager.info(s"Branching Updated for ${child.get("identifier")}. Updated Branching Rules Are : ${child.get(HierarchyConstants.BRANCHING_LOGIC)}") - } else if(request.getRequest.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new util.HashMap[String, AnyRef]()).asInstanceOf[util.Map[String, AnyRef]].nonEmpty) - throw new ClientException("ERR_BRANCHING_LOGIC", s"Branching Is Not Enabled For ${unitId}. Please Enable Branching Or Remove branchingLogic from Request.") - val childList = child.get("children").asInstanceOf[java.util.List[java.util.Map[String,AnyRef]]] - val restructuredChildren: java.util.List[java.util.Map[String,AnyRef]] = restructureUnit(childList, leafNodes, leafNodeIds, (child.get("depth").asInstanceOf[Integer] + 1), unitId) - child.put("children", restructuredChildren) - } else { - for(child <- children) { - if(null !=child.get("children") && !child.get("children").asInstanceOf[java.util.List[java.util.Map[String,AnyRef]]].isEmpty) - addChildrenToUnit(child.get("children").asInstanceOf[java.util.List[java.util.Map[String,AnyRef]]], unitId, leafNodes, leafNodeIds, request) - } - } - } - - def removeChildrenFromUnit(children: java.util.List[java.util.Map[String, AnyRef]], unitId: String, leafNodeIds: java.util.List[String]):Unit = { - val childNodes = children.filter(child => ("Parent".equalsIgnoreCase(child.get("visibility").asInstanceOf[String]) && unitId.equalsIgnoreCase(child.get("identifier").asInstanceOf[String]))).toList - if(null != childNodes && !childNodes.isEmpty){ - val child = childNodes.get(0) - if (isBranchingEnabled(child, new Request(), "remove")) { - TelemetryManager.info(s"Branching Found for ${child.get("identifier")}. Branching Rules Are : ${child.get(HierarchyConstants.BRANCHING_LOGIC)}") - leafNodeIds.foreach(nodeId => { - val updatedBranching = removeBranching(nodeId, child.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new util.HashMap()).asInstanceOf[java.util.Map[String, AnyRef]]) - if (MapUtils.isNotEmpty(updatedBranching)) { - child.put(HierarchyConstants.BRANCHING_LOGIC, updatedBranching) - } - }) - TelemetryManager.info(s"Branching Updated for ${child.get("identifier")}. Updated Branching Rules Are : ${child.get(HierarchyConstants.BRANCHING_LOGIC)}") - } - if(null != child.get("children") && !child.get("children").asInstanceOf[java.util.List[java.util.Map[String,AnyRef]]].isEmpty) { - var filteredLeafNodes = child.get("children").asInstanceOf[java.util.List[java.util.Map[String,AnyRef]]].filter(existingLeafNode => { - !leafNodeIds.contains(existingLeafNode.get("identifier").asInstanceOf[String]) - }) - var index: Integer = 1 - filteredLeafNodes.toList.sortBy(x => x.get("index").asInstanceOf[Integer]).foreach(node => { - node.put("index", index) - index += 1 - }) - child.put("children", filteredLeafNodes) - } - } else { - for(child <- children) { - if(null !=child.get("children") && !child.get("children").asInstanceOf[java.util.List[java.util.Map[String,AnyRef]]].isEmpty) - removeChildrenFromUnit(child.get("children").asInstanceOf[java.util.List[java.util.Map[String,AnyRef]]], unitId, leafNodeIds) - } - } - } - - def updateRootNode(rootNode: Node, request: Request, operation: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext) = { - val req = new Request(request) - val leafNodes = request.get("children").asInstanceOf[java.util.List[String]] - val childNodes = new java.util.ArrayList[String]() - childNodes.addAll(rootNode.getMetadata.getOrDefault("childNodes", Array[String]()).asInstanceOf[Array[String]].toList) - if(operation.equalsIgnoreCase("add")) - childNodes.addAll(leafNodes) - if(operation.equalsIgnoreCase("remove")) - childNodes.removeAll(leafNodes) - if(request.getRequest.containsKey(HierarchyConstants.BRANCHING_LOGIC)) - req.put(HierarchyConstants.BRANCHING_LOGIC, request.get(HierarchyConstants.BRANCHING_LOGIC).asInstanceOf[java.util.Map[String, AnyRef]]) - req.put("childNodes", childNodes.distinct.toArray) - req.getContext.put("identifier", rootNode.getIdentifier.replaceAll(imgSuffix, "")) - req.getContext.put("skipValidation", java.lang.Boolean.TRUE) - DataNode.update(req) - } - - def updateHierarchy(unitId: String, hierarchy: java.util.Map[String, AnyRef], leafNodes: List[Node], rootNode: Node, request: Request, operation: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext) = { - val children = hierarchy.get("children").asInstanceOf[java.util.List[java.util.Map[String, AnyRef]]] - val leafNodeIds = request.get("children").asInstanceOf[java.util.List[String]] - if("add".equalsIgnoreCase(operation)){ - val leafNodesMap:java.util.List[java.util.Map[String, AnyRef]] = convertNodeToMap(leafNodes) - addChildrenToUnit(children, unitId, leafNodesMap, leafNodeIds, request) - } - if("remove".equalsIgnoreCase(operation)) { - removeChildrenFromUnit(children,unitId, leafNodeIds) - } - val rootId = rootNode.getIdentifier.replaceAll(imgSuffix, "") - val updatedHierarchy = new java.util.HashMap[String, AnyRef]() - updatedHierarchy.put("identifier", rootId) - updatedHierarchy.put("children", children) - val req = new Request(request) - req.put("hierarchy", ScalaJsonUtils.serialize(updatedHierarchy)) - req.put("identifier", rootNode.getIdentifier) - oec.graphService.saveExternalProps(req) - } - - def updateHierarchyData(unitId: String, hierarchy: java.util.Map[String, AnyRef], leafNodes: List[Node], rootNode: Node, request: Request, operation: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Node] = { - val children = hierarchy.get("children").asInstanceOf[java.util.List[java.util.Map[String, AnyRef]]] - val leafNodeIds = request.get("children").asInstanceOf[java.util.List[String]] - val childNodes = new java.util.ArrayList[String]() - childNodes.addAll(rootNode.getMetadata.getOrDefault("childNodes", Array[String]()).asInstanceOf[Array[String]].toList) - if("add".equalsIgnoreCase(operation)){ - val leafNodesMap:java.util.List[java.util.Map[String, AnyRef]] = convertNodeToMap(leafNodes) - addChildrenToUnit(children, unitId, leafNodesMap, leafNodeIds, request) - childNodes.addAll(leafNodeIds) - } - if("remove".equalsIgnoreCase(operation)) { - removeChildrenFromUnit(children, unitId, leafNodeIds) - childNodes.removeAll(leafNodeIds) - } - val rootId = rootNode.getIdentifier.replaceAll(imgSuffix, "") - val updatedHierarchy = new java.util.HashMap[String, AnyRef]() - updatedHierarchy.put(HierarchyConstants.IDENTIFIER, rootId) - updatedHierarchy.put(HierarchyConstants.CHILDREN, children) - val req = new Request() - req.setContext(request.getContext) - req.getContext.put(HierarchyConstants.IDENTIFIER, rootNode.getIdentifier) - req.put(HierarchyConstants.CHILD_NODES, childNodes.distinct.toArray) - req.put(HierarchyConstants.HIERARCHY, ScalaJsonUtils.serialize(updatedHierarchy)) - DataNode.update(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]] = { - var maxIndex:Integer = 0 - var leafNodeMap: java.util.Map[String, java.util.Map[String, AnyRef]] = new util.HashMap[String, java.util.Map[String, AnyRef]]() - for(leafNode <- leafNodes){ - leafNodeMap.put(leafNode.get("identifier").asInstanceOf[String], JavaConverters.mapAsJavaMapConverter(leafNode).asJava) - } - var filteredLeafNodes: java.util.List[java.util.Map[String, AnyRef]] = new util.ArrayList[java.util.Map[String, AnyRef]]() - if(null != childList && !childList.isEmpty) { - val childMap:Map[String, java.util.Map[String, AnyRef]] = childList.toList.map(f => f.get("identifier").asInstanceOf[String] -> f).toMap - val existingLeafNodes = childMap.filter(p => leafNodeIds.contains(p._1)) - existingLeafNodes.map(en => { - leafNodeMap.get(en._1).put("index", en._2.get("index").asInstanceOf[Integer]) - }) - filteredLeafNodes = bufferAsJavaList(childList.filter(existingLeafNode => { - !leafNodeIds.contains(existingLeafNode.get("identifier").asInstanceOf[String]) - })) - maxIndex = childMap.values.toList.map(child => child.get("index").asInstanceOf[Integer]).toList.max.asInstanceOf[Integer] - } - leafNodeIds.foreach(id => { - var node = leafNodeMap.getOrDefault(id, new util.HashMap[String, AnyRef]()) - node.put("parent", parent) - node.put("depth", depth) - if( null == node.get("index")) { - val index:Integer = maxIndex + 1 - node.put("index", index) - maxIndex += 1 - } - filteredLeafNodes.add(node) - }) - filteredLeafNodes - } - - 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 = oec.graphService.readExternalProps(req, List("hierarchy")) - responseFuture.map(response => { - if (!ResponseHandler.checkError(response)) { - val hierarchyString = response.getResult.toMap.getOrDefault("hierarchy", "").asInstanceOf[String] - if (StringUtils.isNotEmpty(hierarchyString)) { - Future(JsonUtils.deserialize(hierarchyString, classOf[java.util.Map[String, AnyRef]]).toMap) - } else - 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(imgSuffix, "") + imgSuffix) - val responseFuture = oec.graphService.readExternalProps(req, List("hierarchy")) - responseFuture.map(response => { - if (!ResponseHandler.checkError(response)) { - val hierarchyString = response.getResult.toMap.getOrDefault("hierarchy", "").asInstanceOf[String] - if (StringUtils.isNotEmpty(hierarchyString)) { - JsonUtils.deserialize(hierarchyString, classOf[java.util.Map[String, AnyRef]]).toMap - } else - Map[String, AnyRef]() - } else if (ResponseHandler.checkError(response) && response.getResponseCode.code() == 404) - Map[String, AnyRef]() - else - throw new ServerException("ERR_WHILE_FETCHING_HIERARCHY_FROM_CASSANDRA", "Error while fetching hierarchy from cassandra") - }) - } else if (ResponseHandler.checkError(response) && response.getResponseCode.code() == 404) - Future(Map[String, AnyRef]()) - else - throw new ServerException("ERR_WHILE_FETCHING_HIERARCHY_FROM_CASSANDRA", "Error while fetching hierarchy from cassandra") - }).flatMap(f => f) recoverWith { case e: CompletionException => throw e.getCause } - } - - 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 => { - if (!hierarchy.isEmpty) { - if (StringUtils.isNotEmpty(hierarchy.getOrDefault("status", "").asInstanceOf[String]) && statusList.contains(hierarchy.getOrDefault("status", "").asInstanceOf[String])) { - 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]()) - } - } else { - val searchResponse = searchRootIdInElasticSearch(request.get("rootId").asInstanceOf[String]) - searchResponse.map(response => { - if (!response.isEmpty) { - if (StringUtils.isNotEmpty(response.getOrDefault("identifier", "").asInstanceOf[String])) { - val parentHierarchy = fetchHierarchy(request, response.get("identifier").asInstanceOf[String]) - parentHierarchy.map(hierarchy => { - if (!hierarchy.isEmpty) { - if (StringUtils.isNoneEmpty(hierarchy.getOrDefault("status", "").asInstanceOf[String]) && statusList.contains(hierarchy.getOrDefault("status", "").asInstanceOf[String]) && CollectionUtils.isNotEmpty(mapAsJavaMap(hierarchy).get("children").asInstanceOf[util.ArrayList[util.HashMap[String, AnyRef]]])) { - val bookmarkHierarchy = filterBookmarkHierarchy(mapAsJavaMap(hierarchy).get("children").asInstanceOf[util.ArrayList[util.Map[String, AnyRef]]], request.get("rootId").asInstanceOf[String]) - if (!bookmarkHierarchy.isEmpty) { - rootHierarchy.put("questionSet", hierarchy) - RedisCache.set(hierarchyPrefix + request.get("rootId"), JsonUtils.serialize(hierarchy)) - rootHierarchy - } else { - new util.HashMap[String, AnyRef]() - } - } else { - new util.HashMap[String, AnyRef]() - } - } else { - new util.HashMap[String, AnyRef]() - } - }) - } else { - Future(new util.HashMap[String, AnyRef]()) - } - } else { - Future(new util.HashMap[String, AnyRef]()) - } - }).flatMap(f => f) - } - }).flatMap(f => f) recoverWith { case e: CompletionException => throw e.getCause } - } - - def searchRootIdInElasticSearch(rootId: String)(implicit ec: ExecutionContext): Future[util.Map[String, AnyRef]] = { - val mapper: ObjectMapper = new ObjectMapper() - val searchRequest: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef]() { - put("request", new util.HashMap[String, AnyRef]() { - put("filters", new util.HashMap[String, AnyRef]() { - put("status", new util.ArrayList[String]() { - add("Live"); - add("Unlisted") - }) - put("mimeType", "application/vnd.ekstep.content-collection") - put("childNodes", new util.ArrayList[String]() { - add(rootId) - }) - put("visibility", "Default") - }) - put("fields", new util.ArrayList[String]() { - add("identifier") - }) - }) - } - 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 httpResponse: HttpResponse[String] = Unirest.post(url).header("Content-Type", "application/json").body(mapper.writeValueAsString(searchRequest)).asString - if (httpResponse.getStatus == 200) { - val response: Response = JsonUtils.deserialize(httpResponse.getBody, classOf[Response]) - if (response.get("count").asInstanceOf[Integer] > 0 && CollectionUtils.isNotEmpty(response.get("content").asInstanceOf[util.ArrayList[util.Map[String, AnyRef]]])) { - Future(response.get("content").asInstanceOf[util.ArrayList[util.Map[String, AnyRef]]].get(0)) - } else { - Future(new util.HashMap[String, AnyRef]()) - } - } else { - throw new ServerException("SERVER_ERROR", "Invalid response from search") - } - } - - def filterBookmarkHierarchy(children: util.List[util.Map[String, AnyRef]], bookmarkId: String)(implicit ec: ExecutionContext): util.Map[String, AnyRef] = { - if (CollectionUtils.isNotEmpty(children)) { - val response = children.filter(_.get("identifier") == bookmarkId).toList - if (CollectionUtils.isNotEmpty(response)) { - response.get(0) - } else { - val nextChildren = bufferAsJavaList(children.flatMap(child => { - if (!child.isEmpty && CollectionUtils.isNotEmpty(child.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]])) - child.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]] - else new util.ArrayList[util.Map[String, AnyRef]] - })) - filterBookmarkHierarchy(nextChildren, bookmarkId) - } - } else { - new util.HashMap[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 => { - if (!hierarchy.isEmpty && CollectionUtils.isNotEmpty(mapAsJavaMap(hierarchy).get("children").asInstanceOf[util.ArrayList[util.Map[String, AnyRef]]])) { - val bookmarkHierarchy = filterBookmarkHierarchy(mapAsJavaMap(hierarchy).get("children").asInstanceOf[util.ArrayList[util.Map[String, AnyRef]]], request.get("rootId").asInstanceOf[String]) - if (!bookmarkHierarchy.isEmpty) { - bookmarkHierarchy - } else { - new util.HashMap[String, AnyRef]() - } - } else { - new util.HashMap[String, AnyRef]() - } - }) - } else { - Future(new util.HashMap[String, AnyRef]()) - } - } - - def updateLatestLeafNodes(children: util.List[util.Map[String, AnyRef]], leafNodeMap: util.Map[String, AnyRef]): List[Any] = { - children.toList.map(content => { - if(StringUtils.equalsIgnoreCase("Default", content.getOrDefault("visibility", "").asInstanceOf[String])) { - val metadata: util.Map[String, AnyRef] = leafNodeMap.getOrDefault(content.get("identifier").asInstanceOf[String], new java.util.HashMap[String, AnyRef]()).asInstanceOf[util.Map[String, AnyRef]] - if(HierarchyConstants.RETIRED_STATUS.equalsIgnoreCase(metadata.getOrDefault("status", HierarchyConstants.RETIRED_STATUS).asInstanceOf[String])){ - children.remove(content) - } else { - content.putAll(metadata) - } - } else { - updateLatestLeafNodes(content.getOrDefault("children", new util.ArrayList[Map[String, AnyRef]]).asInstanceOf[util.List[util.Map[String, AnyRef]]], leafNodeMap) - } - }) - } - - def fetchAllLeafNodes(children: util.List[util.Map[String, AnyRef]], leafNodeIds: util.List[String]): List[Any] = { - children.toList.map(content => { - if(StringUtils.equalsIgnoreCase("Default", content.getOrDefault("visibility", "").asInstanceOf[String])) { - leafNodeIds.add(content.get("identifier").asInstanceOf[String]) - leafNodeIds - } else { - fetchAllLeafNodes(content.getOrDefault("children", new util.ArrayList[Map[String, AnyRef]]).asInstanceOf[util.List[util.Map[String, AnyRef]]], leafNodeIds) - } - }) - } - - def getLatestLeafNodes(leafNodeIds : util.List[String])(implicit oec: OntologyEngineContext, ec: ExecutionContext) = { - if(CollectionUtils.isNotEmpty(leafNodeIds)) { - val request = new Request() - request.setContext(new util.HashMap[String, AnyRef]() { - { - put(HierarchyConstants.GRAPH_ID, HierarchyConstants.TAXONOMY_ID) - } - }) - request.put("identifiers", leafNodeIds) - DataNode.list(request).map(nodes => { - val leafNodeMap: Map[String, AnyRef] = nodes.toList.map(node => (node.getIdentifier, NodeUtil.serialize(node, null, node.getObjectType.toLowerCase.replace("image", ""), HierarchyConstants.SCHEMA_VERSION, true).asInstanceOf[AnyRef])).toMap - val imageNodeIds: util.List[String] = JavaConverters.seqAsJavaListConverter(leafNodeIds.toList.map(id => id + HierarchyConstants.IMAGE_SUFFIX)).asJava - request.put("identifiers", imageNodeIds) - DataNode.list(request).map(imageNodes => { - val imageLeafNodeMap: Map[String, AnyRef] = imageNodes.toList.map(imageNode => { - val identifier = imageNode.getIdentifier.replaceAll(HierarchyConstants.IMAGE_SUFFIX, "") - val metadata = NodeUtil.serialize(imageNode, null, imageNode.getObjectType.toLowerCase.replace("image", ""), HierarchyConstants.SCHEMA_VERSION, true) - metadata.replace("identifier", identifier) - (identifier, metadata.asInstanceOf[AnyRef]) - }).toMap - val updatedMap = leafNodeMap ++ imageLeafNodeMap - JavaConverters.mapAsJavaMapConverter(updatedMap).asJava - }) - }).flatMap(f => f) - } else { - Future{new util.HashMap[String, AnyRef]()} - } - } - - def isBranchingEnabled(metadata: java.util.Map[String, AnyRef], request: Request, operation: String): Boolean = { - val isBranchingAvailable = operation match { - case "add" => MapUtils.isNotEmpty(request.getRequest.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new util.HashMap()).asInstanceOf[java.util.Map[String, AnyRef]]) - case "remove" => MapUtils.isNotEmpty(metadata.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]]) - case _ => false - } - StringUtils.equalsIgnoreCase("Yes", metadata.getOrDefault(HierarchyConstants.ALLOW_BRANCHING, "No").asInstanceOf[String]) && isBranchingAvailable - } - - def removeBranching(identifier: String, branchingLogic: java.util.Map[String, AnyRef]): java.util.Map[String, AnyRef] = { - if (branchingLogic.keySet().contains(identifier)) { - val obj: java.util.Map[String, AnyRef] = branchingLogic.getOrDefault(identifier, new util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - val source: java.util.List[String] = obj.getOrDefault(HierarchyConstants.SOURCE, new java.util.ArrayList[String]()).asInstanceOf[java.util.List[String]] - val target: java.util.List[String] = obj.getOrDefault(HierarchyConstants.TARGET, new java.util.ArrayList[String]()).asInstanceOf[java.util.List[String]] - val preCondition: java.util.Map[String, AnyRef] = obj.getOrDefault(HierarchyConstants.PRE_CONDITION, new util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - if ((source.nonEmpty && preCondition.nonEmpty) && target.isEmpty) { - val parentObj: java.util.Map[String, AnyRef] = branchingLogic.getOrDefault(source.get(0), new util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - val pTarget = parentObj.getOrDefault(HierarchyConstants.TARGET, new java.util.ArrayList[String]()).asInstanceOf[java.util.List[String]] - pTarget.remove(identifier) - parentObj.put(HierarchyConstants.TARGET, pTarget) - branchingLogic.put(source.get(0), parentObj) - branchingLogic.remove(identifier) - } else if (source.isEmpty && preCondition.isEmpty) { - if (target.nonEmpty) - throw new ClientException("ERR_BRANCHING_LOGIC", s"Dependent Children Found! Please Remove Children With Identifiers ${target} For Node : ${identifier}") - else branchingLogic.remove(identifier) - } - } - branchingLogic - } - - def addBranching(identifier: String, branchingLogic: java.util.Map[String, AnyRef], request: Request, childrenIds: List[String]): java.util.Map[String, AnyRef] = { - val reqBranching: util.Map[String, AnyRef] = request.getRequest.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new util.HashMap[String, AnyRef]()).asInstanceOf[util.Map[String, AnyRef]] - if (reqBranching.nonEmpty) { - val sourceIds: List[String] = reqBranching.flatMap(entry => entry._2.asInstanceOf[util.Map[String, AnyRef]].get(HierarchyConstants.SOURCE).asInstanceOf[util.ArrayList[String]]).toList - if (!childrenIds.containsAll(sourceIds)) - throw new ClientException("ERR_BRANCHING_LOGIC", s"Source With Identifiers ${sourceIds.diff(childrenIds).asJava} Not Found! Please Provide Valid Source Identifier.") - } - val updatedBranchingLogic = new util.HashMap[String, AnyRef]() - updatedBranchingLogic.putAll(branchingLogic) - reqBranching.map(entry => { - val obj = entry._2.asInstanceOf[java.util.Map[String, AnyRef]] - val source: java.util.List[String] = obj.getOrDefault(HierarchyConstants.SOURCE, new java.util.ArrayList[String]()).asInstanceOf[java.util.List[String]] - if (source.nonEmpty && source.size > 1) - throw new ClientException("ERR_BRANCHING_LOGIC", "An Object Can't Depend On More Than 1 Object") - if (branchingLogic.contains(source.get(0))) { - val parentObj = branchingLogic.getOrDefault(source.get(0), new util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - val pSource: java.util.List[String] = parentObj.getOrDefault(HierarchyConstants.SOURCE, new java.util.ArrayList[String]()).asInstanceOf[java.util.List[String]] - if (pSource.nonEmpty) - throw new ClientException("ERR_BRANCHING_LOGIC", s"${source.get(0)} Is Already Children Of ${pSource.get(0)}. So It Can't Be Parent For ${entry._1}") - val pTarget: java.util.List[String] = parentObj.getOrDefault(HierarchyConstants.TARGET, new java.util.ArrayList[String]()).asInstanceOf[java.util.List[String]] - pTarget.add(entry._1) - parentObj.put(HierarchyConstants.TARGET, pTarget) - updatedBranchingLogic.put(source.get(0), parentObj) - - } else { - val parentObj = Map("target" -> List(entry._1).asJava, "source" -> List().asJava, "preCondition" -> Map().asJava).asJava - updatedBranchingLogic.put(source.get(0), parentObj) - } - updatedBranchingLogic.put(entry._1, entry._2.asInstanceOf[java.util.Map[String, AnyRef]]) - - }) - TelemetryManager.info(s"updated BranchingLogic for ${identifier} : ${updatedBranchingLogic}") - updatedBranchingLogic - } - - -} 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 deleted file mode 100644 index 6ce0dc829..000000000 --- a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala +++ /dev/null @@ -1,561 +0,0 @@ -package org.sunbird.managers - -import java.util -import java.util.concurrent.CompletionException -import org.apache.commons.collections4.{CollectionUtils, MapUtils} -import org.apache.commons.lang3.StringUtils -import org.sunbird.common.dto.{Request, Response, ResponseHandler} -import org.sunbird.common.exception.{ClientException, ErrorCodes, ResourceNotFoundException, ServerException} -import org.sunbird.common.{DateUtils, JsonUtils, Platform} -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.graph.common.Identifier -import org.sunbird.graph.dac.model.Node -import org.sunbird.graph.external.ExternalPropsManager -import org.sunbird.graph.nodes.DataNode -import org.sunbird.graph.schema.DefinitionNode -import org.sunbird.graph.utils.{NodeUtil, ScalaJsonUtils} -import org.sunbird.telemetry.logger.TelemetryManager -import org.sunbird.utils.{HierarchyConstants, HierarchyErrorCodes} - -import scala.collection.JavaConverters._ -import scala.collection.convert.ImplicitConversions._ -import scala.collection.mutable -import scala.concurrent.{ExecutionContext, Future} - -object UpdateHierarchyManager { - val neo4jCreateTypes: java.util.List[String] = Platform.getStringList("neo4j_objecttypes_enabled", List("Question").asJava) - - @throws[Exception] - def updateHierarchy(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - val (nodesModified, hierarchy) = validateRequest(request) - val rootId: String = getRootId(nodesModified, hierarchy) - request.getContext.put(HierarchyConstants.ROOT_ID, rootId) - getValidatedRootNode(rootId, request).map(node => { - getExistingHierarchy(request, node).map(existingHierarchy => { - val existingChildren = existingHierarchy.getOrElse(HierarchyConstants.CHILDREN, new java.util.ArrayList[java.util.HashMap[String, AnyRef]]()).asInstanceOf[java.util.List[java.util.Map[String, AnyRef]]] - val nodes = List(node) - addChildNodesInNodeList(existingChildren, request, nodes).map(list => (existingHierarchy, list)) - }).flatMap(f => f) - .map(result => { - val nodes = result._2 - TelemetryManager.info("NodeList final size: " + nodes.size) - val idMap: mutable.Map[String, String] = mutable.Map() - idMap += (rootId -> rootId) - updateNodesModifiedInNodeList(nodes, nodesModified, request, idMap).map(updatedList => { - val modifiedNodeList = processBranching(updatedList, request, idMap) - getChildrenHierarchy(modifiedNodeList, rootId, hierarchy, idMap, result._1).map(children => { - TelemetryManager.log("Children for root id :" + rootId +" :: " + JsonUtils.serialize(children)) - updateHierarchyData(rootId, children, modifiedNodeList, request).map(node => { - val response = ResponseHandler.OK() - response.put(HierarchyConstants.IDENTIFIER, rootId) - idMap.remove(rootId) - response.put(HierarchyConstants.IDENTIFIERS, mapAsJavaMap(idMap)) - if (request.getContext.getOrDefault("shouldImageDelete", false.asInstanceOf[AnyRef]).asInstanceOf[Boolean]) - deleteHierarchy(request) - Future(response) - }).flatMap(f => f) - }).flatMap(f => f) - }).flatMap(f => f) - }) - }).flatMap(f => f).flatMap(f => f) recoverWith { case e: CompletionException => throw e.getCause } - } - - private def validateRequest(request: Request)(implicit ec: ExecutionContext): (java.util.HashMap[String, AnyRef], java.util.HashMap[String, AnyRef]) = { - if (!request.getRequest.contains(HierarchyConstants.NODES_MODIFIED) && !request.getRequest.contains(HierarchyConstants.HIERARCHY)) - throw new ClientException(ErrorCodes.ERR_BAD_REQUEST.name(), "Hierarchy data is empty") - val nodesModified: java.util.HashMap[String, AnyRef] = request.getRequest.get(HierarchyConstants.NODES_MODIFIED).asInstanceOf[java.util.HashMap[String, AnyRef]] - val hierarchy: java.util.HashMap[String, AnyRef] = request.getRequest.get(HierarchyConstants.HIERARCHY).asInstanceOf[java.util.HashMap[String, AnyRef]] - hierarchy.asScala.keys.foreach(key => { - if (StringUtils.equalsIgnoreCase(nodesModified.getOrDefault(key, new util.HashMap()).asInstanceOf[util.Map[String, AnyRef]] - .getOrDefault(HierarchyConstants.OBJECT_TYPE, "").asInstanceOf[String], "Question")) - throw new ClientException("ERR_QS_UPDATE_HIERARCHY", "Question cannot have children in hierarchy") - }) - (nodesModified, hierarchy) - } - - /** - * Checks if root id is empty, all black or image id - * - * @param nodesModified - * @param hierarchy - * @param ec - * @return - */ - private def getRootId(nodesModified: java.util.HashMap[String, AnyRef], hierarchy: java.util.HashMap[String, AnyRef])(implicit ec: ExecutionContext): String = { - val rootId: String = nodesModified.keySet() - .find(key => nodesModified.get(key).asInstanceOf[java.util.HashMap[String, AnyRef]].get(HierarchyConstants.ROOT).asInstanceOf[Boolean]) - .getOrElse(hierarchy.keySet().find(key => hierarchy.get(key).asInstanceOf[java.util.HashMap[String, AnyRef]].get(HierarchyConstants.ROOT).asInstanceOf[Boolean]).orNull) - if (StringUtils.isEmpty(rootId) && StringUtils.isAllBlank(rootId) || StringUtils.contains(rootId, HierarchyConstants.IMAGE_SUFFIX)) - throw new ClientException(HierarchyErrorCodes.ERR_INVALID_ROOT_ID, "Please Provide Valid Root Node Identifier") - rootId - } - - private def getValidatedRootNode(identifier: String, request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Node] = { - val req = new Request(request) - req.put(HierarchyConstants.IDENTIFIER, identifier) - req.put(HierarchyConstants.MODE, HierarchyConstants.EDIT_MODE) - DataNode.read(req).map(rootNode => { - val metadata: java.util.Map[String, AnyRef] = NodeUtil.serialize(rootNode, new java.util.ArrayList[String](), request.getContext.get("schemaName").asInstanceOf[String], request.getContext.get("version").asInstanceOf[String]) - if (!StringUtils.equals(metadata.get(HierarchyConstants.MIME_TYPE).asInstanceOf[String], HierarchyConstants.QUESTIONSET_MIME_TYPE)) { - TelemetryManager.error("UpdateHierarchyManager.getValidatedRootNode :: Invalid MimeType for Root node id: " + identifier) - throw new ClientException(HierarchyErrorCodes.ERR_INVALID_ROOT_ID, "Invalid MimeType for Root Node Identifier : " + identifier) - } - if(!CollectionUtils.containsAny(Platform.getStringList("root_node_visibility", List("Default").asJava), metadata.getOrDefault(HierarchyConstants.VISIBILITY, "").asInstanceOf[String])) { - TelemetryManager.error("UpdateHierarchyManager.getValidatedRootNode :: Invalid Visibility found for Root node id: " + identifier) - throw new ClientException(HierarchyErrorCodes.ERR_INVALID_ROOT_ID, "Invalid Visibility found for Root Node Identifier : " + identifier) - } - rootNode.setObjectType(HierarchyConstants.QUESTIONSET_OBJECT_TYPE) - rootNode.getMetadata.put(HierarchyConstants.OBJECT_TYPE, HierarchyConstants.QUESTIONSET_OBJECT_TYPE) - rootNode - }) - } - - private def getExistingHierarchy(request: Request, rootNode: Node)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[java.util.HashMap[String, AnyRef]] = { - fetchHierarchy(request, rootNode).map(hierarchyString => { - if (null != hierarchyString && !hierarchyString.asInstanceOf[String].isEmpty) { - JsonUtils.deserialize(hierarchyString.asInstanceOf[String], classOf[java.util.HashMap[String, AnyRef]]) - } else new java.util.HashMap[String, AnyRef]() - }) - } - - 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) - 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) - else { - if (rootNode.getMetadata.containsKey("pkgVersion")) - req.put(HierarchyConstants.IDENTIFIER, rootNode.getIdentifier.replace(HierarchyConstants.IMAGE_SUFFIX, "")) - else { - req.put(HierarchyConstants.IDENTIFIER, if (!rootNode.getIdentifier.endsWith(HierarchyConstants.IMAGE_SUFFIX)) rootNode.getIdentifier + HierarchyConstants.IMAGE_SUFFIX else rootNode.getIdentifier) - } - 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) } - } - } else Future(response.getResult.toMap.getOrElse(HierarchyConstants.HIERARCHY, "").asInstanceOf[String]) - }).flatMap(f => f) - } - - private def addChildNodesInNodeList(childrenMaps: java.util.List[java.util.Map[String, AnyRef]], request: Request, nodes: scala.collection.immutable.List[Node])(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[scala.collection.immutable.List[Node]] = { - if (CollectionUtils.isNotEmpty(childrenMaps)) { - val futures = childrenMaps.map(child => { - addNodeToList(child, request, nodes).map(modifiedList => { - if (!StringUtils.equalsIgnoreCase(HierarchyConstants.DEFAULT, child.get(HierarchyConstants.VISIBILITY).asInstanceOf[String])) { - addChildNodesInNodeList(child.get(HierarchyConstants.CHILDREN).asInstanceOf[java.util.List[java.util.Map[String, AnyRef]]], request, modifiedList) - } else - Future(modifiedList) - }).flatMap(f => f) - }).toList - Future.sequence(futures).map(f => f.flatten.distinct) - } else { - Future(nodes) - } - } - - private def addNodeToList(child: java.util.Map[String, AnyRef], request: Request, nodes: scala.collection.immutable.List[Node])(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[scala.collection.immutable.List[Node]] = { - if (StringUtils.isNotEmpty(child.get(HierarchyConstants.VISIBILITY).asInstanceOf[String])) - if (StringUtils.equalsIgnoreCase(HierarchyConstants.DEFAULT, child.get(HierarchyConstants.VISIBILITY).asInstanceOf[String])) { - getQuestionNode(child.getOrDefault(HierarchyConstants.IDENTIFIER, "").asInstanceOf[String], HierarchyConstants.TAXONOMY_ID).map(node => { - node.getMetadata.put(HierarchyConstants.DEPTH, child.get(HierarchyConstants.DEPTH)) - node.getMetadata.put(HierarchyConstants.PARENT_KEY, child.get(HierarchyConstants.PARENT_KEY)) - node.getMetadata.put(HierarchyConstants.INDEX, child.get(HierarchyConstants.INDEX)) - node.setObjectType(HierarchyConstants.QUESTION_OBJECT_TYPE) - node.getMetadata.put(HierarchyConstants.OBJECT_TYPE, HierarchyConstants.QUESTION_OBJECT_TYPE) - val updatedNodes = node :: nodes - updatedNodes - }) recoverWith { case e: CompletionException => throw e.getCause } - } else { - val childData: java.util.Map[String, AnyRef] = new java.util.HashMap[String, AnyRef] - childData.putAll(child) - childData.remove(HierarchyConstants.CHILDREN) - childData.put(HierarchyConstants.STATUS, "Draft") - val rootNode = getTempNode(nodes, request.getContext.get(HierarchyConstants.ROOT_ID).asInstanceOf[String]) - childData.put(HierarchyConstants.CHANNEL, rootNode.getMetadata.get(HierarchyConstants.CHANNEL)) - val node = NodeUtil.deserialize(childData, request.getContext.get(HierarchyConstants.SCHEMA_NAME).asInstanceOf[String], DefinitionNode.getRelationsMap(request)) - node.setObjectType(node.getMetadata.getOrDefault("objectType", "").asInstanceOf[String]) - val updatedNodes = node :: nodes - Future(updatedNodes) - } - else { - Future(nodes) - } - } - - - private def updateNodesModifiedInNodeList(nodeList: List[Node], nodesModified: java.util.HashMap[String, AnyRef], request: Request, idMap: mutable.Map[String, String])(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[List[Node]] = { - updateRootNode(request.getContext.get(HierarchyConstants.ROOT_ID).asInstanceOf[String], nodeList, nodesModified) - val futures = nodesModified.filter(nodeModified => !StringUtils.startsWith(request.getContext.get(HierarchyConstants.ROOT_ID).asInstanceOf[String], nodeModified._1)) - .map(nodeModified => { - val objectType = nodeModified._2.asInstanceOf[java.util.HashMap[String, AnyRef]].getOrDefault(HierarchyConstants.OBJECT_TYPE, "").asInstanceOf[String] - if(StringUtils.isBlank(objectType)) - throw new ClientException("ERR_UPDATE_QS_HIERARCHY", s"Object Type is mandatory for creation of node with id: ${nodeModified._1}") - val metadata = nodeModified._2.asInstanceOf[java.util.HashMap[String, AnyRef]].getOrDefault(HierarchyConstants.METADATA, new java.util.HashMap()).asInstanceOf[java.util.HashMap[String, AnyRef]] - if(StringUtils.equalsAnyIgnoreCase("QuestionSet", objectType) && !StringUtils.equalsIgnoreCase(metadata.getOrDefault(HierarchyConstants.VISIBILITY, "Parent").asInstanceOf[String], "Parent")) - throw new ClientException("ERR_UPDATE_QS_HIERARCHY", s"Visibility can be only of type Parent for identifier: ${nodeModified._1}") - if(StringUtils.equalsAnyIgnoreCase("Question", objectType) && !HierarchyConstants.QUESTION_VISIBILITY.contains(metadata.getOrDefault(HierarchyConstants.VISIBILITY, "Parent").asInstanceOf[String])) - throw new ClientException("ERR_UPDATE_QS_HIERARCHY", s"Visibility can be only of type ${HierarchyConstants.QUESTION_VISIBILITY.asJava} for identifier: ${nodeModified._1}") - metadata.remove(HierarchyConstants.DIALCODES) - metadata.put(HierarchyConstants.STATUS, "Draft") - metadata.put(HierarchyConstants.LAST_UPDATED_ON, DateUtils.formatCurrentDate) - metadata.put(HierarchyConstants.OBJECT_TYPE, objectType) - if (nodeModified._2.asInstanceOf[java.util.HashMap[String, AnyRef]].containsKey(HierarchyConstants.IS_NEW) - && nodeModified._2.asInstanceOf[java.util.HashMap[String, AnyRef]].get(HierarchyConstants.IS_NEW).asInstanceOf[Boolean]) { - if (!nodeModified._2.asInstanceOf[java.util.HashMap[String, AnyRef]].get(HierarchyConstants.ROOT).asInstanceOf[Boolean] && nodeModified._2.asInstanceOf[java.util.Map[String, AnyRef]].getOrDefault(HierarchyConstants.METADATA, new util.HashMap()).asInstanceOf[java.util.Map[String, AnyRef]].getOrDefault(HierarchyConstants.VISIBILITY, "").asInstanceOf[String].isEmpty) - metadata.put(HierarchyConstants.VISIBILITY, HierarchyConstants.PARENT) - if (nodeModified._2.asInstanceOf[java.util.HashMap[String, AnyRef]].contains(HierarchyConstants.SET_DEFAULT_VALUE)) - createNewNode(nodeModified._1, idMap, metadata, nodeList, request, nodeModified._2.asInstanceOf[java.util.HashMap[String, AnyRef]].get(HierarchyConstants.SET_DEFAULT_VALUE).asInstanceOf[Boolean]) - else - createNewNode(nodeModified._1, idMap, metadata, nodeList, request) - } else { - updateTempNode(request, nodeModified._1, nodeList, idMap, metadata) - } - }) - if (CollectionUtils.isNotEmpty(futures)) - Future.sequence(futures.toList).map(f => f.flatten) - else Future(nodeList) - } - - private def updateRootNode(rootId: String, nodeList: List[Node], nodesModified: java.util.HashMap[String, AnyRef])(implicit ec: ExecutionContext): Unit = { - if (nodesModified.containsKey(rootId)) { - val metadata = nodesModified.getOrDefault(rootId, new java.util.HashMap()).asInstanceOf[java.util.HashMap[String, AnyRef]].getOrDefault(HierarchyConstants.METADATA, new java.util.HashMap()).asInstanceOf[java.util.HashMap[String, AnyRef]] - updateNodeList(nodeList, rootId, metadata) - nodesModified.remove(rootId) - } - } - - 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) - metadata.put(HierarchyConstants.CODE, nodeId) - metadata.put(HierarchyConstants.VERSION_KEY, System.currentTimeMillis + "") - metadata.put(HierarchyConstants.CREATED_ON, DateUtils.formatCurrentDate) - metadata.put(HierarchyConstants.LAST_STATUS_CHANGED_ON, DateUtils.formatCurrentDate) - val rootNode = getTempNode(nodeList, request.getContext.get(HierarchyConstants.ROOT_ID).asInstanceOf[String]) - metadata.put(HierarchyConstants.CHANNEL, rootNode.getMetadata.get(HierarchyConstants.CHANNEL)) - val createRequest: Request = new Request(request) - createRequest.setRequest(metadata) - if (neo4jCreateTypes.contains(objectType)) { - createRequest.getContext.put(HierarchyConstants.SCHEMA_NAME, "question") - DataNode.create(createRequest).map(node => { - node.setGraphId(HierarchyConstants.TAXONOMY_ID) - node.setNodeType(HierarchyConstants.DATA_NODE) - node.setObjectType(objectType) - val updatedList = node :: nodeList - updatedList.distinct - }) - - } else - DefinitionNode.validate(createRequest, setDefaultValue).map(node => { - node.setGraphId(HierarchyConstants.TAXONOMY_ID) - node.setNodeType(HierarchyConstants.DATA_NODE) - node.setObjectType(objectType) - val updatedList = node :: nodeList - updatedList.distinct - }) - } - - private def updateTempNode(request:Request, nodeId: String, nodeList: List[Node], idMap: mutable.Map[String, String], metadata: java.util.HashMap[String, AnyRef])(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[List[Node]] = { - val tempNode: Node = getTempNode(nodeList, nodeId) - if(null == tempNode) - throw new ResourceNotFoundException("ERR_UPDATE_QS_HIERARCHY", s"No node found with id: $nodeId") - else { - val objectType = metadata.getOrDefault("objectType", "").asInstanceOf[String] - metadata.put(HierarchyConstants.IDENTIFIER, tempNode.getIdentifier) - val createRequest: Request = new Request(request) - createRequest.setRequest(metadata) - 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) - nodeList - }) - } else { - if (null != tempNode && StringUtils.isNotBlank(tempNode.getIdentifier)) { - metadata.put(HierarchyConstants.IDENTIFIER, tempNode.getIdentifier) - idMap += (nodeId -> tempNode.getIdentifier) - updateNodeList(nodeList, tempNode.getIdentifier, metadata) - Future(nodeList) - } else throw new ResourceNotFoundException(HierarchyErrorCodes.ERR_CONTENT_NOT_FOUND, "Content not found with identifier: " + nodeId) - } - } - } - - private def validateNodes(nodeList: java.util.List[Node], rootId: String)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[List[Node]] = { - val nodesToValidate = nodeList.filter(node => (StringUtils.equals(HierarchyConstants.PARENT, node.getMetadata.get(HierarchyConstants.VISIBILITY).asInstanceOf[String]) - && !StringUtils.equalsIgnoreCase("Question", node.getObjectType)) - || StringUtils.equalsAnyIgnoreCase(rootId, node.getIdentifier)).toList - DefinitionNode.updateJsonPropsInNodes(nodeList.toList, HierarchyConstants.TAXONOMY_ID, HierarchyConstants.QUESTIONSET_SCHEMA_NAME, HierarchyConstants.SCHEMA_VERSION) - DefinitionNode.validateContentNodes(nodesToValidate, HierarchyConstants.TAXONOMY_ID, HierarchyConstants.QUESTIONSET_SCHEMA_NAME, HierarchyConstants.SCHEMA_VERSION) - } - - def constructHierarchy(list: List[java.util.Map[String, AnyRef]]): java.util.Map[String, AnyRef] = { - val hierarchy: java.util.Map[String, AnyRef] = list.filter(root => root.get(HierarchyConstants.DEPTH).asInstanceOf[Number].intValue() == 0).head - if (MapUtils.isNotEmpty(hierarchy)) { - val maxDepth = list.map(node => node.get(HierarchyConstants.DEPTH).asInstanceOf[Number].intValue()).max - for (i <- 0 to maxDepth) { - val depth = i - val currentLevelNodes: Map[String, List[java.util.Map[String, Object]]] = list.filter(node => node.get(HierarchyConstants.DEPTH).asInstanceOf[Number].intValue() == depth).groupBy(_.get("identifier").asInstanceOf[String].replaceAll(".img", "")) - val nextLevel: List[java.util.Map[String, AnyRef]] = list.filter(node => node.get(HierarchyConstants.DEPTH).asInstanceOf[Number].intValue() == (depth + 1)) - if (CollectionUtils.isNotEmpty(nextLevel) && MapUtils.isNotEmpty(currentLevelNodes)) { - nextLevel.foreach(e => { - val parentId = e.get("parent").asInstanceOf[String] - currentLevelNodes.getOrDefault(parentId, List[java.util.Map[String, AnyRef]]()).foreach(parent => { - val children = parent.getOrDefault(HierarchyConstants.CHILDREN, new java.util.ArrayList[java.util.Map[String, AnyRef]]()).asInstanceOf[java.util.List[java.util.Map[String, AnyRef]]] - children.add(e) - parent.put(HierarchyConstants.CHILDREN, sortByIndex(children)) - }) - }) - } - } - } - hierarchy - } - - @throws[Exception] - private def getChildrenHierarchy(nodeList: List[Node], rootId: String, hierarchyData: java.util.HashMap[String, AnyRef], idMap: mutable.Map[String, String], existingHierarchy: java.util.Map[String, AnyRef])(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[java.util.List[java.util.Map[String, AnyRef]]] = { - val childrenIdentifiersMap: Map[String, Map[String, Int]] = getChildrenIdentifiersMap(hierarchyData, idMap, existingHierarchy) - getPreparedHierarchyData(nodeList, rootId, childrenIdentifiersMap).map(nodeMaps => { - TelemetryManager.info("prepared hierarchy list without filtering: " + nodeMaps.size()) - val filteredNodeMaps = nodeMaps.filter(nodeMap => null != nodeMap.get(HierarchyConstants.DEPTH)).toList - TelemetryManager.info("prepared hierarchy list with filtering: " + filteredNodeMaps.size()) - val hierarchyMap = constructHierarchy(filteredNodeMaps) - if (MapUtils.isNotEmpty(hierarchyMap)) { - hierarchyMap.getOrDefault(HierarchyConstants.CHILDREN, new java.util.ArrayList[java.util.Map[String, AnyRef]]()).asInstanceOf[java.util.List[java.util.Map[String, AnyRef]]] - .filter(child => MapUtils.isNotEmpty(child)) - } - else - new java.util.ArrayList[java.util.Map[String, AnyRef]]() - - }) - } - - private def getChildrenIdentifiersMap(hierarchyData: java.util.Map[String, AnyRef], idMap: mutable.Map[String, String], existingHierarchy: java.util.Map[String, AnyRef]): Map[String, Map[String, Int]] = { - if (MapUtils.isNotEmpty(hierarchyData)) { - hierarchyData.map(entry => idMap.getOrDefault(entry._1, entry._1) -> entry._2.asInstanceOf[java.util.HashMap[String, AnyRef]] - .get(HierarchyConstants.CHILDREN).asInstanceOf[java.util.ArrayList[String]] - .map(id => idMap.getOrDefault(id, id)).zipWithIndex.toMap).toMap - } else { - val tempChildMap: java.util.Map[String, Map[String, Int]] = new java.util.HashMap[String, Map[String, Int]]() - val tempResourceMap: java.util.Map[String, Map[String, Int]] = new java.util.HashMap[String, Map[String, Int]]() - getChildrenIdMapFromExistingHierarchy(existingHierarchy, tempChildMap, tempResourceMap) - tempChildMap.putAll(tempResourceMap) - tempChildMap.toMap - } - } - - private def getChildrenIdMapFromExistingHierarchy(existingHierarchy: java.util.Map[String, AnyRef], tempChildMap: java.util.Map[String, Map[String, Int]], tempResourceMap: java.util.Map[String, Map[String, Int]]): Unit = { - if (existingHierarchy.containsKey(HierarchyConstants.CHILDREN) && CollectionUtils.isNotEmpty(existingHierarchy.get(HierarchyConstants.CHILDREN).asInstanceOf[java.util.ArrayList[java.util.HashMap[String, AnyRef]]])) { - tempChildMap.put(existingHierarchy.get(HierarchyConstants.IDENTIFIER).asInstanceOf[String], existingHierarchy.get(HierarchyConstants.CHILDREN).asInstanceOf[java.util.ArrayList[java.util.HashMap[String, AnyRef]]] - .map(child => child.get(HierarchyConstants.IDENTIFIER).asInstanceOf[String] -> child.get(HierarchyConstants.INDEX).asInstanceOf[Int]).toMap) - existingHierarchy.get(HierarchyConstants.CHILDREN).asInstanceOf[java.util.ArrayList[java.util.HashMap[String, AnyRef]]] - .foreach(child => getChildrenIdMapFromExistingHierarchy(child, tempChildMap, tempResourceMap)) - } else - tempResourceMap.put(existingHierarchy.get(HierarchyConstants.IDENTIFIER).asInstanceOf[String], Map[String, Int]()) - } - - @throws[Exception] - private def getPreparedHierarchyData(nodeList: List[Node], rootId: String, childrenIdentifiersMap: Map[String, Map[String, Int]])(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[java.util.List[java.util.Map[String, AnyRef]]] = { - if (MapUtils.isNotEmpty(childrenIdentifiersMap)) { - val updatedNodeList = getTempNode(nodeList, rootId) :: List() - updateHierarchyRelatedData(childrenIdentifiersMap.getOrElse(rootId, Map[String, Int]()), 1, - rootId, nodeList, childrenIdentifiersMap, updatedNodeList).map(finalEnrichedNodeList => { - TelemetryManager.info("Final enriched list size: " + finalEnrichedNodeList.size) - val childNodeIds = finalEnrichedNodeList.map(node => node.getIdentifier.replaceAll(".img", "")).filterNot(id => StringUtils.containsIgnoreCase(rootId, id)).distinct - TelemetryManager.info("Final enriched ids (childNodes): " + childNodeIds + " :: size: " + childNodeIds.size) - updateNodeList(nodeList, rootId, new java.util.HashMap[String, AnyRef]() { - put(HierarchyConstants.DEPTH, 0.asInstanceOf[AnyRef]) - put(HierarchyConstants.CHILD_NODES, new java.util.ArrayList[String](childNodeIds)) - }) - validateNodes(finalEnrichedNodeList, rootId).map(result => HierarchyManager.convertNodeToMap(finalEnrichedNodeList)) - }).flatMap(f => f) - } else { - updateNodeList(nodeList, rootId, new java.util.HashMap[String, AnyRef]() { - { - put(HierarchyConstants.DEPTH, 0.asInstanceOf[AnyRef]) - } - }) - validateNodes(nodeList, rootId).map(result => HierarchyManager.convertNodeToMap(nodeList)) - } - } - - @throws[Exception] - private def updateHierarchyRelatedData(childrenIds: Map[String, Int], depth: Int, parent: String, nodeList: List[Node], hierarchyStructure: Map[String, Map[String, Int]], enrichedNodeList: scala.collection.immutable.List[Node])(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[List[Node]] = { - val futures = childrenIds.map(child => { - val id = child._1 - val index = child._2 + 1 - val tempNode = getTempNode(nodeList, id) - if (null != tempNode && StringUtils.equalsIgnoreCase(HierarchyConstants.PARENT, tempNode.getMetadata.get(HierarchyConstants.VISIBILITY).asInstanceOf[String])) { - populateHierarchyRelatedData(tempNode, depth, index, parent) - val nxtEnrichedNodeList = tempNode :: enrichedNodeList - if (MapUtils.isNotEmpty(hierarchyStructure.getOrDefault(child._1, Map[String, Int]()))) - updateHierarchyRelatedData(hierarchyStructure.getOrDefault(child._1, Map[String, Int]()), - tempNode.getMetadata.get(HierarchyConstants.DEPTH).asInstanceOf[Int] + 1, id, nodeList, hierarchyStructure, nxtEnrichedNodeList) - else - Future(nxtEnrichedNodeList) - } else { - getQuestionNode(id, HierarchyConstants.TAXONOMY_ID).map(node => { - populateHierarchyRelatedData(node, depth, index, parent) - //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]()))) { - updateHierarchyRelatedData(hierarchyStructure.getOrDefault(id, Map[String, Int]()), node.getMetadata.get(HierarchyConstants.DEPTH).asInstanceOf[Int] + 1, id, nodeList, hierarchyStructure, nxtEnrichedNodeList) - } else - Future(nxtEnrichedNodeList) - }).flatMap(f => f) recoverWith { case e: CompletionException => throw e.getCause } - } - }) - if (CollectionUtils.isNotEmpty(futures)) { - val listOfFutures = Future.sequence(futures.toList) - listOfFutures.map(f => f.flatten.distinct) - } else - Future(enrichedNodeList) - } - - private def populateHierarchyRelatedData(tempNode: Node, depth: Int, index: Int, parent: String) = { - tempNode.getMetadata.put(HierarchyConstants.DEPTH, depth.asInstanceOf[AnyRef]) - tempNode.getMetadata.put(HierarchyConstants.PARENT_KEY, parent.replaceAll(".img", "")) - tempNode.getMetadata.put(HierarchyConstants.INDEX, index.asInstanceOf[AnyRef]) - } - - /** - * This method is to check if all the children of the parent entity are present in the populated map - * - * @param children - * @param populatedChildMap - * @return - */ - def isFullyPopulated(children: List[String], populatedChildMap: mutable.Map[_, _]): Boolean = { - children.forall(child => populatedChildMap.containsKey(child)) - } - - def updateHierarchyData(rootId: String, children: java.util.List[java.util.Map[String, AnyRef]], nodeList: List[Node], request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Node] = { - val node = getTempNode(nodeList, rootId) - val updatedHierarchy = new java.util.HashMap[String, AnyRef]() - updatedHierarchy.put(HierarchyConstants.IDENTIFIER, rootId) - updatedHierarchy.put(HierarchyConstants.CHILDREN, children) - val req = new Request(request) - req.getContext.put(HierarchyConstants.IDENTIFIER, rootId) - val metadata = cleanUpRootData(node) - req.getRequest.putAll(metadata) - req.put(HierarchyConstants.HIERARCHY, ScalaJsonUtils.serialize(updatedHierarchy)) - req.put(HierarchyConstants.IDENTIFIER, rootId) - req.put(HierarchyConstants.CHILDREN, new java.util.ArrayList()) - DataNode.update(req) - } - - private def cleanUpRootData(node: Node)(implicit oec: OntologyEngineContext, ec: ExecutionContext): java.util.Map[String, AnyRef] = { - DefinitionNode.getRestrictedProperties(HierarchyConstants.TAXONOMY_ID, HierarchyConstants.SCHEMA_VERSION, HierarchyConstants.OPERATION_UPDATE_HIERARCHY, HierarchyConstants.QUESTIONSET_SCHEMA_NAME) - .foreach(key => node.getMetadata.remove(key)) - node.getMetadata.remove(HierarchyConstants.STATUS) - node.getMetadata.remove(HierarchyConstants.LAST_UPDATED_ON) - node.getMetadata.remove(HierarchyConstants.LAST_STATUS_CHANGED_ON) - node.getMetadata - } - - /** - * Get the Node with ID provided from List else return Null. - * - * @param nodeList - * @param id - * @return - */ - private def getTempNode(nodeList: List[Node], id: String) = { - nodeList.find(node => StringUtils.startsWith(node.getIdentifier, id)).orNull - } - - private def updateNodeList(nodeList: List[Node], id: String, metadata: java.util.Map[String, AnyRef]): Unit = { - nodeList.foreach(node => { - if(node.getIdentifier.startsWith(id)){ - node.getMetadata.putAll(metadata) - } - }) - } - - def getQuestionNode(identifier: String, graphId: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Node] = { - val request: Request = new Request() - request.setContext(new java.util.HashMap[String, AnyRef]() { - { - put(HierarchyConstants.GRAPH_ID, graphId) - put(HierarchyConstants.VERSION, HierarchyConstants.SCHEMA_VERSION) - put(HierarchyConstants.OBJECT_TYPE, HierarchyConstants.QUESTION_OBJECT_TYPE) - put(HierarchyConstants.SCHEMA_NAME, HierarchyConstants.QUESTION_SCHEMA_NAME) - } - }) - request.setObjectType(HierarchyConstants.QUESTION_OBJECT_TYPE) - request.put(HierarchyConstants.IDENTIFIER, identifier) - request.put(HierarchyConstants.MODE, HierarchyConstants.READ_MODE) - request.put(HierarchyConstants.FIELDS, new java.util.ArrayList[String]()) - DataNode.read(request) - } - - - def sortByIndex(childrenMaps: java.util.List[java.util.Map[String, AnyRef]]): java.util.List[java.util.Map[String, AnyRef]] = { - bufferAsJavaList(childrenMaps.sortBy(_.get("index").asInstanceOf[Int])) - } - - - def deleteHierarchy(request: Request)(implicit ec: ExecutionContext): 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) - } - - private def processBranching(nodeList: List[Node], request: Request, idMap: mutable.Map[String, String])(implicit ec: ExecutionContext, oec: OntologyEngineContext): List[Node] = { - val hierarchy: java.util.HashMap[String, AnyRef] = request.getRequest.get(HierarchyConstants.HIERARCHY).asInstanceOf[java.util.HashMap[String, AnyRef]] - nodeList.distinct.map(node => { - if (StringUtils.equalsIgnoreCase("Yes", node.getMetadata.getOrDefault(HierarchyConstants.ALLOW_BRANCHING, "No").asInstanceOf[String]) && - MapUtils.isNotEmpty(node.getMetadata.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]])) { - validateAndUpdateBranching(node, hierarchy, idMap) - } else if (StringUtils.equalsIgnoreCase("No", node.getMetadata.getOrDefault(HierarchyConstants.ALLOW_BRANCHING, "No").asInstanceOf[String]) && - MapUtils.isNotEmpty(node.getMetadata.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]])) { - throw new ClientException("ERR_BRANCHING_LOGIC", s"Branching Is Not Enabled For: ${node.getIdentifier}. Please Remove branchingLogic from ${node.getIdentifier}") - } else node - }) - } - - private def validateAndUpdateBranching(node: Node, hierarchy: java.util.Map[String, AnyRef], idMap: mutable.Map[String, String]): Node = { - TelemetryManager.info(s"validating branching logic for: ${node.getIdentifier}") - val branchingLogic = node.getMetadata.getOrDefault(HierarchyConstants.BRANCHING_LOGIC, new util.HashMap()).asInstanceOf[java.util.HashMap[String, AnyRef]].toMap - TelemetryManager.info(s"branchingLogic for node ${node.getIdentifier} : ${branchingLogic}") - val updatedBranchingLogic = branchingLogic.map(entry => { - val obj: java.util.HashMap[String, AnyRef] = entry._2.asInstanceOf[java.util.HashMap[String, AnyRef]] - val target = obj.getOrElse(HierarchyConstants.TARGET, new util.ArrayList[String]()).asInstanceOf[java.util.List[String]].toList - val source = obj.getOrElse(HierarchyConstants.SOURCE, new util.ArrayList[String]()).asInstanceOf[java.util.List[String]].toList - val preCondition = obj.getOrElse(HierarchyConstants.PRE_CONDITION, new util.HashMap()).asInstanceOf[java.util.Map[String, AnyRef]].toMap - val children = hierarchy.getOrDefault(node.getIdentifier, new util.HashMap()).asInstanceOf[java.util.HashMap[String, AnyRef]].getOrDefault(HierarchyConstants.CHILDREN, new util.ArrayList[String]()).asInstanceOf[java.util.List[String]].toList - // branching logic should be present for all dependent question - if (!branchingLogic.keySet.containsAll(target)) - throw new ClientException("ERR_BRANCHING_LOGIC", s"Please Provide Branching Rules for : ${branchingLogic.keySet.toList.diff(target).asJava}") - // all dependent object should belong to same parent object. - if (!children.containsAll(target ++ List(entry._1))) - throw new ClientException("ERR_BRANCHING_LOGIC", s"Please Provide Dependent Object Within Same Parent having identifier : ${node.getIdentifier}") - // A dependent object should not depend on more than 1 object - if (source.nonEmpty && source.size > 1) - throw new ClientException("ERR_BRANCHING_LOGIC", "An Object Can't Depend On More Than 1 Object") - // A dependent object should not have further dependency - if ((source.nonEmpty && preCondition.nonEmpty) && target.nonEmpty) - throw new ClientException("ERR_BRANCHING_LOGIC", "A Dependent Object Can't Have Further Dependent Object") - - TelemetryManager.info(s"updating branching Logic for ${entry._1}") - obj.put(HierarchyConstants.TARGET, target.map(id => idMap.getOrElse(id, id)).asJava) - obj.put(HierarchyConstants.SOURCE, source.map(id => idMap.getOrElse(id, id)).asJava) - (idMap.getOrElse(entry._1, entry._1), obj) - }) - TelemetryManager.info(s"branchingLogic after update for ${node.getIdentifier}: " + updatedBranchingLogic.asJava) - node.getMetadata.put(HierarchyConstants.BRANCHING_LOGIC, updatedBranchingLogic.asJava) - node - } - -} diff --git a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/HierarchyConstants.scala b/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/HierarchyConstants.scala deleted file mode 100644 index 25408886c..000000000 --- a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/HierarchyConstants.scala +++ /dev/null @@ -1,60 +0,0 @@ -package org.sunbird.utils - -object HierarchyConstants { - val DATA: String = "data" - val DATA_NODE: String = "DATA_NODE" - val NODES_MODIFIED: String = "nodesModified" - val HIERARCHY: String = "hierarchy" - val ROOT: String = "root" - val SET_DEFAULT_VALUE: String = "setDefaultValue" - val VERSION: String = "version" - val IDENTIFIER: String = "identifier" - val DEPTH: String = "depth" - val PARENT: String = "Parent" - val PARENT_KEY: String = "parent" - val INDEX: String = "index" - val CHILDREN: String = "children" - val VISIBILITY: String = "visibility" - val TAXONOMY_ID: String = "domain" - val METADATA: String = "metadata" - val IS_NEW: String = "isNew" - val DIALCODES: String = "dialcodes" - val QUESTION_OBJECT_TYPE: String = "Question" - val OBJECT_TYPE = "objectType" - val STATUS: String = "status" - val LAST_UPDATED_ON: String = "lastUpdatedOn" - val CODE: String = "code" - val VERSION_KEY: String = "versionKey" - val CREATED_ON: String = "createdOn" - val LAST_STATUS_CHANGED_ON: String = "lastStatusChangedOn" - val CHILD_NODES: String = "childNodes" - val QUESTION_SCHEMA_NAME: String = "question" - val QUESTIONSET_SCHEMA_NAME: String = "questionset" - val SCHEMA_NAME: String = "schemaName" - val SCHEMA_VERSION: String = "1.0" - val CONTENT_ID: String = "identifier" - val IDENTIFIERS: String = "identifiers" - val DEFAULT: String = "Default" - val CHANNEL: String = "channel" - val ROOT_ID: String = "rootId" - val HIERARCHY_LIVE_STATUS: List[String] = List("Live", "Unlisted", "Flagged") - val IMAGE_SUFFIX: String = ".img" - val GRAPH_ID: String = "graph_id" - val MODE: String = "mode" - val EDIT_MODE: String = "edit" - val READ_MODE: String = "read" - val CONCEPTS: String = "concepts" - val FIELDS: String = "fields" - val MIME_TYPE: String = "mimeType" - val RETIRED_STATUS: String = "Retired" - val AUDIENCE: String = "audience" - val QUESTIONSET_MIME_TYPE: String = "application/vnd.sunbird.questionset" - val QUESTIONSET_OBJECT_TYPE: String = "QuestionSet" - val OPERATION_UPDATE_HIERARCHY: String = "updateHierarchy" - val BRANCHING_LOGIC: String = "branchingLogic" - val ALLOW_BRANCHING: String = "allowBranching" - val TARGET: String = "target" - val SOURCE: String = "source" - val PRE_CONDITION: String = "preCondition" - val QUESTION_VISIBILITY: List[String] = List("Default", "Parent") -} diff --git a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/HierarchyErrorCodes.scala b/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/HierarchyErrorCodes.scala deleted file mode 100644 index 7b7e8b9ec..000000000 --- a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/HierarchyErrorCodes.scala +++ /dev/null @@ -1,11 +0,0 @@ -package org.sunbird.utils - -object HierarchyErrorCodes { - val ERR_INVALID_ROOT_ID: String = "ERR_INVALID_ROOT_ID" - val ERR_CONTENT_NOT_FOUND: String = "ERR_CONTENT_NOT_FOUND" - val ERR_HIERARCHY_NOT_FOUND: String = "ERR_HIERARCHY_NOT_FOUND" - val ERR_HIERARCHY_UPDATE_DENIED: String = "ERR_HIERARCHY_UPDATE_DENIED" - val ERR_ADD_HIERARCHY_DENIED: String = "ERR_ADD_HIERARCHY_DENIED" - val ERR_REMOVE_HIERARCHY_DENIED: String = "ERR_REMOVE_HIERARCHY_DENIED" - -} diff --git a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/JavaJsonUtils.scala b/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/JavaJsonUtils.scala deleted file mode 100644 index 8f1275ef3..000000000 --- a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/JavaJsonUtils.scala +++ /dev/null @@ -1,36 +0,0 @@ -package org.sunbird.utils - -import java.lang.reflect.{ParameterizedType, Type} - -import com.fasterxml.jackson.core.`type`.TypeReference -import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper} - -object JavaJsonUtils { - - @transient val mapper = new ObjectMapper() - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - - @throws(classOf[Exception]) - def serialize(obj: AnyRef): String = { - mapper.writeValueAsString(obj) - } - - @throws(classOf[Exception]) - def deserialize[T: Manifest](value: String): T = mapper.readValue(value, typeReference[T]) - - private[this] def typeReference[T: Manifest] = new TypeReference[T] { - override def getType = typeFromManifest(manifest[T]) - } - - - private[this] def typeFromManifest(m: Manifest[_]): Type = { - if (m.typeArguments.isEmpty) { m.runtimeClass } - // $COVERAGE-OFF$Disabling scoverage as this code is impossible to test - else new ParameterizedType { - def getRawType = m.runtimeClass - def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray - def getOwnerType = null - } - // $COVERAGE-ON$ - } -} diff --git a/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/NodeUtil.scala b/assessment-api/qs-hierarchy-manager/src/main/scala/org/sunbird/utils/NodeUtil.scala deleted file mode 100644 index e69de29bb..000000000 diff --git a/assessment-api/qs-hierarchy-manager/src/test/resources/application.conf b/assessment-api/qs-hierarchy-manager/src/test/resources/application.conf deleted file mode 100644 index 82fe873b5..000000000 --- a/assessment-api/qs-hierarchy-manager/src/test/resources/application.conf +++ /dev/null @@ -1,423 +0,0 @@ -# This is the main configuration file for the application. -# https://www.playframework.com/documentation/latest/ConfigFile -# ~~~~~ -# Play uses HOCON as its configuration file format. HOCON has a number -# of advantages over other config formats, but there are two things that -# can be used when modifying settings. -# -# You can include other configuration files in this main application.conf file: -#include "extra-config.conf" -# -# You can declare variables and substitute for them: -#mykey = ${some.value} -# -# And if an environment variable exists when there is no other substitution, then -# HOCON will fall back to substituting environment variable: -#mykey = ${JAVA_HOME} - -## Akka -# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration -# https://www.playframework.com/documentation/latest/JavaAkka#Configuration -# ~~~~~ -# Play uses Akka internally and exposes Akka Streams and actors in Websockets and -# other streaming HTTP responses. -akka { - # "akka.log-config-on-start" is extraordinarly useful because it log the complete - # configuration at INFO level, including defaults and overrides, so it s worth - # putting at the very top. - # - # Put the following in your conf/logback.xml file: - # - # - # - # And then uncomment this line to debug the configuration. - # - #log-config-on-start = true - default-dispatcher { - # This will be used if you have set "executor = "fork-join-executor"" - fork-join-executor { - # Min number of threads to cap factor-based parallelism number to - parallelism-min = 8 - - # The parallelism factor is used to determine thread pool size using the - # following formula: ceil(available processors * factor). Resulting size - # is then bounded by the parallelism-min and parallelism-max values. - parallelism-factor = 32.0 - - # Max number of threads to cap factor-based parallelism number to - parallelism-max = 64 - - # Setting to "FIFO" to use queue like peeking mode which "poll" or "LIFO" to use stack - # like peeking mode which "pop". - task-peeking-mode = "FIFO" - } - } - actors-dispatcher { - type = "Dispatcher" - executor = "fork-join-executor" - fork-join-executor { - parallelism-min = 8 - parallelism-factor = 32.0 - parallelism-max = 64 - } - # Throughput for default Dispatcher, set to 1 for as fair as possible - throughput = 1 - } - actor { - deployment { - /healthActor - { - router = smallest-mailbox-pool - nr-of-instances = 5 - dispatcher = actors-dispatcher - } - /itemSetActor - { - router = smallest-mailbox-pool - nr-of-instances = 2 - dispatcher = actors-dispatcher - } - /questionActor - { - router = smallest-mailbox-pool - nr-of-instances = 5 - dispatcher = actors-dispatcher - } - /questionSetActor - { - router = smallest-mailbox-pool - nr-of-instances = 5 - dispatcher = actors-dispatcher - } - } - } -} - -## Secret key -# http://www.playframework.com/documentation/latest/ApplicationSecret -# ~~~~~ -# The secret key is used to sign Play's session cookie. -# This must be changed for production, but we don't recommend you change it in this file. -play.http.secret.key= a-long-secret-to-calm-the-rage-of-the-entropy-gods - -## Modules -# https://www.playframework.com/documentation/latest/Modules -# ~~~~~ -# Control which modules are loaded when Play starts. Note that modules are -# the replacement for "GlobalSettings", which are deprecated in 2.5.x. -# Please see https://www.playframework.com/documentation/latest/GlobalSettings -# for more information. -# -# You can also extend Play functionality by using one of the publically available -# Play modules: https://playframework.com/documentation/latest/ModuleDirectory -play.modules { - # By default, Play will load any class called Module that is defined - # in the root package (the "app" directory), or you can define them - # explicitly below. - # If there are any built-in modules that you want to enable, you can list them here. - #enabled += my.application.Module - - # If there are any built-in modules that you want to disable, you can list them here. - #disabled += "" - enabled += modules.AssessmentModule -} - -## IDE -# https://www.playframework.com/documentation/latest/IDE -# ~~~~~ -# Depending on your IDE, you can add a hyperlink for errors that will jump you -# directly to the code location in the IDE in dev mode. The following line makes -# use of the IntelliJ IDEA REST interface: -#play.editor="http://localhost:63342/api/file/?file=%s&line=%s" - -## Internationalisation -# https://www.playframework.com/documentation/latest/JavaI18N -# https://www.playframework.com/documentation/latest/ScalaI18N -# ~~~~~ -# Play comes with its own i18n settings, which allow the user's preferred language -# to map through to internal messages, or allow the language to be stored in a cookie. -play.i18n { - # The application languages - langs = [ "en" ] - - # Whether the language cookie should be secure or not - #langCookieSecure = true - - # Whether the HTTP only attribute of the cookie should be set to true - #langCookieHttpOnly = true -} - -## Play HTTP settings -# ~~~~~ -play.http { - ## Router - # https://www.playframework.com/documentation/latest/JavaRouting - # https://www.playframework.com/documentation/latest/ScalaRouting - # ~~~~~ - # Define the Router object to use for this application. - # This router will be looked up first when the application is starting up, - # so make sure this is the entry point. - # Furthermore, it's assumed your route file is named properly. - # So for an application router like `my.application.Router`, - # you may need to define a router file `conf/my.application.routes`. - # Default to Routes in the root package (aka "apps" folder) (and conf/routes) - #router = my.application.Router - - ## Action Creator - # https://www.playframework.com/documentation/latest/JavaActionCreator - # ~~~~~ - #actionCreator = null - - ## ErrorHandler - # https://www.playframework.com/documentation/latest/JavaRouting - # https://www.playframework.com/documentation/latest/ScalaRouting - # ~~~~~ - # If null, will attempt to load a class called ErrorHandler in the root package, - #errorHandler = null - - ## Session & Flash - # https://www.playframework.com/documentation/latest/JavaSessionFlash - # https://www.playframework.com/documentation/latest/ScalaSessionFlash - # ~~~~~ - session { - # Sets the cookie to be sent only over HTTPS. - #secure = true - - # Sets the cookie to be accessed only by the server. - #httpOnly = true - - # Sets the max-age field of the cookie to 5 minutes. - # NOTE: this only sets when the browser will discard the cookie. Play will consider any - # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout, - # you need to put a timestamp in the session and check it at regular intervals to possibly expire it. - #maxAge = 300 - - # Sets the domain on the session cookie. - #domain = "example.com" - } - - flash { - # Sets the cookie to be sent only over HTTPS. - #secure = true - - # Sets the cookie to be accessed only by the server. - #httpOnly = true - } -} - -play.server.http.idleTimeout = 60s -play.http.parser.maxDiskBuffer = 10MB -parsers.anyContent.maxLength = 10MB - -## Netty Provider -# https://www.playframework.com/documentation/latest/SettingsNetty -# ~~~~~ -play.server.netty { - # Whether the Netty wire should be logged - log.wire = true - - # If you run Play on Linux, you can use Netty's native socket transport - # for higher performance with less garbage. - transport = "native" -} - -## WS (HTTP Client) -# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS -# ~~~~~ -# The HTTP client primarily used for REST APIs. The default client can be -# configured directly, but you can also create different client instances -# with customized settings. You must enable this by adding to build.sbt: -# -# libraryDependencies += ws // or javaWs if using java -# -play.ws { - # Sets HTTP requests not to follow 302 requests - #followRedirects = false - - # Sets the maximum number of open HTTP connections for the client. - #ahc.maxConnectionsTotal = 50 - - ## WS SSL - # https://www.playframework.com/documentation/latest/WsSSL - # ~~~~~ - ssl { - # Configuring HTTPS with Play WS does not require programming. You can - # set up both trustManager and keyManager for mutual authentication, and - # turn on JSSE debugging in development with a reload. - #debug.handshake = true - #trustManager = { - # stores = [ - # { type = "JKS", path = "exampletrust.jks" } - # ] - #} - } -} - -## Cache -# https://www.playframework.com/documentation/latest/JavaCache -# https://www.playframework.com/documentation/latest/ScalaCache -# ~~~~~ -# Play comes with an integrated cache API that can reduce the operational -# overhead of repeated requests. You must enable this by adding to build.sbt: -# -# libraryDependencies += cache -# -play.cache { - # If you want to bind several caches, you can bind the individually - #bindCaches = ["db-cache", "user-cache", "session-cache"] -} - -## Filter Configuration -# https://www.playframework.com/documentation/latest/Filters -# ~~~~~ -# There are a number of built-in filters that can be enabled and configured -# to give Play greater security. -# -play.filters { - - # Enabled filters are run automatically against Play. - # CSRFFilter, AllowedHostFilters, and SecurityHeadersFilters are enabled by default. - enabled = [filters.AccessLogFilter] - - # Disabled filters remove elements from the enabled list. - # disabled += filters.CSRFFilter - - - ## CORS filter configuration - # https://www.playframework.com/documentation/latest/CorsFilter - # ~~~~~ - # CORS is a protocol that allows web applications to make requests from the browser - # across different domains. - # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has - # dependencies on CORS settings. - cors { - # Filter paths by a whitelist of path prefixes - #pathPrefixes = ["/some/path", ...] - - # The allowed origins. If null, all origins are allowed. - #allowedOrigins = ["http://www.example.com"] - - # The allowed HTTP methods. If null, all methods are allowed - #allowedHttpMethods = ["GET", "POST"] - } - - ## Security headers filter configuration - # https://www.playframework.com/documentation/latest/SecurityHeaders - # ~~~~~ - # Defines security headers that prevent XSS attacks. - # If enabled, then all options are set to the below configuration by default: - headers { - # The X-Frame-Options header. If null, the header is not set. - #frameOptions = "DENY" - - # The X-XSS-Protection header. If null, the header is not set. - #xssProtection = "1; mode=block" - - # The X-Content-Type-Options header. If null, the header is not set. - #contentTypeOptions = "nosniff" - - # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set. - #permittedCrossDomainPolicies = "master-only" - - # The Content-Security-Policy header. If null, the header is not set. - #contentSecurityPolicy = "default-src 'self'" - } - - ## Allowed hosts filter configuration - # https://www.playframework.com/documentation/latest/AllowedHostsFilter - # ~~~~~ - # Play provides a filter that lets you configure which hosts can access your application. - # This is useful to prevent cache poisoning attacks. - hosts { - # Allow requests to example.com, its subdomains, and localhost:9000. - #allowed = [".example.com", "localhost:9000"] - } -} - -play.http.parser.maxMemoryBuffer = 50MB -akka.http.parsing.max-content-length = 50MB -schema.base_path="../../schemas/" - -# Cassandra Configuration -cassandra.lp.connection="127.0.0.1:9042" -content.keyspace = "content_store" - -# Redis Configuration -redis.host="localhost" -redis.port=6379 -redis.maxConnections=128 - -# Graph Configuration -graph.dir=/data/testingGraphDB -akka.request_timeout=30 -environment.id=10000000 -graph.ids=["domain"] -graph.passport.key.base=31b6fd1c4d64e745c867e61a45edc34a -route.domain="bolt://localhost:7687" -route.bolt.write.domain="bolt://localhost:7687" -route.bolt.read.domain="bolt://localhost:7687" -route.bolt.comment.domain="bolt://localhost:7687" -route.all="bolt://localhost:7687" -route.bolt.write.all="bolt://localhost:7687" -route.bolt.read.all="bolt://localhost:7687" -route.bolt.comment.all="bolt://localhost:7687" - -shard.id=1 -platform.auth.check.enabled=false -platform.cache.ttl=3600000 - -#Top N Config for Search Telemetry -telemetry_env=dev - -installation.id=ekstep - - -languageCode { - assamese : "as" - bengali : "bn" - english : "en" - gujarati : "gu" - hindi : "hi" - kannada : "ka" - marathi : "mr" - odia : "or" - tamil : "ta" - telugu : "te" -} - -kafka { - urls : "localhost:9092" - topic.send.enable : true - topics.instruction : "sunbirddev.assessment.publish.request" -} -objectcategorydefinition.keyspace="category_store" -question { - keyspace = "question_store" - list.limit=20 -} -questionset.keyspace="hierarchy_store" - -cassandra { - lp { - connection: "localhost:9042" - } - lpa { - connection: "localhost:9042" - } -} -neo4j_objecttypes_enabled=["Question"] - -import { - request_size_limit = 200 - output_topic_name = "local.auto.creation.job.request" - required_props { - question = ["name", "code", "mimeType", "framework", "channel"] - questionset = ["name", "code", "mimeType", "framework", "channel"] - } - remove_props { - question = [] - questionset = [] - } -} - -root_node_visibility=["Default","Private"] \ No newline at end of file diff --git a/assessment-api/qs-hierarchy-manager/src/test/resources/cassandra-unit.yaml b/assessment-api/qs-hierarchy-manager/src/test/resources/cassandra-unit.yaml deleted file mode 100755 index a965a8fe5..000000000 --- a/assessment-api/qs-hierarchy-manager/src/test/resources/cassandra-unit.yaml +++ /dev/null @@ -1,590 +0,0 @@ -# Cassandra storage config YAML - -# NOTE: -# See http://wiki.apache.org/cassandra/StorageConfiguration for -# full explanations of configuration directives -# /NOTE - -# The name of the cluster. This is mainly used to prevent machines in -# one logical cluster from joining another. -cluster_name: 'Test Cluster' - -# You should always specify InitialToken when setting up a production -# cluster for the first time, and often when adding capacity later. -# The principle is that each node should be given an equal slice of -# the token ring; see http://wiki.apache.org/cassandra/Operations -# for more details. -# -# If blank, Cassandra will request a token bisecting the range of -# the heaviest-loaded existing node. If there is no load information -# available, such as is the case with a new cluster, it will pick -# a random token, which will lead to hot spots. -#initial_token: - -# See http://wiki.apache.org/cassandra/HintedHandoff -hinted_handoff_enabled: true -# this defines the maximum amount of time a dead host will have hints -# generated. After it has been dead this long, new hints for it will not be -# created until it has been seen alive and gone down again. -max_hint_window_in_ms: 10800000 # 3 hours -# Maximum throttle in KBs per second, per delivery thread. This will be -# reduced proportionally to the number of nodes in the cluster. (If there -# are two nodes in the cluster, each delivery thread will use the maximum -# rate; if there are three, each will throttle to half of the maximum, -# since we expect two nodes to be delivering hints simultaneously.) -hinted_handoff_throttle_in_kb: 1024 -# Number of threads with which to deliver hints; -# Consider increasing this number when you have multi-dc deployments, since -# cross-dc handoff tends to be slower -max_hints_delivery_threads: 2 - -hints_directory: target/embeddedCassandra/hints - -# The following setting populates the page cache on memtable flush and compaction -# WARNING: Enable this setting only when the whole node's data fits in memory. -# Defaults to: false -# populate_io_cache_on_flush: false - -# Authentication backend, implementing IAuthenticator; used to identify users -# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthenticator, -# PasswordAuthenticator}. -# -# - AllowAllAuthenticator performs no checks - set it to disable authentication. -# - PasswordAuthenticator relies on username/password pairs to authenticate -# users. It keeps usernames and hashed passwords in system_auth.credentials table. -# Please increase system_auth keyspace replication factor if you use this authenticator. -authenticator: AllowAllAuthenticator - -# Authorization backend, implementing IAuthorizer; used to limit access/provide permissions -# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthorizer, -# CassandraAuthorizer}. -# -# - AllowAllAuthorizer allows any action to any user - set it to disable authorization. -# - CassandraAuthorizer stores permissions in system_auth.permissions table. Please -# increase system_auth keyspace replication factor if you use this authorizer. -authorizer: AllowAllAuthorizer - -# Validity period for permissions cache (fetching permissions can be an -# expensive operation depending on the authorizer, CassandraAuthorizer is -# one example). Defaults to 2000, set to 0 to disable. -# Will be disabled automatically for AllowAllAuthorizer. -permissions_validity_in_ms: 2000 - - -# The partitioner is responsible for distributing rows (by key) across -# nodes in the cluster. Any IPartitioner may be used, including your -# own as long as it is on the classpath. Out of the box, Cassandra -# provides org.apache.cassandra.dht.{Murmur3Partitioner, RandomPartitioner -# ByteOrderedPartitioner, OrderPreservingPartitioner (deprecated)}. -# -# - RandomPartitioner distributes rows across the cluster evenly by md5. -# This is the default prior to 1.2 and is retained for compatibility. -# - Murmur3Partitioner is similar to RandomPartioner but uses Murmur3_128 -# Hash Function instead of md5. When in doubt, this is the best option. -# - ByteOrderedPartitioner orders rows lexically by key bytes. BOP allows -# scanning rows in key order, but the ordering can generate hot spots -# for sequential insertion workloads. -# - OrderPreservingPartitioner is an obsolete form of BOP, that stores -# - keys in a less-efficient format and only works with keys that are -# UTF8-encoded Strings. -# - CollatingOPP collates according to EN,US rules rather than lexical byte -# ordering. Use this as an example if you need custom collation. -# -# See http://wiki.apache.org/cassandra/Operations for more on -# partitioners and token selection. -partitioner: org.apache.cassandra.dht.Murmur3Partitioner - -# directories where Cassandra should store data on disk. -data_file_directories: - - target/embeddedCassandra/data - -# commit log -commitlog_directory: target/embeddedCassandra/commitlog - -cdc_raw_directory: target/embeddedCassandra/cdc - -# policy for data disk failures: -# stop: shut down gossip and Thrift, leaving the node effectively dead, but -# can still be inspected via JMX. -# best_effort: stop using the failed disk and respond to requests based on -# remaining available sstables. This means you WILL see obsolete -# data at CL.ONE! -# ignore: ignore fatal errors and let requests fail, as in pre-1.2 Cassandra -disk_failure_policy: stop - - -# Maximum size of the key cache in memory. -# -# Each key cache hit saves 1 seek and each row cache hit saves 2 seeks at the -# minimum, sometimes more. The key cache is fairly tiny for the amount of -# time it saves, so it's worthwhile to use it at large numbers. -# The row cache saves even more time, but must store the whole values of -# its rows, so it is extremely space-intensive. It's best to only use the -# row cache if you have hot rows or static rows. -# -# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. -# -# Default value is empty to make it "auto" (min(5% of Heap (in MB), 100MB)). Set to 0 to disable key cache. -key_cache_size_in_mb: - -# Duration in seconds after which Cassandra should -# safe the keys cache. Caches are saved to saved_caches_directory as -# specified in this configuration file. -# -# Saved caches greatly improve cold-start speeds, and is relatively cheap in -# terms of I/O for the key cache. Row cache saving is much more expensive and -# has limited use. -# -# Default is 14400 or 4 hours. -key_cache_save_period: 14400 - -# Number of keys from the key cache to save -# Disabled by default, meaning all keys are going to be saved -# key_cache_keys_to_save: 100 - -# Maximum size of the row cache in memory. -# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. -# -# Default value is 0, to disable row caching. -row_cache_size_in_mb: 0 - -# Duration in seconds after which Cassandra should -# safe the row cache. Caches are saved to saved_caches_directory as specified -# in this configuration file. -# -# Saved caches greatly improve cold-start speeds, and is relatively cheap in -# terms of I/O for the key cache. Row cache saving is much more expensive and -# has limited use. -# -# Default is 0 to disable saving the row cache. -row_cache_save_period: 0 - -# Number of keys from the row cache to save -# Disabled by default, meaning all keys are going to be saved -# row_cache_keys_to_save: 100 - -# saved caches -saved_caches_directory: target/embeddedCassandra/saved_caches - -# commitlog_sync may be either "periodic" or "batch." -# When in batch mode, Cassandra won't ack writes until the commit log -# has been fsynced to disk. It will wait up to -# commitlog_sync_batch_window_in_ms milliseconds for other writes, before -# performing the sync. -# -# commitlog_sync: batch -# commitlog_sync_batch_window_in_ms: 50 -# -# the other option is "periodic" where writes may be acked immediately -# and the CommitLog is simply synced every commitlog_sync_period_in_ms -# milliseconds. -commitlog_sync: periodic -commitlog_sync_period_in_ms: 10000 - -# The size of the individual commitlog file segments. A commitlog -# segment may be archived, deleted, or recycled once all the data -# in it (potentially from each columnfamily in the system) has been -# flushed to sstables. -# -# The default size is 32, which is almost always fine, but if you are -# archiving commitlog segments (see commitlog_archiving.properties), -# then you probably want a finer granularity of archiving; 8 or 16 MB -# is reasonable. -commitlog_segment_size_in_mb: 32 - -# any class that implements the SeedProvider interface and has a -# constructor that takes a Map of parameters will do. -seed_provider: - # Addresses of hosts that are deemed contact points. - # Cassandra nodes use this list of hosts to find each other and learn - # the topology of the ring. You must change this if you are running - # multiple nodes! - - class_name: org.apache.cassandra.locator.SimpleSeedProvider - parameters: - # seeds is actually a comma-delimited list of addresses. - # Ex: ",," - - seeds: "127.0.0.1" - - -# For workloads with more data than can fit in memory, Cassandra's -# bottleneck will be reads that need to fetch data from -# disk. "concurrent_reads" should be set to (16 * number_of_drives) in -# order to allow the operations to enqueue low enough in the stack -# that the OS and drives can reorder them. -# -# On the other hand, since writes are almost never IO bound, the ideal -# number of "concurrent_writes" is dependent on the number of cores in -# your system; (8 * number_of_cores) is a good rule of thumb. -concurrent_reads: 32 -concurrent_writes: 32 - -# Total memory to use for memtables. Cassandra will flush the largest -# memtable when this much memory is used. -# If omitted, Cassandra will set it to 1/3 of the heap. -# memtable_total_space_in_mb: 2048 - -# Total space to use for commitlogs. -# If space gets above this value (it will round up to the next nearest -# segment multiple), Cassandra will flush every dirty CF in the oldest -# segment and remove it. -# commitlog_total_space_in_mb: 4096 - -# This sets the amount of memtable flush writer threads. These will -# be blocked by disk io, and each one will hold a memtable in memory -# while blocked. If you have a large heap and many data directories, -# you can increase this value for better flush performance. -# By default this will be set to the amount of data directories defined. -#memtable_flush_writers: 1 - -# the number of full memtables to allow pending flush, that is, -# waiting for a writer thread. At a minimum, this should be set to -# the maximum number of secondary indexes created on a single CF. -#memtable_flush_queue_size: 4 - -# Whether to, when doing sequential writing, fsync() at intervals in -# order to force the operating system to flush the dirty -# buffers. Enable this to avoid sudden dirty buffer flushing from -# impacting read latencies. Almost always a good idea on SSD:s; not -# necessarily on platters. -trickle_fsync: false -trickle_fsync_interval_in_kb: 10240 - -# TCP port, for commands and data -storage_port: 0 - -# SSL port, for encrypted communication. Unused unless enabled in -# encryption_options -ssl_storage_port: 7011 - -# Address to bind to and tell other Cassandra nodes to connect to. You -# _must_ change this if you want multiple nodes to be able to -# communicate! -# -# Leaving it blank leaves it up to InetAddress.getLocalHost(). This -# will always do the Right Thing *if* the node is properly configured -# (hostname, name resolution, etc), and the Right Thing is to use the -# address associated with the hostname (it might not be). -# -# Setting this to 0.0.0.0 is always wrong. -listen_address: 127.0.0.1 - -start_native_transport: true -# port for the CQL native transport to listen for clients on -native_transport_port: 9042 - -# Whether to start the thrift rpc server. -start_rpc: true - -# Address to broadcast to other Cassandra nodes -# Leaving this blank will set it to the same value as listen_address -# broadcast_address: 1.2.3.4 - -# The address to bind the Thrift RPC service to -- clients connect -# here. Unlike ListenAddress above, you *can* specify 0.0.0.0 here if -# you want Thrift to listen on all interfaces. -# -# Leaving this blank has the same effect it does for ListenAddress, -# (i.e. it will be based on the configured hostname of the node). -rpc_address: localhost -# port for Thrift to listen for clients on -rpc_port: 0 - -# enable or disable keepalive on rpc connections -rpc_keepalive: true - -# Cassandra provides three options for the RPC Server: -# -# sync -> One connection per thread in the rpc pool (see below). -# For a very large number of clients, memory will be your limiting -# factor; on a 64 bit JVM, 128KB is the minimum stack size per thread. -# Connection pooling is very, very strongly recommended. -# -# async -> Nonblocking server implementation with one thread to serve -# rpc connections. This is not recommended for high throughput use -# cases. Async has been tested to be about 50% slower than sync -# or hsha and is deprecated: it will be removed in the next major release. -# -# hsha -> Stands for "half synchronous, half asynchronous." The rpc thread pool -# (see below) is used to manage requests, but the threads are multiplexed -# across the different clients. -# -# The default is sync because on Windows hsha is about 30% slower. On Linux, -# sync/hsha performance is about the same, with hsha of course using less memory. -rpc_server_type: sync - -# Uncomment rpc_min|max|thread to set request pool size. -# You would primarily set max for the sync server to safeguard against -# misbehaved clients; if you do hit the max, Cassandra will block until one -# disconnects before accepting more. The defaults for sync are min of 16 and max -# unlimited. -# -# For the Hsha server, the min and max both default to quadruple the number of -# CPU cores. -# -# This configuration is ignored by the async server. -# -# rpc_min_threads: 16 -# rpc_max_threads: 2048 - -# uncomment to set socket buffer sizes on rpc connections -# rpc_send_buff_size_in_bytes: -# rpc_recv_buff_size_in_bytes: - -# Frame size for thrift (maximum field length). -# 0 disables TFramedTransport in favor of TSocket. This option -# is deprecated; we strongly recommend using Framed mode. -thrift_framed_transport_size_in_mb: 15 - -# The max length of a thrift message, including all fields and -# internal thrift overhead. -thrift_max_message_length_in_mb: 16 - -# Set to true to have Cassandra create a hard link to each sstable -# flushed or streamed locally in a backups/ subdirectory of the -# Keyspace data. Removing these links is the operator's -# responsibility. -incremental_backups: false - -# Whether or not to take a snapshot before each compaction. Be -# careful using this option, since Cassandra won't clean up the -# snapshots for you. Mostly useful if you're paranoid when there -# is a data format change. -snapshot_before_compaction: false - -# Whether or not a snapshot is taken of the data before keyspace truncation -# or dropping of column families. The STRONGLY advised default of true -# should be used to provide data safety. If you set this flag to false, you will -# lose data on truncation or drop. -auto_snapshot: false - -# Add column indexes to a row after its contents reach this size. -# Increase if your column values are large, or if you have a very large -# number of columns. The competing causes are, Cassandra has to -# deserialize this much of the row to read a single column, so you want -# it to be small - at least if you do many partial-row reads - but all -# the index data is read for each access, so you don't want to generate -# that wastefully either. -column_index_size_in_kb: 64 - -# Size limit for rows being compacted in memory. Larger rows will spill -# over to disk and use a slower two-pass compaction process. A message -# will be logged specifying the row key. -#in_memory_compaction_limit_in_mb: 64 - -# Number of simultaneous compactions to allow, NOT including -# validation "compactions" for anti-entropy repair. Simultaneous -# compactions can help preserve read performance in a mixed read/write -# workload, by mitigating the tendency of small sstables to accumulate -# during a single long running compactions. The default is usually -# fine and if you experience problems with compaction running too -# slowly or too fast, you should look at -# compaction_throughput_mb_per_sec first. -# -# This setting has no effect on LeveledCompactionStrategy. -# -# concurrent_compactors defaults to the number of cores. -# Uncomment to make compaction mono-threaded, the pre-0.8 default. -#concurrent_compactors: 1 - -# Multi-threaded compaction. When enabled, each compaction will use -# up to one thread per core, plus one thread per sstable being merged. -# This is usually only useful for SSD-based hardware: otherwise, -# your concern is usually to get compaction to do LESS i/o (see: -# compaction_throughput_mb_per_sec), not more. -#multithreaded_compaction: false - -# Throttles compaction to the given total throughput across the entire -# system. The faster you insert data, the faster you need to compact in -# order to keep the sstable count down, but in general, setting this to -# 16 to 32 times the rate you are inserting data is more than sufficient. -# Setting this to 0 disables throttling. Note that this account for all types -# of compaction, including validation compaction. -compaction_throughput_mb_per_sec: 16 - -# Track cached row keys during compaction, and re-cache their new -# positions in the compacted sstable. Disable if you use really large -# key caches. -#compaction_preheat_key_cache: true - -# Throttles all outbound streaming file transfers on this node to the -# given total throughput in Mbps. This is necessary because Cassandra does -# mostly sequential IO when streaming data during bootstrap or repair, which -# can lead to saturating the network connection and degrading rpc performance. -# When unset, the default is 200 Mbps or 25 MB/s. -# stream_throughput_outbound_megabits_per_sec: 200 - -# How long the coordinator should wait for read operations to complete -read_request_timeout_in_ms: 5000 -# How long the coordinator should wait for seq or index scans to complete -range_request_timeout_in_ms: 10000 -# How long the coordinator should wait for writes to complete -write_request_timeout_in_ms: 2000 -# How long a coordinator should continue to retry a CAS operation -# that contends with other proposals for the same row -cas_contention_timeout_in_ms: 1000 -# How long the coordinator should wait for truncates to complete -# (This can be much longer, because unless auto_snapshot is disabled -# we need to flush first so we can snapshot before removing the data.) -truncate_request_timeout_in_ms: 60000 -# The default timeout for other, miscellaneous operations -request_timeout_in_ms: 10000 - -# Enable operation timeout information exchange between nodes to accurately -# measure request timeouts. If disabled, replicas will assume that requests -# were forwarded to them instantly by the coordinator, which means that -# under overload conditions we will waste that much extra time processing -# already-timed-out requests. -# -# Warning: before enabling this property make sure to ntp is installed -# and the times are synchronized between the nodes. -cross_node_timeout: false - -# Enable socket timeout for streaming operation. -# When a timeout occurs during streaming, streaming is retried from the start -# of the current file. This _can_ involve re-streaming an important amount of -# data, so you should avoid setting the value too low. -# Default value is 0, which never timeout streams. -# streaming_socket_timeout_in_ms: 0 - -# phi value that must be reached for a host to be marked down. -# most users should never need to adjust this. -# phi_convict_threshold: 8 - -# endpoint_snitch -- Set this to a class that implements -# IEndpointSnitch. The snitch has two functions: -# - it teaches Cassandra enough about your network topology to route -# requests efficiently -# - it allows Cassandra to spread replicas around your cluster to avoid -# correlated failures. It does this by grouping machines into -# "datacenters" and "racks." Cassandra will do its best not to have -# more than one replica on the same "rack" (which may not actually -# be a physical location) -# -# IF YOU CHANGE THE SNITCH AFTER DATA IS INSERTED INTO THE CLUSTER, -# YOU MUST RUN A FULL REPAIR, SINCE THE SNITCH AFFECTS WHERE REPLICAS -# ARE PLACED. -# -# Out of the box, Cassandra provides -# - SimpleSnitch: -# Treats Strategy order as proximity. This improves cache locality -# when disabling read repair, which can further improve throughput. -# Only appropriate for single-datacenter deployments. -# - PropertyFileSnitch: -# Proximity is determined by rack and data center, which are -# explicitly configured in cassandra-topology.properties. -# - RackInferringSnitch: -# Proximity is determined by rack and data center, which are -# assumed to correspond to the 3rd and 2nd octet of each node's -# IP address, respectively. Unless this happens to match your -# deployment conventions (as it did Facebook's), this is best used -# as an example of writing a custom Snitch class. -# - Ec2Snitch: -# Appropriate for EC2 deployments in a single Region. Loads Region -# and Availability Zone information from the EC2 API. The Region is -# treated as the Datacenter, and the Availability Zone as the rack. -# Only private IPs are used, so this will not work across multiple -# Regions. -# - Ec2MultiRegionSnitch: -# Uses public IPs as broadcast_address to allow cross-region -# connectivity. (Thus, you should set seed addresses to the public -# IP as well.) You will need to open the storage_port or -# ssl_storage_port on the public IP firewall. (For intra-Region -# traffic, Cassandra will switch to the private IP after -# establishing a connection.) -# -# You can use a custom Snitch by setting this to the full class name -# of the snitch, which will be assumed to be on your classpath. -endpoint_snitch: SimpleSnitch - -# controls how often to perform the more expensive part of host score -# calculation -dynamic_snitch_update_interval_in_ms: 100 -# controls how often to reset all host scores, allowing a bad host to -# possibly recover -dynamic_snitch_reset_interval_in_ms: 600000 -# if set greater than zero and read_repair_chance is < 1.0, this will allow -# 'pinning' of replicas to hosts in order to increase cache capacity. -# The badness threshold will control how much worse the pinned host has to be -# before the dynamic snitch will prefer other replicas over it. This is -# expressed as a double which represents a percentage. Thus, a value of -# 0.2 means Cassandra would continue to prefer the static snitch values -# until the pinned host was 20% worse than the fastest. -dynamic_snitch_badness_threshold: 0.1 - -# request_scheduler -- Set this to a class that implements -# RequestScheduler, which will schedule incoming client requests -# according to the specific policy. This is useful for multi-tenancy -# with a single Cassandra cluster. -# NOTE: This is specifically for requests from the client and does -# not affect inter node communication. -# org.apache.cassandra.scheduler.NoScheduler - No scheduling takes place -# org.apache.cassandra.scheduler.RoundRobinScheduler - Round robin of -# client requests to a node with a separate queue for each -# request_scheduler_id. The scheduler is further customized by -# request_scheduler_options as described below. -request_scheduler: org.apache.cassandra.scheduler.NoScheduler - -# Scheduler Options vary based on the type of scheduler -# NoScheduler - Has no options -# RoundRobin -# - throttle_limit -- The throttle_limit is the number of in-flight -# requests per client. Requests beyond -# that limit are queued up until -# running requests can complete. -# The value of 80 here is twice the number of -# concurrent_reads + concurrent_writes. -# - default_weight -- default_weight is optional and allows for -# overriding the default which is 1. -# - weights -- Weights are optional and will default to 1 or the -# overridden default_weight. The weight translates into how -# many requests are handled during each turn of the -# RoundRobin, based on the scheduler id. -# -# request_scheduler_options: -# throttle_limit: 80 -# default_weight: 5 -# weights: -# Keyspace1: 1 -# Keyspace2: 5 - -# request_scheduler_id -- An identifer based on which to perform -# the request scheduling. Currently the only valid option is keyspace. -# request_scheduler_id: keyspace - -# index_interval controls the sampling of entries from the primrary -# row index in terms of space versus time. The larger the interval, -# the smaller and less effective the sampling will be. In technicial -# terms, the interval coresponds to the number of index entries that -# are skipped between taking each sample. All the sampled entries -# must fit in memory. Generally, a value between 128 and 512 here -# coupled with a large key cache size on CFs results in the best trade -# offs. This value is not often changed, however if you have many -# very small rows (many to an OS page), then increasing this will -# often lower memory usage without a impact on performance. -index_interval: 128 - -# Enable or disable inter-node encryption -# Default settings are TLS v1, RSA 1024-bit keys (it is imperative that -# users generate their own keys) TLS_RSA_WITH_AES_128_CBC_SHA as the cipher -# suite for authentication, key exchange and encryption of the actual data transfers. -# NOTE: No custom encryption options are enabled at the moment -# The available internode options are : all, none, dc, rack -# -# If set to dc cassandra will encrypt the traffic between the DCs -# If set to rack cassandra will encrypt the traffic between the racks -# -# The passwords used in these options must match the passwords used when generating -# the keystore and truststore. For instructions on generating these files, see: -# http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#CreateKeystore -# -encryption_options: - internode_encryption: none - keystore: conf/.keystore - keystore_password: cassandra - truststore: conf/.truststore - truststore_password: cassandra - # More advanced defaults below: - # protocol: TLS - # algorithm: SunX509 - # store_type: JKS - # cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA] \ No newline at end of file diff --git a/assessment-api/qs-hierarchy-manager/src/test/resources/logback.xml b/assessment-api/qs-hierarchy-manager/src/test/resources/logback.xml deleted file mode 100644 index 73529d622..000000000 --- a/assessment-api/qs-hierarchy-manager/src/test/resources/logback.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - %d %msg%n - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assessment-api/qs-hierarchy-manager/src/test/scala/org/sunbird/managers/BaseSpec.scala b/assessment-api/qs-hierarchy-manager/src/test/scala/org/sunbird/managers/BaseSpec.scala deleted file mode 100644 index 01bad4b13..000000000 --- a/assessment-api/qs-hierarchy-manager/src/test/scala/org/sunbird/managers/BaseSpec.scala +++ /dev/null @@ -1,101 +0,0 @@ -package org.sunbird.managers - -import java.io.{File, IOException} - -import com.datastax.driver.core.{ResultSet, Session} -import org.apache.commons.io.FileUtils -import org.cassandraunit.utils.EmbeddedCassandraServerHelper -import org.neo4j.graphdb.GraphDatabaseService -import org.neo4j.graphdb.factory.GraphDatabaseFactory -import org.neo4j.graphdb.factory.GraphDatabaseSettings.Connector.ConnectorType -import org.neo4j.kernel.configuration.BoltConnector -import org.scalatest.{AsyncFlatSpec, BeforeAndAfterAll, BeforeAndAfterEach, Matchers} -import org.sunbird.cassandra.CassandraConnector -import org.sunbird.common.Platform - -class BaseSpec extends AsyncFlatSpec with Matchers with BeforeAndAfterAll with BeforeAndAfterEach{ - - var graphDb: GraphDatabaseService = null - var session: Session = null - - def setUpEmbeddedNeo4j(): Unit = { - if(null == graphDb) { - val bolt: BoltConnector = new BoltConnector("0") - graphDb = new GraphDatabaseFactory() - .newEmbeddedDatabaseBuilder(new File(Platform.config.getString("graph.dir"))) - .setConfig(bolt.`type`, ConnectorType.BOLT.name()) - .setConfig(bolt.enabled, "true").setConfig(bolt.listen_address, "localhost:7687").newGraphDatabase - registerShutdownHook(graphDb) - } - } - - private def registerShutdownHook(graphDb: GraphDatabaseService): Unit = { - Runtime.getRuntime.addShutdownHook(new Thread() { - override def run(): Unit = { - try { - tearEmbeddedNeo4JSetup - } catch { - case e: Exception => - e.printStackTrace() - } - } - }) - } - - - @throws[Exception] - private def tearEmbeddedNeo4JSetup(): Unit = { - if (null != graphDb) graphDb.shutdown - Thread.sleep(2000) - deleteEmbeddedNeo4j(new File(Platform.config.getString("graph.dir"))) - } - - private def deleteEmbeddedNeo4j(emDb: File): Unit = { - try{ - FileUtils.deleteDirectory(emDb) - }catch{ - case e: Exception => - e.printStackTrace() - } - } - - - def setUpEmbeddedCassandra(): Unit = { - System.setProperty("cassandra.unsafesystem", "true") - EmbeddedCassandraServerHelper.startEmbeddedCassandra("/cassandra-unit.yaml", 100000L) - } - - override def beforeAll(): Unit = { - tearEmbeddedNeo4JSetup() - setUpEmbeddedNeo4j() - setUpEmbeddedCassandra() - } - - override def afterAll(): Unit = { - tearEmbeddedNeo4JSetup() - if(null != session && !session.isClosed) - session.close() - EmbeddedCassandraServerHelper.cleanEmbeddedCassandra() - } - - - def executeCassandraQuery(queries: String*): Unit = { - if(null == session || session.isClosed){ - session = CassandraConnector.getSession - } - for(query <- queries) { - session.execute(query) - } - } - - def readFromCassandra(query: String) : ResultSet = { - if(null == session || session.isClosed){ - session = CassandraConnector.getSession - } - session.execute(query) - } - - def createRelationData(): Unit = { - graphDb.execute("UNWIND [{identifier:\"Num:C3:SC2\",code:\"Num:C3:SC2\",keywords:[\"Subconcept\",\"Class 3\"],IL_SYS_NODE_TYPE:\"DATA_NODE\",subject:\"numeracy\",channel:\"in.ekstep\",description:\"Multiplication\",versionKey:\"1484389136575\",gradeLevel:[\"Grade 3\",\"Grade 4\"],IL_FUNC_OBJECT_TYPE:\"Concept\",name:\"Multiplication\",lastUpdatedOn:\"2016-06-15T17:15:45.951+0000\",IL_UNIQUE_ID:\"Num:C3:SC2\",status:\"Live\"}, {code:\"31d521da-61de-4220-9277-21ca7ce8335c\",previewUrl:\"https://ekstep-public-dev.s3-ap-south-1.amazonaws.com/assets/do_11232724509261824014/object-oriented-javascript.pdf\",downloadUrl:\"https://ekstep-public-dev.s3-ap-south-1.amazonaws.com/ecar_files/do_11232724509261824014/untitled-content_1504790847410_do_11232724509261824014_2.0.ecar\",channel:\"in.ekstep\",language:[\"English\"],variants:\"{\\\"spine\\\":{\\\"ecarUrl\\\":\\\"https://ekstep-public-dev.s3-ap-south-1.amazonaws.com/ecar_files/do_11232724509261824014/untitled-content_1504790848197_do_11232724509261824014_2.0_spine.ecar\\\",\\\"size\\\":890.0}}\",mimeType:\"application/pdf\",streamingUrl:\"https://ekstep-public-dev.s3-ap-south-1.amazonaws.com/assets/do_11232724509261824014/object-oriented-javascript.pdf\",idealScreenSize:\"normal\",createdOn:\"2017-09-07T13:24:20.720+0000\",contentDisposition:\"inline\",artifactUrl:\"https://ekstep-public-dev.s3-ap-south-1.amazonaws.com/assets/do_11232724509261824014/object-oriented-javascript.pdf\",contentEncoding:\"identity\",lastUpdatedOn:\"2017-09-07T13:25:53.595+0000\",SYS_INTERNAL_LAST_UPDATED_ON:\"2017-09-07T13:27:28.417+0000\",contentType:\"Resource\",lastUpdatedBy:\"Ekstep\",audience:[\"Student\"],visibility:\"Default\",os:[\"All\"],IL_SYS_NODE_TYPE:\"DATA_NODE\",consumerId:\"e84015d2-a541-4c07-a53f-e31d4553312b\",mediaType:\"content\",osId:\"org.ekstep.quiz.app\",lastPublishedBy:\"Ekstep\",pkgVersion:2,versionKey:\"1504790848417\",license:\"Creative Commons Attribution (CC BY)\",idealScreenDensity:\"hdpi\",s3Key:\"ecar_files/do_11232724509261824014/untitled-content_1504790847410_do_11232724509261824014_2.0.ecar\",size:4864851,lastPublishedOn:\"2017-09-07T13:27:27.410+0000\",createdBy:\"390\",compatibilityLevel:4,IL_FUNC_OBJECT_TYPE:\"Content\",name:\"Untitled Content\",publisher:\"EkStep\",IL_UNIQUE_ID:\"do_11232724509261824014\",status:\"Live\",resourceType:[\"Study material\"]}] as row CREATE (n:domain) SET n += row") - } -} diff --git a/assessment-api/qs-hierarchy-manager/src/test/scala/org/sunbird/managers/HierarchyManagerTest.scala b/assessment-api/qs-hierarchy-manager/src/test/scala/org/sunbird/managers/HierarchyManagerTest.scala deleted file mode 100644 index b1b6dbef6..000000000 --- a/assessment-api/qs-hierarchy-manager/src/test/scala/org/sunbird/managers/HierarchyManagerTest.scala +++ /dev/null @@ -1,128 +0,0 @@ -package org.sunbird.managers - -import java.util - -import org.sunbird.common.JsonUtils -import org.sunbird.common.dto.Request -import org.sunbird.common.exception.ClientException -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.utils.HierarchyConstants - - -import scala.collection.JavaConverters._ - -class HierarchyManagerTest extends BaseSpec { - - implicit val oec: OntologyEngineContext = new OntologyEngineContext - - private val KEYSPACE_CREATE_SCRIPT = "CREATE KEYSPACE IF NOT EXISTS hierarchy_store WITH replication = {'class': 'SimpleStrategy','replication_factor': '1'};" - private val TABLE_CREATE_SCRIPT = "CREATE TABLE IF NOT EXISTS hierarchy_store.questionset_hierarchy (identifier text,hierarchy text,instructions text,outcomeDeclaration text,PRIMARY KEY (identifier));" - private val CATEGORY_STORE_KEYSPACE = "CREATE KEYSPACE IF NOT EXISTS category_store WITH replication = {'class': 'SimpleStrategy','replication_factor': '1'};" - private val CATEGORY_DEF_DATA_TABLE = "CREATE TABLE IF NOT EXISTS category_store.category_definition_data (identifier text PRIMARY KEY, forms map, objectmetadata map);" - private val CATEGORY_DEF_INPUT = List("INSERT INTO category_store.category_definition_data(identifier,objectmetadata) values ('obj-cat:survey_questionset_all',{'config': '{}', 'schema': '{\"properties\":{\"mimeType\":{\"type\":\"string\",\"enum\":[\"application/vnd.sunbird.questionset\"]},\"allowBranching\":{\"type\":\"string\",\"enum\":[\"Yes\",\"No\"],\"default\":\"Yes\"},\"audience\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"Education Official\",\"School leaders (HMs)\",\"Administrator\",\"Teachers\",\"Students\",\"Parents\",\"Others\"]}},\"allowScoring\":{\"type\":\"string\",\"enum\":[\"Yes\",\"No\"],\"default\":\"No\"},\"setPeriod\":{\"type\":\"string\",\"enum\":[\"Yes\",\"No\"]}}}'})", - "INSERT INTO category_store.category_definition_data(identifier,objectmetadata) values ('obj-cat:observation_questionset_all',{'config': '{}', 'schema': '{\"properties\":{\"mimeType\":{\"type\":\"string\",\"enum\":[\"application/vnd.sunbird.questionset\"]},\"allowBranching\":{\"type\":\"string\",\"enum\":[\"Yes\",\"No\"],\"default\":\"Yes\"},\"audience\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"Education Official\",\"School leaders (HMs)\",\"Administrator\",\"Teachers\",\"Students\",\"Parents\",\"Others\"]}},\"allowScoring\":{\"type\":\"string\",\"enum\":[\"Yes\",\"No\"],\"default\":\"No\"}}}'})", - "INSERT INTO category_store.category_definition_data(identifier,objectmetadata) values ('obj-cat:practice-question-set_questionset_all',{'config': '{}', 'schema': '{\"properties\":{\"mimeType\":{\"type\":\"string\",\"enum\":[\"application/vnd.sunbird.questionset\"]}}}'})", - "INSERT INTO category_store.category_definition_data(identifier,objectmetadata) values ('obj-cat:multiple-choice-question_question_all',{'config': '{}', 'schema': '{\"properties\":{\"mimeType\":{\"type\":\"string\",\"enum\":[\"application/vnd.sunbird.question\"]},\"interactionTypes\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"choice\"]}}}}'})", - "INSERT INTO category_store.category_definition_data(identifier,objectmetadata) values ('obj-cat:text_question_all',{'config': '{}', 'schema': '{\"properties\":{\"interactionTypes\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"text\"]}},\"mimeType\":{\"type\":\"string\",\"enum\":[\"application/vnd.sunbird.question\"]}}}'})") - private val HIERARCHY_QS_1 = "INSERT INTO hierarchy_store.questionset_hierarchy (identifier,hierarchy) values('do_obs_123', '{\"identifier\":\"do_obs_123\",\"children\":[{\"parent\":\"do_obs_123\",\"code\":\"do_textq_draft_123\",\"description\":\"Text Type Question 1\",\"language\":[\"English\"],\"mimeType\":\"application/vnd.sunbird.question\",\"createdOn\":\"2022-02-08T13:14:51.741+0000\",\"objectType\":\"Question\",\"primaryCategory\":\"Text\",\"contentDisposition\":\"inline\",\"lastUpdatedOn\":\"2022-02-08T13:14:51.741+0000\",\"contentEncoding\":\"gzip\",\"showSolutions\":\"No\",\"allowAnonymousAccess\":\"Yes\",\"identifier\":\"do_textq_draft_123\",\"lastStatusChangedOn\":\"2022-02-08T13:14:51.741+0000\",\"visibility\":\"Parent\",\"showTimer\":\"No\",\"index\":1,\"languageCode\":[\"en\"],\"version\":1,\"versionKey\":\"1644326091747\",\"showFeedback\":\"No\",\"license\":\"CC BY 4.0\",\"depth\":1,\"compatibilityLevel\":4,\"name\":\"Q1\",\"status\":\"Draft\"},{\"parent\":\"do_obs_123\",\"code\":\"do_mcqq_draft_123\",\"description\":\"MCQ\",\"language\":[\"English\"],\"mimeType\":\"application/vnd.sunbird.question\",\"createdOn\":\"2022-02-08T13:14:51.742+0000\",\"objectType\":\"Question\",\"primaryCategory\":\"Multiple Choice Question\",\"contentDisposition\":\"inline\",\"lastUpdatedOn\":\"2022-02-08T13:14:51.742+0000\",\"contentEncoding\":\"gzip\",\"showSolutions\":\"No\",\"allowAnonymousAccess\":\"Yes\",\"identifier\":\"do_mcqq_draft_123\",\"lastStatusChangedOn\":\"2022-02-08T13:14:51.742+0000\",\"visibility\":\"Parent\",\"showTimer\":\"No\",\"index\":2,\"languageCode\":[\"en\"],\"version\":1,\"versionKey\":\"1644326091748\",\"showFeedback\":\"No\",\"license\":\"CC BY 4.0\",\"depth\":1,\"compatibilityLevel\":4,\"name\":\"Q2\",\"status\":\"Draft\"}]}')" - private val HIERARCHY_QS_2 = "INSERT INTO hierarchy_store.questionset_hierarchy (identifier,hierarchy) values('do_obs_with_section_123', '{\"identifier\":\"do_obs_with_section_123\",\"children\":[{\"parent\":\"do_obs_with_section_123\",\"code\":\"section-1\",\"allowScoring\":\"No\",\"allowSkip\":\"Yes\",\"containsUserData\":\"No\",\"description\":\"section-1\",\"language\":[\"English\"],\"mimeType\":\"application/vnd.sunbird.questionset\",\"showHints\":\"No\",\"createdOn\":\"2022-02-08T18:54:51.117+0000\",\"objectType\":\"QuestionSet\",\"primaryCategory\":\"Observation\",\"contentDisposition\":\"inline\",\"lastUpdatedOn\":\"2022-02-08T18:54:51.117+0000\",\"contentEncoding\":\"gzip\",\"showSolutions\":\"No\",\"allowAnonymousAccess\":\"Yes\",\"identifier\":\"do_section_1\",\"lastStatusChangedOn\":\"2022-02-08T18:54:51.117+0000\",\"requiresSubmit\":\"No\",\"visibility\":\"Parent\",\"showTimer\":\"No\",\"index\":1,\"setType\":\"materialised\",\"languageCode\":[\"en\"],\"version\":1,\"versionKey\":\"1644346491117\",\"showFeedback\":\"No\",\"license\":\"CC BY 4.0\",\"depth\":1,\"createdBy\":\"4e397c42-495e-4fdb-8558-f98176230916\",\"compatibilityLevel\":5,\"name\":\"section-1\",\"navigationMode\":\"non-linear\",\"allowBranching\":\"Yes\",\"shuffle\":true,\"status\":\"Draft\",\"children\":[{\"parent\":\"do_section_1\",\"code\":\"do_textq_draft_123\",\"description\":\"Text Type Question 1\",\"language\":[\"English\"],\"mimeType\":\"application/vnd.sunbird.question\",\"createdOn\":\"2022-02-08T13:14:51.741+0000\",\"objectType\":\"Question\",\"primaryCategory\":\"Text\",\"contentDisposition\":\"inline\",\"lastUpdatedOn\":\"2022-02-08T13:14:51.741+0000\",\"contentEncoding\":\"gzip\",\"showSolutions\":\"No\",\"allowAnonymousAccess\":\"Yes\",\"identifier\":\"do_textq_draft_123\",\"lastStatusChangedOn\":\"2022-02-08T13:14:51.741+0000\",\"visibility\":\"Parent\",\"showTimer\":\"No\",\"index\":1,\"languageCode\":[\"en\"],\"version\":1,\"versionKey\":\"1644326091747\",\"showFeedback\":\"No\",\"license\":\"CC BY 4.0\",\"depth\":1,\"compatibilityLevel\":4,\"name\":\"Q1\",\"status\":\"Draft\"},{\"parent\":\"do_section_1\",\"code\":\"do_mcqq_draft_123\",\"description\":\"MCQ\",\"language\":[\"English\"],\"mimeType\":\"application/vnd.sunbird.question\",\"createdOn\":\"2022-02-08T13:14:51.742+0000\",\"objectType\":\"Question\",\"primaryCategory\":\"Multiple Choice Question\",\"contentDisposition\":\"inline\",\"lastUpdatedOn\":\"2022-02-08T13:14:51.742+0000\",\"contentEncoding\":\"gzip\",\"showSolutions\":\"No\",\"allowAnonymousAccess\":\"Yes\",\"identifier\":\"do_mcqq_draft_123\",\"lastStatusChangedOn\":\"2022-02-08T13:14:51.742+0000\",\"visibility\":\"Parent\",\"showTimer\":\"No\",\"index\":2,\"languageCode\":[\"en\"],\"version\":1,\"versionKey\":\"1644326091748\",\"showFeedback\":\"No\",\"license\":\"CC BY 4.0\",\"depth\":1,\"compatibilityLevel\":4,\"name\":\"Q2\",\"status\":\"Draft\"}]}]}')" - private val HIERARCHY_QS_3 = "INSERT INTO hierarchy_store.questionset_hierarchy (identifier,hierarchy) values('do_obs_with_section_234', '{\"identifier\":\"do_obs_with_section_234\",\"children\":[{\"parent\":\"do_obs_with_section_234\",\"branchingLogic\":{\"do_textq_draft_123\":{\"target\":[\"do_mcqq_draft_123\"],\"preCondition\":{},\"source\":[]},\"do_mcqq_draft_123\":{\"target\":[],\"preCondition\":{\"and\":[{\"eq\":[{\"var\":\"do_textq_draft_123.response1.value\",\"type\":\"responseDeclaration\"},\"0\"]}]},\"source\":[\"do_textq_draft_123\"]}},\"code\":\"section-1\",\"allowScoring\":\"No\",\"allowSkip\":\"Yes\",\"containsUserData\":\"No\",\"description\":\"section-1\",\"language\":[\"English\"],\"mimeType\":\"application/vnd.sunbird.questionset\",\"showHints\":\"No\",\"createdOn\":\"2022-02-08T18:54:51.117+0000\",\"objectType\":\"QuestionSet\",\"primaryCategory\":\"Observation\",\"contentDisposition\":\"inline\",\"lastUpdatedOn\":\"2022-02-08T18:54:51.117+0000\",\"contentEncoding\":\"gzip\",\"showSolutions\":\"No\",\"allowAnonymousAccess\":\"Yes\",\"identifier\":\"do_section_1\",\"lastStatusChangedOn\":\"2022-02-08T18:54:51.117+0000\",\"requiresSubmit\":\"No\",\"visibility\":\"Parent\",\"showTimer\":\"No\",\"index\":1,\"setType\":\"materialised\",\"languageCode\":[\"en\"],\"version\":1,\"versionKey\":\"1644346491117\",\"showFeedback\":\"No\",\"license\":\"CC BY 4.0\",\"depth\":1,\"createdBy\":\"4e397c42-495e-4fdb-8558-f98176230916\",\"compatibilityLevel\":5,\"name\":\"section-1\",\"navigationMode\":\"non-linear\",\"allowBranching\":\"Yes\",\"shuffle\":true,\"status\":\"Draft\",\"children\":[{\"parent\":\"do_section_1\",\"code\":\"do_textq_draft_123\",\"description\":\"Text Type Question 1\",\"language\":[\"English\"],\"mimeType\":\"application/vnd.sunbird.question\",\"createdOn\":\"2022-02-08T13:14:51.741+0000\",\"objectType\":\"Question\",\"primaryCategory\":\"Text\",\"contentDisposition\":\"inline\",\"lastUpdatedOn\":\"2022-02-08T13:14:51.741+0000\",\"contentEncoding\":\"gzip\",\"showSolutions\":\"No\",\"allowAnonymousAccess\":\"Yes\",\"identifier\":\"do_textq_draft_123\",\"lastStatusChangedOn\":\"2022-02-08T13:14:51.741+0000\",\"visibility\":\"Parent\",\"showTimer\":\"No\",\"index\":1,\"languageCode\":[\"en\"],\"version\":1,\"versionKey\":\"1644326091747\",\"showFeedback\":\"No\",\"license\":\"CC BY 4.0\",\"depth\":1,\"compatibilityLevel\":4,\"name\":\"Q1\",\"status\":\"Draft\"},{\"parent\":\"do_section_1\",\"code\":\"do_mcqq_draft_123\",\"description\":\"MCQ\",\"language\":[\"English\"],\"mimeType\":\"application/vnd.sunbird.question\",\"createdOn\":\"2022-02-08T13:14:51.742+0000\",\"objectType\":\"Question\",\"primaryCategory\":\"Multiple Choice Question\",\"contentDisposition\":\"inline\",\"lastUpdatedOn\":\"2022-02-08T13:14:51.742+0000\",\"contentEncoding\":\"gzip\",\"showSolutions\":\"No\",\"allowAnonymousAccess\":\"Yes\",\"identifier\":\"do_mcqq_draft_123\",\"lastStatusChangedOn\":\"2022-02-08T13:14:51.742+0000\",\"visibility\":\"Parent\",\"showTimer\":\"No\",\"index\":2,\"languageCode\":[\"en\"],\"version\":1,\"versionKey\":\"1644326091748\",\"showFeedback\":\"No\",\"license\":\"CC BY 4.0\",\"depth\":1,\"compatibilityLevel\":4,\"name\":\"Q2\",\"status\":\"Draft\"}]}]}')" - - override def beforeAll(): Unit = { - super.beforeAll() - graphDb.execute("UNWIND [" + - "{IL_UNIQUE_ID:\"obj-cat:survey\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-20T09:35:01.320+0000\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",name:\"Survey\",lastUpdatedOn:\"2021-08-20T09:35:01.320+0000\",description:\"Survey\",languageCode:[],createdOn:\"2021-08-20T09:35:01.320+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategory\",versionKey:\"1629452101320\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:observation\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-20T09:35:19.249+0000\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",name:\"Observation\",lastUpdatedOn:\"2021-08-20T09:35:19.249+0000\",description:\"Observation\",languageCode:[],createdOn:\"2021-08-20T09:35:19.249+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategory\",versionKey:\"1629452119249\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:practice-question-set\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2020-10-12T07:07:24.631+0000\",name:\"Practice Question Set\",lastUpdatedOn:\"2020-10-12T07:07:24.631+0000\",description:\"Practice Question Set\",languageCode:[],createdOn:\"2020-10-12T07:07:24.631+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategory\",versionKey:\"1602486444631\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:multiple-choice-question\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-01-04T05:49:19.878+0000\",name:\"Multiple Choice Question\",lastUpdatedOn:\"2021-01-04T05:49:19.878+0000\",description:\"Multiple Choice Question\",languageCode:[],createdOn:\"2021-01-04T05:49:19.878+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategory\",versionKey:\"1609739359878\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:text\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-20T09:36:41.178+0000\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",name:\"Text\",lastUpdatedOn:\"2021-08-20T09:36:41.178+0000\",description:\"Text\",languageCode:[],createdOn:\"2021-08-20T09:36:41.178+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategory\",versionKey:\"1629452201178\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:survey_questionset_all\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-24T16:22:17.524+0000\",visibility:\"Default\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",description:\"Survey\",languageCode:[],createdOn:\"2021-08-24T16:22:17.524+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",versionKey:\"1643101793375\",name:\"Survey\",lastUpdatedOn:\"2022-01-25T09:09:53.375+0000\",targetObjectType:\"QuestionSet\",categoryId:\"obj-cat:survey\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:observation_questionset_all\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-24T16:22:45.014+0000\",visibility:\"Default\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",description:\"Observation\",languageCode:[],createdOn:\"2021-08-24T16:22:45.014+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",versionKey:\"1643101511878\",name:\"Observation\",lastUpdatedOn:\"2022-01-25T09:05:11.878+0000\",targetObjectType:\"QuestionSet\",categoryId:\"obj-cat:observation\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:practice-question-set_questionset_all\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2020-12-10T03:36:57.678+0000\",visibility:\"Default\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",description:\"Practice Question Set\",languageCode:[],createdOn:\"2020-12-10T03:36:57.678+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",versionKey:\"1638263933587\",name:\"Demo Practice Question Set\",lastUpdatedOn:\"2021-11-30T09:18:53.587+0000\",targetObjectType:\"QuestionSet\",categoryId:\"obj-cat:practice-question-set\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:multiple-choice-question_question_all\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-01-04T05:50:31.468+0000\",visibility:\"Default\",consumerId:\"5880ed91-28c4-4d34-9919-036982b0c4ea\",description:\"Multiple Choice Question\",languageCode:[],createdOn:\"2021-01-04T05:50:31.468+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",versionKey:\"1640699675966\",name:\"Multiple Choice Question\",lastUpdatedOn:\"2021-12-28T13:54:35.966+0000\",targetObjectType:\"Question\",categoryId:\"obj-cat:multiple-choice-question\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:text_question_all\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-24T16:23:32.869+0000\",visibility:\"Default\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",description:\"Text\",languageCode:[],createdOn:\"2021-08-24T16:23:32.869+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",versionKey:\"1641394368538\",name:\"Text\",lastUpdatedOn:\"2022-01-05T14:52:48.538+0000\",targetObjectType:\"Question\",categoryId:\"obj-cat:text\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"do_obs_123\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"c288ea98-0a8d-c927-5ec3-e879a90e9e43\",allowScoring:\"No\",allowSkip:\"Yes\",containsUserData:\"No\",language:[\"English\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2022-02-06T20:43:01.535+0000\",primaryCategory:\"Observation\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-06T20:43:01.535+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-06T20:43:01.535+0000\",createdFor:[\"sunbird\"],requiresSubmit:\"No\",visibility:\"Default\",showTimer:\"No\",setType:\"materialised\",languageCode:[\"en\"],version:1,versionKey:\"1644180181535\",showFeedback:\"No\",license:\"CC BY 4.0\",createdBy:\"crt-01\",compatibilityLevel:5,name:\"Test Observation\",navigationMode:\"non-linear\",allowBranching:\"Yes\",shuffle:true,status:\"Draft\"}," + - "{IL_UNIQUE_ID:\"do_obs_with_section_123\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"c288ea98-0a8d-c927-5ec3-e879a90e9e43\",allowScoring:\"No\",allowSkip:\"Yes\",containsUserData:\"No\",language:[\"English\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2022-02-06T20:43:01.535+0000\",primaryCategory:\"Observation\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-06T20:43:01.535+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-06T20:43:01.535+0000\",createdFor:[\"sunbird\"],requiresSubmit:\"No\",visibility:\"Default\",showTimer:\"No\",setType:\"materialised\",languageCode:[\"en\"],version:1,versionKey:\"1644180181535\",showFeedback:\"No\",license:\"CC BY 4.0\",createdBy:\"crt-01\",compatibilityLevel:5,name:\"Test Observation\",navigationMode:\"non-linear\",allowBranching:\"Yes\",shuffle:true,status:\"Draft\",childNodes:[\"do_section_1\"]}," + - "{IL_UNIQUE_ID:\"do_obs_with_section_234\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"c288ea98-0a8d-c927-5ec3-e879a90e9e43\",allowScoring:\"No\",allowSkip:\"Yes\",containsUserData:\"No\",language:[\"English\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2022-02-06T20:43:01.535+0000\",primaryCategory:\"Observation\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-06T20:43:01.535+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-06T20:43:01.535+0000\",createdFor:[\"sunbird\"],requiresSubmit:\"No\",visibility:\"Default\",showTimer:\"No\",setType:\"materialised\",languageCode:[\"en\"],version:1,versionKey:\"1644180181535\",showFeedback:\"No\",license:\"CC BY 4.0\",createdBy:\"crt-01\",compatibilityLevel:5,name:\"Test Observation\",navigationMode:\"non-linear\",allowBranching:\"Yes\",shuffle:true,status:\"Draft\",childNodes:[\"do_section_1\"]}," + - "{IL_UNIQUE_ID:\"do_textq_live_123\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"Q2_1616157220157\",showRemarks:\"No\",channel:\"sunbird\",language:[\"English\"],mimeType:\"application/vnd.sunbird.question\",createdOn:\"2022-02-07T12:49:25.908+0000\",IL_FUNC_OBJECT_TYPE:\"Question\",primaryCategory:\"Text\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-07T12:49:25.908+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-07T12:49:25.908+0000\",visibility:\"Default\",showTimer:\"No\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",languageCode:[\"en\"],version:1,versionKey:\"1644238165908\",showFeedback:\"No\",license:\"CC BY 4.0\",interactionTypes:[\"text\"],compatibilityLevel:4,name:\"Text Type Question\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"do_textq_draft_123\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"Q2_1616157220157\",showRemarks:\"No\",channel:\"sunbird\",language:[\"English\"],mimeType:\"application/vnd.sunbird.question\",createdOn:\"2022-02-07T12:49:25.908+0000\",IL_FUNC_OBJECT_TYPE:\"Question\",primaryCategory:\"Text\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-07T12:49:25.908+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-07T12:49:25.908+0000\",visibility:\"Default\",showTimer:\"No\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",languageCode:[\"en\"],version:1,versionKey:\"1644238165908\",showFeedback:\"No\",license:\"CC BY 4.0\",interactionTypes:[\"text\"],compatibilityLevel:4,name:\"Text Type Question\",status:\"Draft\"}," + - "{IL_UNIQUE_ID:\"do_mcqq_draft_123\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"Q2_1616157220157\",showRemarks:\"No\",channel:\"sunbird\",language:[\"English\"],mimeType:\"application/vnd.sunbird.question\",createdOn:\"2022-02-07T12:49:25.908+0000\",IL_FUNC_OBJECT_TYPE:\"Question\",primaryCategory:\"Multiple Choice Question\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-07T12:49:25.908+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-07T12:49:25.908+0000\",visibility:\"Default\",showTimer:\"No\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",languageCode:[\"en\"],version:1,versionKey:\"1644238165908\",showFeedback:\"No\",license:\"CC BY 4.0\",interactionTypes:[\"choice\"],compatibilityLevel:4,name:\"Text Type Question\",status:\"Draft\"}," + - "{IL_UNIQUE_ID:\"do_mcqq_live_123\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"Q2_1616157220157\",showRemarks:\"No\",channel:\"sunbird\",language:[\"English\"],mimeType:\"application/vnd.sunbird.question\",createdOn:\"2022-02-07T12:49:25.908+0000\",IL_FUNC_OBJECT_TYPE:\"Question\",primaryCategory:\"Multiple Choice Question\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-07T12:49:25.908+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-07T12:49:25.908+0000\",visibility:\"Default\",showTimer:\"No\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",languageCode:[\"en\"],version:1,versionKey:\"1644238165908\",showFeedback:\"No\",license:\"CC BY 4.0\",interactionTypes:[\"choice\"],compatibilityLevel:4,name:\"Text Type Question\",status:\"Live\"}" + - "] as row CREATE (n:domain) SET n += row") - executeCassandraQuery(KEYSPACE_CREATE_SCRIPT, TABLE_CREATE_SCRIPT, CATEGORY_STORE_KEYSPACE, CATEGORY_DEF_DATA_TABLE, HIERARCHY_QS_1, HIERARCHY_QS_2) - executeCassandraQuery(CATEGORY_DEF_INPUT: _*) - println("all query executed...") - - } - - override def beforeEach(): Unit = { - - } - - def getContext(objectType: String): java.util.Map[String, AnyRef] = { - new util.HashMap[String, AnyRef]() { - { - put(HierarchyConstants.GRAPH_ID, HierarchyConstants.TAXONOMY_ID) - put(HierarchyConstants.VERSION, HierarchyConstants.SCHEMA_VERSION) - put(HierarchyConstants.OBJECT_TYPE, objectType) - put(HierarchyConstants.SCHEMA_NAME, objectType.toLowerCase) - put(HierarchyConstants.CHANNEL, "sunbird") - } - } - } - - "addLeafNodesToHierarchy" should "add leaf node under root" in { - val request = new Request() - request.setContext(getContext(HierarchyConstants.QUESTIONSET_OBJECT_TYPE)) - request.putAll(mapAsJavaMap(Map(HierarchyConstants.ROOT_ID -> "do_obs_123", "mode" -> "edit", "children" -> List("do_textq_live_123").asJava))) - val future = HierarchyManager.addLeafNodesToHierarchy(request) - future.map(response => { - assert(response.getResponseCode.code() == 200) - assert(response.getResult.get("children").asInstanceOf[util.List[String]].containsAll(request.get("children").asInstanceOf[util.List[String]])) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.questionset_hierarchy where identifier='do_obs_123'") - .one().getString("hierarchy") - assert(hierarchy.contains("do_textq_live_123")) - }) - } - - "addLeafNodesToHierarchy with section and valid branching logic" should "add leaf node under section along with branching logic" in { - val request = new Request() - request.setContext(getContext(HierarchyConstants.QUESTIONSET_OBJECT_TYPE)) - val branchingLogicStr = "{\"do_textq_live_123\":{\"target\":[],\"preCondition\":{\"and\":[{\"eq\":[{\"var\":\"do_textq_draft_123.response1.value\",\"type\":\"responseDeclaration\"},\"0\"]}]},\"source\":[\"do_textq_draft_123\"]}}" - request.putAll(mapAsJavaMap(Map(HierarchyConstants.ROOT_ID -> "do_obs_with_section_123", "mode" -> "edit", "collectionId" -> "do_section_1", "children" -> List("do_textq_live_123").asJava, "branchingLogic" -> JsonUtils.deserialize(branchingLogicStr, classOf[util.HashMap[String, AnyRef]])))) - val future = HierarchyManager.addLeafNodesToHierarchy(request) - future.map(response => { - assert(response.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.questionset_hierarchy where identifier='do_obs_with_section_123'") - .one().getString("hierarchy") - assert(hierarchy.contains("do_textq_live_123")) - assert(hierarchy.contains("branchingLogic")) - }) - } - - "addLeafNodesToHierarchy with section and invalid branching logic" should "throw client error" in { - val request = new Request() - request.setContext(getContext(HierarchyConstants.QUESTIONSET_OBJECT_TYPE)) - val branchingLogicStr = "{\"do_text_live_123\":{\"target\":[],\"preCondition\":{\"and\":[{\"eq\":[{\"var\":\"do_textq_draft_123.response1.value\",\"type\":\"responseDeclaration\"},\"0\"]}]},\"source\":[\"do_textq_draft_123\"]}}" - request.putAll(mapAsJavaMap(Map(HierarchyConstants.ROOT_ID -> "do_obs_with_section_123", "mode" -> "edit", "collectionId" -> "do_section_1", "children" -> List("do_textq_live_123").asJava, "branchingLogic" -> JsonUtils.deserialize(branchingLogicStr, classOf[util.HashMap[String, AnyRef]])))) - val exception = intercept[ClientException] { - HierarchyManager.addLeafNodesToHierarchy(request) - } - exception.getErrCode shouldEqual "ERR_BAD_REQUEST" - exception.getMessage shouldEqual "Branch Rule Found For The Node Which Is Not A Children Having Identifier : [do_text_live_123]" - } - - "removeLeafNodesToHierarchy" should "remove the leaf node as well as branching logic if present" in { - executeCassandraQuery(HIERARCHY_QS_3) - val request = new Request() - request.setContext(getContext(HierarchyConstants.QUESTIONSET_OBJECT_TYPE)) - request.putAll(mapAsJavaMap(Map(HierarchyConstants.ROOT_ID -> "do_obs_with_section_234", "mode" -> "edit", "collectionId" -> "do_section_1", "children" -> List("do_mcqq_draft_123").asJava))) - HierarchyManager.removeLeafNodesFromHierarchy(request).map(response => { - assert(response.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.questionset_hierarchy where identifier='do_obs_with_section_234'") - .one().getString("hierarchy") - println("hierarchy ::: "+hierarchy) - assert(!hierarchy.contains("do_mcqq_draft_123")) - }) - } -} diff --git a/assessment-api/qs-hierarchy-manager/src/test/scala/org/sunbird/managers/UpdateHierarchyManagerTest.scala b/assessment-api/qs-hierarchy-manager/src/test/scala/org/sunbird/managers/UpdateHierarchyManagerTest.scala deleted file mode 100644 index 8ea1a7029..000000000 --- a/assessment-api/qs-hierarchy-manager/src/test/scala/org/sunbird/managers/UpdateHierarchyManagerTest.scala +++ /dev/null @@ -1,176 +0,0 @@ -package org.sunbird.managers - -import java.util - -import org.apache.commons.collections4.MapUtils -import org.parboiled.common.StringUtils -import org.sunbird.common.JsonUtils -import org.sunbird.common.dto.Request -import org.sunbird.graph.OntologyEngineContext -import org.sunbird.utils.HierarchyConstants - -class UpdateHierarchyManagerTest extends BaseSpec { - - implicit val oec: OntologyEngineContext = new OntologyEngineContext - - private val KEYSPACE_CREATE_SCRIPT = "CREATE KEYSPACE IF NOT EXISTS hierarchy_store WITH replication = {'class': 'SimpleStrategy','replication_factor': '1'};" - private val TABLE_CREATE_SCRIPT = "CREATE TABLE IF NOT EXISTS hierarchy_store.questionset_hierarchy (identifier text,hierarchy text,instructions text,outcomeDeclaration text,PRIMARY KEY (identifier));" - private val CATEGORY_STORE_KEYSPACE = "CREATE KEYSPACE IF NOT EXISTS category_store WITH replication = {'class': 'SimpleStrategy','replication_factor': '1'};" - private val CATEGORY_DEF_DATA_TABLE = "CREATE TABLE IF NOT EXISTS category_store.category_definition_data (identifier text PRIMARY KEY, forms map, objectmetadata map);" - private val CATEGORY_DEF_INPUT = List("INSERT INTO category_store.category_definition_data(identifier,objectmetadata) values ('obj-cat:survey_questionset_all',{'config': '{}', 'schema': '{\"properties\":{\"mimeType\":{\"type\":\"string\",\"enum\":[\"application/vnd.sunbird.questionset\"]},\"allowBranching\":{\"type\":\"string\",\"enum\":[\"Yes\",\"No\"],\"default\":\"Yes\"},\"audience\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"Education Official\",\"School leaders (HMs)\",\"Administrator\",\"Teachers\",\"Students\",\"Parents\",\"Others\"]}},\"allowScoring\":{\"type\":\"string\",\"enum\":[\"Yes\",\"No\"],\"default\":\"No\"},\"setPeriod\":{\"type\":\"string\",\"enum\":[\"Yes\",\"No\"]}}}'})", - "INSERT INTO category_store.category_definition_data(identifier,objectmetadata) values ('obj-cat:observation_questionset_all',{'config': '{}', 'schema': '{\"properties\":{\"mimeType\":{\"type\":\"string\",\"enum\":[\"application/vnd.sunbird.questionset\"]},\"allowBranching\":{\"type\":\"string\",\"enum\":[\"Yes\",\"No\"],\"default\":\"Yes\"},\"audience\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"Education Official\",\"School leaders (HMs)\",\"Administrator\",\"Teachers\",\"Students\",\"Parents\",\"Others\"]}},\"allowScoring\":{\"type\":\"string\",\"enum\":[\"Yes\",\"No\"],\"default\":\"No\"}}}'})", - "INSERT INTO category_store.category_definition_data(identifier,objectmetadata) values ('obj-cat:practice-question-set_questionset_all',{'config': '{}', 'schema': '{\"properties\":{\"mimeType\":{\"type\":\"string\",\"enum\":[\"application/vnd.sunbird.questionset\"]}}}'})", - "INSERT INTO category_store.category_definition_data(identifier,objectmetadata) values ('obj-cat:multiple-choice-question_question_all',{'config': '{}', 'schema': '{\"properties\":{\"mimeType\":{\"type\":\"string\",\"enum\":[\"application/vnd.sunbird.question\"]},\"interactionTypes\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"choice\"]}}}}'})", - "INSERT INTO category_store.category_definition_data(identifier,objectmetadata) values ('obj-cat:text_question_all',{'config': '{}', 'schema': '{\"properties\":{\"interactionTypes\":{\"type\":\"array\",\"items\":{\"type\":\"string\",\"enum\":[\"text\"]}},\"mimeType\":{\"type\":\"string\",\"enum\":[\"application/vnd.sunbird.question\"]}}}'})") - - override def beforeAll(): Unit = { - super.beforeAll() - graphDb.execute("UNWIND [" + - "{IL_UNIQUE_ID:\"obj-cat:survey\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-20T09:35:01.320+0000\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",name:\"Survey\",lastUpdatedOn:\"2021-08-20T09:35:01.320+0000\",description:\"Survey\",languageCode:[],createdOn:\"2021-08-20T09:35:01.320+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategory\",versionKey:\"1629452101320\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:observation\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-20T09:35:19.249+0000\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",name:\"Observation\",lastUpdatedOn:\"2021-08-20T09:35:19.249+0000\",description:\"Observation\",languageCode:[],createdOn:\"2021-08-20T09:35:19.249+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategory\",versionKey:\"1629452119249\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:practice-question-set\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2020-10-12T07:07:24.631+0000\",name:\"Practice Question Set\",lastUpdatedOn:\"2020-10-12T07:07:24.631+0000\",description:\"Practice Question Set\",languageCode:[],createdOn:\"2020-10-12T07:07:24.631+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategory\",versionKey:\"1602486444631\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:multiple-choice-question\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-01-04T05:49:19.878+0000\",name:\"Multiple Choice Question\",lastUpdatedOn:\"2021-01-04T05:49:19.878+0000\",description:\"Multiple Choice Question\",languageCode:[],createdOn:\"2021-01-04T05:49:19.878+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategory\",versionKey:\"1609739359878\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:text\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-20T09:36:41.178+0000\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",name:\"Text\",lastUpdatedOn:\"2021-08-20T09:36:41.178+0000\",description:\"Text\",languageCode:[],createdOn:\"2021-08-20T09:36:41.178+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategory\",versionKey:\"1629452201178\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:survey_questionset_all\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-24T16:22:17.524+0000\",visibility:\"Default\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",description:\"Survey\",languageCode:[],createdOn:\"2021-08-24T16:22:17.524+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",versionKey:\"1643101793375\",name:\"Survey\",lastUpdatedOn:\"2022-01-25T09:09:53.375+0000\",targetObjectType:\"QuestionSet\",categoryId:\"obj-cat:survey\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:observation_questionset_all\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-24T16:22:45.014+0000\",visibility:\"Default\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",description:\"Observation\",languageCode:[],createdOn:\"2021-08-24T16:22:45.014+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",versionKey:\"1643101511878\",name:\"Observation\",lastUpdatedOn:\"2022-01-25T09:05:11.878+0000\",targetObjectType:\"QuestionSet\",categoryId:\"obj-cat:observation\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:practice-question-set_questionset_all\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2020-12-10T03:36:57.678+0000\",visibility:\"Default\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",description:\"Practice Question Set\",languageCode:[],createdOn:\"2020-12-10T03:36:57.678+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",versionKey:\"1638263933587\",name:\"Demo Practice Question Set\",lastUpdatedOn:\"2021-11-30T09:18:53.587+0000\",targetObjectType:\"QuestionSet\",categoryId:\"obj-cat:practice-question-set\",status:\"Live\"},"+ - "{IL_UNIQUE_ID:\"obj-cat:multiple-choice-question_question_all\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-01-04T05:50:31.468+0000\",visibility:\"Default\",consumerId:\"5880ed91-28c4-4d34-9919-036982b0c4ea\",description:\"Multiple Choice Question\",languageCode:[],createdOn:\"2021-01-04T05:50:31.468+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",versionKey:\"1640699675966\",name:\"Multiple Choice Question\",lastUpdatedOn:\"2021-12-28T13:54:35.966+0000\",targetObjectType:\"Question\",categoryId:\"obj-cat:multiple-choice-question\",status:\"Live\"}," + - "{IL_UNIQUE_ID:\"obj-cat:text_question_all\",IL_SYS_NODE_TYPE:\"DATA_NODE\",lastStatusChangedOn:\"2021-08-24T16:23:32.869+0000\",visibility:\"Default\",consumerId:\"64fe2164-1523-4b44-8884-319b07384234\",description:\"Text\",languageCode:[],createdOn:\"2021-08-24T16:23:32.869+0000\",IL_FUNC_OBJECT_TYPE:\"ObjectCategoryDefinition\",versionKey:\"1641394368538\",name:\"Text\",lastUpdatedOn:\"2022-01-05T14:52:48.538+0000\",targetObjectType:\"Question\",categoryId:\"obj-cat:text\",status:\"Live\"}" + - "] as row CREATE (n:domain) SET n += row") - executeCassandraQuery(KEYSPACE_CREATE_SCRIPT, TABLE_CREATE_SCRIPT, CATEGORY_STORE_KEYSPACE, CATEGORY_DEF_DATA_TABLE) - executeCassandraQuery(CATEGORY_DEF_INPUT:_*) - println("all query executed...") - - } - - override def beforeEach(): Unit = { - - } - - def getContext(objectType: String): java.util.Map[String, AnyRef] = { - new util.HashMap[String, AnyRef](){{ - put(HierarchyConstants.GRAPH_ID, HierarchyConstants.TAXONOMY_ID) - put(HierarchyConstants.VERSION , HierarchyConstants.SCHEMA_VERSION) - put(HierarchyConstants.OBJECT_TYPE , objectType) - put(HierarchyConstants.SCHEMA_NAME, objectType.toLowerCase) - put(HierarchyConstants.CHANNEL, "sunbird") - }} - } - - "updateHierarchy" should "create the hierarchy structure for questionset" in { - graphDb.execute("UNWIND [" + - "{IL_UNIQUE_ID:\"do_obs_1234\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"c288ea98-0a8d-c927-5ec3-e879a90e9e43\",allowScoring:\"No\",allowSkip:\"Yes\",containsUserData:\"No\",language:[\"English\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2022-02-06T20:43:01.535+0000\",primaryCategory:\"Observation\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-06T20:43:01.535+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-06T20:43:01.535+0000\",createdFor:[\"sunbird\"],requiresSubmit:\"No\",visibility:\"Default\",showTimer:\"No\",setType:\"materialised\",languageCode:[\"en\"],version:1,versionKey:\"1644180181535\",showFeedback:\"No\",license:\"CC BY 4.0\",createdBy:\"crt-01\",compatibilityLevel:5,name:\"Test Observation\",navigationMode:\"non-linear\",allowBranching:\"Yes\",shuffle:true,status:\"Draft\"}" + - "] as row CREATE (n:domain) SET n += row") - val nodesModifiedString = "{\n \"Q1\": {\n \"metadata\": {\n \"code\": \"Q1\",\n \"name\": \"Q1\",\n \"description\": \"Q1\",\n \"mimeType\": \"application/vnd.sunbird.question\",\n \"primaryCategory\": \"Text\"\n },\n \"objectType\": \"Question\",\n \"root\": false,\n \"isNew\": true\n },\n \"Q2\": {\n \"metadata\": {\n \"code\": \"Q2\",\n \"name\": \"Q2\",\n \"description\": \"Q2\",\n \"mimeType\": \"application/vnd.sunbird.question\",\n \"primaryCategory\": \"Text\"\n },\n \"objectType\": \"Question\",\n \"root\": false,\n \"isNew\": true\n },\n \"Q3\": {\n \"metadata\": {\n \"code\": \"Q3\",\n \"name\": \"Q3\",\n \"description\": \"Q3\",\n \"mimeType\": \"application/vnd.sunbird.question\",\n \"primaryCategory\": \"Text\"\n },\n \"objectType\": \"Question\",\n \"root\": false,\n \"isNew\": true\n },\n \"do_obs_1234\": {\n \"metadata\": {\n \"branchingLogic\": {\n \"Q1\": {\n \"target\": [\n \"Q2\"\n ],\n \"preCondition\": {},\n \"source\": []\n },\n \"Q2\": {\n \"target\": [],\n \"preCondition\": {\n \"and\": [\n {\n \"eq\": [\n {\n \"var\": \"Q1.response1.value\",\n \"type\": \"responseDeclaration\"\n },\n \"0\"\n ]\n }\n ]\n },\n \"source\": [\n \"Q1\"\n ]\n }\n }\n },\n \"objectType\": \"QuestionSet\",\n \"root\": true,\n \"isNew\": false\n }\n}" - val hierarchyString = "{\n \"do_obs_1234\": {\n \"children\": [\n \"Q1\",\n \"Q2\",\n \"Q3\"\n ],\n \"root\": true\n }\n }" - val request = new Request() - val context = getContext(HierarchyConstants.QUESTIONSET_OBJECT_TYPE) - context.put(HierarchyConstants.ROOT_ID, "do_obs_1234") - request.setContext(context) - request.put(HierarchyConstants.NODES_MODIFIED, JsonUtils.deserialize(nodesModifiedString, classOf[util.HashMap[String, AnyRef]])) - request.put(HierarchyConstants.HIERARCHY, JsonUtils.deserialize(hierarchyString, classOf[util.HashMap[String, AnyRef]])) - UpdateHierarchyManager.updateHierarchy(request).map(response => { - assert(response.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.questionset_hierarchy where identifier='do_obs_1234'") - .one().getString("hierarchy") - val result = graphDb.execute("MATCH(n) WHERE n.IL_UNIQUE_ID=\"do_obs_1234\" RETURN n.branchingLogic AS branchingLogic;") - val record = if(result.hasNext) result.next() - val branchingLogic = JsonUtils.deserialize(record.asInstanceOf[java.util.Map[String, AnyRef]].get("branchingLogic").toString, classOf[util.HashMap[String, AnyRef]]) - assert(MapUtils.isNotEmpty(branchingLogic)) - assert(branchingLogic.size()==2) - assert(StringUtils.isNotEmpty(hierarchy)) - }) - } - - "updateHierarchy with instruction metadata at section level" should "create the hierarchy structure for questionset" in { - graphDb.execute("UNWIND [" + - "{IL_UNIQUE_ID:\"do_pqs_1234\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"c288ea98-0a8d-c927-5ec3-e879a90e9e43\",allowScoring:\"No\",allowSkip:\"Yes\",containsUserData:\"No\",language:[\"English\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2022-02-06T20:43:01.535+0000\",primaryCategory:\"Practice Question Set\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-06T20:43:01.535+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-06T20:43:01.535+0000\",createdFor:[\"sunbird\"],requiresSubmit:\"No\",visibility:\"Default\",showTimer:\"No\",setType:\"materialised\",languageCode:[\"en\"],version:1,versionKey:\"1644180181535\",showFeedback:\"No\",license:\"CC BY 4.0\",createdBy:\"crt-01\",compatibilityLevel:5,name:\"Test Observation\",navigationMode:\"non-linear\",allowBranching:\"Yes\",shuffle:true,status:\"Draft\"}" + - "] as row CREATE (n:domain) SET n += row") - val nodesModifiedString = "{\"section-1\":{\"metadata\":{\"code\":\"section-1\",\"name\":\"section-1\",\"description\":\"section-1\",\"mimeType\":\"application/vnd.sunbird.questionset\",\"primaryCategory\":\"Practice Question Set\",\"createdBy\":\"4e397c42-495e-4fdb-8558-f98176230916\",\"instructions\":{\"default\":\"estv\"}},\"objectType\":\"QuestionSet\",\"root\":false,\"isNew\":true},\"Q1\":{\"metadata\":{\"code\":\"Q1\",\"name\":\"Q1\",\"description\":\"Q1\",\"mimeType\":\"application/vnd.sunbird.question\",\"primaryCategory\":\"Text\",\"createdBy\":\"4e397c42-495e-4fdb-8558-f98176230916\"},\"objectType\":\"Question\",\"root\":false,\"isNew\":true},\"Q2\":{\"metadata\":{\"code\":\"Q2\",\"name\":\"Q2\",\"description\":\"Q2\",\"mimeType\":\"application/vnd.sunbird.question\",\"primaryCategory\":\"Text\",\"visibility\":\"Default\",\"createdBy\":\"4e397c42-495e-4fdb-8558-f98176230916\"},\"objectType\":\"Question\",\"root\":false,\"isNew\":true}}" - val hierarchyString = "{\"do_pqs_1234\":{\"children\":[\"section-1\"],\"root\":true},\"section-1\":{\"children\":[\"Q1\",\"Q2\"],\"root\":false}}" - val request = new Request() - val context = getContext(HierarchyConstants.QUESTIONSET_OBJECT_TYPE) - context.put(HierarchyConstants.ROOT_ID, "do_pqs_1234") - request.setContext(context) - request.put(HierarchyConstants.NODES_MODIFIED, JsonUtils.deserialize(nodesModifiedString, classOf[util.HashMap[String, AnyRef]])) - request.put(HierarchyConstants.HIERARCHY, JsonUtils.deserialize(hierarchyString, classOf[util.HashMap[String, AnyRef]])) - UpdateHierarchyManager.updateHierarchy(request).map(response => { - assert(response.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.questionset_hierarchy where identifier='do_pqs_1234'") - .one().getString("hierarchy") - assert(StringUtils.isNotEmpty(hierarchy)) - assert(hierarchy.contains("estv")) - }) - } - - "updateHierarchy with root and section meta" should "update the hierarchy structure for questionset" in { - graphDb.execute("UNWIND [" + - "{IL_UNIQUE_ID:\"do_pqs_12345\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"c288ea98-0a8d-c927-5ec3-e879a90e9e43\",allowScoring:\"No\",allowSkip:\"Yes\",containsUserData:\"No\",language:[\"English\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2022-02-06T20:43:01.535+0000\",primaryCategory:\"Practice Question Set\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-06T20:43:01.535+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-06T20:43:01.535+0000\",createdFor:[\"sunbird\"],requiresSubmit:\"No\",visibility:\"Default\",showTimer:\"No\",setType:\"materialised\",languageCode:[\"en\"],version:1,versionKey:\"1644180181535\",showFeedback:\"No\",license:\"CC BY 4.0\",createdBy:\"crt-01\",compatibilityLevel:5,name:\"Test Observation\",navigationMode:\"non-linear\",allowBranching:\"Yes\",shuffle:true,status:\"Draft\"}" + - "] as row CREATE (n:domain) SET n += row") - val nodesModifiedString = "{\"section-1\":{\"metadata\":{\"code\":\"section-1\",\"name\":\"section-1\",\"description\":\"section-1\",\"mimeType\":\"application/vnd.sunbird.questionset\",\"primaryCategory\":\"Practice Question Set\",\"createdBy\":\"4e397c42-495e-4fdb-8558-f98176230916\"},\"objectType\":\"QuestionSet\",\"root\":false,\"isNew\":true},\"Q1\":{\"metadata\":{\"code\":\"Q1\",\"name\":\"Q1\",\"description\":\"Q1\",\"mimeType\":\"application/vnd.sunbird.question\",\"primaryCategory\":\"Text\",\"createdBy\":\"4e397c42-495e-4fdb-8558-f98176230916\"},\"objectType\":\"Question\",\"root\":false,\"isNew\":true},\"Q2\":{\"metadata\":{\"code\":\"Q2\",\"name\":\"Q2\",\"description\":\"Q2\",\"mimeType\":\"application/vnd.sunbird.question\",\"primaryCategory\":\"Text\",\"visibility\":\"Default\",\"createdBy\":\"4e397c42-495e-4fdb-8558-f98176230916\"},\"objectType\":\"Question\",\"root\":false,\"isNew\":true}}" - val hierarchyString = "{\"do_pqs_12345\":{\"children\":[\"section-1\"],\"root\":true},\"section-1\":{\"children\":[\"Q1\",\"Q2\"],\"root\":false}}" - val request = new Request() - val context = getContext(HierarchyConstants.QUESTIONSET_OBJECT_TYPE) - context.put(HierarchyConstants.ROOT_ID, "do_pqs_12345") - request.setContext(context) - request.put(HierarchyConstants.NODES_MODIFIED, JsonUtils.deserialize(nodesModifiedString, classOf[util.HashMap[String, AnyRef]])) - request.put(HierarchyConstants.HIERARCHY, JsonUtils.deserialize(hierarchyString, classOf[util.HashMap[String, AnyRef]])) - UpdateHierarchyManager.updateHierarchy(request).map(response => { - assert(response.getResponseCode.code() == 200) - val idMap = response.getResult.get("identifiers").asInstanceOf[java.util.Map[String, AnyRef]] - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.questionset_hierarchy where identifier='do_pqs_12345'") - .one().getString("hierarchy") - assert(StringUtils.isNotEmpty(hierarchy)) - val nodesModifiedString = s"""{"do_pqs_12345":{"root":true,"objectType":"QuestionSet","metadata":{"name":"Updated Name - Test QS","language":["English"],"audience":[],"allowScoring":"No","primaryCategory":"Practice Question Set","attributions":[],"maxScore":0},"isNew":false},"${idMap.get("section-1").asInstanceOf[String]}":{"root":false,"objectType":"QuestionSet","metadata":{"name":"Section 1 - Updated Name","description":"updated desc - next update","primaryCategory":"Practice Question Set","attributions":[]},"isNew":false}}""" - val hierarchyString = s"""{"do_pqs_12345":{"name":"Updated Name - Test QS","children":["${idMap.get("section-1").asInstanceOf[String]}"],"root":true},"${idMap.get("section-1").asInstanceOf[String]}":{"name":"Section 1 - Updated Name","children":["${idMap.get("Q1").asInstanceOf[String]}","${idMap.get("Q2").asInstanceOf[String]}"],"root":false},"${idMap.get("Q1").asInstanceOf[String]}":{"children":[],"root":false},"${idMap.get("Q2").asInstanceOf[String]}":{"children":[],"root":false}}""" - val request = new Request() - val context = getContext(HierarchyConstants.QUESTIONSET_OBJECT_TYPE) - context.put(HierarchyConstants.ROOT_ID, "do_pqs_12345") - request.setContext(context) - request.put(HierarchyConstants.NODES_MODIFIED, JsonUtils.deserialize(nodesModifiedString, classOf[util.HashMap[String, AnyRef]])) - request.put(HierarchyConstants.HIERARCHY, JsonUtils.deserialize(hierarchyString, classOf[util.HashMap[String, AnyRef]])) - UpdateHierarchyManager.updateHierarchy(request).map(response => { - assert(response.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.questionset_hierarchy where identifier='do_pqs_12345'") - .one().getString("hierarchy") - assert(StringUtils.isNotEmpty(hierarchy)) - }) - }).flatMap(f => f) - } - - "updateHierarchy with section without children" should "update the hierarchy structure for questionset" in { - graphDb.execute("UNWIND [" + - "{IL_UNIQUE_ID:\"do_pqs_123456\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",IL_SYS_NODE_TYPE:\"DATA_NODE\",code:\"c288ea98-0a8d-c927-5ec3-e879a90e9e43\",allowScoring:\"No\",allowSkip:\"Yes\",containsUserData:\"No\",language:[\"English\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2022-02-06T20:43:01.535+0000\",primaryCategory:\"Practice Question Set\",contentDisposition:\"inline\",lastUpdatedOn:\"2022-02-06T20:43:01.535+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",lastStatusChangedOn:\"2022-02-06T20:43:01.535+0000\",createdFor:[\"sunbird\"],requiresSubmit:\"No\",visibility:\"Default\",showTimer:\"No\",setType:\"materialised\",languageCode:[\"en\"],version:1,versionKey:\"1644180181535\",showFeedback:\"No\",license:\"CC BY 4.0\",createdBy:\"crt-01\",compatibilityLevel:5,name:\"Test Observation\",navigationMode:\"non-linear\",allowBranching:\"Yes\",shuffle:true,status:\"Draft\"}" + - "] as row CREATE (n:domain) SET n += row") - val nodesModifiedString = "{\"section-1\":{\"metadata\":{\"code\":\"section-1\",\"name\":\"section-1\",\"description\":\"section-1\",\"mimeType\":\"application/vnd.sunbird.questionset\",\"primaryCategory\":\"Practice Question Set\",\"createdBy\":\"4e397c42-495e-4fdb-8558-f98176230916\"},\"objectType\":\"QuestionSet\",\"root\":false,\"isNew\":true}}" - val hierarchyString = "{\"do_pqs_123456\":{\"children\":[\"section-1\"],\"root\":true},\"section-1\":{\"children\":[],\"root\":false}}" - val request = new Request() - val context = getContext(HierarchyConstants.QUESTIONSET_OBJECT_TYPE) - context.put(HierarchyConstants.ROOT_ID, "do_pqs_123456") - request.setContext(context) - request.put(HierarchyConstants.NODES_MODIFIED, JsonUtils.deserialize(nodesModifiedString, classOf[util.HashMap[String, AnyRef]])) - request.put(HierarchyConstants.HIERARCHY, JsonUtils.deserialize(hierarchyString, classOf[util.HashMap[String, AnyRef]])) - UpdateHierarchyManager.updateHierarchy(request).map(response => { - assert(response.getResponseCode.code() == 200) - val idMap = response.getResult.get("identifiers").asInstanceOf[java.util.Map[String, AnyRef]] - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.questionset_hierarchy where identifier='do_pqs_123456'") - .one().getString("hierarchy") - assert(StringUtils.isNotEmpty(hierarchy)) - val nodesModifiedString = s"""{"do_pqs_123456":{"root":true,"objectType":"QuestionSet","metadata":{"name":"Updated Name - Test QS","language":["English"],"audience":[],"allowScoring":"No","primaryCategory":"Practice Question Set","attributions":[],"maxScore":0},"isNew":false},"${idMap.get("section-1").asInstanceOf[String]}":{"root":false,"objectType":"QuestionSet","metadata":{"name":"Section 1 - Updated Name","description":"updated desc - next update","primaryCategory":"Practice Question Set","attributions":[]},"isNew":false}}""" - val hierarchyString = s"""{"do_pqs_123456":{"name":"Updated Name - Test QS","children":["${idMap.get("section-1").asInstanceOf[String]}"],"root":true},"${idMap.get("section-1").asInstanceOf[String]}":{"name":"Section 1 - Updated Name","children":[],"root":false}}""" - val request = new Request() - val context = getContext(HierarchyConstants.QUESTIONSET_OBJECT_TYPE) - context.put(HierarchyConstants.ROOT_ID, "do_pqs_123456") - request.setContext(context) - request.put(HierarchyConstants.NODES_MODIFIED, JsonUtils.deserialize(nodesModifiedString, classOf[util.HashMap[String, AnyRef]])) - request.put(HierarchyConstants.HIERARCHY, JsonUtils.deserialize(hierarchyString, classOf[util.HashMap[String, AnyRef]])) - UpdateHierarchyManager.updateHierarchy(request).map(response => { - assert(response.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.questionset_hierarchy where identifier='do_pqs_123456'") - .one().getString("hierarchy") - assert(StringUtils.isNotEmpty(hierarchy)) - }) - }).flatMap(f => f) - } - -} diff --git a/build/assessment-service/Dockerfile b/build/assessment-service/Dockerfile deleted file mode 100644 index d3b28b2cd..000000000 --- a/build/assessment-service/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM sunbird/openjdk-java11-alpine:latest -RUN apk update \ - && apk add unzip \ - && apk add curl \ - && adduser -u 1001 -h /home/sunbird/ -D sunbird \ - && mkdir -p /home/sunbird -RUN chown -R sunbird:sunbird /home/sunbird -USER sunbird -COPY ./assessment-api/assessment-service/target/assessment-service-1.0-SNAPSHOT-dist.zip /home/sunbird/ -RUN unzip /home/sunbird/assessment-service-1.0-SNAPSHOT-dist.zip -d /home/sunbird/ -RUN rm /home/sunbird/assessment-service-1.0-SNAPSHOT-dist.zip -COPY --chown=sunbird ./schemas /home/sunbird/assessment-service-1.0-SNAPSHOT/schemas -WORKDIR /home/sunbird/ -CMD java -XX:+PrintFlagsFinal $JAVA_OPTIONS -cp '/home/sunbird/assessment-service-1.0-SNAPSHOT/lib/*' -Dconfig.file=/home/sunbird/assessment-service-1.0-SNAPSHOT/config/application.conf -Dlogger.file=/home/sunbird/assessment-service-1.0-SNAPSHOT/config/logback.xml play.core.server.ProdServerStart /home/sunbird/assessment-service-1.0-SNAPSHOT diff --git a/build/assessment-service/Jenkinsfile b/build/assessment-service/Jenkinsfile deleted file mode 100644 index ebc9f1a63..000000000 --- a/build/assessment-service/Jenkinsfile +++ /dev/null @@ -1,49 +0,0 @@ -node('build-slave') { - try { - String ANSI_GREEN = "\u001B[32m" - String ANSI_NORMAL = "\u001B[0m" - String ANSI_BOLD = "\u001B[1m" - String ANSI_RED = "\u001B[31m" - String ANSI_YELLOW = "\u001B[33m" - - ansiColor('xterm') { - withEnv(["JAVA_HOME=${JAVA11_HOME}"]) { - stage('Checkout') { - if (!env.hub_org) { - println(ANSI_BOLD + ANSI_RED + "Uh Oh! Please set a Jenkins environment variable named hub_org with value as registery/sunbidrded" + ANSI_NORMAL) - error 'Please resolve the errors and rerun..' - } 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() - 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') { - env.NODE_ENV = "build" - print "Environment will be : ${env.NODE_ENV}" - sh 'mvn clean install -DskipTests=true ' - } - - stage('Package') { - dir('assessment-api') { - sh 'mvn play2:dist -pl assessment-service' - } - sh('chmod 777 build/build.sh') - sh("build/build.sh ${build_tag} ${"assessment-service"} ${env.NODE_NAME} ${hub_org}") - } - stage('ArchiveArtifacts') { - archiveArtifacts "metadata.json" - currentBuild.description = "${build_tag}" - } - } - } - } - catch (err) { - currentBuild.result = "FAILURE" - throw err - } -} diff --git a/build/assessment-service/auto_build_deploy b/build/assessment-service/auto_build_deploy deleted file mode 100644 index d3332edb1..000000000 --- a/build/assessment-service/auto_build_deploy +++ /dev/null @@ -1,58 +0,0 @@ -@Library('deploy-conf') _ -node('build-slave') { - try { - String ANSI_GREEN = "\u001B[32m" - String ANSI_NORMAL = "\u001B[0m" - String ANSI_BOLD = "\u001B[1m" - String ANSI_RED = "\u001B[31m" - String ANSI_YELLOW = "\u001B[33m" - - ansiColor('xterm') { - withEnv(["JAVA_HOME=${JAVA11_HOME}"]) { - stage('Checkout') { - tag_name = env.JOB_NAME.split("/")[-1] - pre_checks() - if (!env.hub_org) { - println(ANSI_BOLD + ANSI_RED + "Uh Oh! Please set a Jenkins environment variable named hub_org with value as registery/sunbidrded" + ANSI_NORMAL) - error 'Please resolve the errors and rerun..' - } else - println(ANSI_BOLD + ANSI_GREEN + "Found environment variable named hub_org with value as: " + hub_org + ANSI_NORMAL) - } - cleanWs() - def scmVars = checkout scm - checkout scm: [$class: 'GitSCM', branches: [[name: "refs/tags/$tag_name"]], userRemoteConfigs: [[url: scmVars.GIT_URL]]] - build_tag = tag_name + "_" + env.BUILD_NUMBER - commit_hash = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() - artifact_version = tag_name + "_" + commit_hash - echo "build_tag: " + build_tag - - // stage Build - env.NODE_ENV = "build" - print "Environment will be : ${env.NODE_ENV}" - sh 'mvn clean install -DskipTests=true ' - -// stage Package - dir('assessment-api') { - sh 'mvn play2:dist -pl assessment-service' - } - sh('chmod 777 build/build.sh') - sh("build/build.sh ${build_tag} ${"assessment-service"} ${env.NODE_NAME} ${hub_org}") - -// stage ArchiveArtifacts - archiveArtifacts "metadata.json" - currentBuild.description = "${build_tag}" - - } - currentBuild.result = "SUCCESS" - slack_notify(currentBuild.result, tag_name) - email_notify() - auto_build_deploy() - } - } - catch (err) { - currentBuild.result = "FAILURE" - slack_notify(currentBuild.result, tag_name) - email_notify() - throw err - } -} diff --git a/content-api/hierarchy-manager/src/test/scala/org/sunbird/managers/TestHierarchy.scala b/content-api/hierarchy-manager/src/test/scala/org/sunbird/managers/TestHierarchy.scala index ba80cadb7..c19f9ad66 100644 --- a/content-api/hierarchy-manager/src/test/scala/org/sunbird/managers/TestHierarchy.scala +++ b/content-api/hierarchy-manager/src/test/scala/org/sunbird/managers/TestHierarchy.scala @@ -153,103 +153,6 @@ class TestHierarchy extends BaseSpec { }) } - "addLeafNodesToHierarchy for QuestionSet object" should "addLeafNodesToHierarchy" ignore { - executeCassandraQuery(script_3) - graphDb.run("UNWIND [{copyright:\"Hello\",code:\"do_113193433773948928111\",allowSkip:\"Yes\",keywords:[\"135\",\"666667\"],containsUserData:\"No\",subject:[\"Hindi\"],description:\"Hello\",language:[\"English\"],medium:[\"Hindi\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2021-01-13T08:29:43.736+0000\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",gradeLevel:[\"Class 7\"],contentDisposition:\"inline\",additionalCategories:[\"Classroom Teaching Video\",\"Concept Map\",\"Textbook\",\"Curiosity Question Set\"],lastUpdatedOn:\"2021-02-08T12:20:33.201+0000\",contentEncoding:\"gzip\",showSolutions:\"Yes\",allowAnonymousAccess:\"Yes\",IL_UNIQUE_ID:\"do_113193433773948928111\",lastStatusChangedOn:\"2021-01-29T06:13:52.095+0000\",audience:[\"Teacher\"],requiresSubmit:\"Yes\",visibility:\"Default\",showTimer:\"Yes\",author:\"Hello\",summaryType:\"Complete\",consumerId:\"fa13b438-8a3d-41b1-8278-33b0c50210e4\",childNodes:[\"do_113193462958120960141\",\"do_113193463656955904143\",\"do_113197944463515648120\",\"do_113209072358883328150\",\"do_113193462438895616139\"],setType:\"materialised\",languageCode:[\"en\"],version:1,versionKey:\"1612786833201\",showFeedback:\"Yes\",license:\"CC BY 4.0\",prevState:\"Draft\",framework:\"ekstep_ncert_k-12\",depth:0,compatibilityLevel:4,name:\"u0926u0941u0903u0916 u0915u093E u0905u0927u093Fu0915u093Eu0930\",navigationMode:\"linear\",topic:[\"Leaves\",\"Water\"],shuffle:true,attributions:[\"Hello\"],board:\"CBSE\",status:\"Review\"}] as row CREATE (n:domain) SET n += row") - val request = new Request() - request.setContext(new util.HashMap[String, AnyRef]() { - { - put("objectType", "Collection") - put("graph_id", "domain") - put("version", "1.0") - put("schemaName", "collection") - put("channel", "b00bc992ef25f1a9a8d63291e20efc8d") - } - }) - - request.put("rootId", "do_11283193441064550414") - request.put("unitId", "do_11283193463014195215") - request.put("children", util.Arrays.asList("do_113193433773948928111")) - request.put("mode","edit") - val future = HierarchyManager.addLeafNodesToHierarchy(request) - future.map(response => { - assert(response.getResponseCode.code() == 200) - assert(response.getResult.get("do_11283193463014195215").asInstanceOf[util.List[String]].containsAll(request.get("children").asInstanceOf[util.List[String]])) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.content_hierarchy where identifier='do_11283193441064550414.img'") - .one().getString("hierarchy") - assert(!response.getResult.get("do_11283193463014195215").asInstanceOf[util.List[String]].contains("do_11283193463014195215")) - assert(hierarchy.contains("do_113193433773948928111")) - }) - } - - ignore should "remove Question object from hierarchy" in { - executeCassandraQuery(script_6) - graphDb.run("UNWIND [{ownershipType:[\"createdBy\"],code:\"SC-2200_3eac25ae-a0c9-4d7c-87be-954406824cb8\",channel:\"sunbird\",description:\"Test-Add/Remove Leaf Node\",language:[\"English\"],mimeType:\"application/vnd.ekstep.content-collection\",idealScreenSize:\"normal\",createdOn:\"2021-03-07T19:23:38.025+0000\",IL_FUNC_OBJECT_TYPE:\"Collection\",contentDisposition:\"inline\",additionalCategories:[\"Textbook\"],lastUpdatedOn:\"2021-03-07T19:24:59.023+0000\",contentEncoding:\"gzip\",contentType:\"TextBook\",dialcodeRequired:\"No\",IL_UNIQUE_ID:\"do_26543193441064550414\",lastStatusChangedOn:\"2021-03-07T19:23:38.025+0000\",audience:[\"Student\"],os:[\"All\"],visibility:\"Default\",childNodes:[\"do_11307457137049600011786\",\"do_11323126865092608011182\",\"do_113212597854404608111\",\"do_11323126865095065611184\"],mediaType:\"content\",osId:\"org.ekstep.quiz.app\",languageCode:[\"en\"],version:2,versionKey:\"1615145099023\",license:\"CC BY 4.0\",idealScreenDensity:\"hdpi\",depth:0,compatibilityLevel:1,userConsent:\"Yes\",name:\"SC-2200-TextBook\",status:\"Draft\"},{copyright:\"Hello\",code:\"do_113193433773948928111\",allowSkip:\"Yes\",keywords:[\"135\",\"666667\"],containsUserData:\"No\",subject:[\"Hindi\"],description:\"Hello\",language:[\"English\"],medium:[\"Hindi\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2021-01-13T08:29:43.736+0000\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",gradeLevel:[\"Class 7\"],contentDisposition:\"inline\",additionalCategories:[\"Classroom Teaching Video\",\"Concept Map\",\"Textbook\",\"Curiosity Question Set\"],lastUpdatedOn:\"2021-02-08T12:20:33.201+0000\",contentEncoding:\"gzip\",showSolutions:\"Yes\",allowAnonymousAccess:\"Yes\",IL_UNIQUE_ID:\"do_113193433773948928111\",lastStatusChangedOn:\"2021-01-29T06:13:52.095+0000\",audience:[\"Teacher\"],requiresSubmit:\"Yes\",visibility:\"Default\",showTimer:\"Yes\",author:\"Hello\",summaryType:\"Complete\",consumerId:\"fa13b438-8a3d-41b1-8278-33b0c50210e4\",childNodes:[\"do_113193462958120960141\",\"do_113193463656955904143\",\"do_113197944463515648120\",\"do_113209072358883328150\",\"do_113193462438895616139\"],setType:\"materialised\",languageCode:[\"en\"],version:1,versionKey:\"1612786833201\",showFeedback:\"Yes\",license:\"CC BY 4.0\",prevState:\"Draft\",framework:\"ekstep_ncert_k-12\",depth:0,compatibilityLevel:4,name:\"u0926u0941u0903u0916 u0915u093E u0905u0927u093Fu0915u093Eu0930\",navigationMode:\"linear\",topic:[\"Leaves\",\"Water\"],shuffle:true,attributions:[\"Hello\"],board:\"CBSE\",status:\"Review\"}] as row CREATE (n:domain) SET n += row") - val request = new Request() - request.setContext(new util.HashMap[String, AnyRef]() { - { - put("objectType", "Collection") - put("graph_id", "domain") - put("version", "1.0") - put("schemaName", "collection") - put("channel", "b00bc992ef25f1a9a8d63291e20efc8d") - } - }) - - request.put("rootId", "do_26543193441064550414") - request.put("unitId", "do_11283193463014195215") - request.put("children", util.Arrays.asList("do_113193433773948928111")) - request.put("mode","edit") - val future = HierarchyManager.addLeafNodesToHierarchy(request) - future.map(response => { - assert(response.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.content_hierarchy where identifier='do_26543193441064550414.img'") - .one().getString("hierarchy") - assert(hierarchy.contains("do_113193433773948928111")) - val removeFuture = HierarchyManager.removeLeafNodesFromHierarchy(request) - removeFuture.map(resp => { - assert(resp.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.content_hierarchy where identifier='do_26543193441064550414.img'") - .one().getString("hierarchy") - assert(!hierarchy.contains("do_113193433773948928111")) - }) - }).flatMap(f => f) - } - - ignore should "removeLeafNodesToHierarchy" in { - executeCassandraQuery(script_3) - graphDb.run("UNWIND [{copyright:\"Hello\",code:\"do_113193433773948928111\",allowSkip:\"Yes\",keywords:[\"135\",\"666667\"],containsUserData:\"No\",subject:[\"Hindi\"],description:\"Hello\",language:[\"English\"],medium:[\"Hindi\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2021-01-13T08:29:43.736+0000\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",gradeLevel:[\"Class 7\"],contentDisposition:\"inline\",additionalCategories:[\"Classroom Teaching Video\",\"Concept Map\",\"Textbook\",\"Curiosity Question Set\"],lastUpdatedOn:\"2021-02-08T12:20:33.201+0000\",contentEncoding:\"gzip\",showSolutions:\"Yes\",allowAnonymousAccess:\"Yes\",IL_UNIQUE_ID:\"do_113193433773948928111\",lastStatusChangedOn:\"2021-01-29T06:13:52.095+0000\",audience:[\"Teacher\"],requiresSubmit:\"Yes\",visibility:\"Default\",showTimer:\"Yes\",author:\"Hello\",summaryType:\"Complete\",consumerId:\"fa13b438-8a3d-41b1-8278-33b0c50210e4\",childNodes:[\"do_113193462958120960141\",\"do_113193463656955904143\",\"do_113197944463515648120\",\"do_113209072358883328150\",\"do_113193462438895616139\"],setType:\"materialised\",languageCode:[\"en\"],version:1,versionKey:\"1612786833201\",showFeedback:\"Yes\",license:\"CC BY 4.0\",prevState:\"Draft\",framework:\"ekstep_ncert_k-12\",depth:0,compatibilityLevel:4,name:\"u0926u0941u0903u0916 u0915u093E u0905u0927u093Fu0915u093Eu0930\",navigationMode:\"linear\",topic:[\"Leaves\",\"Water\"],shuffle:true,attributions:[\"Hello\"],board:\"CBSE\",status:\"Review\"}] as row CREATE (n:domain) SET n += row") - val request = new Request() - request.setContext(new util.HashMap[String, AnyRef]() { - { - put("objectType", "Collection") - put("graph_id", "domain") - put("version", "1.0") - put("schemaName", "collection") - put("channel", "b00bc992ef25f1a9a8d63291e20efc8d") - } - }) - - request.put("rootId", "do_11283193441064550414") - request.put("unitId", "do_11283193463014195215") - request.put("children", util.Arrays.asList("do_113193462958120275141")) - request.put("mode","edit") - val future = HierarchyManager.addLeafNodesToHierarchy(request) - future.map(response => { - assert(response.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.content_hierarchy where identifier='do_11283193441064550414.img'") - .one().getString("hierarchy") - assert(hierarchy.contains("do_113193462958120275141")) - val removeFuture = HierarchyManager.removeLeafNodesFromHierarchy(request) - removeFuture.map(resp => { - assert(resp.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.content_hierarchy where identifier='do_11283193441064550414.img'") - .one().getString("hierarchy") - assert(!hierarchy.contains("do_113193462958120275141")) - }) - }).flatMap(f => f) - } - "removeLeafNodesToHierarchy" should "removeLeafNodesToHierarchy" in { executeCassandraQuery(script_3) val request = new Request() @@ -393,30 +296,6 @@ class TestHierarchy extends BaseSpec { }) } - "getHierarchyWithEditMode having QuestionSet object" should "return the hierarchy" in { - val request = new Request() - executeCassandraQuery(script_5) - graphDb.run("UNWIND [{ownershipType:[\"createdBy\"],code:\"SC-2200_3eac25ae-a0c9-4d7c-87be-954406824cb8\",channel:\"sunbird\",description:\"Test-Add/Remove Leaf Node\",language:[\"English\"],mimeType:\"application/vnd.ekstep.content-collection\",idealScreenSize:\"normal\",createdOn:\"2021-03-07T19:23:38.025+0000\",IL_FUNC_OBJECT_TYPE:\"Collection\",contentDisposition:\"inline\",additionalCategories:[\"Textbook\"],lastUpdatedOn:\"2021-03-07T19:24:59.023+0000\",contentEncoding:\"gzip\",contentType:\"TextBook\",dialcodeRequired:\"No\",IL_UNIQUE_ID:\"do_11323126798764441611181\",lastStatusChangedOn:\"2021-03-07T19:23:38.025+0000\",audience:[\"Student\"],os:[\"All\"],visibility:\"Default\",childNodes:[\"do_11307457137049600011786\",\"do_11323126865092608011182\",\"do_113212597854404608111\",\"do_11323126865095065611184\"],mediaType:\"content\",osId:\"org.ekstep.quiz.app\",languageCode:[\"en\"],version:2,versionKey:\"1615145099023\",license:\"CC BY 4.0\",idealScreenDensity:\"hdpi\",depth:0,compatibilityLevel:1,userConsent:\"Yes\",name:\"SC-2200-TextBook\",status:\"Draft\"}] as row CREATE (n:domain) SET n += row") - graphDb.run("UNWIND [{ownershipType:[\"createdBy\"],copyright:\"Kerala State\",previewUrl:\"https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/assets/do_11307457137049600011786/eng-presentation_1597086905822.pdf\",keywords:[\"By the Hands of the Nature\"],subject:[\"Geography\"],channel:\"0126202691023585280\",downloadUrl:\"https://dockstorage.blob.core.windows.net/sunbird-content-dock/ecar_files/do_11307457137049600011786/by-the-hands-of-the-nature_1597087677810_do_11307457137049600011786_1.0.ecar\",organisation:[\"Kerala State\"],textbook_name:[\"Contemporary India - I\"],showNotification:true,language:[\"English\"],source:\"Kl 4\",mimeType:\"application/pdf\",IL_FUNC_OBJECT_TYPE:\"Content\",sourceURL:\"https://diksha.gov.in/play/content/do_312783564254150656111171\",gradeLevel:[\"Class 9\"],me_totalRatingsCount:36,appIcon:\"https://ntpproductionall.blob.core.windows.net/ntp-content-production/content/do_312783564254150656111171/artifact/screenshot-from-2019-06-14-11-59-39_1560493827569.thumb.png\",level2Name:[\"Physical Features of India\"],appId:\"prod.diksha.portal\",contentEncoding:\"identity\",artifactUrl:\"https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/assets/do_11307457137049600011786/eng-presentation_1597086905822.pdf\",sYS_INTERNAL_LAST_UPDATED_ON:\"2020-08-10T19:27:58.911+0000\",contentType:\"Resource\",IL_UNIQUE_ID:\"do_11307457137049600011786\",audience:[\"Student\"],visibility:\"Default\",author:\"Kerala State\",consumerId:\"89490534-126f-4f0b-82ac-3ff3e49f3468\",mediaType:\"content\",osId:\"org.ekstep.quiz.app\",languageCode:[\"en\"],lastPublishedBy:\"ee2a003a-10a9-4152-8907-a905b9e1f943\",version:2,pragma:[\"external\"],license:\"CC BY 4.0\",prevState:\"Draft\",size:10005190,lastPublishedOn:\"2020-08-10T19:27:57.797+0000\",name:\"By the Hands of the Nature\",status:\"Live\",code:\"6633b233-bc5a-4936-a7a0-da37ebd33868\",prevStatus:\"Processing\",origin:\"do_312783564254150656111171\",streamingUrl:\"https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/assets/do_11307457137049600011786/eng-presentation_1597086905822.pdf\",medium:[\"English\"],posterImage:\"https://ntpproductionall.blob.core.windows.net/ntp-content-production/content/do_312783565429334016112815/artifact/screenshot-from-2019-06-14-11-59-39_1560493827569.png\",idealScreenSize:\"normal\",createdOn:\"2020-07-29T10:03:33.003+0000\",copyrightYear:2019,contentDisposition:\"inline\",lastUpdatedOn:\"2020-08-10T19:27:57.376+0000\",level1Concept:[\"Physical Features of India\"],dialcodeRequired:\"No\",owner:\"Kerala SCERT\",lastStatusChangedOn:\"2020-08-10T19:27:58.907+0000\",createdFor:[\"0126202691023585280\"],creator:\"SAJEEV THOMAS\",os:[\"All\"],level1Name:[\"Contemporary India - I\"],pkgVersion:1,versionKey:\"1597087677376\",idealScreenDensity:\"hdpi\",framework:\"kl_k-12\",s3Key:\"ecar_files/do_11307457137049600011786/by-the-hands-of-the-nature_1597087677810_do_11307457137049600011786_1.0.ecar\",me_averageRating:3,createdBy:\"f20a4bbf-df17-425b-8e43-bd3dd57bde83\",compatibilityLevel:4,ownedBy:\"0126202691023585280\",board:\"CBSE\",resourceType:\"Learn\"},{code:\"finemanfine\",previewUrl:\"https://dockstorage.blob.core.windows.net/sunbird-content-dock/questionset/do_113212597854404608111/do_113212597854404608111_html_1612875515166.html\",allowSkip:\"Yes\",containsUserData:\"No\",downloadUrl:\"https://dockstorage.blob.core.windows.net/sunbird-content-dock/questionset/do_113212597854404608111/test-question-set_1612875514981_do_113212597854404608111_5_SPINE.ecar\",description:\"Updated QS Description\",language:[\"English\"],mimeType:\"application/vnd.sunbird.questionset\",showHints:\"No\",createdOn:\"2021-02-09T10:19:09.026+0000\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",pdfUrl:\"https://dockstorage.blob.core.windows.net/sunbird-content-dock/questionset/do_113212597854404608111/do_113212597854404608111_pdf_1612875515932.pdf\",contentDisposition:\"inline\",lastUpdatedOn:\"2021-02-09T12:58:36.155+0000\",contentEncoding:\"gzip\",showSolutions:\"Yes\",allowAnonymousAccess:\"Yes\",IL_UNIQUE_ID:\"do_113212597854404608111\",lastStatusChangedOn:\"2021-02-09T12:58:36.155+0000\",requiresSubmit:\"Yes\",visibility:\"Default\",showTimer:\"No\",summaryType:\"Complete\",consumerId:\"fa13b438-8a3d-41b1-8278-33b0c50210e4\",childNodes:[\"do_113212598840246272112\",\"do_113212599692050432114\",\"do_113212600505057280116\"],setType:\"materialised\",languageCode:[\"en\"],version:1,pkgVersion:5,versionKey:\"1612875494848\",showFeedback:\"Yes\",license:\"CC BY 4.0\",depth:0,lastPublishedOn:\"2021-02-09T12:58:34.976+0000\",compatibilityLevel:5,name:\"Test Question Set\",navigationMode:\"linear\",shuffle:true,status:\"Live\"}] as row CREATE (n:domain) SET n += row") - request.setContext(new util.HashMap[String, AnyRef]() { - { - put("objectType", "Collection") - put("graph_id", "domain") - put("version", "1.0") - put("schemaName", "collection") - } - }) - request.put("mode","edit") - request.put("rootId", "do_11323126798764441611181") - val future = HierarchyManager.getHierarchy(request) - future.map(response => { - assert(response.getResponseCode.code() == 200) - assert(null != response.getResult.get("content")) - val children = response.getResult.get("content").asInstanceOf[util.Map[String, AnyRef]].get("children").asInstanceOf[java.util.List[java.util.Map[String, AnyRef]]] - assert(null!=children && !children.isEmpty) - }) - } - "getHierarchyForDraftAfterUpdateHierarchyWithoutMode" should "getHierarchy" in { val request = new Request() graphDb.run("UNWIND [{ownershipType:[\"createdBy\"],copyright:\"ORG_002\",previewUrl:\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_112831862871203840114/small.mp4\",downloadUrl:\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_112831862871203840114/test-resource-cert_1566389713658_do_112831862871203840114_1.0.ecar\",channel:\"01246944855007232011\",organisation:[\"ORG_002\"],showNotification:true,language:[\"English\"],mimeType:\"video/mp4\",variants:\"{\\\"spine\\\":{\\\"ecarUrl\\\":\\\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_112831862871203840114/test-resource-cert_1566389714022_do_112831862871203840114_1.0_spine.ecar\\\",\\\"size\\\":35757.0}}\",appIcon:\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_112831862871203840114/artifact/033019_sz_reviews_feat_1564126718632.thumb.jpg\",appId:\"dev.sunbird.portal\",artifactUrl:\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_112831862871203840114/small.mp4\",contentEncoding:\"identity\",lockKey:\"be6bc445-c75e-471d-b46f-71fefe4a1d2f\",contentType:\"Resource\",lastUpdatedBy:\"c4cc494f-04c3-49f3-b3d5-7b1a1984abad\",audience:[\"Student\"],visibility:\"Default\",consumerId:\"273f3b18-5dda-4a27-984a-060c7cd398d3\",mediaType:\"content\",osId:\"org.ekstep.quiz.app\",lastPublishedBy:\"System\",version:1,license:\"Creative Commons Attribution (CC BY)\",prevState:\"Draft\",lastPublishedOn:\"2019-08-21T12:15:13.652+0000\",size:416488,IL_FUNC_OBJECT_TYPE:\"Content\",name:\"Test Resource Cert\",status:\"Draft\",code:\"7e6630c7-3818-4319-92ac-4d08c33904d8\",streamingUrl:\"https://sunbirddevmedia-inct.streaming.media.azure.net/25d7a94c-9be3-471c-926b-51eb5d3c4c2c/small.ism/manifest(format=m3u8-aapl-v3)\",posterImage:\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11281332607717376012/artifact/033019_sz_reviews_feat_1564126718632.jpg\",idealScreenSize:\"normal\",createdOn:\"2019-08-21T12:11:50.644+0000\",contentDisposition:\"inline\",lastUpdatedOn:\"2019-08-21T12:15:13.020+0000\",SYS_INTERNAL_LAST_UPDATED_ON:\"2019-08-21T12:30:16.783+0000\",dialcodeRequired:\"No\",creator:\"Pradyumna\",lastStatusChangedOn:\"2019-08-21T12:15:14.384+0000\",createdFor:[\"01246944855007232011\"],os:[\"All\"],IL_SYS_NODE_TYPE:\"DATA_NODE\",pkgVersion:1,versionKey:\"1566389713020\",idealScreenDensity:\"hdpi\",s3Key:\"ecar_files/do_112831862871203840114/test-resource-cert_1566389713658_do_112831862871203840114_1.0.ecar\",framework:\"K-12\",createdBy:\"c4cc494f-04c3-49f3-b3d5-7b1a1984abad\",compatibilityLevel:1,IL_UNIQUE_ID:\"do_112831862871203840114\",resourceType:\"Learn\"},{ownershipType:[\"createdBy\"],copyright:\"Sunbird\",certTemplate:\"[{\\\"name\\\":\\\"100PercentCompletionCertificate\\\",\\\"issuer\\\":{\\\"name\\\":\\\"Gujarat Council of Educational Research and Training\\\",\\\"url\\\":\\\"https://gcert.gujarat.gov.in/gcert/\\\",\\\"publicKey\\\":[\\\"1\\\",\\\"2\\\"]},\\\"signatoryList\\\":[{\\\"name\\\":\\\"CEO Gujarat\\\",\\\"id\\\":\\\"CEO\\\",\\\"designation\\\":\\\"CEO\\\",\\\"image\\\":\\\"https://cdn.pixabay.com/photo/2014/11/09/08/06/signature-523237__340.jpg\\\"}],\\\"htmlTemplate\\\":\\\"https://drive.google.com/uc?authuser=1&id=1ryB71i0Oqn2c3aqf9N6Lwvet-MZKytoM&export=download\\\",\\\"notifyTemplate\\\":{\\\"subject\\\":\\\"Course completion certificate\\\",\\\"stateImgUrl\\\":\\\"https://sunbirddev.blob.core.windows.net/orgemailtemplate/img/File-0128212938260643843.png\\\",\\\"regardsperson\\\":\\\"Chairperson\\\",\\\"regards\\\":\\\"Minister of Gujarat\\\",\\\"emailTemplateType\\\":\\\"defaultCertTemp\\\"}}]\",downloadUrl:\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_11283193441064550411/test-prad-course-cert_1566398313947_do_11283193441064550411_1.0_spine.ecar\",channel:\"b00bc992ef25f1a9a8d63291e20efc8d\",organisation:[\"Sunbird\"],language:[\"English\"],variants:\"{\\\"online\\\":{\\\"ecarUrl\\\":\\\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_11283193441064550411/test-prad-course-cert_1566398314186_do_11283193441064550411_1.0_online.ecar\\\",\\\"size\\\":4034.0},\\\"spine\\\":{\\\"ecarUrl\\\":\\\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_11283193441064550411/test-prad-course-cert_1566398313947_do_11283193441064550411_1.0_spine.ecar\\\",\\\"size\\\":73256.0}}\",mimeType:\"application/vnd.ekstep.content-collection\",leafNodes:[\"do_112831862871203840114\"],c_sunbird_dev_private_batch_count:0,appIcon:\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11283193441064550411/artifact/033019_sz_reviews_feat_1564126718632.thumb.jpg\",appId:\"local.sunbird.portal\",contentEncoding:\"gzip\",lockKey:\"b079cf15-9e45-4865-be56-2edafa432dd3\",mimeTypesCount:\"{\\\"application/vnd.ekstep.content-collection\\\":1,\\\"video/mp4\\\":1}\",totalCompressedSize:416488,contentType:\"Course\",lastUpdatedBy:\"874ed8a5-782e-4f6c-8f36-e0288455901e\",audience:[\"Student\"],toc_url:\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11283193441064550411/artifact/do_11283193441064550411_toc.json\",visibility:\"Default\",contentTypesCount:\"{\\\"CourseUnit\\\":1,\\\"Resource\\\":1}\",author:\"b00bc992ef25f1a9a8d63291e20efc8d\",childNodes:[\"do_11283193463014195215\"],consumerId:\"273f3b18-5dda-4a27-984a-060c7cd398d3\",mediaType:\"content\",osId:\"org.ekstep.quiz.app\",lastPublishedBy:\"System\",version:2,license:\"Creative Commons Attribution (CC BY)\",prevState:\"Draft\",size:73256,lastPublishedOn:\"2019-08-21T14:38:33.816+0000\",IL_FUNC_OBJECT_TYPE:\"Content\",name:\"test prad course cert\",status:\"Draft\",code:\"org.sunbird.SUi47U\",description:\"Enter description for Course\",posterImage:\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11281332607717376012/artifact/033019_sz_reviews_feat_1564126718632.jpg\",idealScreenSize:\"normal\",createdOn:\"2019-08-21T14:37:23.486+0000\",reservedDialcodes:\"{\\\"I1X4R4\\\":0}\",contentDisposition:\"inline\",lastUpdatedOn:\"2019-08-21T14:38:33.212+0000\",SYS_INTERNAL_LAST_UPDATED_ON:\"2019-11-13T12:54:08.295+0000\",dialcodeRequired:\"No\",creator:\"Creation\",createdFor:[\"ORG_001\"],lastStatusChangedOn:\"2019-08-21T14:38:34.540+0000\",os:[\"All\"],IL_SYS_NODE_TYPE:\"DATA_NODE\",pkgVersion:1,versionKey:\"1566398313212\",idealScreenDensity:\"hdpi\",dialcodes:[\"I1X4R4\"],s3Key:\"ecar_files/do_11283193441064550411/test-prad-course-cert_1566398313947_do_11283193441064550411_1.0_spine.ecar\",depth:0,framework:\"tpd\",me_averageRating:5,createdBy:\"874ed8a5-782e-4f6c-8f36-e0288455901e\",leafNodesCount:1,compatibilityLevel:4,IL_UNIQUE_ID:\"do_11283193441064550411\",c_sunbird_dev_open_batch_count:0,resourceType:\"Course\"}] as row CREATE (n:domain) SET n += row") diff --git a/content-api/hierarchy-manager/src/test/scala/org/sunbird/managers/TestUpdateHierarchy.scala b/content-api/hierarchy-manager/src/test/scala/org/sunbird/managers/TestUpdateHierarchy.scala index 4fd32cf21..c93d33218 100644 --- a/content-api/hierarchy-manager/src/test/scala/org/sunbird/managers/TestUpdateHierarchy.scala +++ b/content-api/hierarchy-manager/src/test/scala/org/sunbird/managers/TestUpdateHierarchy.scala @@ -130,40 +130,6 @@ class TestUpdateHierarchy extends BaseSpec { }) } - "updateHierarchy with One New Unit and Quesstion Object" should "update text book node, create unit and store the hierarchy in cassandra" in { - graphDb.run("UNWIND [{ownershipType:[\"createdBy\"],code:\"SC-2200_3eac25ae-a0c9-4d7c-87be-954406824cb8\",channel:\"sunbird\",description:\"Test-Add/Remove Leaf Node\",language:[\"English\"],mimeType:\"application/vnd.ekstep.content-collection\",idealScreenSize:\"normal\",createdOn:\"2021-03-07T19:23:38.025+0000\",IL_FUNC_OBJECT_TYPE:\"Collection\",contentDisposition:\"inline\",additionalCategories:[\"Textbook\"],lastUpdatedOn:\"2021-03-07T19:24:59.023+0000\",contentEncoding:\"gzip\",contentType:\"TextBook\",dialcodeRequired:\"No\",IL_UNIQUE_ID:\"do_111111111222222222\",lastStatusChangedOn:\"2021-03-07T19:23:38.025+0000\",audience:[\"Student\"],os:[\"All\"],visibility:\"Default\",mediaType:\"content\",osId:\"org.ekstep.quiz.app\",languageCode:[\"en\"],version:2,versionKey:\"1615145099023\",license:\"CC BY 4.0\",idealScreenDensity:\"hdpi\",depth:0,compatibilityLevel:1,userConsent:\"Yes\",name:\"SC-2200-TextBook\",status:\"Draft\"},{code:\"questionId\",subject:[\"Health and Physical Education\"],language:[\"English\"],medium:[\"English\"],mimeType:\"application/vnd.sunbird.question\",createdOn:\"2021-01-13T09:29:06.255+0000\",IL_FUNC_OBJECT_TYPE:\"Question\",gradeLevel:[\"Class 6\"],contentDisposition:\"inline\",lastUpdatedOn:\"2021-02-08T11:19:08.989+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",IL_UNIQUE_ID:\"do_113193462958120275141\",lastStatusChangedOn:\"2021-02-08T11:19:08.989+0000\",visibility:\"Default\",showTimer:\"No\",author:\"Vaibhav\",qType:\"SA\",languageCode:[\"en\"],version:1,versionKey:\"1611554879383\",showFeedback:\"No\",license:\"CC BY 4.0\",prevState:\"Review\",compatibilityLevel:4,name:\"Subjective\",topic:[\"Leaves\"],board:\"CBSE\",status:\"Live\"}] as row CREATE (n:domain) SET n += row") - val request = new Request() - val context = getContext() - context.put(HierarchyConstants.SCHEMA_NAME, "collection") - request.setContext(context) - request.setObjectType(HierarchyConstants.COLLECTION_OBJECT_TYPE) - request.put(HierarchyConstants.NODES_MODIFIED, getNodesModified_3()) - request.put(HierarchyConstants.HIERARCHY, getHierarchy_3("do_111111111222222222", "do_113193462958120275141")) - UpdateHierarchyManager.updateHierarchy(request).map(response => { - assert(response.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.content_hierarchy where identifier='do_111111111222222222'") - .one().getString("hierarchy") - assert(StringUtils.isNotEmpty(hierarchy)) - }) - } - - "updateHierarchy with One New Unit and QuesstionSet Object" should "update text book node, create unit and store the hierarchy in cassandra" in { - graphDb.run("UNWIND [{ownershipType:[\"createdBy\"],code:\"SC-2200_3eac25ae-a0c9-4d7c-87be-954406824cb8\",channel:\"sunbird\",description:\"Test-Add/Remove Leaf Node\",language:[\"English\"],mimeType:\"application/vnd.ekstep.content-collection\",idealScreenSize:\"normal\",createdOn:\"2021-03-07T19:23:38.025+0000\",IL_FUNC_OBJECT_TYPE:\"Collection\",contentDisposition:\"inline\",additionalCategories:[\"Textbook\"],lastUpdatedOn:\"2021-03-07T19:24:59.023+0000\",contentEncoding:\"gzip\",contentType:\"TextBook\",dialcodeRequired:\"No\",IL_UNIQUE_ID:\"do_1111111112222222222223\",lastStatusChangedOn:\"2021-03-07T19:23:38.025+0000\",audience:[\"Student\"],os:[\"All\"],visibility:\"Default\",mediaType:\"content\",osId:\"org.ekstep.quiz.app\",languageCode:[\"en\"],version:2,versionKey:\"1615145099023\",license:\"CC BY 4.0\",idealScreenDensity:\"hdpi\",depth:0,compatibilityLevel:1,userConsent:\"Yes\",name:\"SC-2200-TextBook\",status:\"Draft\"},{code:\"questionId\",subject:[\"Health and Physical Education\"],language:[\"English\"],medium:[\"English\"],mimeType:\"application/vnd.sunbird.questionset\",createdOn:\"2021-01-13T09:29:06.255+0000\",IL_FUNC_OBJECT_TYPE:\"QuestionSet\",gradeLevel:[\"Class 6\"],contentDisposition:\"inline\",lastUpdatedOn:\"2021-02-08T11:19:08.989+0000\",contentEncoding:\"gzip\",showSolutions:\"No\",allowAnonymousAccess:\"Yes\",IL_UNIQUE_ID:\"do_113193462958120277239\",lastStatusChangedOn:\"2021-02-08T11:19:08.989+0000\",visibility:\"Default\",showTimer:\"No\",author:\"Vaibhav\",qType:\"SA\",languageCode:[\"en\"],version:1,versionKey:\"1611554879383\",showFeedback:\"No\",license:\"CC BY 4.0\",prevState:\"Review\",compatibilityLevel:4,name:\"Subjective\",topic:[\"Leaves\"],board:\"CBSE\",status:\"Live\"}] as row CREATE (n:domain) SET n += row") - val request = new Request() - val context = getContext() - context.put(HierarchyConstants.SCHEMA_NAME, "collection") - request.setContext(context) - request.setObjectType(HierarchyConstants.COLLECTION_OBJECT_TYPE) - request.put(HierarchyConstants.NODES_MODIFIED, getNodesModified_3()) - request.put(HierarchyConstants.HIERARCHY, getHierarchy_3("do_1111111112222222222223", "do_113193462958120277239")) - UpdateHierarchyManager.updateHierarchy(request).map(response => { - assert(response.getResponseCode.code() == 200) - val hierarchy = readFromCassandra("Select hierarchy from hierarchy_store.content_hierarchy where identifier='do_1111111112222222222223'") - .one().getString("hierarchy") - assert(StringUtils.isNotEmpty(hierarchy)) - }) - } - "updateHierarchy on already existing hierarchy" should "recompose the hierarchy structure and store in in cassandra and also update neo4j" in { UpdateHierarchyManager.getContentNode("do_31250856200414822416938", HierarchyConstants.TAXONOMY_ID).map(node => { val request = new Request() diff --git a/ontology-engine/graph-engine_2.12/src/test/scala/org/sunbird/graph/nodes/TestDataNode.scala b/ontology-engine/graph-engine_2.12/src/test/scala/org/sunbird/graph/nodes/TestDataNode.scala index bea4bccac..326f3a497 100644 --- a/ontology-engine/graph-engine_2.12/src/test/scala/org/sunbird/graph/nodes/TestDataNode.scala +++ b/ontology-engine/graph-engine_2.12/src/test/scala/org/sunbird/graph/nodes/TestDataNode.scala @@ -663,46 +663,6 @@ class TestDataNode extends BaseSpec { } flatMap(f => f) } - "systemUpdate content with valid data" should "update node metadata" in { - val request = new Request() - request.setObjectType("question") - val context = new util.HashMap[String, AnyRef]() { - { - put("graph_id", "domain") - put("version", "1.0") - put("objectType", "Question") - put("schemaName", "question") - } - } - request.setContext(context) - request.put("code", "finemanfine") - request.put("showFeedback", "Yes") - request.put("showSolutions", "Yes") - request.put("mimeType", "application/vnd.sunbird.question") - request.put("primaryCategory", "Practice Question") - request.put("name", "Test Question") - request.put("visibility", "Default") - request.put("description", "hey") - - val future: Future[Node] = DataNode.create(request) - future map { node => { - assert(null != node) - print(node) - assert(node.getMetadata.get("name").asInstanceOf[String].equalsIgnoreCase("Test Question")) - val req = new Request(request) - req.getContext.put("identifier", node.getIdentifier) - req.put("name", "updated name") - req.put("description", "Updated Description") - val updateFuture = DataNode.systemUpdate(req, util.Arrays.asList(node), "", Option(getHierarchy)) - updateFuture map { resNode => { - assert(resNode.getIdentifier.equals(node.getIdentifier)) - assert(resNode.getMetadata.get("description").equals("Updated Description")) - } - } - } - } flatMap (f => f) - } - "search" should "read data for all identifier" in { executeNeo4jQuery("CREATE (n:domain{IL_UNIQUE_ID:'do_12345',IL_FUNC_OBJECT_TYPE:'Content',status:'Live',ownershipType:[\"createdBy\"],copyright:\"Sunbird\",previewUrl:\"https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1129067102240194561252-latest\"});") val request = new Request() diff --git a/platform-modules/url-manager/src/test/java/org/sunbird/url/util/HttpUrlUtilTest.java b/platform-modules/url-manager/src/test/java/org/sunbird/url/util/HttpUrlUtilTest.java index 170ad2640..9551b579e 100644 --- a/platform-modules/url-manager/src/test/java/org/sunbird/url/util/HttpUrlUtilTest.java +++ b/platform-modules/url-manager/src/test/java/org/sunbird/url/util/HttpUrlUtilTest.java @@ -26,12 +26,11 @@ public class HttpUrlUtilTest { @Test public void testGetMetadataWithValidUrl() { - String url = "https://sunbirddevbbpublic.blob.core.windows.net/sunbird-content-staging/content/assets/do_2137327580080128001217/gateway-of-india.jpg"; + String url = "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_11400964389868339217/indiagate.jpeg"; Map result = HTTPUrlUtil.getMetadata(url); assertTrue(result.size() == 2); assertTrue(result.containsKey("size")); assertTrue(result.containsKey("type")); - assertEquals("image/jpeg", (String) result.get("type")); assertTrue((Long) result.get("size") > 0); } @@ -62,7 +61,7 @@ public void testGetMetadataWithValidUrlExpectServerException() { @Test public void testDownloadFileWithValidUrl() { String downloadFolder = "/tmp/content/" + System.currentTimeMillis() + "_temp/do_123"; - String driveUrl = "https://sunbirddevbbpublic.blob.core.windows.net/sunbird-content-staging/content/assets/do_2137327580080128001217/gateway-of-india.jpg"; + String driveUrl = "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_11400964389868339217/indiagate.jpeg"; java.io.File appIconFile = HTTPUrlUtil.downloadFile(driveUrl,downloadFolder); assertTrue(appIconFile.exists()); try {FileUtils.deleteDirectory(appIconFile.getParentFile().getParentFile());} catch(IOException io) {} diff --git a/schemas/question/1.0/config.json b/schemas/question/1.0/config.json deleted file mode 100644 index b37306e3a..000000000 --- a/schemas/question/1.0/config.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "objectType": "Question", - "relations": { - "questionSet": { - "type": "hasSequenceMember", - "direction": "in", - "objects": ["QuestionSet", "QuestionSetImage"] - } - }, - "restrictProps": { - "create" : [ - "status" - ], - "update" : [ - "visibility", "code", "status", "mimeType" - ] - }, - "version": "enable", - "versionCheckMode": "ON", - "frameworkCategories": ["board","medium","subject","gradeLevel","topic"], - "orgFrameworkTerms": ["boardIds", "gradeLevelIds", "subjectIds", "mediumIds", "topicsIds"], - "targetFrameworkTerms": ["targetFWIds", "targetBoardIds", "targetGradeLevelIds", "targetSubjectIds", "targetMediumIds", "targetTopicIds"], - "cacheEnabled": false, - "schema_restrict_api": true, - "external": { - "tableName": "question_data", - "properties": { - "body": { - "type": "blob" - }, - "editorState": { - "type": "string" - }, - "answer": { - "type": "blob" - }, - "solutions": { - "type": "string" - }, - "instructions": { - "type": "string" - }, - "hints": { - "type": "string" - }, - "media": { - "type": "string" - }, - "responseDeclaration": { - "type": "string" - }, - "interactions": { - "type": "string" - } - }, - "primaryKey": ["identifier"] - } -} \ No newline at end of file diff --git a/schemas/question/1.0/schema.json b/schemas/question/1.0/schema.json deleted file mode 100644 index ad5234e9c..000000000 --- a/schemas/question/1.0/schema.json +++ /dev/null @@ -1,604 +0,0 @@ -{ - "$id": "question-schema.json", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Question", - "type": "object", - "required": [ - "name", - "code", - "mimeType", - "primaryCategory" - ], - "properties": { - "name": { - "type": "string", - "minLength": 5 - }, - "code": { - "type": "string" - }, - "description": { - "type": "string" - }, - "mimeType": { - "type": "string", - "enum": [ - "application/vnd.sunbird.question" - ] - }, - "primaryCategory": { - "type": "string" - }, - "additionalCategories": { - "type": "array", - "items": { - "type": "string" - } - }, - "visibility": { - "type": "string", - "default": "Default", - "enum": [ - "Default", - "Parent", - "Private", - "Protected" - ] - }, - "copyright": { - "type": "string" - }, - "license": { - "type": "string", - "default": "CC BY 4.0" - }, - "lockKey": { - "type": "string" - }, - "assets": { - "type": "array" - }, - "audience": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "Student", - "Teacher", - "Administrator", - "Parent" - ], - "default": "Student" - } - }, - "author": { - "type": "string" - }, - "owner": { - "type": "string" - }, - "attributions": { - "type": "array" - }, - "consumerId": { - "type": "string" - }, - "contentEncoding": { - "type": "string", - "enum": [ - "gzip", - "identity" - ], - "default": "gzip" - }, - "contentDisposition": { - "type": "string", - "enum": [ - "inline", - "online", - "attachment", - "online-only" - ], - "default": "inline" - }, - "appIcon": { - "type": "string", - "format": "url" - }, - "publishChecklist": { - "type": "array" - }, - "publishComment": { - "type": "string" - }, - "compatibilityLevel": { - "type": "number", - "default": 4 - }, - "status": { - "type": "string", - "enum": [ - "Draft", - "Review", - "Live", - "Retired" - ], - "default": "Draft" - }, - "prevState": { - "type": "string" - }, - "prevStatus": { - "type": "string" - }, - "lastStatusChangedOn": { - "type": "string" - }, - "keywords": { - "type": "array", - "items": { - "type": "string" - } - }, - "pkgVersion": { - "type": "number" - }, - "version": { - "type": "number", - "default": 1 - }, - "versionKey": { - "type": "string" - }, - "language": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "English", - "Hindi", - "Assamese", - "Bengali", - "Gujarati", - "Kannada", - "Malayalam", - "Marathi", - "Nepali", - "Odia", - "Punjabi", - "Tamil", - "Telugu", - "Urdu", - "Sanskrit", - "Maithili", - "Other" - ] - }, - "default": ["English"] - }, - "languageCode": { - "type": "array" - }, - "channel": { - "type": "string" - }, - "framework": { - "type": "string" - }, - "subject" : { - "type": "array" - }, - "medium" : { - "type": "array" - }, - "board" : { - "type": "string" - }, - "gradeLevel" : { - "type": "array" - }, - "topic" : { - "type": "array" - }, - "boardIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "gradeLevelIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "subjectIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "mediumIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "topicsIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetFWIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetBoardIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetGradeLevelIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetSubjectIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetMediumIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetTopicIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_FWIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_boardIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_subjectIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_mediumIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_topicIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_gradeLevelIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_boards": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_subjects": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_mediums": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_topics": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_gradeLevels": { - "type": "array", - "items": { - "type": "string" - } - }, - "createdOn": { - "type": "string" - }, - "createdFor": { - "type": "array" - }, - "createdBy": { - "type": "string" - }, - "artifactUrl": { - "type": "string", - "format": "url" - }, - "lastUpdatedOn": { - "type": "string" - }, - "lastUpdatedBy": { - "type": "string" - }, - "lastSubmittedOn": { - "type": "string" - }, - "lastSubmittedBy": { - "type": "string" - }, - "publisher": { - "type": "string" - }, - "lastPublishedOn": { - "type": "string" - }, - "lastPublishedBy": { - "type": "string" - }, - "publishError": { - "type": "string" - }, - "reviewError": { - "type": "string" - }, - - "body": { - "type": "string", - "description": "External Property" - }, - "editorState": { - "type": "object", - "description": "External Property" - }, - "answer": { - "type": "string", - "description": "External Property" - }, - "solutions": { - "type": "array", - "items": { - "type": "string" - }, - "description": "External Property" - }, - "instructions": { - "type": "object", - "description": "External Property" - }, - "hints": { - "type": "array", - "items": { - "type": "string" - }, - "description": "External Property" - }, - "media": { - "type": "array", - "items": { - "type": "object" - }, - "description": "External Property" - }, - "responseDeclaration": { - "type": "object", - "description": "External Property" - }, - "interactions": { - "type": "object", - "description": "External Property" - }, - - - "qType": { - "type": "string", - "enum": [ - "MCQ", - "FTB", - "SA", - "MCQ-MCA", - "MCQ-SCA", - "MTF" - ] - }, - "scoringMode": { - "type": "string", - "enum": [ - "system", - "none" - ] - }, - "qumlVersion": { - "type": "number" - }, - "timeLimit": { - "type": "number" - }, - "maxScore": { - "type": "number" - }, - "showTimer": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "showFeedback": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "showSolutions": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "interactionTypes":{ - "type": "array", - "items": { - "type": "string", - "enum": [ - "choice", - "text", - "select", - "date", - "file-upload", - "canvas" - ] - } - }, - "templateId":{ - "type": "string" - }, - "bloomsLevel" : { - "description": "Cognitive processes involved to answer the question set.", - "type": "string", - "enum": [ - "remember", - "understand", - "apply", - "analyse", - "evaluate", - "create" - ] - }, - "feedback": { - "type": "object" - }, - "responseProcessing": { - "type": "object" - }, - "templateDeclaration": { - "type": "object" - }, - - "dailySummaryReportEnabled": { - "type": "string", - "enum": [ - "Yes", - "No" - ] - }, - "allowAnonymousAccess": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "Yes" - }, - "termsAndConditions": { - "type": "string" - }, - "expectedDuration": { - "type": "number" - }, - "completionCriteria": { - "type": "object" - }, - "collaborators": { - "type": "array" - }, - "semanticVersion": { - "type": "string" - }, - "schemaVersion": { - "type": "string" - }, - "requestChanges": { - "type": "string" - }, - "variants": { - "type": "object" - }, - "rejectComment": { - "type": "string" - }, - "showRemarks": { - "type": "string", - "enum": [ - "Yes", - "No" - ] - }, - "remarks": { - "type": "object" - }, - "showEvidence": { - "type": "string", - "enum": [ - "Yes", - "No" - ] - }, - "evidence": { - "type": "object" - }, - "accessibility": { - "type": "array", - "items": { - "type": "object" - } - }, - "origin": { - "type": "string" - }, - "originData": { - "type": "object" - }, - "choices": { - "type": "object", - "description": "Choices which needs to be used in MCQ / MTF type question" - }, - "rhsChoices": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Choices which needs to be used in RHS of MTF type question" - }, - "downloadUrl": { - "type": "string", - "format": "url" - } - }, - "additionalProperties": false -} diff --git a/schemas/questionset/1.0/config.json b/schemas/questionset/1.0/config.json deleted file mode 100644 index f8764d715..000000000 --- a/schemas/questionset/1.0/config.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "objectType": "QuestionSet", - "relations": { - "children": { - "type": "hasSequenceMember", - "direction": "out", - "objects": [ - "Question", - "QuestionImage", - "QuestionSet", - "QuestionSetImage" - ] - }, - "collection": { - "type": "hasSequenceMember", - "direction": "in", - "objects": [ - "QuestionSet", - "QuestionSetImage" - ] - } - }, - "version": "enable", - "versionCheckMode": "OFF", - "frameworkCategories": [ - "board", - "medium", - "subject", - "gradeLevel", - "topic" - ], - "orgFrameworkTerms": [ - "boardIds", - "gradeLevelIds", - "subjectIds", - "mediumIds", - "topicsIds" - ], - "targetFrameworkTerms": [ - "targetFWIds", - "targetBoardIds", - "targetGradeLevelIds", - "targetSubjectIds", - "targetMediumIds", - "targetTopicIds" - ], - "cacheEnabled": false, - "schema_restrict_api": true, - "restrictProps": { - "create": [ - "children", - "status" - ], - "update": [ - "children", - "visibility", - "code", - "status", - "mimeType" - ], - "updateHierarchy": [ - "variants", - "config", - "reservedDialcodes" - ] - }, - "external": { - "tableName": "questionset_hierarchy", - "properties": { - "hierarchy": { - "type": "string" - }, - "instructions": { - "type": "string" - }, - "outcomeDeclaration": { - "type": "string" - } - }, - "primaryKey": [ - "identifier" - ] - } -} \ No newline at end of file diff --git a/schemas/questionset/1.0/schema.json b/schemas/questionset/1.0/schema.json deleted file mode 100644 index 96da2520d..000000000 --- a/schemas/questionset/1.0/schema.json +++ /dev/null @@ -1,717 +0,0 @@ -{ - "$id": "questionset-schema.json", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "QuestionSet", - "type": "object", - "required": [ - "name", - "code", - "mimeType", - "primaryCategory" - ], - "properties": { - "name": { - "type": "string", - "minLength": 5 - }, - "code": { - "type": "string" - }, - "description": { - "type": "string" - }, - "mimeType": { - "type": "string", - "enum": [ - "application/vnd.sunbird.questionset" - ] - }, - "primaryCategory": { - "type": "string" - }, - "additionalCategories": { - "type": "array", - "items": { - "type": "string" - } - }, - "visibility": { - "type": "string", - "default": "Default", - "enum": [ - "Default", - "Parent", - "Private", - "Protected" - ] - }, - "copyright": { - "type": "string" - }, - "license": { - "type": "string", - "default": "CC BY 4.0" - }, - "lockKey": { - "type": "string" - }, - "assets": { - "type": "array" - }, - "audience": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "Student", - "Teacher", - "Administrator", - "Parent" - ], - "default": "Student" - } - }, - "posterImage": { - "type": "string", - "format": "url" - }, - "author": { - "type": "string" - }, - "owner": { - "type": "string" - }, - "attributions": { - "type": "array" - }, - "consumerId": { - "type": "string" - }, - "contentEncoding": { - "type": "string", - "enum": [ - "gzip", - "identity" - ], - "default": "gzip" - }, - "contentDisposition": { - "type": "string", - "enum": [ - "inline", - "online", - "attachment", - "online-only" - ], - "default": "inline" - }, - "appIcon": { - "type": "string", - "format": "url" - }, - "publishChecklist": { - "type": "array" - }, - "publishComment": { - "type": "string" - }, - "compatibilityLevel": { - "type": "number", - "default": 5 - }, - "childNodes": { - "type": "array" - }, - "depth": { - "type": "number" - }, - "index": { - "type": "number" - }, - "parent": { - "type": "string" - }, - "downloadUrl": { - "type": "string", - "format": "url" - }, - "previewUrl": { - "type": "string", - "format": "url" - }, - "pdfUrl": { - "type": "string", - "format": "url" - }, - "variants": { - "type": "object" - }, - "size": { - "type": "number" - }, - "checksum": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "Draft", - "Review", - "Live", - "Retired" - ], - "default": "Draft" - }, - "prevState": { - "type": "string" - }, - "prevStatus": { - "type": "string" - }, - "lastStatusChangedOn": { - "type": "string" - }, - "keywords": { - "type": "array", - "items": { - "type": "string" - } - }, - "pkgVersion": { - "type": "number" - }, - "version": { - "type": "number", - "default": 1 - }, - "versionKey": { - "type": "string" - }, - "language": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "English", - "Hindi", - "Assamese", - "Bengali", - "Gujarati", - "Kannada", - "Malayalam", - "Marathi", - "Nepali", - "Odia", - "Punjabi", - "Tamil", - "Telugu", - "Urdu", - "Sanskrit", - "Maithili", - "Other" - ] - }, - "default": ["English"] - }, - "languageCode": { - "type": "array" - }, - "channel": { - "type": "string" - }, - "framework": { - "type": "string" - }, - "subject" : { - "type": "array" - }, - "medium" : { - "type": "array" - }, - "board" : { - "type": "string" - }, - "gradeLevel" : { - "type": "array" - }, - "topic" : { - "type": "array" - }, - "boardIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "gradeLevelIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "subjectIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "mediumIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "topicsIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetFWIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetBoardIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetGradeLevelIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetSubjectIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetMediumIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "targetTopicIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_FWIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_boardIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_subjectIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_mediumIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_topicIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_gradeLevelIds": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_boards": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_subjects": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_mediums": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_topics": { - "type": "array", - "items": { - "type": "string" - } - }, - "se_gradeLevels": { - "type": "array", - "items": { - "type": "string" - } - }, - "createdOn": { - "type": "string" - }, - "createdFor": { - "type": "array" - }, - "createdBy": { - "type": "string" - }, - "lastUpdatedOn": { - "type": "string" - }, - "lastUpdatedBy": { - "type": "string" - }, - "lastSubmittedOn": { - "type": "string" - }, - "lastSubmittedBy": { - "type": "string" - }, - "publisher": { - "type": "string" - }, - "lastPublishedOn": { - "type": "string" - }, - "lastPublishedBy": { - "type": "string" - }, - "publishError": { - "type": "string" - }, - "reviewError": { - "type": "string" - }, - "dailySummaryReportEnabled": { - "type": "string", - "enum": [ - "Yes", - "No" - ] - }, - "allowAnonymousAccess": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "Yes" - }, - "termsAndConditions": { - "type": "string" - }, - "expectedDuration": { - "type": "number" - }, - "completionCriteria": { - "type": "object" - }, - "collaborators": { - "type": "array" - }, - "semanticVersion": { - "type": "string" - }, - "schemaVersion": { - "type": "string" - }, - "maxScore": { - "type": "number" - }, - "setType": { - "type": "string", - "enum": [ - "materialised", - "dynamic" - ], - "default": "materialised" - }, - "setCriteria": { - "type": "object" - }, - "feedback": { - "type": "object" - }, - "scoringMode": { - "type": "string", - "enum": [ - "system", - "none" - ] - }, - "qumlVersion": { - "type": "number" - }, - "timeLimits": { - "type": "object" - }, - "showTimer": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "showHints": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "showFeedback": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "showSolutions": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "bloomsLevel" : { - "description": "Cognitive processes involved to answer the question set.", - "type": "string", - "enum": [ - "remember", - "understand", - "apply", - "analyse", - "evaluate", - "create" - ] - }, - "navigationMode": { - "type": "string", - "enum": [ - "linear", - "non-linear" - ], - "default": "non-linear" - }, - "allowSkip": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "Yes" - }, - "outcomeProcessing": { - "type": "object" - }, - "requiresSubmit": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "summaryType": { - "type": "string", - "enum": [ - "Complete", - "Score", - "Duration", - "Score & Duration" - ] - }, - "shuffle": { - "type": "boolean", - "default": true - }, - "totalQuestions": { - "type": "number" - }, - "maxQuestions": { - "type": "number" - }, - "containsUserData": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "maxAttempts": { - "type": "number" - }, - "instructions": { - "type": "object", - "description": "External Property" - }, - "requestChanges": { - "type": "string" - }, - "generateDIALCodes": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "rejectComment": { - "type": "string" - }, - "allowBranching": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "branchingLogic": { - "type": "object", - "description": "Store rules for dependent question" - }, - "entityType": { - "type": "string" - }, - "secondaryLanguage": { - "type": "array" - }, - "allowScoring": { - "type": "string", - "enum": [ - "Yes", - "No" - ] - }, - "allowMultipleInstances": { - "type": "string", - "enum": [ - "Yes", - "No" - ] - }, - "instances": { - "type": "object" - }, - "startDate": { - "type": "string" - }, - "endDate": { - "type": "string" - }, - "ecm": { - "type": "array" - }, - "recordedBy": { - "type": "string", - "enum": [ - "Self", - "External" - ] - }, - "renderingSequence": { - "type": "object" - }, - "accessibility": { - "type": "array", - "items": { - "type": "object" - } - }, - "outcomeDeclaration": { - "type": "object", - "description": "External Property" - }, - "origin": { - "type": "string" - }, - "originData": { - "type": "object" - }, - "trackable": { - "type": "object", - "properties": { - "enabled": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - }, - "autoBatch": { - "type": "string", - "enum": [ - "Yes", - "No" - ], - "default": "No" - } - }, - "default": { - "enabled": "No", - "autoBatch": "No" - }, - "additionalProperties": false - }, - "purpose": { - "type": "string" - }, - "scoreCutoffType": { - "type": "string", - "enum": [ - "AssessmentLevel", - "SectionLevel" - ], - "default": "AssessmentLevel" - }, - "subTitle": { - "type": "string" - }, - "minimumPassPercentage": { - "type": "number" - }, - "additionalKeywords": { - "type": "array", - "items": { - "type": "string" - } - }, - "additionalInstructions": { - "type": "string" - }, - "reviewStatus": { - "type": "string" - } - }, - "additionalProperties": false -}