package apigen.depencency_resolver @Suppress("UNCHECKED_CAST") class FileParser { companion object { const val NAME_JSON_KEY = "name" const val PARENT_JSON_KEY = "parent" const val TYPE_JSON_KEY = "type" } private val defaultTypes = hashSetOf( "Bool", "String", "DateTime", "Long", "Int", "Double", "Decimal", "Date", "DateTimeTimestamp", "Color", "StringDecimal", "Url", "Map", "null" // Костыль, чтобы не писать проверки на null при получении типа из мапы ) fun getAllTypeNamesFromJson(model: Map): Set { val currentModelType = Type.getType(model[NAME_JSON_KEY].toString()) var generic = "" if (currentModelType is TypeWithGeneric) { generic = currentModelType.getGenericTypeName() } val parentRawTypeName = model[PARENT_JSON_KEY].toString() return model.entries .fold(setOf(parentRawTypeName)) { foundRawTypeNames: Set, jsonEntry: Map.Entry -> foldDependencies(foundRawTypeNames, jsonEntry) } .minus(defaultTypes) .minus(generic) .fold(setOf()) { foundTypeNames, rawTypeName -> foundTypeNames + getTypeFromRawTypeNames(rawTypeName) } } private fun foldDependencies(foundTypes: Set, jsonEntry: Map.Entry): Set { val value = jsonEntry.value val newTypes: Set = when { (value as? Collection>) != null -> { getTypeFromCollection(value) } (value as? Map) != null && jsonEntry.key == TYPE_JSON_KEY -> { val typeName = value[NAME_JSON_KEY].toString() val parentTypeName = value[PARENT_JSON_KEY].toString() setOf(typeName, parentTypeName) } else -> setOf() } return if (newTypes.isEmpty()) { foundTypes } else { foundTypes + newTypes } } private fun getTypeFromCollection(value: Collection>): Set = value.fold(setOf()) { types: Set, collectionEntry: Map -> types + getAllTypeNamesFromJson(collectionEntry) } private fun getTypeFromRawTypeNames(typeName: String): Set { val type = Type.getType(typeName) val newTypeNames = mutableSetOf() when (type) { is SimpleType -> { newTypeNames.add(type.getMainTypeName()) } is ArrayType -> { newTypeNames.add(type.getMainTypeName()) } is MapType -> { newTypeNames.addAll(type.getSubTypeNames()) } is TypeWithGeneric -> { newTypeNames.add(type.getMainTypeName()) } } return newTypeNames } }