class LoginInteractor(private val api: Api) { fun login(email: String, password: String): Observable { return when { !EMAIL_PATTERN.matcher(email).matches() -> Observable.just(LoginError(ErrorClass.INVALID_EMAIL)) password.length < 6 -> Observable.just(LoginError(ErrorClass.INVALID_PASSWORD) as LoginResult) else -> api.login(Credentials(email, password)) .map { response -> LoginSuccess(response.token, response.info) as LoginResult } .onErrorReturn { throwable -> when (throwable) { is HttpException -> convertHttpException(throwable) is SocketException -> LoginError(ErrorClass.FAILED_TO_CONNECT) else -> LoginError(ErrorClass.SERVER_NOT_RESPONDING) } } .startWith(PendingLogin) } } // по хорошему неплохо бы словить 400, мол сервер ведь тоже должен валидировать данные, // но я не придумал как впихнуть это в ошибку, это нужно менять возвращаемый тип от апи private fun convertHttpException(error: HttpException): LoginResult = when (error.statusCode) { HttpURLConnection.HTTP_NOT_FOUND -> LoginError(ErrorClass.USER_NOT_FOUND) HttpURLConnection.HTTP_UNAUTHORIZED -> LoginError(ErrorClass.WRONG_CREDENTIALS) else -> LoginError(ErrorClass.SERVER_INTERNAL_ERROR) } companion object { @JvmField val EMAIL_PATTERN: Pattern = Pattern.compile( "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" + "\\@" + "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" + "(" + "\\." + "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" + ")+" ) } }