Skip to content

Commit

Permalink
feat: #109 Added the json config object and the cache for the standar…
Browse files Browse the repository at this point in the history
…d dictionaries.
  • Loading branch information
dmitry-weirdo committed Dec 9, 2024
1 parent 513b155 commit c01275b
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.apache.logging.log4j.Logger;
import ru.klavogonki.statistics.Config;
import ru.klavogonki.statistics.dictionaries.NonStandardDictionaryData;
import ru.klavogonki.statistics.dictionaries.StandardDictionaryData;
import ru.klavogonki.statistics.export.StatisticsGeneratorConfig;

import java.io.File;
Expand Down Expand Up @@ -68,6 +69,21 @@ public static List<NonStandardDictionaryData> parseNonStandardDictionaryData(Inp
}
}

public static List<StandardDictionaryData> parseStandardDictionaryData(InputStream inputStream) {
TypeReference<List<StandardDictionaryData>> typeReference = new TypeReference<>() {
};

try {
ObjectMapper mapper = createObjectMapper();

return mapper.readValue(inputStream, typeReference);
} catch (IOException e) {
String errorMessage = String.format("Error on parsing inputStream \"%s\" to class %s", inputStream, typeReference.getClass().getName());

throw handleError(e, errorMessage);
}
}

public static void serialize(File file, Object object) {
try {
ObjectMapper mapper = createObjectMapper();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import ru.klavogonki.common.UrlConstructor
* Нестандартный словарь.
*
* Конфигурируется на основе JSON-файла, а НЕ захардкоженного энума.
*
* @see [StandardDictionaryData]
*/
@JsonPropertyOrder(
"code",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package ru.klavogonki.statistics.dictionaries

import org.apache.logging.log4j.kotlin.Logging
import ru.klavogonki.common.DictionaryTag
import ru.klavogonki.common.StandardDictionary
import ru.klavogonki.statistics.util.JacksonUtils

object StandardDictionariesCache : Logging {

private const val STANDARD_DICTIONARIES_JSON_RESOURCE = "/dictionaries/standard-dictionaries.json"

private val standardDictionaries = parse()

private val dictionaryByCode: Map<String, StandardDictionaryData> = standardDictionaries
.groupBy { it.klavogonkiName }
.mapValues { it.value.first() } // we're sure the code (klavogonkiName) is unique

private fun parse(): List<StandardDictionaryData> {
val fileName = this.javaClass.getResourceAsStream(STANDARD_DICTIONARIES_JSON_RESOURCE)

val standardDictionaries = JacksonUtils.parseStandardDictionaryData(fileName)

logger.info(
"Total standard dictionaries read from json file \"$STANDARD_DICTIONARIES_JSON_RESOURCE\": " +
"${standardDictionaries.size}."
)

// validate no duplicate ids
validate(standardDictionaries)

return standardDictionaries
}

private fun validate(dictionaries: List<StandardDictionaryData>) {
val repeatCodeToCount: Map<String, Int> = dictionaries
.groupingBy { it.klavogonkiName }
.eachCount()
.filter { it.value > 1 }

if (repeatCodeToCount.isNotEmpty()) {
repeatCodeToCount.forEach {
logger.error("Duplicate dictionary code (klavogonkiName) ${it.key}: used ${it.value} times.")
}
}

check(repeatCodeToCount.isEmpty()) {
"Duplicate dictionary codes: $repeatCodeToCount"
}

logger.info("No dictionary code duplicates.")
}

fun getDictionary(klavogonkiName: String): StandardDictionaryData {
return dictionaryByCode[klavogonkiName]
?: error("No dictionary found by code = $klavogonkiName.")
}

fun getDictionary(dictionary: StandardDictionary): StandardDictionaryData {
return getDictionary(dictionary.klavogonkiName)
}

@JvmStatic
fun main(args: Array<String>) {
val normal = getDictionary(StandardDictionary.normal)
logger.info("Normal dictionary: \n$normal")

val bad = getDictionary("bad_code")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package ru.klavogonki.statistics.dictionaries

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonPropertyOrder
import com.fasterxml.jackson.annotation.JsonSetter
import com.fasterxml.jackson.annotation.Nulls
import ru.klavogonki.common.DictionaryTag
import ru.klavogonki.common.DictionaryUtils
import ru.klavogonki.common.StandardDictionary
import ru.klavogonki.common.UrlConstructor

/**
* Стандартный словарь Клавогонок.
*
* Конфигурируется на основе JSON-файла, а НЕ захардкоженного энума.
*
* @see [NonStandardDictionaryData]
*/
@JsonPropertyOrder(
"klavogonkiName",
"displayName",
"displayNamePrepositional",
"tags",
"top"
)
data class StandardDictionaryData(

/**
* Строковый код словаря. Как используется на клавогонках.
* @see [ru.klavogonki.common.StandardDictionary.klavogonkiName]
*/
@JsonProperty("klavogonkiName")
@JvmField val klavogonkiName: String,

/**
* Русское название словаря для отображения.
*/
@JsonProperty("displayName")
@JvmField val displayName: String,

/**
* Русское название словаря для отображения, в предложном падеже.
*/
@JsonProperty("displayNamePrepositional")
@JvmField val displayNamePrepositional: String,

/**
* Тэги словаря. Может быть пустым множеством.
*/
@JsonProperty("tags")
@JsonSetter(nulls = Nulls.AS_EMPTY) // if null in json -> parse to empty set
@JvmField val tags: Set<DictionaryTag>,

/**
* Метаданные для генерации топа по нестандартному словарю.
*
* Может быть не указано, если топ по словарю не генерируется.
*/
@JsonProperty("top")
@JvmField val top: NonStandardDictionaryTopData?
) {
fun getStandardDictionary() = StandardDictionary.getByKlavogonkiName(klavogonkiName)

// todo: think whether this should be also configured by the json file
fun getLink() = getStandardDictionary().wikiPageUrl
}

0 comments on commit c01275b

Please sign in to comment.