Skip to content

Instantly share code, notes, and snippets.

@makiftutuncu
Created August 22, 2016 12:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save makiftutuncu/80a1513394be3485f3b852915a491205 to your computer and use it in GitHub Desktop.
Save makiftutuncu/80a1513394be3485f3b852915a491205 to your computer and use it in GitHub Desktop.
A Play controller to collect all districts of all cities of all countries of MuezzinAPI
def test: Action[AnyContent] = {
def countriesToCities(countries: List[Country]): Future[Maybe[Map[Country, List[City]]]] = {
val idToCountryMap: Map[Int, Country] = countries.map {
country: Country =>
country.id -> country
}.toMap
val futureMaybeCitiesList: List[Future[Maybe[List[City]]]] = countries.map {
country: Country =>
Thread.sleep(20)
CityFetcherService.getCities(country.id)
}
Future.sequence(futureMaybeCitiesList).map {
maybeCitiesList: List[Maybe[List[City]]] =>
maybeCitiesList.foldLeft(Maybe(Map.empty[Country, List[City]])) {
case (maybeCountryToCitiesMap: Maybe[Map[Country, List[City]]], maybeCities: Maybe[List[City]]) =>
if (maybeCities.hasErrors) {
Maybe(maybeCountryToCitiesMap.maybeErrors.getOrElse(Errors.empty) ++ maybeCities.errors)
} else if (maybeCountryToCitiesMap.hasErrors) {
maybeCountryToCitiesMap
} else {
val cities: List[City] = maybeCities.value
val country: Country = idToCountryMap(cities.head.countryId)
Maybe(maybeCountryToCitiesMap.value + (country -> cities))
}
}
}
}
def citiesToDistricts(cities: List[City]): Future[Maybe[Map[City, List[District]]]] = {
val idToCityMap: Map[Int, City] = cities.map {
city: City =>
city.id -> city
}.toMap
val initialCityToDistrictsMap: Map[City, List[District]] = cities.map {
city: City =>
city -> List.empty[District]
}.toMap
val futureMaybeDistrictsList: List[Future[Maybe[List[District]]]] = cities.map {
city: City =>
Thread.sleep(20)
DistrictFetcherService.getDistricts(city.id)
}
Future.sequence(futureMaybeDistrictsList).map {
maybeDistrictsList: List[Maybe[List[District]]] =>
maybeDistrictsList.foldLeft(Maybe(initialCityToDistrictsMap)) {
case (maybeCityToDistrictsMap: Maybe[Map[City, List[District]]], maybeDistricts: Maybe[List[District]]) =>
if (maybeDistricts.hasErrors) {
Maybe(maybeCityToDistrictsMap.maybeErrors.getOrElse(Errors.empty) ++ maybeDistricts.errors)
} else if (maybeCityToDistrictsMap.hasErrors) {
maybeCityToDistrictsMap
} else {
val districts: List[District] = maybeDistricts.value
if (districts.isEmpty) {
maybeCityToDistrictsMap
} else {
val city: City = idToCityMap(districts.head.cityId)
Maybe(maybeCityToDistrictsMap.value + (city -> districts))
}
}
}
}
}
Action.async {
val futureMaybeResult: Future[Maybe[Map[Country, Map[City, List[District]]]]] = {
CountryFetcherService.getCountries.flatMap {
maybeCountries: Maybe[List[Country]] =>
if (maybeCountries.hasErrors) {
Future.successful(Maybe(maybeCountries.errors))
} else {
val countries: List[Country] = maybeCountries.value
countriesToCities(countries).flatMap {
maybeCountriesToCitiesMap: Maybe[Map[Country, List[City]]] =>
if (maybeCountriesToCitiesMap.hasErrors) {
Future.successful(Maybe(maybeCountriesToCitiesMap.errors))
} else {
val countriesToCitiesMap: Map[Country, List[City]] = maybeCountriesToCitiesMap.value
countriesToCitiesMap.foldLeft(Future.successful(Maybe(Map.empty[Country, Map[City, List[District]]]))) {
case (futureMaybeResult: Future[Maybe[Map[Country, Map[City, List[District]]]]], (country: Country, cities: List[City])) =>
futureMaybeResult.flatMap {
maybeResult: Maybe[Map[Country, Map[City, List[District]]]] =>
if (maybeResult.hasErrors) {
Future.successful(Maybe(maybeResult.errors))
} else {
citiesToDistricts(cities).map {
maybeCitiesToDistrictsMap: Maybe[Map[City, List[District]]] =>
if (maybeCitiesToDistrictsMap.hasErrors) {
Maybe(maybeCitiesToDistrictsMap.errors)
} else {
Maybe(maybeResult.value + (country -> maybeCitiesToDistrictsMap.value))
}
}
}
}
}
}
}
}
}
}
futureMaybeResult.map {
maybeResult: Maybe[Map[Country, Map[City, List[District]]]] =>
if (maybeResult.hasErrors) {
ServiceUnavailable(maybeResult.errors.represent(JsonErrorRepresenter, includeWhen = false))
} else {
val countriesJson: JsObject = maybeResult.value.map {
case (country: Country, citiesToDistrictsMap: Map[City, List[District]]) =>
val citiesJson: JsObject = citiesToDistrictsMap.map {
case (city: City, districts: List[District]) =>
val districtsJson: JsObject = districts.foldLeft(Json.obj())(_ ++ _.toJson)
Json.obj(city.id.toString -> (city.toJson ++ (if (districts.isEmpty) Json.obj() else Json.obj("districts" -> districtsJson))))
}.foldLeft(Json.obj())(_ ++ _)
Json.obj(country.id.toString -> (country.toJson ++ Json.obj("cities" -> citiesJson)))
}.foldLeft(Json.obj())(_ ++ _)
val result: JsObject = Json.obj("countries" -> countriesJson)
Ok(result)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment