Skip to content
Draft
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
20 changes: 15 additions & 5 deletions api/src/main/kotlin/edu/wgu/osmt/RoutePaths.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ object RoutePaths {
const val SKILL_UPDATE = "$SKILL_DETAIL/update"
const val SKILL_AUDIT_LOG = "$SKILL_DETAIL/log"

//categories
private const val CATEGORY_PATH = "/categories"
const val CATEGORY_LIST = CATEGORY_PATH
const val CATEGORY_DETAIL = "$CATEGORY_PATH/{identifier}"
const val CATEGORY_SKILLS = "$CATEGORY_DETAIL/skills"
const val METADATA_PATH = "/metadata"
const val KEYWORD_PATH = "${METADATA_PATH}/keywords"
const val KEYWORD_LIST = KEYWORD_PATH
const val KEYWORD_CREATE = KEYWORD_PATH
const val KEYWORD_DETAIL = "$KEYWORD_PATH/{id}"
const val KEYWORD_UPDATE = "$KEYWORD_DETAIL/update"
const val KEYWORD_REMOVE = "$KEYWORD_DETAIL/remove"
const val KEYWORD_SKILLS = "${KEYWORD_DETAIL}/skills"

//collections
private const val COLLECTIONS_PATH = "/collections"
Expand Down Expand Up @@ -71,6 +74,13 @@ object RoutePaths {
const val ES_ADMIN_DELETE_INDICES = "$ES_ADMIN/delete-indices"
const val ES_ADMIN_REINDEX = "$ES_ADMIN/reindex"

const val JOB_CODE_PATH = "$METADATA_PATH/jobcodes"
const val JOB_CODE_CREATE = JOB_CODE_PATH
const val JOB_CODE_LIST = JOB_CODE_PATH
const val JOB_CODE_DETAIL = "$JOB_CODE_PATH/{id}"
const val JOB_CODE_UPDATE = "$JOB_CODE_DETAIL/update"
const val JOB_CODE_REMOVE = "$JOB_CODE_DETAIL/remove"

object QueryParams {
const val FROM = "from"
const val SIZE = "size"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ class ApiCollectionV2(
return result
}
}
}
}
38 changes: 33 additions & 5 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/ApiKeyword.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,66 @@ package edu.wgu.osmt.api.model

import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonProperty
import edu.wgu.osmt.config.AppConfig
import edu.wgu.osmt.keyword.Keyword
import edu.wgu.osmt.keyword.KeywordDao
import edu.wgu.osmt.keyword.KeywordTypeEnum
import org.springframework.beans.factory.annotation.Autowired

