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
4 changes: 2 additions & 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 @@ -62,8 +62,8 @@ class ApiSkill(private val rsd: RichSkillDescriptor, private val cs: Set<Collect
get() = rsd.searchingKeywords.mapNotNull { it.value }

@get:JsonProperty
val category: String?
get() = rsd.category?.value
val categories: List<String>
get() = rsd.categories.mapNotNull { it.value }

@get:JsonProperty
val id: String
Expand Down
6 changes: 3 additions & 3 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/ApiSkillSummary.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ApiSkillSummary(
@JsonProperty val archiveDate: LocalDateTime? = null,
@JsonProperty val skillName: String,
@JsonProperty val skillStatement: String,
@JsonProperty val category: String? = null,
@JsonProperty val categories: List<String> = listOf(),
@JsonProperty val keywords: List<String> = listOf(),
@JsonProperty val occupations: List<ApiJobCode> = listOf()
) {
Expand All @@ -31,7 +31,7 @@ class ApiSkillSummary(
archiveDate = rsd.archiveDate,
skillName = rsd.name,
skillStatement = rsd.statement,
category = rsd.category?.value,
categories = rsd.categories.mapNotNull { it.value },
keywords = rsd.keywords.mapNotNull { it.value },
occupations = rsd.jobCodes.map { ApiJobCode.fromJobCode(it) }
)
Expand All @@ -51,7 +51,7 @@ class ApiSkillSummary(
archiveDate,
name,
statement,
category,
categories,
searchingKeywords,
jobCodes.map { ApiJobCode.fromJobCode(it) })
}
Expand Down
6 changes: 3 additions & 3 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/ApiSkillUpdate.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ data class ApiSkillUpdate(
@JsonProperty("status")
val publishStatus: PublishStatus? = null,

@JsonProperty("category")
val category: String? = null,

@JsonProperty("collections")
val collections: ApiStringListUpdate? = null,

@JsonProperty("authors")
val authors: ApiStringListUpdate? = null,

@JsonProperty("categories")
val categories: ApiStringListUpdate? = null,

@JsonProperty("keywords")
val keywords: ApiStringListUpdate? = null,

Expand Down
15 changes: 1 addition & 14 deletions api/src/main/kotlin/edu/wgu/osmt/api/model/ApiSortEnum.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package edu.wgu.osmt.api.model

import edu.wgu.osmt.config.CATEGORY_ASC
import edu.wgu.osmt.config.CATEGORY_DESC
import edu.wgu.osmt.config.CATEGORY_SORT_INSENSITIVE
import edu.wgu.osmt.config.NAME_ASC
import edu.wgu.osmt.config.NAME_DESC
import edu.wgu.osmt.config.NAME_SORT_INSENSITIVE
Expand Down Expand Up @@ -44,16 +41,6 @@ interface SortOrderCompanion<T> where T: SortOrder{
* Provides an enum for Rich skills that defines elasticsearch sorting
*/
enum class SkillSortEnum(override val apiValue: String) : SortOrder {
CategoryAsc(CATEGORY_ASC) {
override val sort = Sort.by(
Sort.Order.asc(CATEGORY_SORT_INSENSITIVE),
Sort.Order.asc(NAME_SORT_INSENSITIVE))
},
CategoryDesc(CATEGORY_DESC) {
override val sort = Sort.by(
Sort.Order.desc(CATEGORY_SORT_INSENSITIVE),
Sort.Order.asc(NAME_SORT_INSENSITIVE))
},
NameAsc(NAME_ASC) {
override val sort = Sort.by(NAME_SORT_INSENSITIVE).ascending()
},
Expand All @@ -64,7 +51,7 @@ enum class SkillSortEnum(override val apiValue: String) : SortOrder {
companion object : SortOrderCompanion<SkillSortEnum> {
override val logger: Logger = LoggerFactory.getLogger(SkillSortEnum::class.java)

override val defaultSort = CategoryAsc
override val defaultSort = NameAsc

override fun forApiValue(apiValue: String): SkillSortEnum {
return values().find { it.apiValue == apiValue } ?: NameAsc.also {
Expand Down
5 changes: 0 additions & 5 deletions api/src/main/kotlin/edu/wgu/osmt/config/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ const val QUOTED_SEARCH_REGEX_PATTERN = "([\"\'])(?:(?=(\\\\?))\\2.)*?\\1"
const val DEFAULT_WORKSPACE_NAME = "My Workspace"

// API parameter constants
const val CATEGORY_ASC = "name.asc"
const val CATEGORY_DESC = "name.desc"
const val NAME_ASC = "skill.asc"
const val NAME_DESC = "skill.desc"


// ElasticSearch Index Names
const val INDEX_RICHSKILL_DOC = "richskill_v1"
const val INDEX_COLLECTION_DOC = "collection_v1"
Expand All @@ -20,5 +17,3 @@ const val INDEX_KEYWORD_DOC = "keyword"
// ElasticSearch Sort Criteria
const val SORT_INSENSITIVE = ".sort_insensitive"
const val NAME_SORT_INSENSITIVE = "name${SORT_INSENSITIVE}"
const val CATEGORY_SORT_INSENSITIVE = "category${SORT_INSENSITIVE}"

14 changes: 6 additions & 8 deletions api/src/main/kotlin/edu/wgu/osmt/csv/BatchImportRichSkill.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class RichSkillRow: CsvRow {
@CsvBindByName(column = "Skill Name")
var skillName: String? = null

@CsvBindByName(column = "Skill Category")
var skillCategory: String? = null
@CsvBindByName(column = "Skill Categories")
var skillCategories: String? = null

@CsvBindByName(column = "Contextualized Skill Statement")
var skillStatement: String? = null
Expand Down Expand Up @@ -134,8 +134,8 @@ class BatchImportRichSkill: CsvImport<RichSkillRow> {
log.info("Processing ${rows.size} rows...")

for (row in rows) transaction {
var category: KeywordDao? = null
var authors: List<KeywordDao>? = null
var categories: List<KeywordDao>? = null
var keywords: List<KeywordDao>? = null
var standards: List<KeywordDao>? = null
var certifications: List<KeywordDao>? = null
Expand All @@ -148,8 +148,7 @@ class BatchImportRichSkill: CsvImport<RichSkillRow> {
var occupations: List<JobCodeDao>? = null
var collections: List<CollectionDao>? = null

category = row.skillCategory?.let { keywordRepository.findOrCreate(KeywordTypeEnum.Category, value = it) }

categories = parseKeywords(KeywordTypeEnum.Category, row.skillCategories)
keywords = parseKeywords(KeywordTypeEnum.Keyword, row.keywords)
standards = parseKeywords(KeywordTypeEnum.Standard, row.standards)
certifications = parseKeywords(KeywordTypeEnum.Certification, row.certifications)
Expand All @@ -171,16 +170,15 @@ class BatchImportRichSkill: CsvImport<RichSkillRow> {
alignments = listOf( keywordRepository.findOrCreate(KeywordTypeEnum.Alignment, value = row.alignmentTitle, uri = row.alignmentUri) ).filterNotNull()
}

val allKeyWords = concatenate(keywords, authors, standards, certifications, employers, alignments)
val allKeyWords = concatenate(keywords, authors, categories, standards, certifications, employers, alignments)
val allJobcodes = concatenate(blsMajor,blsMinor,blsBroad,blsDetailed,occupations)

if (row.skillName != null && row.skillStatement != null) {
richSkillRepository.create(RsdUpdateObject(
name = row.skillName!!,
statement = row.skillStatement!!,
category = NullableFieldUpdate(category),
keywords = allKeyWords?.let { ListFieldUpdate(add = it) },
collections = collections?.let {ListFieldUpdate(add = it)},
collections = collections?.let { ListFieldUpdate(add = it) },
jobCodes = allJobcodes?.let { ListFieldUpdate(add = it) },
), user)
log.info("created skill '${row.skillName!!}'")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class RichSkillCsvExport(
CsvColumn("RSD Name") { it.rs.name },
CsvColumn("Authors") { it.rs.authors.map { author -> author.value ?: "" }.joinToString(listDelimiter) },
CsvColumn("Skill Statement") { it.rs.statement },
CsvColumn("Category") { it.rs.category?.value ?: "" },
CsvColumn("Categories") { it.rs.categories.map{ category -> category.value ?: "" }.joinToString(listDelimiter) },
CsvColumn("Keywords") { it.rs.searchingKeywords.map { keyword -> keyword.value ?: "" }.joinToString(listDelimiter) },
CsvColumn("Standards") { it.rs.standards.map { keyword -> keyword.value ?: "" }.joinToString(listDelimiter) },
CsvColumn("Certifications") { it.rs.certifications.map { keyword -> keyword.value ?: "" }.joinToString(listDelimiter) },
Expand Down
28 changes: 6 additions & 22 deletions api/src/main/kotlin/edu/wgu/osmt/richskill/RichSkillDescriptor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ data class RichSkillDescriptor(
val statement: String,
val jobCodes: List<JobCode> = listOf(),
val keywords: List<Keyword> = listOf(),
val category: Keyword? = null,
override val archiveDate: LocalDateTime? = null,
override val publishDate: LocalDateTime? = null,
val collections: List<Collection> = listOf()
Expand All @@ -38,6 +37,9 @@ data class RichSkillDescriptor(
val authors: List<Keyword>
get() = this.keywords.filter { it.type == KeywordTypeEnum.Author }

val categories: List<Keyword>
get() = this.keywords.filter { it.type == KeywordTypeEnum.Category }

val certifications: List<Keyword>
get() = this.keywords.filter { it.type == KeywordTypeEnum.Certification }

Expand Down Expand Up @@ -78,7 +80,7 @@ fun RichSkillDescriptor.diff(old: RichSkillDescriptor?): List<Change> {
val comparisons: List<Comparison<*>> = listOf(
Comparison(RichSkillDescriptor::name.name, RichSkillDescriptorComparisons::compareName, old, new),
Comparison(RichSkillDescriptor::statement.name, RichSkillDescriptorComparisons::compareStatement, old, new),
Comparison(RichSkillDescriptor::category.name, RichSkillDescriptorComparisons::compareCategory, old, new),
Comparison(RichSkillDescriptor::categories.name, RichSkillDescriptorComparisons::compareCategories, old, new),
Comparison(RichSkillDescriptor::authors.name, RichSkillDescriptorComparisons::compareAuthors, old, new),
Comparison(
RichSkillDescriptor::publishStatus.name,
Expand Down Expand Up @@ -112,36 +114,18 @@ data class RsdUpdateObject(
override val id: Long? = null,
val name: String? = null,
val statement: String? = null,
val category: NullableFieldUpdate<KeywordDao>? = null,
val keywords: ListFieldUpdate<KeywordDao>? = null,
val jobCodes: ListFieldUpdate<JobCodeDao>? = null,
val collections: ListFieldUpdate<CollectionDao>? = null,
override val publishStatus: PublishStatus? = null
) : UpdateObject<RichSkillDescriptorDao>, HasPublishStatus<RichSkillDescriptorDao> {

init {
validate(this) {
validate(RsdUpdateObject::category).validate {
validate(NullableFieldUpdate<KeywordDao>::t).validate {
validate(KeywordDao::type).isEqualTo(KeywordTypeEnum.Category)
}
}
}
}

override fun applyToDao(dao: RichSkillDescriptorDao): Unit {
dao.updateDate = LocalDateTime.now(ZoneOffset.UTC)

applyPublishStatus(dao)
name?.let { dao.name = it }
statement?.let { dao.statement = it }
category?.let {
if (it.t != null) {
dao.category = it.t
} else {
dao.category = null
}
}
applyKeywords()
applyJobCodes()
applyCollections()
Expand Down Expand Up @@ -204,8 +188,8 @@ object RichSkillDescriptorComparisons {
return r.statement
}

fun compareCategory(r: RichSkillDescriptor): String? {
return r.category?.value
fun compareCategories(receiver: RichSkillDescriptor): String? {
return keywordsCompare(receiver, RichSkillDescriptor::categories)
}

fun compareAuthors(receiver: RichSkillDescriptor): String? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ class RichSkillDescriptorDao(id: EntityID<Long>) : LongEntity(id), OutputsModel<

var keywords by KeywordDao via RichSkillKeywords

var category by KeywordDao optionalReferencedOn RichSkillDescriptorTable.category

var collections by CollectionDao via CollectionSkills

override fun toModel(): RichSkillDescriptor {
Expand All @@ -43,7 +41,6 @@ class RichSkillDescriptorDao(id: EntityID<Long>) : LongEntity(id), OutputsModel<
statement = statement,
jobCodes = jobCodes.map { it.toModel() }.sortedBy { it.code },
keywords = keywords.map { it.toModel() }.sortedBy { it.id!! },
category = category?.toModel(),
archiveDate = archiveDate,
publishDate = publishDate,
collections = collections.map { it.toModel() }.toList().sortedBy { it.name }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ object RichSkillDescriptorTable : LongIdTable("RichSkillDescriptor"), TableWithU
val uuid = varchar("uuid", 36).uniqueIndex()
val name = text("name")
val statement = text("statement")
val category = reference(
"cat_id",
KeywordTable,
onDelete = ReferenceOption.RESTRICT,
onUpdate = ReferenceOption.CASCADE
).nullable()
}

// many-to-many table for RichSkillDescriptor and JobCode relationship
Expand Down
10 changes: 4 additions & 6 deletions api/src/main/kotlin/edu/wgu/osmt/richskill/RichSkillDoc.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,16 @@ data class RichSkillDoc(
@get:JsonProperty("skillStatement")
val statement: String,

@Nullable
@MultiField(
mainField = Field(type = Text, analyzer = "english_stemmer"),
otherFields = [
InnerField(suffix = "", type = Search_As_You_Type),
InnerField(suffix = "raw", analyzer = "whitespace_exact", type = Text),
InnerField(suffix = "keyword", type = Keyword),
InnerField(suffix = "sort_insensitive", type = Keyword, normalizer = "lowercase_normalizer")
InnerField(suffix = "keyword", type = Keyword)
]
)
@get:JsonProperty
val category: String? = null,
@get:JsonProperty("categories")
val categories: List<String> = listOf(),

@MultiField(
mainField = Field(type = Text, analyzer = "english_stemmer"),
Expand Down Expand Up @@ -170,7 +168,7 @@ data class RichSkillDoc(
uri = "${appConfig.baseUrl}/api/skills/${dao.uuid}",
name = dao.name,
statement = dao.statement,
category = dao.category?.value,
categories = dao.keywords.filter { it.type == KeywordTypeEnum.Category }.mapNotNull { it.value },
authors = dao.keywords.filter { it.type == KeywordTypeEnum.Author }.mapNotNull { it.value },
publishStatus = dao.publishStatus(),
searchingKeywords = dao.keywords.filter { it.type == KeywordTypeEnum.Keyword }.mapNotNull { it.value },
Expand Down
10 changes: 5 additions & 5 deletions api/src/main/kotlin/edu/wgu/osmt/richskill/RichSkillEsRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ class CustomRichSkillQueriesImpl @Autowired constructor(override val elasticSear
}
category.nullIfEmpty()?.let {
if (it.matches(Regex(QUOTED_SEARCH_REGEX_PATTERN))) {
bq.must(simpleQueryStringQuery(it).field("${RichSkillDoc::category.name}.keyword").defaultOperator(Operator.AND))
bq.must(simpleQueryStringQuery(it).field("${RichSkillDoc::categories.name}.raw").defaultOperator(Operator.AND))
} else {
bq.must(matchBoolPrefixQuery(RichSkillDoc::category.name, it))
bq.must(matchBoolPrefixQuery(RichSkillDoc::categories.name, it))
}
}
author.nullIfEmpty()?.let {
Expand Down Expand Up @@ -203,7 +203,7 @@ class CustomRichSkillQueriesImpl @Autowired constructor(override val elasticSear
)
with(filteredQuery) {
categories?. let {
bq.must(buildNestedQueries(RichSkillDoc::category.name, it))
bq.must(buildNestedQueries(RichSkillDoc::categories.name, it))
}
keywords?. let {
it.mapNotNull {
Expand Down Expand Up @@ -256,7 +256,7 @@ class CustomRichSkillQueriesImpl @Autowired constructor(override val elasticSear
simpleQueryStringQuery(query).field("${RichSkillDoc::name.name}.raw").boost(2.0f)
.defaultOperator(Operator.AND),
simpleQueryStringQuery(query).field("${RichSkillDoc::statement.name}.raw").defaultOperator(Operator.AND),
simpleQueryStringQuery(query).field("${RichSkillDoc::category.name}.raw").defaultOperator(Operator.AND),
simpleQueryStringQuery(query).field("${RichSkillDoc::categories.name}.raw").defaultOperator(Operator.AND),
simpleQueryStringQuery(query).field("${RichSkillDoc::searchingKeywords.name}.raw")
.defaultOperator(Operator.AND),
simpleQueryStringQuery(query).field("${RichSkillDoc::standards.name}.raw").defaultOperator(Operator.AND),
Expand All @@ -270,7 +270,7 @@ class CustomRichSkillQueriesImpl @Autowired constructor(override val elasticSear
val queries = listOf(
matchPhrasePrefixQuery(RichSkillDoc::name.name, query).boost(2.0f),
matchPhrasePrefixQuery(RichSkillDoc::statement.name, query),
matchPhrasePrefixQuery(RichSkillDoc::category.name, query),
matchPhrasePrefixQuery(RichSkillDoc::categories.name, query),
matchPhrasePrefixQuery(RichSkillDoc::searchingKeywords.name, query),
matchPhrasePrefixQuery(RichSkillDoc::standards.name, query),
matchPhrasePrefixQuery(RichSkillDoc::certifications.name, query),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ class RichSkillRepositoryImpl @Autowired constructor(
this.updateDate = LocalDateTime.now(ZoneOffset.UTC)
this.creationDate = LocalDateTime.now(ZoneOffset.UTC)
this.uuid = UUID.randomUUID().toString()
this.category = updateObject.category?.t
}

updateObject.copy(id = newRsd.id.value).applyToDao(newRsd)
Expand Down Expand Up @@ -202,14 +201,8 @@ class RichSkillRepositoryImpl @Autowired constructor(
}

override fun rsdUpdateFromApi(skillUpdate: ApiSkillUpdate, user: String, email: String): RsdUpdateObject {
val categoryKeyword = skillUpdate.category?.let {
keywordRepository.findOrCreate(KeywordTypeEnum.Category, value = it)
}

val addingCollections = mutableListOf<CollectionDao>()
val removingCollections = mutableListOf<CollectionDao>()
val addingAuthors = mutableListOf<KeywordDao>()
val removingAuthors = mutableListOf<KeywordDao>()
val addingKeywords = mutableListOf<KeywordDao>()
val removingKeywords = mutableListOf<KeywordDao>()
val jobsToAdd = mutableListOf<JobCodeDao>()
Expand Down Expand Up @@ -282,6 +275,7 @@ class RichSkillRepositoryImpl @Autowired constructor(
}

skillUpdate.authors?.let { lookupKeywords(it, KeywordTypeEnum.Author) }
skillUpdate.categories?.let { lookupKeywords(it, KeywordTypeEnum.Category) }
skillUpdate.keywords?.let { lookupKeywords(it, KeywordTypeEnum.Keyword) }
skillUpdate.certifications?.let { lookupReferences(it, KeywordTypeEnum.Certification) }
skillUpdate.standards?.let { lookupAlignments(it, KeywordTypeEnum.Standard) }
Expand Down Expand Up @@ -311,9 +305,6 @@ class RichSkillRepositoryImpl @Autowired constructor(
name = skillUpdate.skillName,
statement = skillUpdate.skillStatement,
publishStatus = skillUpdate.publishStatus,
category = if (skillUpdate.category != null || skillUpdate.category?.isBlank() == true) NullableFieldUpdate(
categoryKeyword
) else null,
keywords = allKeywordsUpdate,
jobCodes = jobCodesUpdate,
collections = if (addingCollections.size + removingCollections.size > 0) ListFieldUpdate(
Expand Down
Loading