Skip to content

Commit 9387339

Browse files
committed
DOPE-176: add missing Token functions and expressions for token handling
1 parent 274c292 commit 9387339

17 files changed

Lines changed: 735 additions & 73 deletions

File tree

core/src/main/kotlin/ch/ergon/dope/resolvable/expression/type/function/string/TokensExpression.kt

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package ch.ergon.dope.resolvable.expression.type.function.token
2+
3+
import ch.ergon.dope.resolvable.expression.operator.FunctionOperator
4+
import ch.ergon.dope.resolvable.expression.type.TypeExpression
5+
import ch.ergon.dope.resolvable.expression.type.function.token.factory.ContainsTokenOptions
6+
import ch.ergon.dope.resolvable.expression.type.toDopeType
7+
import ch.ergon.dope.validtype.BooleanType
8+
import ch.ergon.dope.validtype.StringType
9+
import ch.ergon.dope.validtype.ValidType
10+
11+
data class ContainsTokenExpression(
12+
val inputObject: TypeExpression<out ValidType>,
13+
val tokenExpression: TypeExpression<StringType>,
14+
val options: ContainsTokenOptions? = null,
15+
) : FunctionOperator<BooleanType>
16+
17+
fun TypeExpression<out ValidType>.containsToken(
18+
tokenExpression: TypeExpression<StringType>,
19+
options: ContainsTokenOptions? = null,
20+
) = ContainsTokenExpression(this, tokenExpression, options)
21+
22+
fun TypeExpression<out ValidType>.containsToken(
23+
tokenExpression: String,
24+
options: ContainsTokenOptions? = null,
25+
) = containsToken(tokenExpression.toDopeType(), options)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package ch.ergon.dope.resolvable.expression.type.function.token
2+
3+
import ch.ergon.dope.resolvable.expression.operator.FunctionOperator
4+
import ch.ergon.dope.resolvable.expression.type.TypeExpression
5+
import ch.ergon.dope.resolvable.expression.type.function.token.factory.ContainsTokenOptions
6+
import ch.ergon.dope.resolvable.expression.type.toDopeType
7+
import ch.ergon.dope.validtype.BooleanType
8+
import ch.ergon.dope.validtype.StringType
9+
import ch.ergon.dope.validtype.ValidType
10+
11+
data class ContainsTokenLikeExpression(
12+
val inputObject: TypeExpression<out ValidType>,
13+
val tokenExpression: TypeExpression<StringType>,
14+
val options: ContainsTokenOptions? = null,
15+
) : FunctionOperator<BooleanType>
16+
17+
fun TypeExpression<out ValidType>.containsTokenLike(
18+
tokenExpression: TypeExpression<StringType>,
19+
options: ContainsTokenOptions? = null,
20+
) = ContainsTokenLikeExpression(this, tokenExpression, options)
21+
22+
fun TypeExpression<out ValidType>.containsTokenLike(
23+
tokenExpression: String,
24+
options: ContainsTokenOptions? = null,
25+
) = containsTokenLike(tokenExpression.toDopeType(), options)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package ch.ergon.dope.resolvable.expression.type.function.token
2+
3+
import ch.ergon.dope.resolvable.expression.operator.FunctionOperator
4+
import ch.ergon.dope.resolvable.expression.type.TypeExpression
5+
import ch.ergon.dope.resolvable.expression.type.function.token.factory.ContainsTokenOptions
6+
import ch.ergon.dope.resolvable.expression.type.toDopeType
7+
import ch.ergon.dope.validtype.BooleanType
8+
import ch.ergon.dope.validtype.StringType
9+
import ch.ergon.dope.validtype.ValidType
10+
11+
data class ContainsTokenRegexpExpression(
12+
val inputObject: TypeExpression<out ValidType>,
13+
val tokenExpression: TypeExpression<StringType>,
14+
val options: ContainsTokenOptions? = null,
15+
) : FunctionOperator<BooleanType>
16+
17+
fun TypeExpression<out ValidType>.containsTokenRegexp(
18+
tokenExpression: TypeExpression<StringType>,
19+
options: ContainsTokenOptions? = null,
20+
) = ContainsTokenRegexpExpression(this, tokenExpression, options)
21+
22+
fun TypeExpression<out ValidType>.containsTokenRegexp(
23+
tokenExpression: String,
24+
options: ContainsTokenOptions? = null,
25+
) = containsTokenRegexp(tokenExpression.toDopeType(), options)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package ch.ergon.dope.resolvable.expression.type.function.token
2+
3+
import ch.ergon.dope.resolvable.expression.operator.FunctionOperator
4+
import ch.ergon.dope.resolvable.expression.type.TypeExpression
5+
import ch.ergon.dope.resolvable.expression.type.function.token.factory.CustomTokenOptions
6+
import ch.ergon.dope.resolvable.expression.type.toDopeType
7+
import ch.ergon.dope.validtype.ArrayType
8+
import ch.ergon.dope.validtype.StringType
9+
10+
data class TokensExpression(
11+
val inString: TypeExpression<ArrayType<StringType>>,
12+
val options: CustomTokenOptions? = null,
13+
) : FunctionOperator<ArrayType<StringType>>
14+
15+
fun TypeExpression<ArrayType<StringType>>.tokens(options: CustomTokenOptions? = null) = TokensExpression(this, options)
16+
17+
fun List<String>.tokens(options: CustomTokenOptions? = null) = toDopeType().tokens(options)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package ch.ergon.dope.resolvable.expression.type.function.token.factory
2+
3+
import ch.ergon.dope.resolvable.Resolvable
4+
5+
data class ContainsTokenOptions(
6+
val names: Boolean? = null,
7+
val case: TokenCases? = null,
8+
val specials: Boolean? = null,
9+
val split: Boolean? = null,
10+
val trim: Boolean? = null,
11+
) : Resolvable
12+
13+
fun containsTokenOptions(
14+
names: Boolean? = null,
15+
case: TokenCases? = null,
16+
specials: Boolean? = null,
17+
split: Boolean? = null,
18+
trim: Boolean? = null,
19+
) = ContainsTokenOptions(names, case, specials, split, trim)

