Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@ package org.sunbird.actors

import org.apache.commons.lang3.StringUtils
import org.sunbird.actor.core.BaseActor
import org.sunbird.common.Slug
import org.sunbird.common.dto.{Request, Response, ResponseHandler}
import org.sunbird.common.exception.ClientException
import org.sunbird.graph.OntologyEngineContext
import org.sunbird.graph.dac.enums.RelationTypes
import org.sunbird.graph.dac.model.Node
import org.sunbird.graph.nodes.DataNode
import org.sunbird.graph.utils.NodeUtil
import org.sunbird.utils.Constants
import org.sunbird.utils.taxonomy.RequestUtil
import org.sunbird.utils.taxonomy.{RequestUtil, TaxonomyUtil}

import java.util
import scala.jdk.CollectionConverters._
Expand Down Expand Up @@ -50,11 +48,11 @@ class CategoryInstanceActor @Inject()(implicit oec: OntologyEngineContext) exten
DataNode.read(getFrameworkReq).map(node => {
if (null != node && StringUtils.equalsAnyIgnoreCase(node.getIdentifier, frameworkId)) {
validateCategoryObject(request).map(catNode => {
request.getRequest.put(Constants.IDENTIFIER, generateIdentifier(frameworkId, catNode.getIdentifier))
request.getRequest.put(Constants.IDENTIFIER, TaxonomyUtil.generateIdentifier(frameworkId, catNode.getIdentifier))
val frameworkList = new util.ArrayList[Map[String, AnyRef]]
val relationMap = new util.HashMap[String, AnyRef]
relationMap.put("identifier", frameworkId)
relationMap.put("index", getCategoryIndex(node))
relationMap.put("index", TaxonomyUtil.getNextSequenceIndex(node))
frameworkList.add(relationMap)
request.put("frameworks", frameworkList)
DataNode.create(request).map(node => {
Expand All @@ -66,14 +64,6 @@ class CategoryInstanceActor @Inject()(implicit oec: OntologyEngineContext) exten
}).flatMap(f => f)
}

private def getCategoryIndex(node: Node): Integer = {
val indexList = (node.getOutRelations.asScala ++ node.getInRelations.asScala).filter(r => (StringUtils.equals(r.getRelationType,RelationTypes.SEQUENCE_MEMBERSHIP.relationName()) && StringUtils.equals(r.getStartNodeId, node.getIdentifier)))
.map(relation => {
relation.getMetadata.getOrDefault("IL_SEQUENCE_INDEX",1.asInstanceOf[Number]).asInstanceOf[Number].intValue()
})
if (indexList.nonEmpty) indexList.max + 1 else 1
}

private def read(request: Request): Future[Response] = {
validateCategoryInstanceObject(request).map(node => {
val metadata: util.Map[String, AnyRef] = NodeUtil.serialize(node, null, request.getContext.get("schemaName").asInstanceOf[String], request.getContext.get("version").asInstanceOf[String])
Expand All @@ -85,15 +75,15 @@ class CategoryInstanceActor @Inject()(implicit oec: OntologyEngineContext) exten
val categoryId = request.getContext.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String];
RequestUtil.restrictProperties(request)
validateCategoryInstanceObject(request)
request.getContext.put(Constants.IDENTIFIER, generateIdentifier(request.getRequest.getOrDefault(Constants.FRAMEWORK, "").asInstanceOf[String], categoryId))
request.getContext.put(Constants.IDENTIFIER, TaxonomyUtil.generateIdentifier(request.getRequest.getOrDefault(Constants.FRAMEWORK, "").asInstanceOf[String], categoryId))
DataNode.update(request).map(node => {
ResponseHandler.OK.put(Constants.IDENTIFIER, node.getIdentifier).put(Constants.VERSION_KEY, node.getMetadata.get("versionKey"))
})
}

private def retire(request: Request): Future[Response] = {
validateCategoryInstanceObject(request)
request.getContext.put(Constants.IDENTIFIER, generateIdentifier(request.getRequest.getOrDefault(Constants.FRAMEWORK, "").asInstanceOf[String], request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String]))
request.getContext.put(Constants.IDENTIFIER, TaxonomyUtil.generateIdentifier(request.getRequest.getOrDefault(Constants.FRAMEWORK, "").asInstanceOf[String], request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String]))
request.getRequest.put("status", "Retired")
DataNode.update(request).map(node => {
ResponseHandler.OK.put(Constants.IDENTIFIER, node.getIdentifier).put(Constants.VERSION_KEY, node.getMetadata.get("versionKey"))
Expand All @@ -105,7 +95,7 @@ class CategoryInstanceActor @Inject()(implicit oec: OntologyEngineContext) exten
val categoryId = request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String]
if (frameworkId.isEmpty()) throw new ClientException("ERR_INVALID_FRAMEWORK_ID", s"Invalid FrameworkId: '${frameworkId}' for CategoryInstance ")
if (categoryId.isEmpty()) throw new ClientException("ERR_INVALID_CATEGORY_ID", s"Invalid CategoryId: '${categoryId}' for categoryInstance")
val categoryInstanceId = generateIdentifier(frameworkId, categoryId)
val categoryInstanceId = TaxonomyUtil.generateIdentifier(frameworkId, categoryId)
val getCategoryReq = new Request()
getCategoryReq.setContext(new util.HashMap[String, AnyRef]() {
{
Expand Down Expand Up @@ -140,10 +130,4 @@ class CategoryInstanceActor @Inject()(implicit oec: OntologyEngineContext) exten
})(ec)
}

private def generateIdentifier(scopeId: String, code: String): String = {
var id: String = null
if (StringUtils.isNotBlank(scopeId)) id = Slug.makeSlug(scopeId + "_" + code)
id
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ package org.sunbird.actors

import org.apache.commons.lang3.StringUtils
import org.sunbird.actor.core.BaseActor
import org.sunbird.common.{Platform, Slug}
import org.sunbird.common.Platform
import org.sunbird.common.dto.{Request, Response, ResponseHandler}
import org.sunbird.common.exception.{ClientException, ResponseCode }
import org.sunbird.graph.OntologyEngineContext
import org.sunbird.graph.dac.enums.RelationTypes
import org.sunbird.graph.dac.model.Node
import org.sunbird.graph.nodes.DataNode
import org.sunbird.graph.utils.NodeUtil
import org.sunbird.utils.Constants
import org.sunbird.utils.taxonomy.RequestUtil
import org.sunbird.utils.taxonomy.{RequestUtil, TaxonomyUtil}
import java.util
import javax.inject.Inject
import scala.concurrent.{ExecutionContext, Future}
Expand Down Expand Up @@ -39,13 +38,13 @@ class TermActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor
RequestUtil.restrictProperties(request)
val frameworkId = request.getRequest.getOrDefault(Constants.FRAMEWORK, "").asInstanceOf[String]
val categoryData = validateCategoryInstance(request)
val categoryId = generateIdentifier(frameworkId, request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String])
val categoryId = TaxonomyUtil.generateIdentifier(frameworkId, request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String])
categoryData.flatMap(node => {
if (null != node && StringUtils.equalsAnyIgnoreCase(node.getIdentifier, categoryId)) {
val identifier = new util.ArrayList[String]
var codeError = 0
var serverError = 0
val index: Integer = getIndex(node)
val index: Integer = TaxonomyUtil.getNextSequenceIndex(node)
var i: Integer = 0
val future = requestList.asScala.map(req => {
val categoryList = new util.ArrayList[util.Map[String, AnyRef]]
Expand All @@ -55,7 +54,7 @@ class TermActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor
i = (i + 1)
categoryList.add(relationMap)
request.put("categories", categoryList)
request.getRequest.put(Constants.IDENTIFIER, generateIdentifier(categoryId, req.getOrDefault(Constants.CODE, "").asInstanceOf[String]))
request.getRequest.put(Constants.IDENTIFIER, TaxonomyUtil.generateIdentifier(categoryId, req.getOrDefault(Constants.CODE, "").asInstanceOf[String]))
request.getRequest.putAll(req)
DataNode.create(request).map(termNode =>
identifier.add(termNode.getIdentifier)
Expand Down Expand Up @@ -98,14 +97,6 @@ class TermActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor
}
}

private def getIndex(node: Node): Integer = {
val indexList = (node.getOutRelations.asScala ++ node.getInRelations.asScala).filter(r => (StringUtils.equals(r.getRelationType, RelationTypes.SEQUENCE_MEMBERSHIP.relationName()) && StringUtils.equals(r.getStartNodeId, node.getIdentifier)))
.map(relation => {
relation.getMetadata.getOrDefault("IL_SEQUENCE_INDEX", 1.asInstanceOf[Number]).asInstanceOf[Number].intValue()
})
if (indexList.nonEmpty) indexList.max + 1 else 1
}

private def read(request: Request): Future[Response] = {
validateCategoryInstance(request)
validateTerm(request).map(node => {
Expand All @@ -118,9 +109,9 @@ class TermActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor
val termId = request.getContext.getOrDefault(Constants.TERM, "").asInstanceOf[String];
val frameworkId = request.getRequest.getOrDefault(Constants.FRAMEWORK, "").asInstanceOf[String]
RequestUtil.restrictProperties(request)
val categoryId = generateIdentifier(frameworkId, request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String])
val categoryId = TaxonomyUtil.generateIdentifier(frameworkId, request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String])
validateCategoryInstance(request)
request.getContext.put(Constants.IDENTIFIER, generateIdentifier(categoryId, termId))
request.getContext.put(Constants.IDENTIFIER, TaxonomyUtil.generateIdentifier(categoryId, termId))
DataNode.update(request).map(node => {
ResponseHandler.OK.put(Constants.IDENTIFIER, node.getIdentifier).put(Constants.VERSION_KEY, node.getMetadata.get("versionKey"))
})
Expand All @@ -129,9 +120,9 @@ class TermActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor
private def retire(request: Request): Future[Response] = {
val termId = request.getContext.getOrDefault(Constants.TERM, "").asInstanceOf[String];
val frameworkId = request.getRequest.getOrDefault(Constants.FRAMEWORK, "").asInstanceOf[String]
val categoryId = generateIdentifier(frameworkId, request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String])
val categoryId = TaxonomyUtil.generateIdentifier(frameworkId, request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String])
validateCategoryInstance(request)
request.getContext.put(Constants.IDENTIFIER, generateIdentifier(categoryId, termId))
request.getContext.put(Constants.IDENTIFIER, TaxonomyUtil.generateIdentifier(categoryId, termId))
request.getRequest.put("status", "Retired")
DataNode.update(request).map(node => {
ResponseHandler.OK.put(Constants.IDENTIFIER, node.getIdentifier).put(Constants.VERSION_KEY, node.getMetadata.get("versionKey"))
Expand All @@ -141,7 +132,7 @@ class TermActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor
private def validateTerm(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext) = {
val termId = request.getRequest.getOrDefault(Constants.TERM, "").asInstanceOf[String]
if (termId.isEmpty()) throw new ClientException("ERR_INVALID_TERM_ID", s"Invalid TermId: '${termId}' for Term")
val categoryInstanceId = generateIdentifier(request.getRequest.getOrDefault(Constants.FRAMEWORK, "").asInstanceOf[String], request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String])
val categoryInstanceId = TaxonomyUtil.generateIdentifier(request.getRequest.getOrDefault(Constants.FRAMEWORK, "").asInstanceOf[String], request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String])
val getTermReq = new Request()
getTermReq.setContext(new util.HashMap[String, AnyRef]() {
{
Expand All @@ -150,9 +141,9 @@ class TermActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor
})
getTermReq.getContext.put(Constants.SCHEMA_NAME, Constants.TERM_SCHEMA_NAME)
getTermReq.getContext.put(Constants.VERSION, Constants.TERM_SCHEMA_VERSION)
getTermReq.put(Constants.IDENTIFIER, generateIdentifier(categoryInstanceId, termId))
getTermReq.put(Constants.IDENTIFIER, TaxonomyUtil.generateIdentifier(categoryInstanceId, termId))
DataNode.read(getTermReq)(oec, ec).map(node => {
if (null != node && StringUtils.equalsAnyIgnoreCase(node.getIdentifier, generateIdentifier(categoryInstanceId, termId))) node
if (null != node && StringUtils.equalsAnyIgnoreCase(node.getIdentifier, TaxonomyUtil.generateIdentifier(categoryInstanceId, termId))) node
else throw new ClientException("ERR_CHANNEL_NOT_FOUND/ ERR_FRAMEWORK_NOT_FOUND", s"Given channel/framework is not related to given category")
})(ec)
}
Expand All @@ -162,7 +153,7 @@ class TermActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor
val categoryId = request.getRequest.getOrDefault(Constants.CATEGORY, "").asInstanceOf[String]
if (frameworkId.isEmpty()) throw new ClientException("ERR_INVALID_FRAMEWORK_ID", s"Invalid FrameworkId: '${frameworkId}' for Term ")
if (categoryId.isEmpty()) throw new ClientException("ERR_INVALID_CATEGORY_ID", s"Invalid CategoryId: '${categoryId}' for Term")
val categoryInstanceId = generateIdentifier(frameworkId, categoryId)
val categoryInstanceId = TaxonomyUtil.generateIdentifier(frameworkId, categoryId)
val getCategoryInstanceReq = new Request()
getCategoryInstanceReq.setContext(new util.HashMap[String, AnyRef]() {
{
Expand Down Expand Up @@ -191,10 +182,4 @@ class TermActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor
}
}

private def generateIdentifier(scopeId: String, code: String): String = {
var id: String = null
if (StringUtils.isNotBlank(scopeId)) id = Slug.makeSlug(scopeId + "_" + code)
id
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.sunbird.utils.taxonomy

import org.apache.commons.lang3.StringUtils
import org.sunbird.common.Slug
import org.sunbird.graph.dac.enums.RelationTypes
import org.sunbird.graph.dac.model.Node

import scala.jdk.CollectionConverters._

/**
* Shared utility methods used across taxonomy actors (TermActor, CategoryInstanceActor, etc.)
* that were previously duplicated in each actor class.
*/
object TaxonomyUtil {

/**
* Generates a slugified composite identifier from a scope (e.g. frameworkId or categoryId)
* and a code. Returns null when scopeId is blank to preserve backward compatibility.
*/
def generateIdentifier(scopeId: String, code: String): String =
if (StringUtils.isNotBlank(scopeId)) Slug.makeSlug(scopeId + "_" + code) else null

/**
* Calculates the next available sequence index from a node's SEQUENCE_MEMBERSHIP
* out-relations. Returns 1 if the node has no existing sequence members,
* otherwise returns max(existing index) + 1.
*/
def getNextSequenceIndex(node: Node): Integer = {
val indexList = (node.getOutRelations.asScala ++ node.getInRelations.asScala)
.filter(r =>
StringUtils.equals(r.getRelationType, RelationTypes.SEQUENCE_MEMBERSHIP.relationName()) &&
StringUtils.equals(r.getStartNodeId, node.getIdentifier))
.map(r => r.getMetadata
.getOrDefault("IL_SEQUENCE_INDEX", 1.asInstanceOf[Number])
.asInstanceOf[Number].intValue())
if (indexList.nonEmpty) indexList.max + 1 else 1
}
}