//@file:JvmName("PopulateGolfer") package golf.handicap.hibernate.db import dmo.fs.entities.PersistedGolfer import dmo.fs.utils.Err import golf.handicap.Golfer import golf.handicap.routes.GrpcRoutesHibernate import handicap.grpc.* import handicap.grpc.Golfer.* import handicap.grpc.Golfer.newBuilder import handicap.grpc.ListPublicGolfers import io.smallrye.mutiny.Uni import io.vertx.mutiny.core.Promise import jakarta.persistence.criteria.CriteriaQuery import org.hibernate.reactive.mutiny.Mutiny import org.slf4j.LoggerFactory import java.sql.SQLException import java.time.LocalDateTime import java.time.ZoneId import java.time.ZonedDateTime import java.util.concurrent.CompletableFuture class PopulateGolfer : SqlConstants(), IPopulateGolfer { companion object { private val LOGGER = LoggerFactory.getLogger(PopulateGolfer::class.java.name) } @Throws(SQLException::class, InterruptedException::class) override fun getGolfer(handicapGolfer: Golfer, cmd: Int, sessionFactory: Mutiny.SessionFactory): Uni { val golferPromise = Promise.promise() val builder = sessionFactory.criteriaBuilder val golferCriteria = builder.createQuery(PersistedGolfer::class.java) val root = golferCriteria.from(PersistedGolfer::class.java) var returnGolfer: Golfer var resultGolfer: PersistedGolfer? = null var isGolferFound = false handicapGolfer.message = "Golfer not found" getVertxContext().runOnContext { _ -> sessionFactory.openSession().onItemOrFailure().invoke { session, err -> if (handicapGolfer.pin!!.trim { it <= ' ' } != "") { val query: CriteriaQuery = golferCriteria.select(root) .where( builder.equal( root.get("pin"), handicapGolfer.pin ) ) var cf: CompletableFuture = CompletableFuture.completedFuture(null) cf = session.createQuery(query).singleResult.onItemOrFailure().invoke { persistedGolfer, throwable -> if (throwable != null && !throwable.message!!.startsWith(Err.displayErr(66))) { LOGGER.error(throwable.message) session.close().subscribeAsCompletionStage() cf.complete(persistedGolfer) throw RuntimeException(throwable) } if (persistedGolfer != null) { isGolferFound = true returnGolfer = buildReturnGolfer(persistedGolfer) cf.complete(persistedGolfer) } else { if (handicapGolfer.firstName!!.length < 3 || handicapGolfer.lastName!!.length < 5) { handicapGolfer.status = -1 var which = "Last" if (handicapGolfer.firstName!!.length < 3) { which = "First" } handicapGolfer.message = which + Err.displayErr(69) golferPromise.complete(handicapGolfer) cf.complete(resultGolfer) } else { val equalFirstName = builder.equal(root.get("firstName"), handicapGolfer.firstName) val equalLastName = builder.equal(root.get("lastName"), handicapGolfer.lastName) val queryByName: CriteriaQuery = golferCriteria.select(root) val criteria = queryByName.select(root) .where(builder.and(equalFirstName, equalLastName)) session.createQuery(criteria).singleResult.onItemOrFailure() .invoke { resultGolfer, throwable -> if (throwable != null && !throwable.message!!.startsWith( Err.displayErr(66) ) ) { LOGGER.error(throwable.message) cf.complete(resultGolfer) session.close().subscribeAsCompletionStage() throw RuntimeException(throwable.message) } if (resultGolfer != null) { returnGolfer = buildReturnGolfer(resultGolfer) isGolferFound = true cf.complete(resultGolfer) } else { handicapGolfer.status = -1; if (handicapGolfer.firstName!!.length < 3 || handicapGolfer.lastName!!.length < 5 ) { var which = "Last" if (handicapGolfer.firstName!!.length < 3) { which = "First" } handicapGolfer.message = which + Err.displayErr(69) golferPromise.complete(handicapGolfer) cf.complete(resultGolfer) } } }.subscribe().asCompletionStage() } } }.subscribe().asCompletionStage() cf.whenComplete { persistedGolfer, throwable -> if (throwable != null) { LOGGER.error(Err.displayErr(70), throwable.message) } val closePromise = Promise.promise() try { if (isGolferFound && cmd == 8) { val golferQuery = session.createMutationQuery(UPDATE_GOLFER_HANDICAP) .setParameter(1, handicapGolfer.overlap) .setParameter(2, handicapGolfer.public) .setParameter(3, handicapGolfer.country) .setParameter(4, handicapGolfer.state) .setParameter(5, handicapGolfer.handicap) .setParameter(6, LocalDateTime.now().withNano(0)) .setParameter(7, handicapGolfer.pin) golferQuery.executeUpdate().onItemOrFailure().invoke { _, err -> closePromise.complete(null) if (throwable != null && !throwable.message!!.startsWith(Err.displayErr(66))) { LOGGER.info(Err.displayErr(71), err.message) session.close().subscribeAsCompletionStage() throw RuntimeException(err.message) } }.subscribeAsCompletionStage() } else if (!isGolferFound) { val persistedGolfer: PersistedGolfer = transformGolfer(handicapGolfer, resultGolfer, cmd) session.persist(persistedGolfer).onItemOrFailure().call { _, err -> if (throwable != null && !throwable.message!!.startsWith(Err.displayErr(66))) { LOGGER.error("Pin: ${persistedGolfer.pin} - " + Err.displayErr(72), err.message) } closePromise.complete(persistedGolfer) Uni.createFrom().item("") }.subscribeAsCompletionStage() } else { closePromise.complete(persistedGolfer) } closePromise.future().onItemOrFailure().invoke { persistedGolfer, _ -> session.flush().onItemOrFailure().invoke { _, error -> if (throwable != null && !throwable.message!!.startsWith(Err.displayErr(66))) { LOGGER.error(Err.displayErr(73), error.message) } session.close().onItemOrFailure().invoke { _, error -> if (error != null) { LOGGER.error(Err.displayErr(74), error.message) } if (persistedGolfer != null) { returnGolfer = buildReturnGolfer(persistedGolfer) returnGolfer.message = "Logged In" returnGolfer.status = 0 } else { returnGolfer = handicapGolfer } golferPromise.complete(returnGolfer) }.subscribeAsCompletionStage() }.subscribeAsCompletionStage() }.subscribeAsCompletionStage() } catch (e: Exception) { if (resultGolfer?.lastName != null) { handicapGolfer.status = -3 } else { handicapGolfer.status = -2 } handicapGolfer.message = e.message golferPromise.complete(handicapGolfer) e.printStackTrace() } } } else { session.flush().onItemOrFailure().invoke { _, error -> session.close().subscribeAsCompletionStage() if (error != null) { throw RuntimeException(error.message) } golferPromise.complete(handicapGolfer) }.subscribeAsCompletionStage() } }.subscribeAsCompletionStage() } return golferPromise.future() } @Throws(SQLException::class, InterruptedException::class) override fun getGolfers(sessionFactory: Mutiny.SessionFactory): Uni { val golferPromise = Promise.promise() getVertxContext().runOnContext { _ -> sessionFactory.openSession().onItemOrFailure().invoke { session, err -> if (err != null) { session.close().subscribeAsCompletionStage() throw RuntimeException(err.message) } val builder = sessionFactory.criteriaBuilder val golferCriteria = builder.createQuery(PersistedGolfer::class.java) val root = golferCriteria.from(PersistedGolfer::class.java) val query: CriteriaQuery = golferCriteria.select(root) session.createQuery(query).resultList.onItemOrFailure().invoke { golfers, throwable -> if (throwable != null) { throwable.printStackTrace() session.close().subscribeAsCompletionStage() throw RuntimeException(throwable.message) } val golfersBuilder = ListPublicGolfers.newBuilder() var golferBuilder: handicap.grpc.Golfer.Builder? golfers.forEach { golfer -> if (golfer.pin != GrpcRoutesHibernate.handicapAdminPin) { val concatName = golfer.lastName + ", " + golfer.firstName golferBuilder = newBuilder() golferBuilder!!.name = concatName golfersBuilder.addGolfer(golferBuilder) } } session.close().onItemOrFailure().invoke { golferPromise.complete(golfersBuilder) }.subscribeAsCompletionStage() }.subscribe().with {} }.subscribeAsCompletionStage() } return golferPromise.future() } private fun buildReturnGolfer(resultGolfer: PersistedGolfer): Golfer { val handicapGolfer = Golfer() handicapGolfer.pin = resultGolfer.pin resultGolfer.golferId = handicapGolfer.pin?.let { PersistedGolfer.GolferId(it) } handicapGolfer.firstName = resultGolfer.firstName handicapGolfer.lastName = resultGolfer.lastName handicapGolfer.handicap = resultGolfer.handicap?.toDouble() ?: 0.0 handicapGolfer.country = resultGolfer.country handicapGolfer.state = resultGolfer.state handicapGolfer.overlap = resultGolfer.overlapYears == true handicapGolfer.public = resultGolfer.publicDisplay == true val localDateTime = LocalDateTime.now() val zdt = ZonedDateTime.of(localDateTime, ZoneId.systemDefault()) val date = zdt.toInstant().toEpochMilli() handicapGolfer.lastLogin = date return handicapGolfer } private fun transformGolfer(handicapGolfer: Golfer, resultGolfer: PersistedGolfer?, cmd: Int): PersistedGolfer { val persistedGolfer = PersistedGolfer() val isLogin = cmd == 3 || handicapGolfer.pin?.length == 0 persistedGolfer.pin = resultGolfer?.pin ?: handicapGolfer.pin persistedGolfer.golferId = handicapGolfer.pin?.let { PersistedGolfer.GolferId(it) } persistedGolfer.firstName = resultGolfer?.firstName ?: handicapGolfer.firstName persistedGolfer.lastName = resultGolfer?.lastName ?: handicapGolfer.lastName persistedGolfer.handicap = resultGolfer?.handicap ?: handicapGolfer.handicap.toBigDecimal() persistedGolfer.lastLogin = LocalDateTime.now().withNano(0) if(persistedGolfer.firstName!!.isEmpty() || persistedGolfer.lastName!!.isEmpty()) { persistedGolfer.firstName = null persistedGolfer.lastName = null } /* Login first before changing values with subsequent login * cmd = 3 - first login * cmd = 8 - subsequent login button clicks * */ persistedGolfer.country = if (cmd == 8 || resultGolfer?.country == null) handicapGolfer.country else resultGolfer.country persistedGolfer.state = if (cmd == 8 || resultGolfer?.state == null) handicapGolfer.state else resultGolfer.state persistedGolfer.overlapYears = if (cmd == 8 || resultGolfer?.overlapYears == null) handicapGolfer.overlap else resultGolfer.overlapYears persistedGolfer.publicDisplay = if (cmd == 8 || resultGolfer?.publicDisplay == null) handicapGolfer.public else resultGolfer.publicDisplay return persistedGolfer } }