code cleanup
This commit is contained in:
parent
fd93a03576
commit
9117f5d6d5
|
@ -1,149 +0,0 @@
|
||||||
/*
|
|
||||||
* Twidere - Twitter client for Android
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<SQLSelectQuery, String[]> 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<SQLSelectQuery, String[]> 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<SQLSelectQuery, String[]> 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<SQLSelectQuery, String[]> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,18 +1,18 @@
|
||||||
/*
|
/*
|
||||||
* Twidere - Twitter client for Android
|
* Twidere - Twitter client for Android
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
@ -248,7 +248,7 @@ object Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getColumnsFromProjection(vararg projection: String): Selectable {
|
fun getColumnsFromProjection(projection: Array<String>?): Selectable {
|
||||||
if (projection == null) return AllColumns()
|
if (projection == null) return AllColumns()
|
||||||
val length = projection.size
|
val length = projection.size
|
||||||
val columns = arrayOfNulls<Column>(length)
|
val columns = arrayOfNulls<Column>(length)
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* Twidere - Twitter client for Android
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<String>?,
|
||||||
|
selection: String?,
|
||||||
|
selectionArgs: Array<String>?,
|
||||||
|
sortOrder: String?,
|
||||||
|
accountKey: UserKey): Pair<SQLSelectQuery, Array<String>> {
|
||||||
|
return withRelationship(Utils.getColumnsFromProjection(projection), selection,
|
||||||
|
selectionArgs, sortOrder, accountKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withRelationship(select: Selectable,
|
||||||
|
selection: String?,
|
||||||
|
selectionArgs: Array<String>?,
|
||||||
|
sortOrder: String?,
|
||||||
|
accountKey: UserKey): Pair<SQLSelectQuery, Array<String>> {
|
||||||
|
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<String>
|
||||||
|
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<SQLSelectQuery, Array<String>>(qb.build(), mergedArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withScore(projection: Array<String>?,
|
||||||
|
selection: String?,
|
||||||
|
selectionArgs: Array<String>?,
|
||||||
|
sortOrder: String?,
|
||||||
|
accountKey: UserKey,
|
||||||
|
limit: Int): Pair<SQLSelectQuery, Array<String>> {
|
||||||
|
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<SQLSelectQuery, Array<String>>(qb.build(), mergedArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun valueOrZero(column: String): String = "CASE WHEN $column IS NULL THEN 0 ELSE $column END"
|
||||||
|
|
||||||
|
}
|
|
@ -134,7 +134,7 @@ object SuggestionsCursorCreator {
|
||||||
val whereArgs = nicknameKeys + queryEscaped + queryEscaped
|
val whereArgs = nicknameKeys + queryEscaped + queryEscaped
|
||||||
val orderBy = arrayOf(CachedUsers.SCORE, CachedUsers.LAST_SEEN, CachedUsers.SCREEN_NAME, CachedUsers.NAME)
|
val orderBy = arrayOf(CachedUsers.SCORE, CachedUsers.LAST_SEEN, CachedUsers.SCREEN_NAME, CachedUsers.NAME)
|
||||||
val ascending = booleanArrayOf(false, false, true, true)
|
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,
|
val (sql, bindingArgs) = CachedUsersQueryBuilder.withScore(mappedProjection,
|
||||||
where.sql, whereArgs, OrderBy(orderBy, ascending).sql, accountKey, 0)
|
where.sql, whereArgs, OrderBy(orderBy, ascending).sql, accountKey, 0)
|
||||||
return db.rawQuery(sql.sql, bindingArgs)
|
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 order = arrayOf(CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME, CachedUsers.NAME)
|
||||||
val ascending = booleanArrayOf(false, false, true, true)
|
val ascending = booleanArrayOf(false, false, true, true)
|
||||||
val orderBy = OrderBy(order, ascending)
|
val orderBy = OrderBy(order, ascending)
|
||||||
val usersProjection = selection.mapToArray { suggestionUsersProjectionMap[it] }
|
val usersProjection = selection.mapToArray { suggestionUsersProjectionMap[it]!! }
|
||||||
val usersQuery = CachedUsersQueryBuilder.withScore(usersProjection,
|
val usersQuery = CachedUsersQueryBuilder.withScore(usersProjection,
|
||||||
usersSelection.sql, selectionArgs, orderBy.sql, accountKey, 0)
|
usersSelection.sql, selectionArgs, orderBy.sql, accountKey, 0)
|
||||||
return db.rawQuery(usersQuery.first.sql, usersQuery.second)
|
return db.rawQuery(usersQuery.first.sql, usersQuery.second)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Twidere - Twitter client for Android
|
* Twidere - Twitter client for Android
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -33,9 +33,9 @@ class SystemHosts {
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun resolve(hostToResolve: String): List<InetAddress> {
|
fun resolve(hostToResolve: String): List<InetAddress> {
|
||||||
File(HOSTS_PATH).bufferedReader().use {
|
File(HOSTS_PATH).bufferedReader().use {
|
||||||
var line: String?
|
var line: String
|
||||||
do {
|
while (true) {
|
||||||
line = it.readLine()
|
line = it.readLine() ?: break
|
||||||
val scanner = Scanner(line)
|
val scanner = Scanner(line)
|
||||||
if (!scanner.hasNext()) continue
|
if (!scanner.hasNext()) continue
|
||||||
val address = scanner.next()
|
val address = scanner.next()
|
||||||
|
@ -48,7 +48,7 @@ class SystemHosts {
|
||||||
return listOf(resolved)
|
return listOf(resolved)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (line != null)
|
}
|
||||||
}
|
}
|
||||||
throw UnknownHostException(hostToResolve)
|
throw UnknownHostException(hostToResolve)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue