"Replace" template generation, Placeholder generation, Mask generation

This commit is contained in:
airatmeister 2022-12-21 17:37:30 +03:00
parent 1cef096d45
commit bcf8bf6cfe
11 changed files with 85 additions and 40 deletions

37
text-processing/README.md Normal file
View File

@ -0,0 +1,37 @@
text-processing
=====
### Общее описание
Модуль содержит функционал:
- Генерация "Replace" шаблона из регулярного выражения и возможность подстановки его в строку,
- Генерация Placeholder из регулярного выражения,
- Генерация маски для `EditText` из регулярного выражения и возможность его подстановки.
Модуль содержит класс `TextFormatter`, который в качестве аргумента принимает `String` в виде регулярного выражения.
* Функция `getFormattedText` - принимает входящий параметр в виде строки для форматирования, возвращает отформатированную строку,
* Функция `getPlaceholder` - возвращает Placeholder соответствующий регулярному выражению,
* Функция `getRegexReplace` - возвращает "Replace" шаблон регулярного выражения,
* Функция `mask` - принимает входящим параметром `EditText` и применяет к нему маску сгенерированую по регулярному выражению.
### Пример применения `textFormatter`
```kotlin
class MainActivity : Activity() {
/**
* replace шаблон - $1/$2
* placeholder - 12/34
* **/
private val textFormatter = TextFormatter("(\\d{2})\\/?(\\d{2})")
private lateinit var editText: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
editText = findViewById(R.id.editText)
editText.hint = textFormatter.getPlaceholder() //В результате placeholder будет 12/34
textFormatter.mask(editText) //Применение маски соответствующей регулярному выражению из textFormatter
}
}
```

View File

@ -1,6 +1,6 @@
package ru.touchin.roboswag.textprocessing
import android.widget.TextView
import android.widget.EditText
import ru.touchin.roboswag.textprocessing.generators.DecoroMaskGenerator
import ru.touchin.roboswag.textprocessing.generators.PlaceholderGenerator
import ru.touchin.roboswag.textprocessing.generators.regexgenerator.RegexReplaceGenerator
@ -8,23 +8,28 @@ import ru.touchin.roboswag.textprocessing.generators.regexgenerator.RegexReplace
class TextFormatter(private val regex: String) {
private val regexReplaceGenerator = RegexReplaceGenerator()
private val decoroMaskGenerator = DecoroMaskGenerator()
private val pcreGeneratorItem = regexReplaceGenerator.regexToRegexReplace(regex)
private val regexReplaceString = pcreGeneratorItem.regexReplaceString
private val matrixOfSymbols = pcreGeneratorItem.matrixOfSymbols
private val placeholderGenerator = PlaceholderGenerator(matrixOfSymbols)
fun getFormatText(inputText: String) = inputText.replace(Regex(regex), regexReplaceString)
fun getFormattedText(inputText: String) = inputText.replace(Regex(regex), regexReplaceString)
fun getPlaceholder() = placeholderGenerator.getPlaceholder()
fun getPlaceholder() = placeholderGenerator.placeholder
fun getRegexReplace() = regexReplaceString
fun mask(textView: TextView) {
fun mask(editText: EditText) {
val formatWatcher = decoroMaskGenerator.mask(
placeholderGenerator.getPlaceholder(),
placeholderGenerator.placeholder,
matrixOfSymbols
)
formatWatcher.installOn(textView)
formatWatcher.installOn(editText)
}
}
}

View File

@ -12,16 +12,13 @@ class DecoroMaskGenerator {
* если возможный символ всего один, то символ хардкодится в слот
* **/
fun mask(placeholder: String, matrixOfSymbols: Matrix<Char>): MaskFormatWatcher {
val slots = mutableListOf<Slot>()
for (i in placeholder.indices) {
slots.add(
if (matrixOfSymbols[i].size == 1) {
PredefinedSlots.hardcodedSlot(placeholder[i])
} else {
CustomValidator.customSlot(matrixOfSymbols[i])
}
)
val slots = placeholder.mapIndexed { index, char ->
if (matrixOfSymbols[index].size == 1) {
PredefinedSlots.hardcodedSlot(char)
} else {
CustomValidator.customSlot(matrixOfSymbols[index])
}
}
return MaskFormatWatcher(MaskImpl.createTerminated(slots.toTypedArray()))
}
}
}

View File

@ -1,3 +1,3 @@
package ru.touchin.roboswag.textprocessing.generators
typealias Matrix<T> = List<List<T>>
typealias Matrix<T> = List<List<T>>

View File

