diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/database/CachedUsersQueryBuilder.java b/twidere/src/main/java/org/mariotaku/twidere/util/database/CachedUsersQueryBuilder.java deleted file mode 100644 index f8db67b2e..000000000 --- a/twidere/src/main/java/org/mariotaku/twidere/util/database/CachedUsersQueryBuilder.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2017 Mariotaku Lee - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.mariotaku.twidere.util.database; - -import org.mariotaku.sqliteqb.library.Columns; -import org.mariotaku.sqliteqb.library.Expression; -import org.mariotaku.sqliteqb.library.Join; -import org.mariotaku.sqliteqb.library.OrderBy; -import org.mariotaku.sqliteqb.library.Selectable; -import org.mariotaku.sqliteqb.library.Table; -import org.mariotaku.sqliteqb.library.Tables; -import org.mariotaku.sqliteqb.library.query.SQLSelectQuery; -import org.mariotaku.twidere.model.UserKey; -import org.mariotaku.twidere.provider.TwidereDataStore; -import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships; -import org.mariotaku.twidere.util.TwidereArrayUtils; -import org.mariotaku.twidere.util.Utils; - -import java.util.Locale; - -import kotlin.Pair; - -/** - * Created by mariotaku on 2017/2/17. - */ -public final class CachedUsersQueryBuilder { - - private CachedUsersQueryBuilder() { - } - - public static Pair withRelationship(final String[] projection, - final String selection, - final String[] selectionArgs, - final String sortOrder, - final UserKey accountKey) { - return withRelationship(Utils.INSTANCE.getColumnsFromProjection(projection), selection, - selectionArgs, sortOrder, accountKey); - } - - public static Pair withRelationship(final Selectable select, - final String selection, - final String[] selectionArgs, - final String sortOrder, - final UserKey accountKey) { - final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder(); - qb.select(select).from(new Tables(TwidereDataStore.CachedUsers.TABLE_NAME)); - final Columns.Column relationshipsUserKey = new Columns.Column(new Table(CachedRelationships.TABLE_NAME), - CachedRelationships.USER_KEY); - final Columns.Column usersUserKey = new Columns.Column(new Table(TwidereDataStore.CachedUsers.TABLE_NAME), - CachedRelationships.USER_KEY); - final Columns.Column relationshipsAccountKey = new Columns.Column(new Table(CachedRelationships.TABLE_NAME), - CachedRelationships.ACCOUNT_KEY); - final Expression on = Expression.and( - Expression.equals(relationshipsUserKey, usersUserKey), - Expression.equalsArgs(relationshipsAccountKey.getSQL()) - ); - qb.join(new Join(false, Join.Operation.LEFT, new Table(CachedRelationships.TABLE_NAME), on)); - final Expression userTypeExpression; - final String host = accountKey.getHost(); - final String[] accountKeyArgs; - if (host == null) { - userTypeExpression = Expression.notLikeRaw(new Columns.Column(new Table(TwidereDataStore.CachedUsers.TABLE_NAME), - TwidereDataStore.CachedUsers.USER_KEY), "'%@%'"); - accountKeyArgs = new String[]{accountKey.toString()}; - } else { - userTypeExpression = Expression.likeRaw(new Columns.Column(new Table(TwidereDataStore.CachedUsers.TABLE_NAME), - TwidereDataStore.CachedUsers.USER_KEY), "'%@'||?"); - accountKeyArgs = new String[]{accountKey.toString(), host}; - } - if (selection != null) { - qb.where(Expression.and(userTypeExpression, new Expression(selection))); - } else { - qb.where(userTypeExpression); - } - if (sortOrder != null) { - qb.orderBy(new OrderBy(sortOrder)); - } - final String[] mergedArgs = new String[TwidereArrayUtils.arraysLength(accountKeyArgs, selectionArgs)]; - TwidereArrayUtils.mergeArray(mergedArgs, accountKeyArgs, selectionArgs); - return new Pair<>(qb.build(), mergedArgs); - } - - public static Pair withScore(final String[] projection, - final String selection, - final String[] selectionArgs, - final String sortOrder, - final UserKey accountKey, - final int limit) { - final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder(); - final Selectable select = Utils.INSTANCE.getColumnsFromProjection(projection); - final Columns.Column[] columns = new Columns.Column[TwidereDataStore.CachedUsers.COLUMNS.length + 1]; - for (int i = 0, j = columns.length - 1; i < j; i++) { - final String column = TwidereDataStore.CachedUsers.COLUMNS[i]; - if (TwidereDataStore.CachedUsers._ID.equals(column) || TwidereDataStore.CachedUsers.USER_KEY.equals(column)) { - columns[i] = new Columns.Column(new Table(TwidereDataStore.CachedUsers.TABLE_NAME), column, column); - } else { - columns[i] = new Columns.Column(column); - } - } - final String expr = String.format(Locale.ROOT, "%s * 100 + %s * 50 + %s * 50 - %s * 100 - %s * 100 - %s * 100", - valueOrZero(CachedRelationships.FOLLOWING, CachedRelationships.NOTIFICATIONS_ENABLED, - CachedRelationships.FOLLOWED_BY, CachedRelationships.BLOCKING, - CachedRelationships.BLOCKED_BY, CachedRelationships.MUTING)); - columns[columns.length - 1] = new Columns.Column(expr, "score"); - qb.select(select); - final Pair pair = withRelationship(new Columns(columns), null, - null, null, accountKey); - qb.from(pair.getFirst()); - final String[] mergedArgs = new String[TwidereArrayUtils.arraysLength(pair.getSecond(), selectionArgs)]; - TwidereArrayUtils.mergeArray(mergedArgs, pair.getSecond(), selectionArgs); - if (selection != null) { - qb.where(new Expression(selection)); - } - if (sortOrder != null) { - qb.orderBy(new OrderBy(sortOrder)); - } - if (limit > 0) { - qb.limit(limit); - } - return new Pair<>(qb.build(), mergedArgs); - } - - private static Object[] valueOrZero(String... columns) { - final String[] result = new String[columns.length]; - for (int i = 0, j = columns.length; i < j; i++) { - result[i] = String.format(Locale.ROOT, "CASE WHEN %s IS NULL THEN 0 ELSE %s END", - columns[i], columns[i]); - } - return result; - } - -} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/Utils.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/Utils.kt index 6ab33dc8e..8776590e1 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/Utils.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/Utils.kt @@ -1,18 +1,18 @@ /* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2014 Mariotaku Lee - * + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -248,7 +248,7 @@ object Utils { } - fun getColumnsFromProjection(vararg projection: String): Selectable { + fun getColumnsFromProjection(projection: Array?): Selectable { if (projection == null) return AllColumns() val length = projection.size val columns = arrayOfNulls(length) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/database/CachedUsersQueryBuilder.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/database/CachedUsersQueryBuilder.kt new file mode 100644 index 000000000..f42eee001 --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/database/CachedUsersQueryBuilder.kt @@ -0,0 +1,134 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.mariotaku.twidere.util.database + +import org.mariotaku.ktextension.mapToArray +import org.mariotaku.sqliteqb.library.* +import org.mariotaku.sqliteqb.library.query.SQLSelectQuery +import org.mariotaku.twidere.model.UserKey +import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships +import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers +import org.mariotaku.twidere.util.Utils + +/** + * Created by mariotaku on 2017/2/17. + */ +object CachedUsersQueryBuilder { + + val scoreExpr = "${valueOrZero(CachedRelationships.FOLLOWING)} * 100 + " + + "${valueOrZero(CachedRelationships.NOTIFICATIONS_ENABLED)} * 50 + " + + "${valueOrZero(CachedRelationships.FOLLOWED_BY)} * 50 - " + + "${valueOrZero(CachedRelationships.BLOCKING)} * 100 - " + + "${valueOrZero(CachedRelationships.BLOCKED_BY)} * 100 - " + + "${valueOrZero(CachedRelationships.MUTING)} * 100" + + fun withRelationship(projection: Array?, + selection: String?, + selectionArgs: Array?, + sortOrder: String?, + accountKey: UserKey): Pair> { + return withRelationship(Utils.getColumnsFromProjection(projection), selection, + selectionArgs, sortOrder, accountKey) + } + + fun withRelationship(select: Selectable, + selection: String?, + selectionArgs: Array?, + sortOrder: String?, + accountKey: UserKey): Pair> { + val qb = SQLSelectQuery.Builder() + qb.select(select).from(Tables(CachedUsers.TABLE_NAME)) + val relationshipsUserKey = Columns.Column(Table(CachedRelationships.TABLE_NAME), + CachedRelationships.USER_KEY) + val usersUserKey = Columns.Column(Table(CachedUsers.TABLE_NAME), + CachedRelationships.USER_KEY) + val relationshipsAccountKey = Columns.Column(Table(CachedRelationships.TABLE_NAME), + CachedRelationships.ACCOUNT_KEY) + val on = Expression.and( + Expression.equals(relationshipsUserKey, usersUserKey), + Expression.equalsArgs(relationshipsAccountKey.sql) + ) + qb.join(Join(false, Join.Operation.LEFT, Table(CachedRelationships.TABLE_NAME), on)) + val userTypeExpression: Expression + val host = accountKey.host + val accountKeyArgs: Array + if (host == null) { + userTypeExpression = Expression.notLikeRaw(Columns.Column(Table(CachedUsers.TABLE_NAME), + CachedUsers.USER_KEY), "'%@%'") + accountKeyArgs = arrayOf(accountKey.toString()) + } else { + userTypeExpression = Expression.likeRaw(Columns.Column(Table(CachedUsers.TABLE_NAME), + CachedUsers.USER_KEY), "'%@'||?") + accountKeyArgs = arrayOf(accountKey.toString(), host) + } + if (selection != null) { + qb.where(Expression.and(userTypeExpression, Expression(selection))) + } else { + qb.where(userTypeExpression) + } + if (sortOrder != null) { + qb.orderBy(OrderBy(sortOrder)) + } + val mergedArgs = if (selectionArgs != null) { + accountKeyArgs + selectionArgs + } else { + accountKeyArgs + } + return Pair>(qb.build(), mergedArgs) + } + + fun withScore(projection: Array?, + selection: String?, + selectionArgs: Array?, + sortOrder: String?, + accountKey: UserKey, + limit: Int): Pair> { + val qb = SQLSelectQuery.Builder() + val select = Utils.getColumnsFromProjection(projection) + val columns = CachedUsers.COLUMNS.mapToArray { column -> + if (CachedUsers._ID == column || CachedUsers.USER_KEY == column) { + return@mapToArray Columns.Column(Table(CachedUsers.TABLE_NAME), column, column) + } else { + return@mapToArray Columns.Column(column) + } + } + Columns.Column(scoreExpr, "score") + qb.select(select) + val pair = withRelationship(Columns(*columns), null, null, null, accountKey) + qb.from(pair.first) + val mergedArgs = if (selectionArgs != null) { + pair.second + selectionArgs + } else { + pair.second + } + if (selection != null) { + qb.where(Expression(selection)) + } + if (sortOrder != null) { + qb.orderBy(OrderBy(sortOrder)) + } + if (limit > 0) { + qb.limit(limit) + } + return Pair>(qb.build(), mergedArgs) + } + + private fun valueOrZero(column: String): String = "CASE WHEN $column IS NULL THEN 0 ELSE $column END" + +} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/database/SuggestionsCursorCreator.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/database/SuggestionsCursorCreator.kt index b8286051d..1252decd3 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/database/SuggestionsCursorCreator.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/database/SuggestionsCursorCreator.kt @@ -134,7 +134,7 @@ object SuggestionsCursorCreator { val whereArgs = nicknameKeys + queryEscaped + queryEscaped val orderBy = arrayOf(CachedUsers.SCORE, CachedUsers.LAST_SEEN, CachedUsers.SCREEN_NAME, CachedUsers.NAME) val ascending = booleanArrayOf(false, false, true, true) - val mappedProjection = nonNullProjection.mapToArray { autoCompleteUsersProjectionMap[it] } + val mappedProjection = nonNullProjection.mapToArray { autoCompleteUsersProjectionMap[it]!! } val (sql, bindingArgs) = CachedUsersQueryBuilder.withScore(mappedProjection, where.sql, whereArgs, OrderBy(orderBy, ascending).sql, accountKey, 0) return db.rawQuery(sql.sql, bindingArgs) @@ -162,7 +162,7 @@ object SuggestionsCursorCreator { val order = arrayOf(CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME, CachedUsers.NAME) val ascending = booleanArrayOf(false, false, true, true) val orderBy = OrderBy(order, ascending) - val usersProjection = selection.mapToArray { suggestionUsersProjectionMap[it] } + val usersProjection = selection.mapToArray { suggestionUsersProjectionMap[it]!! } val usersQuery = CachedUsersQueryBuilder.withScore(usersProjection, usersSelection.sql, selectionArgs, orderBy.sql, accountKey, 0) return db.rawQuery(usersQuery.first.sql, usersQuery.second) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/net/SystemHosts.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/net/SystemHosts.kt index 4c24e204d..2a7a6affb 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/net/SystemHosts.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/net/SystemHosts.kt @@ -1,7 +1,7 @@ /* - * Twidere - Twitter client for Android + * Twidere - Twitter client for Android * - * Copyright (C) 2012-2015 Mariotaku Lee + * Copyright (C) 2012-2017 Mariotaku Lee * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,9 +33,9 @@ class SystemHosts { @Throws(IOException::class) fun resolve(hostToResolve: String): List { File(HOSTS_PATH).bufferedReader().use { - var line: String? - do { - line = it.readLine() + var line: String + while (true) { + line = it.readLine() ?: break val scanner = Scanner(line) if (!scanner.hasNext()) continue val address = scanner.next() @@ -48,7 +48,7 @@ class SystemHosts { return listOf(resolved) } } - } while (line != null) + } } throw UnknownHostException(hostToResolve) }