All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cz.jalasoft.transportation.czechrailway.flow.TrainDetailPageFlow.scala Maven / Gradle / Ivy

The newest version!
package cz.jalasoft.transportation.czechrailway.flow

import java.net.URI
import java.text.SimpleDateFormat
import java.util.Date

import cz.jalasoft.net.http.HttpClient
import cz.jalasoft.net.http.URIBuilder._
import cz.jalasoft.transportation.Transport
import cz.jalasoft.transportation.czechrailway.ConnectionProperties._
import cz.jalasoft.transportation.czechrailway.Loggable
import cz.jalasoft.transportation.czechrailway.page._
import cz.jalasoft.transportation.exception.{TransportInfoRetrievalException, TransportRetrievalException}

import scala.collection._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
import scala.util.{Failure, Success, Try}

object TrainDetailPageFlow {

  private val DATE_PATTERN = "dd.MM.YYYY"
  private val TRAIN_LOOKUP_REQUEST_PAYLOAD_PATTERN = "Mask=%s&form-date=%s&cmdSearch=Vyhledat"

  private lazy val LOOKUP_URL = http
    .host(host)
    .port(port)
    .path(lookupTrainPath)
    .build

  private def trainDetailUri(path : String) : URI = {
    http.host(host)
    .port(port)
    .path(path)
    .build
  }

  //private lazy val client = new NettyHttpClient

  private def lookupTrainRequestBody(train : String) = {
    val formattedDate = new SimpleDateFormat(DATE_PATTERN).format(new Date());

    s"Mask=${train}&form-date=${formattedDate}&cmdSearch=Vyhledat"
  }

  def apply(client : HttpClient) = new TrainDetailPageFlow(client)

}

/**
 * Created by Honza Lastovicka on 11.7.15.
 */
final class TrainDetailPageFlow private (client : HttpClient) extends Loggable {

  def flow(train : Transport) : TrainDetailPage = {
    debug(s"Startin loading train detail page for train ${train.fullName()}")

    val singletonSeq = flow(train.fullName())

    if (singletonSeq.size != 1) {
      val message = "Unexpected number of train detail pages: " + singletonSeq.size + ", expected 1"
      throw new TransportInfoRetrievalException(train, message)
    }

    singletonSeq head
  }

  def flow(train : String) : Seq[TrainDetailPage] = {
    debug(s"Starting loading train details for train ${train}")

    searchTrain(train) match {
      case Success(p: TrainDetailPage) => Seq(p)
      case Success(p: MultipleTrainsPage) => loadMultipleTrainDetails(train, p)
      case Success(p: NoTrainPage) => Seq()
      case Success(p: UnknownPage) => throw new TransportRetrievalException(train, "Unknown page")
      case Failure(e : Exception) => throw new TransportRetrievalException(train, e)
      case Failure(e) => throw e
    }
  }

  private def searchTrain(train : String) : Try[Page] = {
    val response = sendLookupRequest(train)
    debug("Loading train detail responded with code " + response.getStatusCode)

    response match {
      case ok if response.isStatusOK => Success(Page(response.getContentAsString))
      case _ => Failure(new TransportRetrievalException(train, "An error occurred during retrieving response for train search request: " + response.getStatusCode + ": " + response.getReason))
    }
  }

  private def sendLookupRequest(train : String) = client
    .postRequest()
    .to(TrainDetailPageFlow.LOOKUP_URL)
    .withFormParametersPayload(TrainDetailPageFlow.lookupTrainRequestBody(train))
    .send

  private def loadMultipleTrainDetails(train : String, trainsPage : MultipleTrainsPage) : Seq[TrainDetailPage] = {
    val urls : Seq[(String, String)] = trainsPage.trainsHostsAndPaths
    debug("Starting loading trains details for " + urls.size + " pages")

    val triedPages : Seq[Try[TrainDetailPage]] =
      urls.map({
        case (path, params) => Future { loadTrainDetailPage(train, path, params)}
      }).map(Await.result(_, Duration.Inf))

    triedPages collect { case Failure(e) => error("Retrieving of a page detailed ended with an error", e)}

    triedPages collect {
      case Success(p) if p.isCzechRailwayCompany => p
    }
  }

  private def loadTrainDetailPage(train : String, path: String, params : String) : Try[TrainDetailPage] = {

      debug("Starting loading trains detail page for url params " + params)

      val response = sendTrainDetailRequest(path, params)
      debug("Trains info page retrieved with status code " + response.getStatusCode)

      if (!response.isStatusOK) {
        Failure(new TransportRetrievalException(train, "An error occurred during retrievig train detail response for train " + train + ": " + response.getStatusCode + ": " + response.getReason))
      }

      Page(response.getContentAsString) match {
        case p : TrainDetailPage => Success(p)
        case _ => Failure(new TransportRetrievalException(train, "An error occurred during retrieving train detail for train " + train + ": unknown format of train detail page."))
      }
  }

  private def sendTrainDetailRequest(path : String, params : String) = client.getRequest
    .to(TrainDetailPageFlow.trainDetailUri(path))
    .rawUrlParameters(params)
    .send()

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy