improve whitespace handling in text classifier (#1696)
This commit is contained in:
@@ -17,33 +17,34 @@ internal interface TextClassifier {
|
|||||||
|
|
||||||
internal class TextClassifierImpl : TextClassifier {
|
internal class TextClassifierImpl : TextClassifier {
|
||||||
override suspend fun classify(context: Context, query: String): TextClassificationResult {
|
override suspend fun classify(context: Context, query: String): TextClassificationResult {
|
||||||
|
val trimmedQuery = query.trim()
|
||||||
return when {
|
return when {
|
||||||
query.matches(Regex("^\\S+@\\S+$")) -> TextClassificationResult(
|
trimmedQuery.matches(Regex("^\\S+@\\S+$")) -> TextClassificationResult(
|
||||||
type = TextType.Email,
|
type = TextType.Email,
|
||||||
text = query,
|
text = trimmedQuery,
|
||||||
email = query
|
email = trimmedQuery
|
||||||
)
|
)
|
||||||
|
|
||||||
query.matches(Regex("^\\+?[0-9- /.]{4,18}$")) -> TextClassificationResult(
|
trimmedQuery.matches(Regex("^\\+?[0-9- /.]{4,18}$")) -> TextClassificationResult(
|
||||||
type = TextType.PhoneNumber,
|
type = TextType.PhoneNumber,
|
||||||
text = query,
|
text = trimmedQuery,
|
||||||
phoneNumber = query
|
phoneNumber = trimmedQuery
|
||||||
)
|
)
|
||||||
|
|
||||||
query.matches(Regex("^(http(s)?://.)?(www\\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$")) -> TextClassificationResult(
|
trimmedQuery.matches(Regex("^(http(s)?://.)?(www\\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$")) -> TextClassificationResult(
|
||||||
type = TextType.Url,
|
type = TextType.Url,
|
||||||
text = query,
|
text = trimmedQuery,
|
||||||
url = query
|
url = trimmedQuery
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
parseDate(context, query)?.let { return it }
|
parseDate(context, trimmedQuery)?.let { return it }
|
||||||
TextClassificationResult(type = TextType.Text, text = query)
|
TextClassificationResult(type = TextType.Text, text = trimmedQuery)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseDate(context: Context, query: String): TextClassificationResult? {
|
private fun parseDate(context: Context, trimmedQuery: String): TextClassificationResult? {
|
||||||
val dateTimeFormat = SimpleDateFormat(
|
val dateTimeFormat = SimpleDateFormat(
|
||||||
DateFormat.getBestDateTimePattern(
|
DateFormat.getBestDateTimePattern(
|
||||||
Locale.getDefault(),
|
Locale.getDefault(),
|
||||||
@@ -52,11 +53,11 @@ internal class TextClassifierImpl : TextClassifier {
|
|||||||
context.resources.configuration.locales[0]
|
context.resources.configuration.locales[0]
|
||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
dateTimeFormat.parse(query)?.let {
|
dateTimeFormat.parse(trimmedQuery)?.let {
|
||||||
val dateTime = LocalDateTime.ofInstant(it.toInstant(), ZoneId.systemDefault())
|
val dateTime = LocalDateTime.ofInstant(it.toInstant(), ZoneId.systemDefault())
|
||||||
return TextClassificationResult(
|
return TextClassificationResult(
|
||||||
type = TextType.DateTime,
|
type = TextType.DateTime,
|
||||||
text = query,
|
text = trimmedQuery,
|
||||||
time = dateTime.toLocalTime(),
|
time = dateTime.toLocalTime(),
|
||||||
date = dateTime.toLocalDate(),
|
date = dateTime.toLocalDate(),
|
||||||
)
|
)
|
||||||
@@ -66,10 +67,10 @@ internal class TextClassifierImpl : TextClassifier {
|
|||||||
}
|
}
|
||||||
val dateFormat = DateFormat.getDateFormat(context)
|
val dateFormat = DateFormat.getDateFormat(context)
|
||||||
try {
|
try {
|
||||||
dateFormat.parse(query)?.let {
|
dateFormat.parse(trimmedQuery)?.let {
|
||||||
return TextClassificationResult(
|
return TextClassificationResult(
|
||||||
type = TextType.Date,
|
type = TextType.Date,
|
||||||
text = query,
|
text = trimmedQuery,
|
||||||
date = LocalDateTime.ofInstant(it.toInstant(), ZoneId.systemDefault())
|
date = LocalDateTime.ofInstant(it.toInstant(), ZoneId.systemDefault())
|
||||||
.toLocalDate()
|
.toLocalDate()
|
||||||
)
|
)
|
||||||
@@ -85,10 +86,10 @@ internal class TextClassifierImpl : TextClassifier {
|
|||||||
context.resources.configuration.locales[0]
|
context.resources.configuration.locales[0]
|
||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
timeFormat.parse(query)?.let {
|
timeFormat.parse(trimmedQuery)?.let {
|
||||||
return TextClassificationResult(
|
return TextClassificationResult(
|
||||||
type = TextType.Time,
|
type = TextType.Time,
|
||||||
text = query,
|
text = trimmedQuery,
|
||||||
time = LocalDateTime.ofInstant(it.toInstant(), ZoneId.systemDefault())
|
time = LocalDateTime.ofInstant(it.toInstant(), ZoneId.systemDefault())
|
||||||
.toLocalTime(),
|
.toLocalTime(),
|
||||||
)
|
)
|
||||||
@@ -98,40 +99,46 @@ internal class TextClassifierImpl : TextClassifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val seconds = context.getString(R.string.unit_second_symbol)
|
val seconds = context.getString(R.string.unit_second_symbol)
|
||||||
if (query.matches(Regex("^[0-9]+ ${seconds}$"))) {
|
val secondsMatch = Regex("^([0-9]+)\\s?${seconds}$").find(trimmedQuery)
|
||||||
val value = query.substringBefore(" ").toLong()
|
if (secondsMatch != null) {
|
||||||
|
val value = secondsMatch.groups[1]!!.value.toLong()
|
||||||
return TextClassificationResult(
|
return TextClassificationResult(
|
||||||
type = TextType.Timespan,
|
type = TextType.Timespan,
|
||||||
text = query,
|
text = trimmedQuery,
|
||||||
timespan = Duration.ofSeconds(value)
|
timespan = Duration.ofSeconds(value)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val days = context.getString(R.string.unit_day_symbol)
|
val days = context.getString(R.string.unit_day_symbol)
|
||||||
if (query.matches(Regex("^[0-9]+ ${days}$"))) {
|
val daysMatch = Regex("^([0-9]+)\\s?${days}$").find(trimmedQuery)
|
||||||
val value = query.substringBefore(" ").toLong()
|
if (daysMatch != null) {
|
||||||
|
val value = daysMatch.groups[1]!!.value.toLong()
|
||||||
return TextClassificationResult(
|
return TextClassificationResult(
|
||||||
type = TextType.Timespan,
|
type = TextType.Timespan,
|
||||||
text = query,
|
text = trimmedQuery,
|
||||||
timespan = Duration.ofDays(value)
|
timespan = Duration.ofDays(value)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val minutes = context.getString(R.string.unit_minute_symbol)
|
val minutes = context.getString(R.string.unit_minute_symbol)
|
||||||
if (query.matches(Regex("^[0-9]+ ${minutes}$"))) {
|
val minutesMatch = Regex("^([0-9]+)\\s?${minutes}$").find(trimmedQuery)
|
||||||
val value = query.substringBefore(" ").toLong()
|
if (minutesMatch != null) {
|
||||||
|
val value = minutesMatch.groups[1]!!.value.toLong()
|
||||||
val then = LocalDateTime.now().plusMinutes(value)
|
val then = LocalDateTime.now().plusMinutes(value)
|
||||||
return TextClassificationResult(
|
return TextClassificationResult(
|
||||||
type = TextType.Timespan,
|
type = TextType.Timespan,
|
||||||
text = query,
|
text = trimmedQuery,
|
||||||
timespan = Duration.ofMinutes(value)
|
timespan = Duration.ofMinutes(value)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val hours = context.getString(R.string.unit_hour_symbol)
|
val hours = context.getString(R.string.unit_hour_symbol)
|
||||||
if (query.matches(Regex("^[0-9]+ ${hours}$"))) {
|
val hoursMatch = Regex("^([0-9]+)\\s?${hours}$").find(trimmedQuery)
|
||||||
val value = query.substringBefore(" ").toLong()
|
if (hoursMatch != null) {
|
||||||
|
val value = hoursMatch.groups[1]!!.value.toLong()
|
||||||
return TextClassificationResult(
|
return TextClassificationResult(
|
||||||
type = TextType.Timespan,
|
type = TextType.Timespan,
|
||||||
text = query,
|
text = trimmedQuery,
|
||||||
timespan = Duration.ofHours(value)
|
timespan = Duration.ofHours(value)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user