diff options
author | Brinda Santh <brindasanth@in.ibm.com> | 2019-08-30 10:13:00 -0400 |
---|---|---|
committer | Brinda Santh <brindasanth@in.ibm.com> | 2019-08-30 10:13:00 -0400 |
commit | b7ab2e2c1aa96168169bac8e76e9e9b5f71e7839 (patch) | |
tree | a600240969b9d8987d97e244492b3628eacb68a0 /ms/controllerblueprints/modules | |
parent | 03f4454b17e13f8b723659583ddb36dbaa4bd1f8 (diff) |
Refactor model types load to designer api.
Change-Id: Icc75c2cac2b9522fc20aa2247aafa8a1f494758e
Issue-ID: CCSDK-1663
Signed-off-by: Brinda Santh <brindasanth@in.ibm.com>
Diffstat (limited to 'ms/controllerblueprints/modules')
5 files changed, 0 insertions, 532 deletions
diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/BluePrintCatalogLoadService.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/BluePrintCatalogLoadService.kt deleted file mode 100644 index 9e456c7f9..000000000 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/BluePrintCatalogLoadService.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * Modifications Copyright © 2019 IBM. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.cds.controllerblueprints.service.load - -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.async -import kotlinx.coroutines.runBlocking -import org.apache.commons.lang.text.StrBuilder -import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Service -import java.io.File -import java.util.* - -@Service -open class BluePrintCatalogLoadService(private val controllerBlueprintsCatalogService: BluePrintCatalogService) { - - private val log = LoggerFactory.getLogger(BluePrintCatalogLoadService::class.java) - - open fun loadPathsBluePrintModelCatalog(paths: List<String>) { - paths.forEach { loadPathBluePrintModelCatalog(it) } - } - - open fun loadPathBluePrintModelCatalog(path: String) { - - val files = File(path).listFiles() - runBlocking { - val errorBuilder = StrBuilder() - val deferredResults = mutableListOf<Deferred<Unit>>() - - for (file in files) { - deferredResults += async { - loadBluePrintModelCatalog(errorBuilder, file) - } - } - - for (deferredResult in deferredResults) { - deferredResult.await() - } - - if (!errorBuilder.isEmpty) { - log.error(errorBuilder.toString()) - } - } - } - - open suspend fun loadBluePrintModelCatalog(errorBuilder: StrBuilder, file: File) { - try { - controllerBlueprintsCatalogService.saveToDatabase(UUID.randomUUID().toString(), file) - } catch (e: Exception) { - errorBuilder.appendln("Couldn't load BlueprintModel(${file.name}: ${e.message}") - } - } - -}
\ No newline at end of file diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/BluePrintDatabaseLoadService.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/BluePrintDatabaseLoadService.kt deleted file mode 100644 index 11c91ab77..000000000 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/BluePrintDatabaseLoadService.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * Modifications Copyright © 2019 IBM. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.cds.controllerblueprints.service.load - -import kotlinx.coroutines.runBlocking -import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration -import org.slf4j.LoggerFactory -import org.springframework.boot.context.event.ApplicationReadyEvent -import org.springframework.context.event.EventListener -import org.springframework.stereotype.Service - -@Service -open class BluePrintDatabaseLoadService(private val bluePrintLoadConfiguration: BluePrintLoadConfiguration, - private val modelTypeLoadService: ModelTypeLoadService, - private val resourceDictionaryLoadService: ResourceDictionaryLoadService, - private val bluePrintCatalogLoadService: BluePrintCatalogLoadService) { - - private val log = LoggerFactory.getLogger(BluePrintDatabaseLoadService::class.java) - - - @EventListener(ApplicationReadyEvent::class) - open fun init() = runBlocking { - if (bluePrintLoadConfiguration.loadInitialData) { - initModelTypes() - initResourceDictionary() - initBluePrintCatalog() - } else { - log.info("Initial data load is disabled") - } - - } - - open suspend fun initModelTypes() { - log.info("model types load configuration(${bluePrintLoadConfiguration.loadModelType}) " + - "under paths(${bluePrintLoadConfiguration.loadModeTypePaths})") - - if (bluePrintLoadConfiguration.loadModelType) { - val paths = bluePrintLoadConfiguration.loadModeTypePaths?.split(",") - paths?.let { - modelTypeLoadService.loadPathsModelType(paths) - } - } - } - - open suspend fun initResourceDictionary() { - log.info("resource dictionary load configuration(${bluePrintLoadConfiguration.loadResourceDictionary}) " + - "under paths(${bluePrintLoadConfiguration.loadResourceDictionaryPaths})") - - if (bluePrintLoadConfiguration.loadResourceDictionary) { - val paths = bluePrintLoadConfiguration.loadResourceDictionaryPaths?.split(",") - paths?.let { - resourceDictionaryLoadService.loadPathsResourceDictionary(paths) - } - } - } - - open suspend fun initBluePrintCatalog() { - log.info("blueprint load configuration(${bluePrintLoadConfiguration.loadBluePrint}) " + - "under paths(${bluePrintLoadConfiguration.loadBluePrintPaths})") - - if (bluePrintLoadConfiguration.loadBluePrint) { - val paths = bluePrintLoadConfiguration.loadBluePrintPaths?.split(",") - paths?.let { - bluePrintCatalogLoadService.loadPathsBluePrintModelCatalog(paths) - } - } - } -}
\ No newline at end of file diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ControllerBlueprintCatalogServiceImpl.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ControllerBlueprintCatalogServiceImpl.kt deleted file mode 100755 index 0e7a7d94a..000000000 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ControllerBlueprintCatalogServiceImpl.kt +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * Modifications Copyright © 2019 Bell Canada. - * Modifications Copyright © 2019 IBM. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.cds.controllerblueprints.service.load - -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException -import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants -import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration -import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode -import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir -import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintValidatorService -import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPath -import org.onap.ccsdk.cds.controllerblueprints.db.resources.BlueprintCatalogServiceImpl -import org.onap.ccsdk.cds.controllerblueprints.service.domain.BlueprintModel -import org.onap.ccsdk.cds.controllerblueprints.service.domain.BlueprintModelContent -import org.onap.ccsdk.cds.controllerblueprints.service.repository.ControllerBlueprintModelRepository -import org.slf4j.LoggerFactory -import org.springframework.dao.DataIntegrityViolationException -import org.springframework.stereotype.Service -import java.io.File -import java.nio.file.Files -import java.nio.file.Path -import java.util.* - -/** - * Similar implementation in [org.onap.ccsdk.cds.blueprintsprocessor.db.BlueprintProcessorCatalogServiceImpl] - */ -@Service("controllerBlueprintsCatalogService") -class ControllerBlueprintCatalogServiceImpl(bluePrintDesignTimeValidatorService: BluePrintValidatorService, - private val bluePrintLoadConfiguration: BluePrintLoadConfiguration, - private val blueprintModelRepository: ControllerBlueprintModelRepository) - : BlueprintCatalogServiceImpl(bluePrintLoadConfiguration, bluePrintDesignTimeValidatorService) { - - - private val log = LoggerFactory.getLogger(ControllerBlueprintCatalogServiceImpl::class.toString()) - - init { - log.info("BlueprintProcessorCatalogServiceImpl initialized") - } - - override suspend fun delete(name: String, version: String) { - // Cleaning Deployed Blueprint - deleteDir(bluePrintLoadConfiguration.blueprintDeployPath, name, version) - // Cleaning Data Base - blueprintModelRepository.deleteByArtifactNameAndArtifactVersion(name, version) - } - - override suspend fun get(name: String, version: String, extract: Boolean): Path? { - val path = if (extract) { - normalizedPath(bluePrintLoadConfiguration.blueprintDeployPath, name, version) - } else { - normalizedPath(bluePrintLoadConfiguration.blueprintArchivePath, UUID.randomUUID().toString(), "cba.zip") - } - blueprintModelRepository.findByArtifactNameAndArtifactVersion(name, version)?.also { - it.blueprintModelContent.run { - path.toFile().writeBytes(this!!.content!!).let { - return path - } - } - } - return null - } - - override suspend fun save(metadata: MutableMap<String, String>, archiveFile: File) { - - val artifactName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME] - val artifactVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION] - - check(archiveFile.isFile && !archiveFile.isDirectory) { - throw BluePrintException("Not a valid Archive file(${archiveFile.absolutePath})") - } - - blueprintModelRepository.findByArtifactNameAndArtifactVersion(artifactName!!, artifactVersion!!)?.let { - log.info("Overwriting blueprint model :$artifactName::$artifactVersion") - blueprintModelRepository.deleteByArtifactNameAndArtifactVersion(artifactName, artifactVersion) - } - - val blueprintModel = BlueprintModel() - blueprintModel.id = metadata[BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID] - blueprintModel.artifactType = ApplicationConstants.ASDC_ARTIFACT_TYPE_SDNC_MODEL - blueprintModel.published = metadata[BluePrintConstants.PROPERTY_BLUEPRINT_VALID] - ?: BluePrintConstants.FLAG_N - blueprintModel.artifactName = artifactName - blueprintModel.artifactVersion = artifactVersion - blueprintModel.updatedBy = metadata[BluePrintConstants.METADATA_TEMPLATE_AUTHOR] - blueprintModel.tags = metadata[BluePrintConstants.METADATA_TEMPLATE_TAGS] - blueprintModel.artifactDescription = "Controller Blueprint for $artifactName:$artifactVersion" - - val blueprintModelContent = BlueprintModelContent() - blueprintModelContent.id = metadata[BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID] - blueprintModelContent.contentType = "CBA_ZIP" - blueprintModelContent.name = "$artifactName:$artifactVersion" - blueprintModelContent.description = "$artifactName:$artifactVersion CBA Zip Content" - blueprintModelContent.content = Files.readAllBytes(archiveFile.toPath()) - blueprintModelContent.blueprintModel = blueprintModel - // Set the Blueprint Model Content into blueprintModel - blueprintModel.blueprintModelContent = blueprintModelContent - - try { - blueprintModelRepository.saveAndFlush(blueprintModel) - } catch (ex: DataIntegrityViolationException) { - throw BluePrintException(ErrorCode.CONFLICT_ADDING_RESOURCE.value, "The blueprint entry " + - "is already exist in database: ${ex.message}", ex) - } - } -}
\ No newline at end of file diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ModelTypeLoadService.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ModelTypeLoadService.kt deleted file mode 100644 index 0fd30f206..000000000 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ModelTypeLoadService.kt +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * Modifications Copyright © 2019 IBM. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.cds.controllerblueprints.service.load - -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope -import org.apache.commons.io.FilenameUtils -import org.apache.commons.lang3.text.StrBuilder -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException -import org.onap.ccsdk.cds.controllerblueprints.core.data.* -import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile -import org.onap.ccsdk.cds.controllerblueprints.core.readNBText -import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils -import org.onap.ccsdk.cds.controllerblueprints.service.domain.ModelType -import org.onap.ccsdk.cds.controllerblueprints.service.handler.ModelTypeHandler -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Service -import java.io.File - -@Service -open class ModelTypeLoadService(private val modelTypeHandler: ModelTypeHandler) { - - private val log = LoggerFactory.getLogger(ModelTypeLoadService::class.java) - private val updateBySystem = "System" - - open suspend fun loadPathsModelType(modelTypePaths: List<String>) { - modelTypePaths.forEach { - loadPathModelType(it) - } - } - - /** - * Load the Model Type file content from the defined path, Load of sequencing should be maintained. - */ - open suspend fun loadPathModelType(modelTypePath: String) { - log.info(" ****** loadModelType($modelTypePath) ********") - try { - val errorBuilder = StrBuilder() - - coroutineScope { - val dataTypeFiles = normalizedFile("$modelTypePath", "data_type").listFiles() - val deferred = dataTypeFiles.map { - async { - loadModelType(it, DataType::class.java, errorBuilder) - } - } - deferred.awaitAll() - } - - coroutineScope { - val artifactTypeFiles = normalizedFile("$modelTypePath", "artifact_type").listFiles() - val deferred = artifactTypeFiles.map { - async { - loadModelType(it, ArtifactType::class.java, errorBuilder) - } - } - deferred.awaitAll() - } - - coroutineScope { - val relationshipTypeFiles = normalizedFile("$modelTypePath", "relationship_type").listFiles() - val deferred = relationshipTypeFiles.map { - async { - loadModelType(it, RelationshipType::class.java, errorBuilder) - } - } - deferred.awaitAll() - } - - coroutineScope { - val nodeTypeFiles = normalizedFile("$modelTypePath", "node_type").listFiles() - val deferred = nodeTypeFiles.map { - async { - loadModelType(it, NodeType::class.java, errorBuilder) - } - } - deferred.awaitAll() - } - - if (!errorBuilder.isEmpty) { - log.error(errorBuilder.toString()) - } - } catch (e: Exception) { - log.error("Failed to loade ModelTypes under($modelTypePath)", e) - } - } - - private suspend inline fun <reified T> loadModelType(file: File, classType: Class<T>, errorBuilder: StrBuilder) { - try { - log.trace("Loading ${classType.name} (${file.name})") - val dataKey = FilenameUtils.getBaseName(file.name) - val definitionContent = file.readNBText() - val definition = JacksonUtils.readValue(definitionContent, classType) as EntityType - //checkNotNull(definition) { "failed to get data type from file : ${file.name}" } - - val modelType = ModelType() - val definitionType: String? - when (T::class) { - DataType::class -> { - definitionType = BluePrintConstants.MODEL_DEFINITION_TYPE_DATA_TYPE - } - RelationshipType::class -> { - definitionType = BluePrintConstants.MODEL_DEFINITION_TYPE_RELATIONSHIP_TYPE - } - ArtifactType::class -> { - definitionType = BluePrintConstants.MODEL_DEFINITION_TYPE_ARTIFACT_TYPE - } - NodeType::class -> { - definitionType = BluePrintConstants.MODEL_DEFINITION_TYPE_NODE_TYPE - } - else -> { - throw BluePrintException("couldn't process model type($classType) definition") - } - } - modelType.definitionType = definitionType - modelType.derivedFrom = definition.derivedFrom - modelType.description = definition.description - modelType.definition = JacksonUtils.jsonNode(definitionContent) - modelType.modelName = dataKey - modelType.version = definition.version - modelType.updatedBy = updateBySystem - modelType.tags = (dataKey + "," + definition.derivedFrom + "," + definitionType) - modelTypeHandler.saveModel(modelType) - log.trace("${classType.name}(${file.name}) loaded successfully ") - } catch (e: Exception) { - errorBuilder.appendln("Couldn't load ${classType.name}(${file.name}: ${e.message}") - } - } -}
\ No newline at end of file diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ResourceDictionaryLoadService.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ResourceDictionaryLoadService.kt deleted file mode 100644 index 25db333a0..000000000 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ResourceDictionaryLoadService.kt +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright © 2017-2018 AT&T Intellectual Property. - * Modifications Copyright © 2019 IBM. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.cds.controllerblueprints.service.load - -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope -import org.apache.commons.lang3.StringUtils -import org.apache.commons.lang3.text.StrBuilder -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException -import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile -import org.onap.ccsdk.cds.controllerblueprints.core.readNBText -import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils -import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition -import org.onap.ccsdk.cds.controllerblueprints.service.domain.ResourceDictionary -import org.onap.ccsdk.cds.controllerblueprints.service.handler.ResourceDictionaryHandler -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Service -import java.io.File - -@Service -open class ResourceDictionaryLoadService(private val resourceDictionaryHandler: ResourceDictionaryHandler) { - - private val log = LoggerFactory.getLogger(ResourceDictionaryLoadService::class.java) - - open suspend fun loadPathsResourceDictionary(paths: List<String>) { - coroutineScope { - val deferred = paths.map { - async { - loadPathResourceDictionary(it) - } - } - deferred.awaitAll() - } - } - - open suspend fun loadPathResourceDictionary(path: String) { - log.info(" ******* loadResourceDictionary($path) ********") - val files = normalizedFile(path).listFiles() - val errorBuilder = StrBuilder() - - coroutineScope() { - val deferred = files.map { - async { - loadResourceDictionary(errorBuilder, it) - } - } - deferred.awaitAll() - } - - if (!errorBuilder.isEmpty) { - log.error(errorBuilder.toString()) - } - - } - - private suspend fun loadResourceDictionary(errorBuilder: StrBuilder, file: File) { - try { - log.trace("Loading NodeType(${file.name}}") - val definitionContent = file.readNBText() - val resourceDefinition = JacksonUtils.readValue(definitionContent, ResourceDefinition::class.java) - if (resourceDefinition != null) { - - checkNotNull(resourceDefinition.property) { "Failed to get Property Definition" } - val resourceDictionary = ResourceDictionary() - resourceDictionary.name = resourceDefinition.name - resourceDictionary.definition = resourceDefinition - - checkNotNull(resourceDefinition.property) { "Property field is missing" } - resourceDictionary.description = resourceDefinition.property.description - resourceDictionary.dataType = resourceDefinition.property.type - - if (resourceDefinition.property.entrySchema != null) { - resourceDictionary.entrySchema = resourceDefinition.property.entrySchema!!.type - } - resourceDictionary.updatedBy = resourceDefinition.updatedBy - - if (StringUtils.isBlank(resourceDefinition.tags)) { - resourceDictionary.tags = (resourceDefinition.name + ", " + resourceDefinition.updatedBy - + ", " + resourceDefinition.updatedBy) - - } else { - resourceDictionary.tags = resourceDefinition.tags - } - resourceDictionaryHandler.saveResourceDictionary(resourceDictionary) - - log.trace("Resource dictionary(${file.name}) loaded successfully ") - } else { - throw BluePrintException("couldn't get dictionary from content information") - } - } catch (e: Exception) { - errorBuilder.appendln("Couldn't load Resource dictionary (${file.name}: ${e.message}") - } - } - -}
\ No newline at end of file |