All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ru.pocketbyte.locolaser.properties.resource.file.PropertiesResourceFile.kt Maven / Gradle / Ivy

package ru.pocketbyte.locolaser.properties.resource.file

import ru.pocketbyte.locolaser.entity.Quantity
import ru.pocketbyte.locolaser.config.ExtraParams
import ru.pocketbyte.locolaser.resource.entity.*
import ru.pocketbyte.locolaser.resource.file.ResourceStreamFile
import ru.pocketbyte.locolaser.resource.formatting.FormattingType
import ru.pocketbyte.locolaser.resource.formatting.JavaFormattingType
import ru.pocketbyte.locolaser.resource.formatting.NoFormattingType
import ru.pocketbyte.locolaser.utils.PluralUtils
import ru.pocketbyte.locolaser.utils.commentShouldBeWritten
import java.io.File
import java.io.IOException
import java.io.LineNumberReader
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Paths
import java.util.regex.Pattern

class PropertiesResourceFile(
    file:File,
    private val locale: String
):ResourceStreamFile(file) {

    companion object {

        const val GENERATED_COMMENT = "# AUTO-GENERATED FILE. DO NOT MODIFY.\r\n" +
                "#\r\n" +
                "# This file was automatically generated by the LocoLaser tool.\r\n" +
                "# It should not be modified by hand."

        private const val COMMENT_SINGLE_LINE = "#"
        private const val KEY_VALUE_PATTERN = "((?:[^\"]|\\\\\")+)=((?:[^\"]|\\\\\")*)"

        internal fun toPlatformValue(string:String):String {
            return string
                    .replace("\"", "\\\"")
                    .replace("\n", "\\n")
        }

        internal fun fromPlatformValue(string:String):String {
            return string
                    .replace("\\\"", "\"")
                    .replace("\\n", "\n")
        }
    }

    override val formattingType: FormattingType = JavaFormattingType

    override fun read(extraParams: ExtraParams?):ResMap? {
        if (file.exists()) {
            val currentLocaleMap = ResLocale()

            val keyValueMatcher = Pattern.compile(KEY_VALUE_PATTERN).matcher("")

            val path = Paths.get(file.toURI())
            try {
                Files.newBufferedReader(path, StandardCharsets.UTF_8).use { reader-> LineNumberReader(reader).use { lineReader->

                    var line:String?
                    var comment:StringBuilder? = null

                    do {
                        line = lineReader.readLine()
                        if (line == null || GENERATED_COMMENT.contains(line)) {
                            comment = null
                            continue
                        }

                        if (line.startsWith(COMMENT_SINGLE_LINE)) {
                            val commentString = line.substring(COMMENT_SINGLE_LINE.length).trim { it <= ' ' }
                            if (comment == null)
                                comment = StringBuilder(commentString)
                            else
                                comment.append("\n").append(commentString)
                            continue
                        }

                        keyValueMatcher.reset(line)
                        if (keyValueMatcher.find() && keyValueMatcher.groupCount() == 2) {
                            val commentString = comment?.toString()
                            val keyString = keyValueMatcher.group(1)
                            val valueString = keyValueMatcher.group(2)
                            val quantitySeparatorIndex = keyString.lastIndexOf(".")
                            val quantity = if (quantitySeparatorIndex > 0) {
                                PluralUtils.quantityFromString(
                                    keyString.substring(quantitySeparatorIndex + 1)
                                )
                            } else { null }

                            if (quantity != null) {
                                val key = keyString.substring(0, quantitySeparatorIndex)
                                val item = currentLocaleMap[key] ?: ResItem(key)
                                item.addValue(valueString, commentString, quantity)
                                currentLocaleMap.put(item)
                            } else {
                                val item = ResItem(keyString)
                                item.addValue(valueString, commentString, Quantity.OTHER)
                                currentLocaleMap.put(item)
                            }

                            comment = null
                            continue
                        }

                        // Nothing found
                        comment = null
                    } while (line != null) }
                }
            }
            catch (e:IOException) {
                // Do nothing
                e.printStackTrace()
            }

            return ResMap().apply {
                put(locale, currentLocaleMap)
            }
        }
        return null
    }

    @Throws(IOException::class)
    override fun write(resMap:ResMap, extraParams: ExtraParams?) {
        open()

        writeStringLn(GENERATED_COMMENT)
        writeln()

        val items = resMap[locale] ?: return

        for (key in items.keys) {
            val resItem = items[key]
            if (resItem != null) {
                if (resItem.isHasQuantities) {
                    for (value in resItem.values) {
                        if (commentShouldBeWritten(value, extraParams)) {
                            writeComment(value.comment)
                        }
                        writeString(resItem.key)
                        writeString(".")
                        writeString(value.quantity.toString())
                        writeString("=")
                        writeStringLn(toPlatformValue(value.value))
                    }
                } else {
                    val value = resItem.valueForQuantity(Quantity.OTHER)
                    if (value != null) {
                        if (commentShouldBeWritten(value, extraParams)) {
                            writeComment(value.comment)
                        }
                        writeString(resItem.key)
                        writeString("=")
                        writeStringLn(toPlatformValue(value.value))
                    }
                }
            }
        }

        close()
    }

    private fun ResItem.addValue(value: String, comment: String?, quantity: Quantity) {
        val formattingArguments = formattingType.argumentsFromValue(value)
        val formattingType = if (formattingArguments?.isEmpty() != false) NoFormattingType else formattingType
        this.addValue(ResValue(value, comment, quantity, formattingType, formattingArguments))
    }

    private fun writeComment(comment: String?) {
        writeString(COMMENT_SINGLE_LINE)
        writeString(" ")
        writeStringLn(comment?.replace("\n", "\n$COMMENT_SINGLE_LINE ") ?: "")
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy