Skip to content

Commit 6725207

Browse files
committed
refactor(common, validate): extract validate to use case
1 parent 952a100 commit 6725207

File tree

7 files changed

+147
-94
lines changed

7 files changed

+147
-94
lines changed

application/src/androidMain/kotlin/com/neoutils/neoregex/App.android.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ fun AndroidApp() {
7373
}
7474

7575
@Composable
76-
fun NeoAppBar(
76+
private fun NeoAppBar(
7777
modifier: Modifier = Modifier,
7878
background: Color = colorScheme.surfaceContainer,
7979
shadowElevation: Dp = dimensions.tiny,

application/src/webMain/kotlin/com/neoutils/neoregex/App.web.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ private fun Header(
164164
)
165165

166166
@Composable
167-
fun TopLabel(
167+
private fun TopLabel(
168168
text: String,
169169
visible: Boolean = true,
170170
onClose: () -> Unit = {},

feature/validator/src/commonMain/kotlin/com/neoutils/neoregex/feature/validator/ValidatorViewModel.kt

Lines changed: 21 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ import com.neoutils.neoregex.core.common.util.ObservableMutableMap
2525
import com.neoutils.neoregex.core.repository.pattern.PatternRepository
2626
import com.neoutils.neoregex.core.repository.testcase.TestCasesRepository
2727
import com.neoutils.neoregex.core.sharedui.component.FooterAction
28-
import com.neoutils.neoregex.core.common.model.Match
2928
import com.neoutils.neoregex.feature.validator.action.ValidatorAction
29+
import com.neoutils.neoregex.feature.validator.component.TestCaseAction
30+
import com.neoutils.neoregex.feature.validator.component.toTestCaseUi
3031
import com.neoutils.neoregex.feature.validator.model.TestCaseQueue
31-
import com.neoutils.neoregex.feature.validator.model.TestPattern
3232
import com.neoutils.neoregex.feature.validator.model.TestCaseValidation
33-
import com.neoutils.neoregex.feature.validator.component.TestCaseAction
33+
import com.neoutils.neoregex.feature.validator.model.TestPattern
34+
import com.neoutils.neoregex.feature.validator.usecase.ValidateUseCase
3435
import com.neoutils.neoregex.feature.validator.state.ValidatorUiState
35-
import com.neoutils.neoregex.feature.validator.component.toTestCaseUi
3636
import kotlinx.coroutines.*
3737
import kotlinx.coroutines.flow.*
3838
import kotlin.uuid.ExperimentalUuidApi
@@ -45,11 +45,11 @@ import kotlin.uuid.Uuid
4545
)
4646
class ValidatorViewModel(
4747
private val patternRepository: PatternRepository,
48-
private val testCasesRepository: TestCasesRepository
48+
private val testCasesRepository: TestCasesRepository,
49+
private val validateUserCase: ValidateUseCase,
50+
private val testCaseQueue: TestCaseQueue
4951
) : ScreenModel {
5052

51-
private val testCaseQueue = TestCaseQueue()
52-
5353
private val expanded = MutableStateFlow(testCasesRepository.all.firstOrNull()?.uuid)
5454
private val results = ObservableMutableMap<Uuid, TestCaseValidation>()
5555

@@ -91,19 +91,19 @@ class ValidatorViewModel(
9191
testPattern,
9292
) { history, pattern, testCases, testPattern ->
9393
ValidatorUiState(
94-
pattern = pattern,
95-
history = history,
9694
testCases = testCases,
9795
testPattern = testPattern,
96+
pattern = pattern,
97+
history = history,
9898
)
9999
}.stateIn(
100100
scope = screenModelScope,
101101
started = SharingStarted.WhileSubscribed(),
102102
initialValue = ValidatorUiState(
103-
history = patternRepository.historyFlow.value,
104-
pattern = patternRepository.flow.value,
105103
testCases = testCasesUi.value,
106104
testPattern = testPattern.value,
105+
pattern = patternRepository.flow.value,
106+
history = patternRepository.historyFlow.value,
107107
)
108108
)
109109

@@ -137,14 +137,17 @@ class ValidatorViewModel(
137137
val testCase = testCaseQueue.dequeue()
138138

139139
if (testCase != null) {
140-
validationJob[testCase.uuid] = launch {
141140

142-
results[testCase.uuid] = TestCaseValidation(
141+
results[testCase.uuid] = TestCaseValidation(
142+
testCase = testCase,
143+
result = TestCaseValidation.Result.RUNNING,
144+
)
145+
146+
validationJob[testCase.uuid] = launch {
147+
results[testCase.uuid] = validateUserCase(
143148
testCase = testCase,
144-
result = TestCaseValidation.Result.RUNNING
149+
regex = testPattern.value.regex.getOrThrow()
145150
)
146-
147-
results[testCase.uuid] = validate(testCase)
148151
}
149152

150153
// wait execution
@@ -158,77 +161,6 @@ class ValidatorViewModel(
158161
}
159162
}
160163

161-
private fun validate(
162-
testCase: TestCase,
163-
regex: Regex = testPattern.value.regex.getOrThrow()
164-
): TestCaseValidation {
165-
166-
val result = regex.findAll(testCase.text)
167-
168-
val matches = buildList {
169-
result.forEachIndexed { index, match ->
170-
add(
171-
Match(
172-
text = match.value,
173-
range = match.range,
174-
groups = match.groupValues.drop(n = 1),
175-
number = index.inc(),
176-
)
177-
)
178-
}
179-
}
180-
181-
return when (testCase.case) {
182-
TestCase.Case.MATCH_ANY -> {
183-
if (matches.isEmpty()) {
184-
TestCaseValidation(
185-
testCase = testCase,
186-
result = TestCaseValidation.Result.ERROR,
187-
matches = matches
188-
)
189-
} else {
190-
TestCaseValidation(
191-
testCase = testCase,
192-
result = TestCaseValidation.Result.SUCCESS,
193-
matches = matches
194-
)
195-
}
196-
}
197-
198-
TestCase.Case.MATCH_FULL -> {
199-
if (regex.matches(testCase.text)) {
200-
TestCaseValidation(
201-
testCase = testCase,
202-
result = TestCaseValidation.Result.SUCCESS,
203-
matches = matches
204-
)
205-
} else {
206-
TestCaseValidation(
207-
testCase = testCase,
208-
result = TestCaseValidation.Result.ERROR,
209-
matches = matches
210-
)
211-
}
212-
}
213-
214-
TestCase.Case.MATCH_NONE -> {
215-
if (matches.isEmpty()) {
216-
TestCaseValidation(
217-
testCase = testCase,
218-
result = TestCaseValidation.Result.SUCCESS,
219-
matches = matches
220-
)
221-
} else {
222-
TestCaseValidation(
223-
testCase = testCase,
224-
result = TestCaseValidation.Result.ERROR,
225-
matches = matches
226-
)
227-
}
228-
}
229-
}
230-
}
231-
232164
private fun addToQueue(
233165
newTestCase: TestCase,
234166
withDelay: Boolean = false
@@ -273,8 +205,8 @@ class ValidatorViewModel(
273205
fun onAction(action: ValidatorAction) {
274206
when (action) {
275207
is ValidatorAction.AddTestCase -> {
276-
expanded.value = action.newTestCase.uuid
277208
testCasesRepository.set(action.newTestCase)
209+
expanded.value = action.newTestCase.uuid
278210
}
279211
}
280212
}
@@ -293,9 +225,7 @@ class ValidatorViewModel(
293225
}
294226

295227
if (oldTestCase != newTestCase) {
296-
addToQueue(
297-
newTestCase
298-
)
228+
addToQueue(newTestCase)
299229
}
300230
}
301231

feature/validator/src/commonMain/kotlin/com/neoutils/neoregex/feature/validator/di/ValidatorModule.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,19 @@
1919
package com.neoutils.neoregex.feature.validator.di
2020

2121
import com.neoutils.neoregex.feature.validator.ValidatorViewModel
22+
import com.neoutils.neoregex.feature.validator.model.TestCaseQueue
23+
import com.neoutils.neoregex.feature.validator.usecase.ValidateUseCase
2224
import org.koin.core.module.dsl.factoryOf
2325
import org.koin.dsl.module
2426

2527
val validatorModule = module {
28+
29+
// others
30+
factory { TestCaseQueue() }
31+
32+
// use cases
33+
factory { ValidateUseCase() }
34+
35+
// view model
2636
factoryOf(::ValidatorViewModel)
2737
}

feature/validator/src/commonMain/kotlin/com/neoutils/neoregex/feature/validator/model/TestPattern.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
/*
2+
* NeoRegex.
3+
*
4+
* Copyright (C) 2025 Irineu A. Silva.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
119
package com.neoutils.neoregex.feature.validator.model
220

321
data class TestPattern(

feature/validator/src/commonMain/kotlin/com/neoutils/neoregex/feature/validator/state/ValidatorUiState.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ data class ValidatorUiState(
4343

4444
fun ValidatorUiState(
4545
testCases: List<TestCaseUi>,
46+
testPattern: TestPattern,
4647
pattern: Text,
4748
history: History,
48-
testPattern: TestPattern,
4949
): ValidatorUiState {
5050

5151
val testableCases = testCases.filter { it.text.isNotEmpty() }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* NeoRegex.
3+
*
4+
* Copyright (C) 2025 Irineu A. Silva.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
19+
package com.neoutils.neoregex.feature.validator.usecase
20+
21+
import com.neoutils.neoregex.core.common.model.Match
22+
import com.neoutils.neoregex.core.common.model.TestCase
23+
import com.neoutils.neoregex.feature.validator.model.TestCaseValidation
24+
25+
class ValidateUseCase {
26+
27+
operator fun invoke(
28+
testCase: TestCase,
29+
regex: Regex
30+
): TestCaseValidation {
31+
32+
val results = regex.findAll(testCase.text)
33+
34+
val matches = mutableListOf<Match>()
35+
36+
results.mapIndexedTo(matches) { index, match ->
37+
Match(
38+
text = match.value,
39+
range = match.range,
40+
groups = match.groupValues.drop(n = 1),
41+
number = index.inc(),
42+
)
43+
}
44+
45+
return when (testCase.case) {
46+
TestCase.Case.MATCH_ANY -> {
47+
if (matches.isEmpty()) {
48+
TestCaseValidation(
49+
testCase = testCase,
50+
result = TestCaseValidation.Result.ERROR,
51+
matches = matches
52+
)
53+
} else {
54+
TestCaseValidation(
55+
testCase = testCase,
56+
result = TestCaseValidation.Result.SUCCESS,
57+
matches = matches
58+
)
59+
}
60+
}
61+
62+
TestCase.Case.MATCH_FULL -> {
63+
if (regex.matches(testCase.text)) {
64+
TestCaseValidation(
65+
testCase = testCase,
66+
result = TestCaseValidation.Result.SUCCESS,
67+
matches = matches
68+
)
69+
} else {
70+
TestCaseValidation(
71+
testCase = testCase,
72+
result = TestCaseValidation.Result.ERROR,
73+
matches = matches
74+
)
75+
}
76+
}
77+
78+
TestCase.Case.MATCH_NONE -> {
79+
if (matches.isEmpty()) {
80+
TestCaseValidation(
81+
testCase = testCase,
82+
result = TestCaseValidation.Result.SUCCESS,
83+
matches = matches
84+
)
85+
} else {
86+
TestCaseValidation(
87+
testCase = testCase,
88+
result = TestCaseValidation.Result.ERROR,
89+
matches = matches
90+
)
91+
}
92+
}
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)