@JsonInclude(JsonInclude.Include.ALWAYS)
class ApiKeyword(
private val keyword: Keyword,
private val totalSkills: Long?,
private val appConfig: AppConfig
) {
@get:JsonProperty
val type: KeywordTypeEnum
get() = keyword.type

@get:JsonProperty
val id: Long?
get() = keyword.id

@get:JsonProperty
val value: String?
val name: String?
get() = keyword.value

@get:JsonProperty
val framework: String?
get() = keyword.framework

@get:JsonProperty
val type: KeywordTypeEnum
get() = keyword.type

@get:JsonProperty("url")
val url: String?
get() = keyword.uri

@get:JsonProperty
val skillCount: Long?
get() = totalSkills

@get:JsonProperty
val publicUrl: String
get() = "${appConfig.baseUrl}/api/metadata/keywords/${id}"

companion object {
fun fromDao(
keywordDao: KeywordDao,
appConfig: AppConfig
): ApiKeyword {
return ApiKeyword(
keyword = keywordDao.toModel(),
totalSkills = keywordDao.skills.count(),
appConfig = appConfig
)
}

fun fromModel(
keyword: Keyword,
appConfig: AppConfig
): ApiKeyword {
return ApiKeyword(
totalSkills = keyword.id?.let { KeywordDao.findById(it)?.skills?.count() ?: 0 },
keyword = keyword,
appConfig = appConfig
)
}
}
Expand Down
18 changes: 18 additions & 0 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/ApiKeywordUpdate.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package edu.wgu.osmt.api.model

import com.fasterxml.jackson.annotation.JsonProperty
import edu.wgu.osmt.keyword.KeywordTypeEnum
import javax.validation.constraints.NotBlank

data class ApiKeywordUpdate (
@NotBlank
@JsonProperty("name")
val name: String,
@JsonProperty("url")
val uri: String? = null,
@NotBlank
@JsonProperty("type")
val type: KeywordTypeEnum,
@JsonProperty("framework")
val framework: String? = null
)
86 changes: 81 additions & 5 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/ApiNamedReference.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import edu.wgu.osmt.db.JobCodeLevel
import edu.wgu.osmt.jobcode.JobCode
import edu.wgu.osmt.keyword.Keyword


@JsonInclude(JsonInclude.Include.NON_EMPTY)
data class ApiNamedReference(
val id: String? = null,
Expand All @@ -20,7 +19,6 @@ data class ApiNamedReference(
}
}


@JsonInclude(JsonInclude.Include.NON_EMPTY)
data class ApiAlignment(
@get:JsonProperty("id") // these explicit decorators are needed to help jackson
Expand Down Expand Up @@ -73,18 +71,96 @@ data class ApiStringListUpdate(
val remove: List<String>? = null
)

data class JobCodeV2(
val major: String?,
val minor: String?,
val broad: String?,
val detailed: String?,
val code: String?,
val name: String?,
val description: String?,
val framework: String?,
val url: String?,
val majorCode: String?,
val minorCode: String?,
val broadCode: String?,
val detailedCode: String?,
val jobRoleCode: String?
) {

companion object factory {
fun fromJobCode(jobCode: JobCode): JobCodeV2 {
return JobCodeV2(
major = jobCode.major,
minor = jobCode.minor,
broad = jobCode.broad,
detailed = jobCode.detailed,
code = jobCode.code,
name = jobCode.name,
description = jobCode.description,
framework = jobCode.framework,
url = jobCode.url,
majorCode = jobCode.majorCode,
minorCode = jobCode.minorCode,
broadCode = jobCode.broadCode,
detailedCode = jobCode.detailedCode,
jobRoleCode = jobCode.jobRoleCode
)
}
}
}

@JsonInclude(JsonInclude.Include.NON_EMPTY)
data class ApiJobCode(
class ApiJobCode(
var id: Long? = null,
val code: String,
val targetNode: String? = null,
val targetNodeName: String? = null,
val frameworkName: String? = null,
val level: JobCodeLevel? = null,
val parents: List<ApiJobCode>? = null
val parents: List<ApiJobCode>? = null,
var jobCodeLevelAsNumber: Int? = null,
) {
companion object factory {
fun fromJobCode(jobCode: JobCode, level: JobCodeLevel? = null, parents: List<ApiJobCode>? = null): ApiJobCode {
return ApiJobCode(code=jobCode.code, targetNodeName=jobCode.name, targetNode=jobCode.url, frameworkName=jobCode.framework, level=level, parents=parents)
return ApiJobCode(
id = jobCode.id,
code = jobCode.code,
targetNodeName = jobCode.name,
targetNode = jobCode.url,
frameworkName = jobCode.framework,
level = level,
parents = parents,
jobCodeLevelAsNumber = jobCode.jobCodeLevelAsNumber
)
}

fun fromJobCodeV2(jobCode: JobCode, level: JobCodeLevel? = null, parents: List<ApiJobCode>? = null): ApiJobCode {
return ApiJobCode(
code = jobCode.code,
targetNodeName = jobCode.name,
targetNode = jobCode.url,
frameworkName = jobCode.framework,
level = level,
parents = parents
)
}

fun getLevelFromJobCode(jobCode: JobCode): JobCodeLevel {
return when (jobCode.code) {
jobCode.majorCode -> {
JobCodeLevel.Major
}
jobCode.minorCode -> {
JobCodeLevel.Minor
}
jobCode.broadCode -> {
JobCodeLevel.Broad
}
else -> {
JobCodeLevel.Detailed
}
}
}
}
}
3 changes: 1 addition & 2 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/ApiSkill.kt
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ open class ApiSkill(@JsonIgnore open val rsd: RichSkillDescriptor, @JsonIgnore o
get() = rsd.alignments.map { ApiAlignment.fromKeyword(it) }

@get:JsonProperty
val occupations: List<ApiJobCode>
open val occupations: List<ApiJobCode>
get() {
return rsd.jobCodes.filter { it.code.isNotBlank() }.map { jobCode ->
val parents = listOfNotNull(
Expand All @@ -97,7 +97,6 @@ open class ApiSkill(@JsonIgnore open val rsd: RichSkillDescriptor, @JsonIgnore o
jobCode.broad?.let {jobCode.broadCode?.let { ApiJobCode(code=it, targetNodeName=jobCode.broad, level=JobCodeLevel.Broad) }},
jobCode.detailed?.let {jobCode.detailedCode?.let { ApiJobCode(code=it, targetNodeName=jobCode.detailed, level=JobCodeLevel.Detailed) }}
).distinct()

ApiJobCode.fromJobCode(jobCode, parents=parents)
}
}
Expand Down
13 changes: 11 additions & 2 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/ApiSkillSummaryV2.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class ApiSkillSummaryV2(
categories = rsd.categories.mapNotNull { it.value },
category = rsd.categories.mapNotNull { it.value }.sorted().joinToString(SEMICOLON),
keywords = rsd.keywords.mapNotNull { it.value },
occupations = rsd.jobCodes.map { ApiJobCode.fromJobCode(it) }
occupations = rsd.jobCodes.map { ApiJobCode.fromJobCodeV2(it) }
)
}

Expand All @@ -52,7 +52,16 @@ class ApiSkillSummaryV2(
categories = apiSkillSummary.categories,
category = apiSkillSummary.categories.sorted().joinToString(SEMICOLON),
keywords = apiSkillSummary.keywords,
occupations = apiSkillSummary.occupations
occupations = apiSkillSummary.occupations.map {
ApiJobCode(
code = it.code,
targetNode = it.targetNode,
targetNodeName = it.targetNodeName,
frameworkName = it.frameworkName,
level = it.level,
parents = it.parents
)
}
)

}
Expand Down
16 changes: 16 additions & 0 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/ApiSkillV2.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty
import edu.wgu.osmt.collection.Collection
import edu.wgu.osmt.config.AppConfig
import edu.wgu.osmt.config.SEMICOLON
import edu.wgu.osmt.db.JobCodeLevel
import edu.wgu.osmt.richskill.RichSkillDescriptor
import edu.wgu.osmt.richskill.RichSkillDescriptorDao

Expand All @@ -30,6 +31,21 @@ class ApiSkillV2(
val category: String
get() = rsd.categories.mapNotNull { it.value }.sorted().joinToString(SEMICOLON)

@get:JsonProperty
override val occupations: List<ApiJobCode>
get() {
return rsd.jobCodes.filter { it.code.isNotBlank() }.map { jobCode ->
val parents = listOfNotNull(
jobCode.major.let {jobCode.majorCode?.let { ApiJobCode(code=it, targetNodeName=jobCode.major, level= JobCodeLevel.Major) }},
jobCode.minor.let{jobCode.minorCode?.let { ApiJobCode(code=it, targetNodeName=jobCode.minor, level= JobCodeLevel.Minor) }},
jobCode.broad?.let {jobCode.broadCode?.let { ApiJobCode(code=it, targetNodeName=jobCode.broad, level= JobCodeLevel.Broad) }},
jobCode.detailed?.let {jobCode.detailedCode?.let { ApiJobCode(code=it, targetNodeName=jobCode.detailed, level= JobCodeLevel.Detailed) }}
).distinct()

ApiJobCode.fromJobCodeV2(jobCode, parents=parents)
}
}

companion object {
fun fromDao(rsdDao: RichSkillDescriptorDao, appConfig: AppConfig): ApiSkillV2 {
return ApiSkillV2(rsdDao.toModel(), rsdDao.collections.map{ it.toModel() }.filter { !it.isWorkspace() }.toSet(), appConfig)
Expand Down
22 changes: 11 additions & 11 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/ApiSortEnum.kt
Original file line number Diff line number Diff line change
Expand Up @@ -95,27 +95,27 @@ enum class CollectionSortEnum(override val apiValue: String) : SortOrder {
* Provides an enum for Keywords that defines elasticsearch sorting
*/
enum class KeywordSortEnum(override val apiValue: String) : SortOrder {
KeywordAsc("keyword.asc") {
override val sort = Sort.by("value").ascending()
KeywordNameAsc("name.asc") {
override val sort = Sort.by("value.sort_insensitive").ascending()
},
KeywordDesc("keyword.desc") {
override val sort = Sort.by("value").descending()
KeywordNameDesc("name.desc") {
override val sort = Sort.by("value.sort_insensitive").descending()
},
SkillCountAsc("skillCount.asc") {
override val sort = Sort.by("skillCount").ascending()
KeywordFrameworkAsc("framework.asc") {
override val sort = Sort.by("framework.sort_insensitive").ascending()
},
SkillCountDesc("skillCount.desc") {
override val sort = Sort.by("skillCount").descending()
KeywordFrameworkDesc("framework.desc") {
override val sort = Sort.by("framework.sort_insensitive").descending()
};

companion object : SortOrderCompanion<KeywordSortEnum> {
override val logger: Logger = LoggerFactory.getLogger(KeywordSortEnum::class.java)

override val defaultSort = KeywordAsc
override val defaultSort = KeywordNameAsc

override fun forApiValue(apiValue: String): KeywordSortEnum {
return values().find { it.apiValue == apiValue } ?: KeywordAsc.also {
logger.warn("Sort with value ${apiValue} could not be found; using default ${KeywordAsc.apiValue} sort")
return values().find { it.apiValue == apiValue } ?: KeywordNameAsc.also {
logger.warn("Sort with value ${apiValue} could not be found; using default ${KeywordNameAsc.apiValue} sort")
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/JobCodeSortEnum.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package edu.wgu.osmt.api.model

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.data.domain.Sort

enum class JobCodeSortEnum(override val apiValue: String): SortOrder {
NameAsc("name.asc") {
override val sort = Sort.by("name.sort_insensitive").ascending()
},
NameDesc("name.desc") {
override val sort = Sort.by("name.sort_insensitive").descending()
},
CodeAsc("code.asc") {
override val sort = Sort.by("code.keyword").ascending()
},
CodeDesc("code.desc") {
override val sort = Sort.by("code.keyword").descending()
},
JobCodeAsc("jobCodeLevel.asc") {
override val sort = Sort.by("jobCodeLevelAsNumber").ascending()
},
JobCodeDesc("jobCodeLevel.desc") {
override val sort = Sort.by("jobCodeLevelAsNumber").descending()
};

companion object : SortOrderCompanion<JobCodeSortEnum> {
override val logger: Logger = LoggerFactory.getLogger(JobCodeSortEnum::class.java)

override val defaultSort = NameAsc

override fun forApiValue(apiValue: String): JobCodeSortEnum {
return values().find { it.apiValue == apiValue } ?: NameAsc.also {
logger.warn("Sort with value $apiValue could not be found; using default ${NameAsc.apiValue} sort")
}
}
}
}
Loading