core/src/main/kotlin/ch/ergon/dope/resolvable/expression/type/function/string/factory/Tokens.kt renamed to core/src/main/kotlin/ch/ergon/dope/resolvable/expression/type/function/token/factory/Tokens.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package ch.ergon.dope.resolvable.expression.type.function.string.factory
1+
package ch.ergon.dope.resolvable.expression.type.function.token.factory
22

33
import ch.ergon.dope.resolvable.Resolvable
44

couchbase/src/main/kotlin/ch/ergon/dope/couchbase/resolver/CouchbaseResolver.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import ch.ergon.dope.resolvable.expression.rowscope.windowdefinition.WindowDefin
3030
import ch.ergon.dope.resolvable.expression.rowscope.windowdefinition.WindowFrameClause
3131
import ch.ergon.dope.resolvable.expression.type.CaseClass
3232
import ch.ergon.dope.resolvable.expression.type.ObjectEntryPrimitive
33-
import ch.ergon.dope.resolvable.expression.type.function.string.factory.CustomTokenOptions
33+
import ch.ergon.dope.resolvable.expression.type.function.token.factory.ContainsTokenOptions
34+
import ch.ergon.dope.resolvable.expression.type.function.token.factory.CustomTokenOptions
3435
import ch.ergon.dope.resolver.QueryResolver
3536

3637
interface AbstractCouchbaseResolver : QueryResolver<CouchbaseDopeQuery> {
@@ -88,6 +89,8 @@ class CouchbaseResolver(
8889

8990
is Asterisk -> resolve(resolvable)
9091

92+
is ContainsTokenOptions -> resolve(resolvable)
93+
9194
is CustomTokenOptions -> resolve(resolvable)
9295

9396
is HashOrNestedLoopHint -> resolve(resolvable)

couchbase/src/main/kotlin/ch/ergon/dope/couchbase/resolver/expression/FunctionOperatorResolver.kt

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ch.ergon.dope.couchbase.util.formatFunctionQueryString
77
import ch.ergon.dope.merge
88
import ch.ergon.dope.orEmpty
99
import ch.ergon.dope.resolvable.expression.operator.FunctionOperator
10+
import ch.ergon.dope.resolvable.expression.type.TypeExpression
1011
import ch.ergon.dope.resolvable.expression.type.function.FunctionExpression
1112
import ch.ergon.dope.resolvable.expression.type.function.array.ArrayFunctionExpression
1213
import ch.ergon.dope.resolvable.expression.type.function.conditional.DecodeExpression
@@ -17,9 +18,15 @@ import ch.ergon.dope.resolvable.expression.type.function.search.ISearchFunctionE
1718
import ch.ergon.dope.resolvable.expression.type.function.search.SearchDependencyFunctionExpression
1819
import ch.ergon.dope.resolvable.expression.type.function.search.SearchFunctionType
1920
import ch.ergon.dope.resolvable.expression.type.function.string.MaskExpression
20-
import ch.ergon.dope.resolvable.expression.type.function.string.TokensExpression
21+
import ch.ergon.dope.resolvable.expression.type.function.token.ContainsTokenExpression
22+
import ch.ergon.dope.resolvable.expression.type.function.token.ContainsTokenLikeExpression
23+
import ch.ergon.dope.resolvable.expression.type.function.token.ContainsTokenRegexpExpression
24+
import ch.ergon.dope.resolvable.expression.type.function.token.TokensExpression
25+
import ch.ergon.dope.resolvable.expression.type.function.token.factory.ContainsTokenOptions
2126
import ch.ergon.dope.resolvable.expression.type.function.type.ToNumberExpression
2227
import ch.ergon.dope.resolvable.expression.type.toDopeType
28+
import ch.ergon.dope.validtype.StringType
29+
import ch.ergon.dope.validtype.ValidType
2330

2431
interface FunctionOperatorResolver : AbstractCouchbaseResolver {
2532
fun resolve(typeExpression: FunctionOperator<*>): CouchbaseDopeQuery = when (typeExpression) {
@@ -78,16 +85,37 @@ interface FunctionOperatorResolver : AbstractCouchbaseResolver {
7885
}
7986

8087
is TokensExpression -> {
81-
val inString = typeExpression.inStr.toDopeType().toDopeQuery(this)
88+
val inStringDopeQuery = typeExpression.inString.toDopeQuery(this)
8289
val optionsDopeQuery = typeExpression.options?.toDopeQuery(this).takeIf { !it?.queryString.isNullOrEmpty() }
8390
val functionQueryString = formatFunctionQueryString(
8491
"TOKENS",
85-
inString.queryString,
92+
inStringDopeQuery.queryString,
8693
optionsDopeQuery?.queryString,
8794
)
8895
CouchbaseDopeQuery(functionQueryString, optionsDopeQuery?.parameters.orEmpty())
8996
}
9097

98+
is ContainsTokenExpression -> resolveContainsTokenFunction(
99+
"CONTAINS_TOKEN",
100+
typeExpression.inputObject,
101+
typeExpression.tokenExpression,
102+
typeExpression.options,
103+
)
104+
105+
is ContainsTokenLikeExpression -> resolveContainsTokenFunction(
106+
"CONTAINS_TOKEN_LIKE",
107+
typeExpression.inputObject,
108+
typeExpression.tokenExpression,
109+
typeExpression.options,
110+
)
111+
112+
is ContainsTokenRegexpExpression -> resolveContainsTokenFunction(
113+
"CONTAINS_TOKEN_REGEXP",
114+
typeExpression.inputObject,
115+
typeExpression.tokenExpression,
116+
typeExpression.options,
117+
)
118+
91119
is MaskExpression -> {
92120
val inputStringDopeQuery = typeExpression.inStr.toDopeQuery(this)
93121
val optionsString =
@@ -187,4 +215,25 @@ interface FunctionOperatorResolver : AbstractCouchbaseResolver {
187215

188216
else -> throw UnsupportedOperationException("Not supported: $typeExpression")
189217
}
218+
219+
private fun resolveContainsTokenFunction(
220+
symbol: String,
221+
inputObject: TypeExpression<out ValidType>,
222+
tokenExpression: TypeExpression<StringType>,
223+
options: ContainsTokenOptions?,
224+
): CouchbaseDopeQuery {
225+
val inputObjectDopeQuery = inputObject.toDopeQuery(this)
226+
val tokenExpressionDopeQuery = tokenExpression.toDopeQuery(this)
227+
val optionsDopeQuery = options?.toDopeQuery(this).takeIf { !it?.queryString.isNullOrEmpty() }
228+
val functionQueryString = formatFunctionQueryString(
229+
symbol,
230+
inputObjectDopeQuery.queryString,
231+
tokenExpressionDopeQuery.queryString,
232+
optionsDopeQuery?.queryString,
233+
)
234+
return CouchbaseDopeQuery(
235+
functionQueryString,
236+
inputObjectDopeQuery.parameters.merge(tokenExpressionDopeQuery.parameters, optionsDopeQuery?.parameters),
237+
)
238+
}
190239
}

couchbase/src/main/kotlin/ch/ergon/dope/couchbase/resolver/expression/TypeExpressionResolver.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ import ch.ergon.dope.resolvable.expression.type.collection.SatisfiesExpression
4040
import ch.ergon.dope.resolvable.expression.type.function.array.UnpackExpression
4141
import ch.ergon.dope.resolvable.expression.type.function.date.DateComponentType
4242
import ch.ergon.dope.resolvable.expression.type.function.date.DateUnitType
43-
import ch.ergon.dope.resolvable.expression.type.function.string.factory.CustomTokenOptions
43+
import ch.ergon.dope.resolvable.expression.type.function.token.factory.ContainsTokenOptions
44+
import ch.ergon.dope.resolvable.expression.type.function.token.factory.CustomTokenOptions
4445
import ch.ergon.dope.resolvable.expression.type.range.RangeIndexedLike
4546
import ch.ergon.dope.resolvable.expression.type.range.RangeLike
4647
import ch.ergon.dope.resolvable.expression.type.relational.BetweenExpression
@@ -380,4 +381,20 @@ interface TypeExpressionResolver : InfixOperatorResolver, FunctionOperatorResolv
380381

381382
return CouchbaseDopeQuery(queryString = queryString)
382383
}
384+
385+
fun resolve(containsTokenOptions: ContainsTokenOptions): CouchbaseDopeQuery {
386+
val options = listOfNotNull(
387+
containsTokenOptions.names?.let { "names" to it },
388+
containsTokenOptions.case?.let { "case" to "\"${it.queryString}\"" },
389+
containsTokenOptions.specials?.let { "specials" to it },
390+
containsTokenOptions.split?.let { "split" to it },
391+
containsTokenOptions.trim?.let { "trim" to it },
392+
)
393+
val queryString = options
394+
.joinToString(", ", "{", "}") { (key, value) -> "\"$key\": $value" }
395+
.takeIf { options.isNotEmpty() }
396+
.orEmpty()
397+
398+
return CouchbaseDopeQuery(queryString = queryString)
399+
}
383400
}

0 commit comments

Comments
 (0)