リファクタ

This commit is contained in:
tateisu 2019-01-29 10:56:24 +09:00
parent df7384d1ff
commit 157306ca08
17 changed files with 74 additions and 142 deletions

View File

@ -147,3 +147,4 @@ repositories {
}
apply plugin: 'com.google.gms.google-services'

View File

@ -29,7 +29,7 @@ class TestDuplicateMap {
private fun genStatus(
parser : TootParser,
accountJson : JSONObject,
statusId : Long,
statusId : String,
uri : String?,
url : String?
):TootStatus{
@ -49,7 +49,7 @@ class TestDuplicateMap {
map : DuplicateMap,
parser : TootParser,
accountJson : JSONObject,
statusId : Long,
statusId : String,
uri : String?,
url : String?
) {
@ -80,7 +80,7 @@ class TestDuplicateMap {
map,
parser,
account1Json,
1L,
"1",
"http://${parser.linkHelper.host}/@${account1.username}/1",
"http://${parser.linkHelper.host}/@${account1.username}/1"
)
@ -89,7 +89,7 @@ class TestDuplicateMap {
map,
parser,
account1Json,
2L,
"2",
"http://${parser.linkHelper.host}/@${account1.username}/2",
"http://${parser.linkHelper.host}/@${account1.username}/2"
)
@ -98,7 +98,7 @@ class TestDuplicateMap {
map,
parser,
account1Json,
3L,
"3",
null, // "http://${parser.linkHelper.host}/@${account1.username}/3",
"http://${parser.linkHelper.host}/@${account1.username}/3"
)
@ -107,7 +107,7 @@ class TestDuplicateMap {
map,
parser,
account1Json,
4L,
"4",
null, // "http://${parser.linkHelper.host}/@${account1.username}/4",
null //"http://${parser.linkHelper.host}/@${account1.username}/4"
)
@ -116,7 +116,7 @@ class TestDuplicateMap {
map,
parser,
account1Json,
EntityId.INVALID_ID_LONG,
"",
null, // "http://${parser.linkHelper.host}/@${account1.username}/4",
null //"http://${parser.linkHelper.host}/@${account1.username}/4"
)

View File

@ -1618,7 +1618,7 @@ class ActMain : AppCompatActivity()
if(m.find()) {
try {
val host = m.group(1)
val status_id = EntityIdString(m.group(3))
val status_id = EntityId(m.group(3))
// ステータスをアプリ内で開く
Action_Toot.conversationOtherInstance(
@ -1642,7 +1642,7 @@ class ActMain : AppCompatActivity()
if(m.find()) {
try {
val host = m.group(1)
val status_id = EntityIdString(m.group(2))
val status_id = EntityId(m.group(2))
// ステータスをアプリ内で開く
Action_Toot.conversationOtherInstance(
this@ActMain,
@ -2296,7 +2296,7 @@ class ActMain : AppCompatActivity()
try {
// https://mastodon.juggler.jp/@SubwayTooter/(status_id)
val host = m.group(1)
val status_id = EntityIdString(m.group(3))
val status_id = EntityId(m.group(3))
if(accessInto.isNA || ! host.equals(accessInto.host, ignoreCase = true)) {
Action_Toot.conversationOtherInstance(
this@ActMain,
@ -2327,7 +2327,7 @@ class ActMain : AppCompatActivity()
try {
// https://misskey.xyz/notes/(id)
val host = m.group(1)
val status_id = EntityIdString(m.group(2))
val status_id = EntityId(m.group(2))
if(accessInto.isNA || ! host.equals(accessInto.host, ignoreCase = true)) {
Action_Toot.conversationOtherInstance(
this@ActMain,
@ -2358,7 +2358,7 @@ class ActMain : AppCompatActivity()
try {
// https://misskey.xyz/objects/(id)
val host = m.group(1)
// ステータスIDではないのでどのタンスで開くにせよ検索APIを通すことになるval object_id = EntityIdString(m.group(2))
// ステータスIDではないのでどのタンスで開くにせよ検索APIを通すことになるval object_id = EntityId(m.group(2))
Action_Toot.conversationOtherInstance(
this@ActMain,
opener.pos,
@ -2380,7 +2380,7 @@ class ActMain : AppCompatActivity()
try {
// https://misskey.xyz/notes/(id)
val host = m.group(1)
val status_id = EntityIdString(m.group(2))
val status_id = EntityId(m.group(2))
if(accessInto.isNA || ! host.equals(accessInto.host, ignoreCase = true)) {
Action_Toot.conversationOtherInstance(
this@ActMain,

View File

@ -11,7 +11,7 @@ import android.provider.BaseColumns
import android.util.JsonReader
import android.util.JsonToken
import android.util.JsonWriter
import jp.juggler.subwaytooter.api.entity.EntityIdString
import jp.juggler.subwaytooter.api.entity.EntityId
import jp.juggler.subwaytooter.table.*
import jp.juggler.util.*
import org.apache.commons.io.IOUtils
@ -73,7 +73,7 @@ object AppDataExporter {
}
is EntityIdString -> {
is EntityId -> {
writer.name(k)
writer.value(o.toString())
}

View File

@ -927,10 +927,10 @@ class Column(
when(type) {
TYPE_PROFILE, TYPE_LIST_TL, TYPE_LIST_MEMBER ->
profile_id == EntityIdString(getParamAt(params, 0))
profile_id == EntityId(getParamAt(params, 0))
TYPE_CONVERSATION, TYPE_BOOSTED_BY, TYPE_FAVOURITED_BY, TYPE_LOCAL_AROUND, TYPE_FEDERATED_AROUND, TYPE_ACCOUNT_AROUND ->
status_id == EntityIdString(getParamAt(params, 0))
status_id == EntityId(getParamAt(params, 0))
TYPE_HASHTAG -> getParamAt<String>(params, 0) == hashtag
@ -3446,7 +3446,7 @@ class Column(
} else {
val m = reMaxId.matcher(result.link_older)
if(m.find()) {
EntityIdString(m.group(1))
EntityId(m.group(1))
} else {
null
}
@ -3458,12 +3458,12 @@ class Column(
var m = reMinId.matcher(result.link_newer)
if(m.find()) {
bMinIdMatched = true
EntityIdString(m.group(1))
EntityId(m.group(1))
} else {
m = reSinceId.matcher(result.link_newer)
if(m.find()) {
bMinIdMatched = false
EntityIdString(m.group(1))
EntityId(m.group(1))
} else {
null
}

View File

@ -25,7 +25,6 @@ import jp.juggler.subwaytooter.api.TootApiCallback
import jp.juggler.subwaytooter.api.TootApiClient
import jp.juggler.subwaytooter.api.TootParser
import jp.juggler.subwaytooter.api.entity.EntityId
import jp.juggler.subwaytooter.api.entity.EntityIdString
import jp.juggler.subwaytooter.api.entity.TootNotification
import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.subwaytooter.table.*
@ -388,8 +387,8 @@ class PollingWorker private constructor(contextArg : Context) {
private fun getEntityOrderId(account : SavedAccount, src : JSONObject) : EntityId =
if( account.isMisskey){
when(val created_at = src.parseString("createdAt")) {
null -> EntityId.defaultString
else -> EntityIdString(TootStatus.parseTime(created_at).toString())
null -> EntityId.DEFAULT
else -> EntityId(TootStatus.parseTime(created_at).toString())
}
}else{
EntityId.mayDefault(src.parseString("id"))

View File

@ -238,8 +238,8 @@ internal class StreamReader(
when(event) {
"delete" -> when(payload){
is Long -> fireDeleteId(EntityIdString(payload.toString()))
is String ->fireDeleteId(EntityIdString(payload.toString()))
is Long -> fireDeleteId(EntityId(payload.toString()))
is String ->fireDeleteId(EntityId(payload.toString()))
else -> log.d("unsupported payload type. $payload")
}

View File

@ -163,7 +163,7 @@ object Action_Account {
if( this.ta != null) return r2
val jsonObject = JSONObject().apply{
put("id", EntityId.CONFIRMING_ID_LONG)
put("id", EntityId.CONFIRMING.toString() )
put("username",username)
put("acct",username)
put("acct",username)

View File

@ -742,7 +742,7 @@ object Action_Toot {
try {
val m = reDetailedStatusTime.matcher(string)
if(m.find()) {
local_status_id = EntityIdString(m.group(1))
local_status_id = EntityId(m.group(1))
}
} catch(ex : Throwable) {
log.e(ex, "openStatusRemote: can't parse status id from HTML data.")

View File

@ -8,45 +8,25 @@ import jp.juggler.util.getStringOrNull
import jp.juggler.util.notZero
import org.json.JSONObject
abstract class EntityId : Comparable<EntityId> {
class EntityId(val x : String) : Comparable<EntityId> {
companion object {
const val INVALID_ID_LONG = - 1L
const val CONFIRMING_ID_LONG = - 2L
// val defaultLong = EntityIdLong(INVALID_ID_LONG)
val defaultString = EntityIdString("")
// IDのパース失敗時にエラー扱いしたくない場合に使われる
internal val DEFAULT = EntityId("<>default")
// マストドンのアカウント作成APIで作成した直後は「IDが発行されてない」状態になる
val confirmingId = EntityIdString("-2")
internal val CONFIRMING = EntityId("<>confirming")
// fun mayDefault(x : Long?) = when(x) {
// null -> defaultLong
// else -> EntityIdLong(x)
// }
fun mayDefault(x : String?) = if(x==null) DEFAULT else EntityId(x)
fun mayDefault(x : String?) = when(x) {
null -> defaultString
else -> EntityIdString(x)
}
// fun mayNull(x : Long?) = when(x) {
// null -> null
// else -> EntityIdLong(x)
// }
fun mayNull(x : String?) = when(x) {
null -> null
else -> EntityIdString(x)
}
fun mayNull(x : String?) = if(x==null) null else EntityId(x)
fun String.decode() : EntityId? {
if(this.isEmpty()) return null
// first character is 'L' for EntityIdLong, 'S' for EntityIdString.
// integer id is removed at https://source.joinmastodon.org/mastodon/docs/commit/e086d478afa140e7b0b9a60183655315966ad9ff
return EntityIdString(this.substring(1))
return EntityId(this.substring(1))
}
fun from(intent : Intent?, key : String) =
@ -58,7 +38,7 @@ abstract class EntityId : Comparable<EntityId> {
// 内部保存データのデコード用。APIレスポンスのパースに使ってはいけない
fun from(data : JSONObject?, key : String) : EntityId? {
val o = data?.opt(key)
if(o is Long) return EntityIdString(o.toString())
if(o is Long) return EntityId(o.toString())
return (o as? String)?.decode()
}
@ -67,12 +47,7 @@ abstract class EntityId : Comparable<EntityId> {
}
private fun encode() : String {
val prefix = when(this) {
// integer id is removed at https://source.joinmastodon.org/mastodon/docs/commit/e086d478afa140e7b0b9a60183655315966ad9ff
// is EntityIdLong -> 'L'
is EntityIdString -> 'S'
else -> error("unknown type")
}
val prefix = 'S'
return "$prefix$this"
}
@ -87,15 +62,24 @@ abstract class EntityId : Comparable<EntityId> {
}
val isDefault : Boolean
get() = when(this) {
// integer id is removed at https://source.joinmastodon.org/mastodon/docs/commit/e086d478afa140e7b0b9a60183655315966ad9ff
// is EntityIdLong -> this == defaultLong
is EntityIdString -> this == defaultString
else -> false
}
get() = this == DEFAULT
val notDefault : Boolean
get() = ! isDefault
get() = this != DEFAULT
override fun compareTo(other : EntityId) : Int =
(x.length - other.x.length).notZero() ?: x.compareTo(other.x)
override fun equals(other : Any?) : Boolean = if(other is EntityId) {
x == other.x
} else {
false
}
override fun hashCode() = x.hashCode()
override fun toString() = x
}
fun EntityId?.putMayNull(cv : ContentValues, key : String) {
@ -106,55 +90,3 @@ fun EntityId?.putMayNull(cv : ContentValues, key : String) {
}
}
//class EntityIdLong(val x : Long) : EntityId() {
//
// override fun compareTo(other : EntityId) = when(other) {
// this -> 0
// is EntityIdLong -> x.compareTo(other.x)
// else -> error("EntityIdLong: compare with ${other::javaClass.name}")
// }
//
// override fun equals(other : Any?) = when(other) {
// is EntityIdLong -> x == other.x
// is EntityIdString -> x.toString() == other.x
// else -> false
// }
//
// override fun hashCode() = (x xor x.ushr(32)).toInt()
//
// override fun toString() = x.toString()
//
// override fun toLong() = x
//
// override fun putMisskeyUntil(dst : JSONObject) : JSONObject = dst.put("untilDate", x)
// override fun putMisskeySince(dst : JSONObject) : JSONObject = dst.put("sinceDate", x)
//
//}
class EntityIdString(val x : String) : EntityId() {
override fun compareTo(other : EntityId) = when(other) {
is EntityIdString -> {
// first: compare by length. '9' is smaller than '11'
// second: lexically order
(x.length - other.x.length).notZero() ?: x.compareTo(other.x)
}
else -> error("EntityIdString: compare with ${other::class.java.simpleName}")
}
override fun equals(other : Any?) = when(other) {
is EntityIdString -> x == other.x
// integer id is removed at https://source.joinmastodon.org/mastodon/docs/commit/e086d478afa140e7b0b9a60183655315966ad9ff
// is EntityIdLong -> x == other.x.toString()
else -> false
}
override fun hashCode() = x.hashCode()
override fun toString() = x
// override fun toLong() = x.toLong() // may throw exception.
// abstract fun toLong() : Long
}

View File

@ -14,5 +14,5 @@ abstract class TimelineItem{
// 大小比較のためのIDを取得する
// 比較が不要な場合は defaultString を返す
open fun getOrderId() :EntityId = EntityId.defaultString
open fun getOrderId() :EntityId = EntityId.DEFAULT
}

View File

@ -244,7 +244,7 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
ServiceType.TOOTSEARCH -> {
// tootsearch のアカウントのIDはどのタンス上のものか分からないので役に立たない
this.id = EntityId.defaultString
this.id = EntityId.DEFAULT
sv = src.notEmptyOrThrow("acct")
this.host = findHostFromUrl(sv, null, url)

View File

@ -181,7 +181,7 @@ class TootAttachment : TootAttachmentLike {
}
fun encodeJson() = jsonObject {
put(KEY_IS_STRING_ID, id is EntityIdString)
put(KEY_IS_STRING_ID, true)
put(KEY_ID, id.toString())
put(KEY_TYPE, type)
put(KEY_URL, url)

View File

@ -45,7 +45,7 @@ class TootRelationShip(parser:TootParser,src : JSONObject) {
init {
if( parser.serviceType == ServiceType.MISSKEY){
this.id = EntityId.defaultString
this.id = EntityId.DEFAULT
following = src.optBoolean("isFollowing")
followed_by = src.optBoolean("isFollowed")

View File

@ -206,7 +206,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
this.id = EntityId.mayDefault(misskeyId)
// ページネーションには日時を使う
this._orderId = EntityIdString(time_created_at.toString())
this._orderId = EntityId(time_created_at.toString())
// お気に入りカラムなどではパース直後に変更することがある
@ -397,7 +397,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
// 投稿元タンスでのIDを調べる。失敗するかもしれない
// FIXME: Pleromaだとダメそうな印象
this.uri = src.parseString("uri") ?: error("missing uri")
this.id = findStatusIdFromUri(uri, url) ?: EntityId.defaultString
this.id = findStatusIdFromUri(uri, url) ?: EntityId.DEFAULT
this.time_created_at = TootStatus.parseTime(this.created_at)
this.media_attachments = parseListOrNull(
@ -922,7 +922,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
fun validStatusId(src : EntityId?) : EntityId? =
when{
src == null -> null
src == EntityId.defaultString -> null
src == EntityId.DEFAULT -> null
src.toString().startsWith("-") -> null
else -> src
}
@ -941,29 +941,29 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
if(uri?.isNotEmpty() == true) {
// https://friends.nico/users/(who)/statuses/(status_id)
var m = reTootUriAP1.matcher(uri)
if(m.find()) return EntityIdString(m.group(2))
if(m.find()) return EntityId(m.group(2))
// https://server/@user/(status_id)
m = reTootUriAP2.matcher(uri)
if(m.find()) return EntityIdString(m.group(2))
if(m.find()) return EntityId(m.group(2))
// https://misskey.xyz/notes/5b802367744b650030a13640
m = reStatusPageMisskey.matcher(uri)
if( m.find()) return EntityIdString(m.group(2))
if( m.find()) return EntityId(m.group(2))
// https://pl.at7s.me/objects/feeb4399-cd7a-48c8-8999-b58868daaf43
// tootsearch中の投稿からIDを読めるようにしたい
// しかしこのURL中のuuidはステータスIDではないので、無意味
// m = reObjects.matcher(uri)
// if(m.find()) return EntityIdString(m.group(2))
// if(m.find()) return EntityId(m.group(2))
// https://pl.telteltel.com/notice/9fGFPu4LAgbrTby0xc
m = reStatusPageNotice.matcher(uri)
if(m.find()) return EntityIdString(m.group(2))
if(m.find()) return EntityId(m.group(2))
// tag:mstdn.osaka,2017-12-19:objectId=5672321:objectType=Status
m = reTootUriOS.matcher(uri)
if(m.find()) return EntityIdString(m.group(2))
if(m.find()) return EntityId(m.group(2))
log.w("can't parse status uri: $uri")
}
@ -972,25 +972,25 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
// https://friends.nico/users/(who)/statuses/(status_id)
var m = reTootUriAP1.matcher(url)
if(m.find()) return EntityIdString(m.group(2))
if(m.find()) return EntityId(m.group(2))
// https://friends.nico/@(who)/(status_id)
m = reTootUriAP2.matcher(url)
if(m.find()) return EntityIdString(m.group(2))
if(m.find()) return EntityId(m.group(2))
// https://misskey.xyz/notes/5b802367744b650030a13640
m = reStatusPageMisskey.matcher(url)
if( m.find()) return EntityIdString(m.group(2))
if( m.find()) return EntityId(m.group(2))
// https://pl.at7s.me/objects/feeb4399-cd7a-48c8-8999-b58868daaf43
// tootsearch中の投稿からIDを読めるようにしたい
// しかしこのURL中のuuidはステータスIDではないので、無意味
// m = reObjects.matcher(url)
// if(m.find()) return EntityIdString(m.group(2))
// if(m.find()) return EntityId(m.group(2))
// https://pl.telteltel.com/notice/9fGFPu4LAgbrTby0xc
m = reStatusPageNotice.matcher(url)
if(m.find()) return EntityIdString(m.group(2))
if(m.find()) return EntityId(m.group(2))
log.w("can't parse status URL: $url")

View File

@ -926,13 +926,13 @@ class SavedAccount(
val isConfirmed :Boolean
get(){
val myId = this.loginAccount?.id
return myId != EntityId.confirmingId
return myId != EntityId.CONFIRMING
}
fun checkConfirmed(context:Context,client : TootApiClient) : TootApiResult? {
try {
val myId = this.loginAccount?.id
if(db_id != INVALID_DB_ID && myId == EntityId.confirmingId ) {
if(db_id != INVALID_DB_ID && myId == EntityId.CONFIRMING ) {
val accessToken = getAccessToken()
if(accessToken != null) {
val result = client.getUserCredential(accessToken, isMisskey = false)

View File

@ -888,7 +888,7 @@ object MisskeyMarkdownDecoder {
if(mentions.find { m -> m.acct == shortAcct } == null) {
mentions.add(
TootMention(
jp.juggler.subwaytooter.api.entity.EntityId.Companion.defaultString
jp.juggler.subwaytooter.api.entity.EntityId.Companion.DEFAULT
, userUrl
, shortAcct
, username