@ -2,9 +2,10 @@ package ru.touchin.roboswag.textprocessing.generators
class PlaceholderGenerator(matrixOfSymbols: Matrix<Char>) {
private var placeholder: String = ""
val placeholder = generatePlaceholder(matrixOfSymbols)
init {
private fun generatePlaceholder(matrixOfSymbols: Matrix<Char>): String {
val placeholderStringBuilder = StringBuilder()
val indexes = hashMapOf<List<Char>, Int>()
for (listOfSymbols in matrixOfSymbols) {
indexes[listOfSymbols] = 0
@ -13,18 +14,17 @@ class PlaceholderGenerator(matrixOfSymbols: Matrix<Char>) {
if (listOfSymbols.isEmpty()) continue
/** Если элемент без повторений **/
if (listOfSymbols.size == 1) {
placeholder += listOfSymbols[0]
placeholderStringBuilder.append(listOfSymbols[0])
continue
}
indexes[listOfSymbols]?.let {
var index = it
if (listOfSymbols.size <= index) index = 0
placeholder += listOfSymbols[index]
placeholderStringBuilder.append(listOfSymbols[index])
index++
indexes[listOfSymbols] = index
}
}
return placeholderStringBuilder.toString()
}
fun getPlaceholder() = placeholder
}
}

View File

@ -5,4 +5,4 @@ import ru.touchin.roboswag.textprocessing.generators.Matrix
class PCREGeneratorItem(
val regexReplaceString: String,
val matrixOfSymbols: Matrix<Char>
)
)

View File

@ -4,12 +4,15 @@ import ru.touchin.roboswag.textprocessing.pcre.parser.PCREBaseListener
import ru.touchin.roboswag.textprocessing.pcre.parser.PCREParser
class PCREGeneratorListener : PCREBaseListener() {
/**
* Лист для placeholder, где индекс - номер буквы для placeholder
* значение - возможные символы для placeholder
* **/
private val matrixOfSymbols = mutableListOf<List<Char>>()
private var currentGroupIndex = 1
private var regexReplaceString = ""
/** Элемент поиска с регулярного выражения
@ -72,8 +75,8 @@ class PCREGeneratorListener : PCREBaseListener() {
fun toPCREGeneratorItem() = PCREGeneratorItem(
regexReplaceString,
matrixOfSymbols.map { it ->
it.filter {
matrixOfSymbols.map { chars ->
chars.filter {
it != '\\'
}
}
@ -100,4 +103,4 @@ class PCREGeneratorListener : PCREBaseListener() {
val endRange = atomStr[atomStr.length - 2]
return startRange.rangeTo(endRange).toMutableList()
}
}
}

View File

@ -10,12 +10,18 @@ class RegexReplaceGenerator {
fun regexToRegexReplace(regex: String): PCREGeneratorItem {
val stringStream = CharStreams.fromString(regex)
val lexer = PCRELexer(stringStream)
val parser = PCREParser(CommonTokenStream(lexer))
val parseContext = parser.parse()
val walker = ParseTreeWalker()
val pcreGeneratorListener = PCREGeneratorListener()
walker.walk(pcreGeneratorListener, parseContext)
return pcreGeneratorListener.toPCREGeneratorItem()
}
}
}

View File

@ -13,4 +13,4 @@ class CustomValidator private constructor(
override fun validate(value: Char): Boolean {
return slotSymbols.contains(value)
}
}
}

View File

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>

View File

@ -11,7 +11,7 @@ class TextFormatterTest {
val inputText = "0622"
val item = TextFormatter(regex)
Assert.assertEquals("$1\\/$2", item.getRegexReplace())
Assert.assertEquals("06/22", item.getFormatText(inputText))
Assert.assertEquals("06/22", item.getFormattedText(inputText))
Assert.assertEquals("12/34", item.getPlaceholder())
}
@ -21,7 +21,7 @@ class TextFormatterTest {
val inputText = "1234345612353534"
val item = TextFormatter(regex)
Assert.assertEquals("\$1 \$2 \$3 \$4", item.getRegexReplace())
Assert.assertEquals("1234 3456 1235 3534", item.getFormatText(inputText))
Assert.assertEquals("1234 3456 1235 3534", item.getFormattedText(inputText))
Assert.assertEquals("1234 5678 9012 3456", item.getPlaceholder())
}
@ -31,7 +31,7 @@ class TextFormatterTest {
val inputText = "9091344422"
val item = TextFormatter(regex)
Assert.assertEquals("\\+7 \\($1\\) $2 $3 $4", item.getRegexReplace())
Assert.assertEquals("+7 (909) 134 44 22", item.getFormatText(inputText))
Assert.assertEquals("+7 (909) 134 44 22", item.getFormattedText(inputText))
Assert.assertEquals("+7 (123) 456 78 90", item.getPlaceholder())
}
@ -41,7 +41,7 @@ class TextFormatterTest {
val inputText = "IVБЮ349823"
val item = TextFormatter(regex)
Assert.assertEquals("\$1-\$2 № \$3", item.getRegexReplace())
Assert.assertEquals("IV-БЮ № 349823", item.getFormatText(inputText))
Assert.assertEquals("IV-БЮ № 349823", item.getFormattedText(inputText))
Assert.assertEquals("AB-АБ № 123456", item.getPlaceholder())
}
@ -51,7 +51,7 @@ class TextFormatterTest {
val inputText = "5332.4"
val item = TextFormatter(regex)
Assert.assertEquals("\$1\$2 ₽", item.getRegexReplace())
Assert.assertEquals("5332.4 ₽", item.getFormatText(inputText))
Assert.assertEquals("5332.4 ₽", item.getFormattedText(inputText))
Assert.assertEquals("1.2 ₽", item.getPlaceholder())
}
}
}