diff --git a/piikii-application/src/main/kotlin/com/piikii/application/domain/generic/Origin.kt b/piikii-application/src/main/kotlin/com/piikii/application/domain/generic/Origin.kt index 2ef60bb8..84c5f793 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/domain/generic/Origin.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/domain/generic/Origin.kt @@ -1,7 +1,7 @@ package com.piikii.application.domain.generic -enum class Origin { - AVOCADO, - LEMON, - MANUAL, +enum class Origin(val prefix: String) { + AVOCADO("A"), + LEMON("L"), + MANUAL("M"), } diff --git a/piikii-application/src/main/kotlin/com/piikii/application/domain/place/OriginPlace.kt b/piikii-application/src/main/kotlin/com/piikii/application/domain/place/OriginPlace.kt index 08d11ffa..d8df2fbb 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/domain/place/OriginPlace.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/domain/place/OriginPlace.kt @@ -6,7 +6,7 @@ import com.piikii.application.domain.generic.ThumbnailLinks data class OriginPlace( val id: Long?, val name: String, - val originMapId: Long, + val originMapId: OriginMapId, val url: String, val thumbnailLinks: ThumbnailLinks, val address: String? = null, @@ -18,3 +18,21 @@ data class OriginPlace( val category: String?, val origin: Origin, ) + +@JvmInline +value class OriginMapId(val value: String) { + fun toId(): String { + return value.split(SEPARATOR).last() + } + + companion object { + private const val SEPARATOR: String = "_" + + fun of( + id: Long, + origin: Origin, + ): OriginMapId { + return OriginMapId("${origin.prefix}$SEPARATOR$id") + } + } +} diff --git a/piikii-application/src/main/kotlin/com/piikii/application/domain/place/OriginPlaceService.kt b/piikii-application/src/main/kotlin/com/piikii/application/domain/place/OriginPlaceService.kt index a7533afd..ea8905b4 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/domain/place/OriginPlaceService.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/domain/place/OriginPlaceService.kt @@ -22,8 +22,10 @@ class OriginPlaceService( ExceptionCode.NOT_SUPPORT_AUTO_COMPLETE_URL, "No AutoComplete client found for $url", ) - val placeId = originPlaceAutoCompleteClient.extractPlaceId(plainUrl) - return originPlaceAutoCompleteClient.getAutoCompletedPlace(url = plainUrl, placeId = placeId) + val originMapId = originPlaceAutoCompleteClient.extractOriginMapId(plainUrl) + return originPlaceQueryPort.findByOriginMapId(originMapId) + ?: originPlaceAutoCompleteClient.getAutoCompletedPlace(url = plainUrl, originMapId = originMapId) + .let { originPlaceCommandPort.save(it) } } private fun getUrlOfRemovedParameters(url: String): String { diff --git a/piikii-application/src/main/kotlin/com/piikii/application/port/input/dto/request/PlaceRequest.kt b/piikii-application/src/main/kotlin/com/piikii/application/port/input/dto/request/PlaceRequest.kt index 308351f6..2548302b 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/port/input/dto/request/PlaceRequest.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/port/input/dto/request/PlaceRequest.kt @@ -46,17 +46,6 @@ data class AddPlaceRequest( @field:Max(value = 5, message = "별점은 5 이하여야 합니다.") @field:Schema(description = "별점 (0-5)", example = "4.5") val starGrade: Float?, - @field:NotNull(message = "장소 정보 제공처") - @field:Schema( - description = "장소 정보 제공처", - allowableValues = [ - "AVOCADO", - "LEMON", - "MANUAL", - ], - example = "MANUAL", - ) - val origin: Origin, @field:NotBlank(message = "메모는 필수이며 빈 문자열이 허용되지 않습니다.") @field:Size(max = 50, message = "메모는 50자를 초과할 수 없습니다.") @field:Schema(description = "메모", example = "맛있는 레스토랑") @@ -83,7 +72,7 @@ data class AddPlaceRequest( address = address, phoneNumber = phoneNumber, starGrade = starGrade, - origin = origin, + origin = Origin.MANUAL, memo = memo, ) } @@ -116,16 +105,6 @@ data class ModifyPlaceRequest( @field:Max(value = 5, message = "별점은 5 이하여야 합니다.") @field:Schema(description = "별점 (0-5)", example = "4.5") val starGrade: Float?, - @field:Schema( - description = "장소 정보 제공처", - allowableValues = [ - "AVOCADO", - "LEMON", - "MANUAL", - ], - example = "MANUAL", - ) - val origin: Origin, @field:NotBlank(message = "메모는 필수이며 빈 문자열이 허용되지 않습니다.") @field:Size(max = 50, message = "메모는 50자를 초과할 수 없습니다.") @field:Schema(description = "메모", example = "맛있는 레스토랑") @@ -153,7 +132,7 @@ data class ModifyPlaceRequest( address = address, phoneNumber = phoneNumber, starGrade = starGrade, - origin = origin, + origin = Origin.MANUAL, memo = memo, ) } diff --git a/piikii-application/src/main/kotlin/com/piikii/application/port/output/persistence/OriginPlacePort.kt b/piikii-application/src/main/kotlin/com/piikii/application/port/output/persistence/OriginPlacePort.kt index cc145cf0..a9542c2a 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/port/output/persistence/OriginPlacePort.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/port/output/persistence/OriginPlacePort.kt @@ -1,20 +1,12 @@ package com.piikii.application.port.output.persistence +import com.piikii.application.domain.place.OriginMapId import com.piikii.application.domain.place.OriginPlace interface OriginPlaceQueryPort { - fun retrieve(id: Long): OriginPlace - - fun retrieveAll(ids: List): List + fun findByOriginMapId(originMapId: OriginMapId): OriginPlace? } interface OriginPlaceCommandPort { fun save(originPlace: OriginPlace): OriginPlace - - fun update( - originPlace: OriginPlace, - id: Long, - ) - - fun delete(id: Long) } diff --git a/piikii-application/src/main/kotlin/com/piikii/application/port/output/web/OriginPlaceAutoCompleteClient.kt b/piikii-application/src/main/kotlin/com/piikii/application/port/output/web/OriginPlaceAutoCompleteClient.kt index e75ed824..d90c44c4 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/port/output/web/OriginPlaceAutoCompleteClient.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/port/output/web/OriginPlaceAutoCompleteClient.kt @@ -1,14 +1,15 @@ package com.piikii.application.port.output.web +import com.piikii.application.domain.place.OriginMapId import com.piikii.application.domain.place.OriginPlace interface OriginPlaceAutoCompleteClient { fun isAutoCompleteSupportedUrl(url: String): Boolean - fun extractPlaceId(url: String): String + fun extractOriginMapId(url: String): OriginMapId fun getAutoCompletedPlace( url: String, - placeId: String, + originMapId: OriginMapId, ): OriginPlace } diff --git a/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/adapter/OriginPlaceAdapter.kt b/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/adapter/OriginPlaceAdapter.kt index 26eafb46..fed559d0 100644 --- a/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/adapter/OriginPlaceAdapter.kt +++ b/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/adapter/OriginPlaceAdapter.kt @@ -1,11 +1,11 @@ package com.piikii.output.persistence.postgresql.adapter +import com.piikii.application.domain.place.OriginMapId import com.piikii.application.domain.place.OriginPlace import com.piikii.application.port.output.persistence.OriginPlaceCommandPort import com.piikii.application.port.output.persistence.OriginPlaceQueryPort import com.piikii.output.persistence.postgresql.persistence.entity.OriginPlaceEntity import com.piikii.output.persistence.postgresql.persistence.repository.OriginPlaceRepository -import jakarta.persistence.EntityNotFoundException import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional @@ -16,34 +16,11 @@ class OriginPlaceAdapter( ) : OriginPlaceCommandPort, OriginPlaceQueryPort { @Transactional override fun save(originPlace: OriginPlace): OriginPlace { - val entity = OriginPlaceEntity.from(originPlace) - originPlaceRepository.save(entity) - return entity.toDomain() + return originPlaceRepository.save(OriginPlaceEntity.from(originPlace)) + .toDomain() } - @Transactional - override fun update( - originPlace: OriginPlace, - id: Long, - ) { - TODO("Not yet implemented") - } - - @Transactional - override fun delete(id: Long) { - TODO("Not yet implemented") - } - - override fun retrieve(id: Long): OriginPlace { - val originPlaceEntity = originPlaceRepository.findById(id) - if (originPlaceEntity.isPresent) { - return originPlaceEntity.get().toDomain() - } - // TODO 예외 정의 - throw EntityNotFoundException() - } - - override fun retrieveAll(ids: List): List { - TODO("Not yet implemented") + override fun findByOriginMapId(originMapId: OriginMapId): OriginPlace? { + return originPlaceRepository.findByOriginMapId(originMapId)?.toDomain() } } diff --git a/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/OriginPlaceEntity.kt b/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/OriginPlaceEntity.kt index 30504073..54659512 100644 --- a/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/OriginPlaceEntity.kt +++ b/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/OriginPlaceEntity.kt @@ -2,6 +2,7 @@ package com.piikii.output.persistence.postgresql.persistence.entity import com.piikii.application.domain.generic.Origin import com.piikii.application.domain.generic.ThumbnailLinks +import com.piikii.application.domain.place.OriginMapId import com.piikii.application.domain.place.OriginPlace import com.piikii.output.persistence.postgresql.persistence.common.BaseEntity import jakarta.persistence.Column @@ -19,13 +20,13 @@ import org.hibernate.annotations.SQLRestriction @SQLDelete(sql = "UPDATE piikii.origin_place SET is_deleted = true WHERE id = ?") @DynamicUpdate class OriginPlaceEntity( - @Column(name = "origin_map_id", nullable = false) - val originMapId: Long, + @Column(name = "origin_map_id", nullable = false, unique = true) + val originMapId: OriginMapId, @Column(name = "name", length = 255, nullable = false) var name: String, @Column(name = "url", nullable = false, length = 255) val url: String, - @Column(name = "thumbnail_links", nullable = false, length = 255) + @Column(name = "thumbnail_links", columnDefinition = "TEXT") val thumbnailLinks: String, @Column(name = "address", length = 255) val address: String? = null, diff --git a/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/PlaceEntity.kt b/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/PlaceEntity.kt index 463c51d8..6b4d43f9 100644 --- a/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/PlaceEntity.kt +++ b/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/PlaceEntity.kt @@ -28,7 +28,7 @@ class PlaceEntity( var name: String, @Column(name = "url", length = 255) var url: String?, - @Column(name = "thumbnail_links", length = 255, nullable = false) + @Column(name = "thumbnail_links", columnDefinition = "TEXT") var thumbnailLinks: String?, @Column(name = "address", length = 255) var address: String?, diff --git a/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/repository/OriginPlaceRepository.kt b/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/repository/OriginPlaceRepository.kt index 6c4f3bf3..7266c061 100644 --- a/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/repository/OriginPlaceRepository.kt +++ b/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/repository/OriginPlaceRepository.kt @@ -1,6 +1,9 @@ package com.piikii.output.persistence.postgresql.persistence.repository +import com.piikii.application.domain.place.OriginMapId import com.piikii.output.persistence.postgresql.persistence.entity.OriginPlaceEntity import org.springframework.data.jpa.repository.JpaRepository -interface OriginPlaceRepository : JpaRepository +interface OriginPlaceRepository : JpaRepository { + fun findByOriginMapId(originMapId: OriginMapId): OriginPlaceEntity? +} diff --git a/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/adapter/AvocadoPlaceAutoCompleteClient.kt b/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/adapter/AvocadoPlaceAutoCompleteClient.kt index 78a67690..d90db6f2 100644 --- a/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/adapter/AvocadoPlaceAutoCompleteClient.kt +++ b/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/adapter/AvocadoPlaceAutoCompleteClient.kt @@ -1,34 +1,35 @@ package com.piikii.output.web.avocado.adapter +import com.piikii.application.domain.place.OriginMapId import com.piikii.application.domain.place.OriginPlace import com.piikii.application.port.output.web.OriginPlaceAutoCompleteClient import com.piikii.common.exception.ExceptionCode import com.piikii.common.exception.PiikiiException -import com.piikii.output.web.avocado.parser.AvocadoPlaceIdParserStrategy +import com.piikii.output.web.avocado.parser.AvocadoOriginMapIdParserStrategy import org.springframework.stereotype.Component import org.springframework.web.client.RestClient import org.springframework.web.client.body @Component class AvocadoPlaceAutoCompleteClient( - private val avocadoPlaceIdParserStrategy: AvocadoPlaceIdParserStrategy, + private val avocadoOriginMapIdParserStrategy: AvocadoOriginMapIdParserStrategy, private val avocadoApiClient: RestClient, ) : OriginPlaceAutoCompleteClient { override fun isAutoCompleteSupportedUrl(url: String): Boolean { - return avocadoPlaceIdParserStrategy.getParserBySupportedUrl(url) != null + return avocadoOriginMapIdParserStrategy.getParserBySupportedUrl(url) != null } - override fun extractPlaceId(url: String): String { - return avocadoPlaceIdParserStrategy.getParserBySupportedUrl(url)?.parsePlaceId(url) + override fun extractOriginMapId(url: String): OriginMapId { + return avocadoOriginMapIdParserStrategy.getParserBySupportedUrl(url)?.parseOriginMapId(url) ?: throw PiikiiException(ExceptionCode.NOT_SUPPORT_AUTO_COMPLETE_URL) } override fun getAutoCompletedPlace( url: String, - placeId: String, + originMapId: OriginMapId, ): OriginPlace { return avocadoApiClient.get() - .uri("/$placeId") + .uri("/${originMapId.toId()}") .retrieve() .body() ?.toOriginPlace(url) diff --git a/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/adapter/AvocadoPlaceInfoResponse.kt b/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/adapter/AvocadoPlaceInfoResponse.kt index f048f85b..2f3cf857 100644 --- a/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/adapter/AvocadoPlaceInfoResponse.kt +++ b/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/adapter/AvocadoPlaceInfoResponse.kt @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.annotation.JsonProperty import com.piikii.application.domain.generic.Origin import com.piikii.application.domain.generic.ThumbnailLinks +import com.piikii.application.domain.place.OriginMapId import com.piikii.application.domain.place.OriginPlace @JsonIgnoreProperties(ignoreUnknown = true) @@ -27,7 +28,7 @@ data class AvocadoPlaceInfoResponse( fun toOriginPlace(url: String): OriginPlace { return OriginPlace( id = null, - originMapId = id, + originMapId = OriginMapId.of(id = id, origin = Origin.AVOCADO), name = name, url = url, thumbnailLinks = ThumbnailLinks(images ?: emptyList()), diff --git a/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/config/AvocadoConfig.kt b/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/config/AvocadoConfig.kt index 9ff938aa..cb0127b8 100644 --- a/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/config/AvocadoConfig.kt +++ b/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/config/AvocadoConfig.kt @@ -54,6 +54,7 @@ data class AvocadoUrl( ) { data class Regex( val web: String, + val mobileWeb: String, val share: String, ) } diff --git a/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/parser/AvocadoOriginMapIdParser.kt b/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/parser/AvocadoOriginMapIdParser.kt new file mode 100644 index 00000000..d5468546 --- /dev/null +++ b/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/parser/AvocadoOriginMapIdParser.kt @@ -0,0 +1,77 @@ +package com.piikii.output.web.avocado.parser + +import com.piikii.application.domain.generic.Origin +import com.piikii.application.domain.place.OriginMapId +import com.piikii.output.web.avocado.config.AvocadoProperties +import com.piikii.output.web.avocado.parser.AvocadoOriginMapIdParser.Companion.ORIGIN_MAP_IP_REGEX +import org.springframework.stereotype.Component +import org.springframework.web.client.RestClient + +@Component +class AvocadoOriginMapIdParserStrategy(private val parsers: List) { + fun getParserBySupportedUrl(url: String): AvocadoOriginMapIdParser? { + return parsers.firstOrNull { it.getParserBySupportedUrl(url) != null } + } +} + +interface AvocadoOriginMapIdParser { + fun getParserBySupportedUrl(url: String): AvocadoOriginMapIdParser? + + fun parseOriginMapId(url: String): OriginMapId? + + /** + * Regex를 이용해 OriginMapId 반환 + * - Regex Match 결과로부터 첫 번째 값을 꺼내 OriginMapId 변환 및 반환 + * + * @return OriginMapId + */ + fun MatchResult?.parseFromMatchResult(): OriginMapId? { + return this?.groupValues + ?.getOrNull(1) + ?.toLongOrNull() + ?.let { OriginMapId.of(id = it, origin = Origin.AVOCADO) } + } + + companion object { + const val ORIGIN_MAP_IP_REGEX = "\\d+" + } +} + +@Component +class MapUrlIdParser(properties: AvocadoProperties) : AvocadoOriginMapIdParser { + private val regexes: List = + listOf( + "${properties.url.regex.web}($ORIGIN_MAP_IP_REGEX)".toRegex(), + "${properties.url.regex.mobileWeb}($ORIGIN_MAP_IP_REGEX)/home".toRegex(), + ) + + override fun getParserBySupportedUrl(url: String): AvocadoOriginMapIdParser? = + takeIf { regexes.any { regex -> regex.matches(url) } } + + override fun parseOriginMapId(url: String): OriginMapId? { + return regexes.first { it.matches(url) }.find(url).parseFromMatchResult() + } +} + +@Component +class ShareUrlIdParser( + properties: AvocadoProperties, +) : AvocadoOriginMapIdParser { + private val regex: Regex = properties.url.regex.share.toRegex() + private val idParameterRegex: Regex = "id=(\\d+)".toRegex() + private val client: RestClient = RestClient.builder().build() + + override fun getParserBySupportedUrl(url: String): AvocadoOriginMapIdParser? = takeIf { regex.matches(url) } + + override fun parseOriginMapId(url: String): OriginMapId? { + val response = + client.get().uri(url) + .retrieve() + .toEntity(Map::class.java) + if (response.statusCode.is3xxRedirection && response.headers.location != null) { + return idParameterRegex.find(response.headers.location.toString()) + .parseFromMatchResult() + } + return null + } +} diff --git a/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/parser/AvocadoPlaceIdParser.kt b/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/parser/AvocadoPlaceIdParser.kt deleted file mode 100644 index 59b4b791..00000000 --- a/piikii-output-web/avocado/src/main/kotlin/com/piikii/output/web/avocado/parser/AvocadoPlaceIdParser.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.piikii.output.web.avocado.parser - -import com.piikii.output.web.avocado.config.AvocadoProperties -import org.springframework.stereotype.Component -import org.springframework.web.client.RestClient - -@Component -class AvocadoPlaceIdParserStrategy(private val parsers: List) { - fun getParserBySupportedUrl(url: String): AvocadoPlaceIdParser? { - return parsers.find { it.pattern().matches(url) } - } -} - -interface AvocadoPlaceIdParser { - fun pattern(): Regex - - fun parsePlaceId(url: String): String? -} - -@Component -class MapPlaceIdParser(properties: AvocadoProperties) : AvocadoPlaceIdParser { - private val patternRegex: Regex = "${properties.url.regex.web}$PLACE_ID_REGEX".toRegex() - private val parseRegex: Regex = "${properties.url.regex.web}($PLACE_ID_REGEX)".toRegex() - - override fun pattern(): Regex { - return patternRegex - } - - override fun parsePlaceId(url: String): String? { - return parseRegex.find(url)?.groupValues?.get(1) - } - - companion object { - const val PLACE_ID_REGEX = "\\d+" - } -} - -@Component -class SharePlaceIdParser( - properties: AvocadoProperties, -) : AvocadoPlaceIdParser { - private val regex: Regex = properties.url.regex.share.toRegex() - private val idParameterRegex: Regex = "id=(\\d+)".toRegex() - private val client: RestClient = RestClient.builder().build() - - override fun pattern(): Regex { - return regex - } - - override fun parsePlaceId(url: String): String? { - val response = - client.get().uri(url) - .retrieve() - .toEntity(Map::class.java) - if (response.statusCode.is3xxRedirection && response.headers.location != null) { - val extractedId = idParameterRegex.find(response.headers.location.toString()) - return extractedId?.groupValues?.get(1) - } - return null - } -} diff --git a/piikii-output-web/avocado/src/main/resources/avocado-config/application.yml b/piikii-output-web/avocado/src/main/resources/avocado-config/application.yml index 13d5f9b4..e67dd9b4 100644 --- a/piikii-output-web/avocado/src/main/resources/avocado-config/application.yml +++ b/piikii-output-web/avocado/src/main/resources/avocado-config/application.yml @@ -5,6 +5,7 @@ avocado: url: regex: web: ${AVOCADO_WEB_URL_REGEX} + mobile-web: ${AVOCADO_MOBILE_WEB_URL_REGEX} share: ${AVOCADO_SHARE_URL_REGEX} api: ${AVOCADO_API_URL} referer: ${AVOCADO_REFERER_URL} diff --git a/piikii-output-web/avocado/src/test/kotlin/com/piikii/output/web/avocado/AvocadoPlaceAutoCompleteClientTest.kt b/piikii-output-web/avocado/src/test/kotlin/com/piikii/output/web/avocado/AvocadoPlaceAutoCompleteClientTest.kt index 6b9252d2..5e96361c 100644 --- a/piikii-output-web/avocado/src/test/kotlin/com/piikii/output/web/avocado/AvocadoPlaceAutoCompleteClientTest.kt +++ b/piikii-output-web/avocado/src/test/kotlin/com/piikii/output/web/avocado/AvocadoPlaceAutoCompleteClientTest.kt @@ -1,8 +1,10 @@ package com.piikii.output.web.avocado +import com.piikii.application.domain.generic.Origin +import com.piikii.application.domain.place.OriginMapId import com.piikii.output.web.avocado.adapter.AvocadoPlaceAutoCompleteClient -import com.piikii.output.web.avocado.parser.MapPlaceIdParser -import com.piikii.output.web.avocado.parser.SharePlaceIdParser +import com.piikii.output.web.avocado.parser.MapUrlIdParser +import com.piikii.output.web.avocado.parser.ShareUrlIdParser import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test @@ -17,39 +19,42 @@ import org.springframework.test.context.ContextConfiguration @ContextConfiguration(classes = [TestConfiguration::class]) class AvocadoPlaceAutoCompleteClientTest { @Autowired - lateinit var sharePlaceIdParser: SharePlaceIdParser + lateinit var shareUrlIdParser: ShareUrlIdParser @Autowired - lateinit var mapPlaceIdParser: MapPlaceIdParser + lateinit var mapUrlIdParser: MapUrlIdParser + + @Autowired + lateinit var mapMobileUrlIdParser: MapUrlIdParser @Autowired lateinit var avocadoPlaceAutoCompleteClient: AvocadoPlaceAutoCompleteClient @Test - fun sharePlaceIdParserTest() { + fun shareUrlIdParserTest() { val url = "주소를 입력하세요" - val parse = sharePlaceIdParser.parsePlaceId(url) + val parse = shareUrlIdParser.parseOriginMapId(url) println("parse = $parse") } @Test - fun mapPlaceIdParserTest() { + fun mapUrlIdParserTest() { val url = "주소를 입력하세요" - val pattern = mapPlaceIdParser.pattern() - assertThat(pattern.matches(url)).isTrue() + val pattern = mapUrlIdParser.getParserBySupportedUrl(url) + assertThat(pattern).isNotNull() - val parse = mapPlaceIdParser.parsePlaceId(url) + val parse = mapUrlIdParser.parseOriginMapId(url) println("parse = $parse") } @Test fun getAutoCompletedPlaceTest() { val url = "주소를 입력하세요" - val id = "id를 입력하세요" + val id = 123L - val originPlace = avocadoPlaceAutoCompleteClient.getAutoCompletedPlace(url, id) + val originPlace = avocadoPlaceAutoCompleteClient.getAutoCompletedPlace(url, OriginMapId.of(id, Origin.AVOCADO)) println("originPlace = $originPlace") } } diff --git a/piikii-output-web/avocado/src/test/resources/application-test.yml b/piikii-output-web/avocado/src/test/resources/application-test.yml index 13d5f9b4..e67dd9b4 100644 --- a/piikii-output-web/avocado/src/test/resources/application-test.yml +++ b/piikii-output-web/avocado/src/test/resources/application-test.yml @@ -5,6 +5,7 @@ avocado: url: regex: web: ${AVOCADO_WEB_URL_REGEX} + mobile-web: ${AVOCADO_MOBILE_WEB_URL_REGEX} share: ${AVOCADO_SHARE_URL_REGEX} api: ${AVOCADO_API_URL} referer: ${AVOCADO_REFERER_URL} diff --git a/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/adapter/LemonPlaceAutoCompleteClient.kt b/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/adapter/LemonPlaceAutoCompleteClient.kt index f34b9941..2379d019 100644 --- a/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/adapter/LemonPlaceAutoCompleteClient.kt +++ b/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/adapter/LemonPlaceAutoCompleteClient.kt @@ -1,34 +1,35 @@ package com.piikii.output.web.lemon.adapter +import com.piikii.application.domain.place.OriginMapId import com.piikii.application.domain.place.OriginPlace import com.piikii.application.port.output.web.OriginPlaceAutoCompleteClient import com.piikii.common.exception.ExceptionCode import com.piikii.common.exception.PiikiiException -import com.piikii.output.web.lemon.parser.LemonPlaceIdParser +import com.piikii.output.web.lemon.parser.LemonOriginMapIdParser import org.springframework.stereotype.Component import org.springframework.web.client.RestClient import org.springframework.web.client.body @Component class LemonPlaceAutoCompleteClient( - private val lemonPlaceIdParser: LemonPlaceIdParser, + private val lemonOriginMapIdParser: LemonOriginMapIdParser, private val lemonApiClient: RestClient, ) : OriginPlaceAutoCompleteClient { override fun isAutoCompleteSupportedUrl(url: String): Boolean { - return lemonPlaceIdParser.isAutoCompleteSupportedUrl(url) + return lemonOriginMapIdParser.isAutoCompleteSupportedUrl(url) } - override fun extractPlaceId(url: String): String { - return lemonPlaceIdParser.parse(url) + override fun extractOriginMapId(url: String): OriginMapId { + return lemonOriginMapIdParser.parseOriginMapId(url) ?: throw PiikiiException(ExceptionCode.NOT_SUPPORT_AUTO_COMPLETE_URL) } override fun getAutoCompletedPlace( url: String, - placeId: String, + originMapId: OriginMapId, ): OriginPlace { return lemonApiClient.get() - .uri("/$placeId") + .uri("/${originMapId.toId()}") .retrieve() .body() ?.toOriginPlace(url) diff --git a/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/adapter/LemonPlaceInfoResponse.kt b/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/adapter/LemonPlaceInfoResponse.kt index 17bac969..6529cede 100644 --- a/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/adapter/LemonPlaceInfoResponse.kt +++ b/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/adapter/LemonPlaceInfoResponse.kt @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.annotation.JsonProperty import com.piikii.application.domain.generic.Origin import com.piikii.application.domain.generic.ThumbnailLinks +import com.piikii.application.domain.place.OriginMapId import com.piikii.application.domain.place.OriginPlace @JsonIgnoreProperties(ignoreUnknown = true) @@ -11,7 +12,7 @@ data class LemonPlaceInfoResponse( val isMapUser: String?, val isExist: Boolean?, val basicInfo: BasicInfo, - val comment: Comment, + val comment: Comment?, val menuInfo: MenuInfo, val photo: Photo, ) { @@ -20,7 +21,7 @@ data class LemonPlaceInfoResponse( return OriginPlace( id = null, name = basicInfo.name, - originMapId = basicInfo.cid, + originMapId = OriginMapId.of(id = basicInfo.cid, origin = Origin.LEMON), url = url, thumbnailLinks = ThumbnailLinks(basicInfo.mainPhotoUrl), address = fullAddress, @@ -42,7 +43,7 @@ data class LemonPlaceInfoResponse( @JsonProperty("mainphotourl") val mainPhotoUrl: String, @JsonProperty("phonenum") - val phoneNumber: String, + val phoneNumber: String?, val address: Address, val homepage: String?, val category: Category, diff --git a/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/config/LemonConfig.kt b/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/config/LemonConfig.kt index 36fdae81..30dec31e 100644 --- a/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/config/LemonConfig.kt +++ b/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/config/LemonConfig.kt @@ -28,5 +28,6 @@ data class LemonUrl( ) { data class Regex( val web: String, + val mobileWeb: String, ) } diff --git a/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/parser/LemonOriginMapIdParser.kt b/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/parser/LemonOriginMapIdParser.kt new file mode 100644 index 00000000..2a611fea --- /dev/null +++ b/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/parser/LemonOriginMapIdParser.kt @@ -0,0 +1,32 @@ +package com.piikii.output.web.lemon.parser + +import com.piikii.application.domain.generic.Origin +import com.piikii.application.domain.place.OriginMapId +import com.piikii.output.web.lemon.config.LemonProperties +import org.springframework.stereotype.Component + +@Component +class LemonOriginMapIdParser( + properties: LemonProperties, +) { + private val regexes: List = + listOf( + "${properties.url.regex.web}($ORIGIN_MAP_IP_REGEX)".toRegex(), + "${properties.url.regex.mobileWeb}($ORIGIN_MAP_IP_REGEX)".toRegex(), + ) + + fun isAutoCompleteSupportedUrl(url: String): Boolean = regexes.any { it.matches(url) } + + fun parseOriginMapId(url: String): OriginMapId? { + return regexes.firstOrNull { it.matches(url) } + ?.find(url) + ?.groupValues + ?.getOrNull(1) + ?.toLongOrNull() + ?.let { OriginMapId.of(id = it, origin = Origin.LEMON) } + } + + companion object { + const val ORIGIN_MAP_IP_REGEX = "\\d+" + } +} diff --git a/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/parser/LemonPlaceIdParser.kt b/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/parser/LemonPlaceIdParser.kt deleted file mode 100644 index c7b29160..00000000 --- a/piikii-output-web/lemon/src/main/kotlin/com/piikii/output/web/lemon/parser/LemonPlaceIdParser.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.piikii.output.web.lemon.parser - -import com.piikii.output.web.lemon.config.LemonProperties -import org.springframework.stereotype.Component - -@Component -class LemonPlaceIdParser( - properties: LemonProperties, -) { - private val patternRegex: Regex = "${properties.url.regex.web}$PLACE_ID_REGEX".toRegex() - private val parseRegex: Regex = "${properties.url.regex.web}($PLACE_ID_REGEX)".toRegex() - - fun isAutoCompleteSupportedUrl(url: String): Boolean { - return patternRegex.matches(url) - } - - fun parse(url: String): String? { - if (!isAutoCompleteSupportedUrl(url)) { - return null - } - return parseRegex.find(url)?.groupValues?.get(1) - } - - companion object { - const val PLACE_ID_REGEX = "\\d+" - } -} diff --git a/piikii-output-web/lemon/src/main/resources/lemon-config/application.yml b/piikii-output-web/lemon/src/main/resources/lemon-config/application.yml index 32e5663c..3511c715 100644 --- a/piikii-output-web/lemon/src/main/resources/lemon-config/application.yml +++ b/piikii-output-web/lemon/src/main/resources/lemon-config/application.yml @@ -2,4 +2,5 @@ lemon: url: regex: web: ${LEMON_WEB_URL_REGEX} + mobile-web: ${LEMON_MOBILE_WEB_URL_REGEX} api: ${LEMON_API_URL} diff --git a/piikii-output-web/lemon/src/test/kotlin/com/piikii/output/web/lemon/LemonPlaceAutoCompleteClientTest.kt b/piikii-output-web/lemon/src/test/kotlin/com/piikii/output/web/lemon/LemonPlaceAutoCompleteClientTest.kt index 7f4a2ff1..54c72b6a 100644 --- a/piikii-output-web/lemon/src/test/kotlin/com/piikii/output/web/lemon/LemonPlaceAutoCompleteClientTest.kt +++ b/piikii-output-web/lemon/src/test/kotlin/com/piikii/output/web/lemon/LemonPlaceAutoCompleteClientTest.kt @@ -1,5 +1,7 @@ package com.piikii.output.web.lemon +import com.piikii.application.domain.generic.Origin +import com.piikii.application.domain.place.OriginMapId import com.piikii.output.web.lemon.adapter.LemonPlaceAutoCompleteClient import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Disabled @@ -27,9 +29,9 @@ class LemonPlaceAutoCompleteClientTest { @Test fun getAutoCompletedPlaceTest() { val url = "URL을 입력해주세요" - val id = "id를 입력해주세요" + val id = 123L - val originPlace = lemonPlaceAutoCompleteClient.getAutoCompletedPlace(url, id) + val originPlace = lemonPlaceAutoCompleteClient.getAutoCompletedPlace(url, OriginMapId.of(id, Origin.LEMON)) println("originPlace = $originPlace") } } diff --git a/piikii-output-web/lemon/src/test/resources/application-test.yml b/piikii-output-web/lemon/src/test/resources/application-test.yml index 32e5663c..3511c715 100644 --- a/piikii-output-web/lemon/src/test/resources/application-test.yml +++ b/piikii-output-web/lemon/src/test/resources/application-test.yml @@ -2,4 +2,5 @@ lemon: url: regex: web: ${LEMON_WEB_URL_REGEX} + mobile-web: ${LEMON_MOBILE_WEB_URL_REGEX} api: ${LEMON_API_URL}