com.apothesource.pillfill.service.prescription.impl.DefaultPrescriptionServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.apothesource.pillfill.service.prescription.impl.DefaultPrescriptionServiceImpl.java

Source

/*
 *
 *  * The MIT License
 *  *
 *  * Copyright {$YEAR} Apothesource, Inc.
 *  *
 *  * Permission is hereby granted, free of charge, to any person obtaining a copy
 *  * of this software and associated documentation files (the "Software"), to deal
 *  * in the Software without restriction, including without limitation the rights
 *  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  * copies of the Software, and to permit persons to whom the Software is
 *  * furnished to do so, subject to the following conditions:
 *  *
 *  * The above copyright notice and this permission notice shall be included in
 *  * all copies or substantial portions of the Software.
 *  *
 *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  * THE SOFTWARE.
 *
 */
package com.apothesource.pillfill.service.prescription.impl;

import com.apothesource.pillfill.datamodel.PrescriptionType;
import com.apothesource.pillfill.datamodel.aggregation.AccountAggregationTaskRequest;
import com.apothesource.pillfill.datamodel.aggregation.AccountAggregationTaskResponse;
import com.apothesource.pillfill.datamodel.aggregation.Point;
import com.apothesource.pillfill.datamodel.userdatatype.Credential;
import com.apothesource.pillfill.network.PFNetworkManager;
import com.apothesource.pillfill.service.prescription.PrescriptionService;
import com.apothesource.pillfill.service.PFServiceEndpoints;

import static com.apothesource.pillfill.utilites.ReactiveUtils.subscribeIoObserveImmediate;

import com.google.common.base.Joiner;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.IOException;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import rx.Observable;
import rx.exceptions.OnErrorThrowable;
import timber.log.Timber;

/**
 * Created by Michael Ramirez on 5/29/15. Copyright 2015, Apothesource, Inc. All Rights Reserved.
 */
public class DefaultPrescriptionServiceImpl implements PrescriptionService {
    private static final Logger log = Logger.getLogger("RxServiceImpl");
    private static final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
    public static final Type RX_LIST_TYPE = new TypeToken<ArrayList<PrescriptionType>>() {
    }.getType();
    private static final String HTTP_CONTENT_TYPE_JSON = "application/json";
    public static final int EXTRACT_TIMEOUT_SECONDS = 60;
    public static final int EXTRACT_POLL_TIME_SECONDS = 5;

    @Override
    public Observable<PrescriptionType> getPrescription(String rxId) {
        return getPrescriptions(Collections.singletonList(rxId));
    }

    public Observable<PrescriptionType> getPrescriptionWithRevId(String rxId, String revId) {
        throw new UnsupportedOperationException("Not implmenented yet");
    }

    @Override
    public Observable<PrescriptionType> getPrescriptions(List<String> rxIds) {
        return subscribeIoObserveImmediate(subscriber -> {
            if (rxIds == null || rxIds.isEmpty()) {
                log.warning("Cannot load prescriptions- empty id list");
                subscriber.onCompleted();
            } else {
                int idx = 0;
                while (idx < rxIds.size()) {
                    int batchSize = (rxIds.size() - idx > 100) ? 100 : rxIds.size() - idx;
                    List<String> reqList = rxIds.subList(idx, idx + batchSize);
                    final String url = String.format(PFServiceEndpoints.PRESCRIPTIONS_URL,
                            Joiner.on("%2C").skipNulls().join(reqList));
                    log.info(String.format("Requesting url: %s", url));
                    try {
                        OkHttpClient connection = PFNetworkManager.getPinnedPFHttpClient();
                        Request request = new Request.Builder().url(url).addHeader("Cache-Control", "no-cache")
                                .build();

                        Response response = connection.newCall(request).execute();

                        if (response.code() != 200) {
                            subscriber.onError(new RuntimeException(
                                    String.format("Invalid response code: %d", response.code())));
                            return;
                        } else {
                            Type type = new TypeToken<ArrayList<PrescriptionType>>() {
                            }.getType();
                            ArrayList<PrescriptionType> retList = gson.fromJson(response.body().string(), type);
                            Observable.from(retList).forEach(subscriber::onNext);
                        }
                    } catch (Exception e) {
                        subscriber.onError(e);
                        return;
                    }
                    idx += batchSize;
                }
                subscriber.onCompleted();
            }
        });
    }

    @Override
    public Observable<AccountAggregationTaskResponse> requestPrescriptionExtraction(Credential c, Point location) {
        AccountAggregationTaskRequest request = new AccountAggregationTaskRequest();
        request.datasource = c.getSource();
        request.username = c.getUsername();
        request.location = location;
        request.dob = c.getDob();
        request.password = c.getPassword();
        return requestPrescriptionExtraction(request);
    }

    @Override
    public Observable<AccountAggregationTaskResponse> requestPrescriptionExtraction(
            AccountAggregationTaskRequest request) {
        return subscribeIoObserveImmediate(subscriber -> {
            String responseStr = null;

            try {
                OkHttpClient client = PFNetworkManager.getPinnedPFHttpClient();
                Request req = new Request.Builder()
                        .post(RequestBody.create(MediaType.parse(HTTP_CONTENT_TYPE_JSON), gson.toJson(request)))
                        .url(PFServiceEndpoints.RX_REQUEST_EXTRACT_URL).build();

                Response res = client.newCall(req).execute();
                responseStr = res.body().string();
                AccountAggregationTaskResponse response = gson.fromJson(responseStr,
                        AccountAggregationTaskResponse.class);
                subscriber.onNext(response);
                subscriber.onCompleted();
            } catch (IOException e) {
                log.log(Level.SEVERE, "Communication error during extraction request.");
                subscriber.onError(e);
            } catch (JsonSyntaxException e) {
                log.severe(String.format("Error parsing response: %s", responseStr));
                subscriber.onError(e);
            }
        });
    }

    @Override
    public Observable<AccountAggregationTaskResponse> getExtractResponse(AccountAggregationTaskResponse task) {
        return subscribeIoObserveImmediate(subscriber -> {
            OkHttpClient client = PFNetworkManager.getPinnedPFHttpClient();
            String statusUrl = String.format(PFServiceEndpoints.RX_EXTRACT_STATUS_URL, task.taskId);
            Request req = new Request.Builder().url(statusUrl).build();

            String responseStr = null;
            try {
                Response res = client.newCall(req).execute();
                responseStr = res.body().string();
                AccountAggregationTaskResponse response = gson.fromJson(responseStr,
                        AccountAggregationTaskResponse.class);
                subscriber.onNext(response);
                subscriber.onCompleted();
            } catch (IOException e) {
                Timber.e(e, "Error requesting extract status from server.");
                subscriber.onError(e);
            } catch (JsonParseException e) {
                Timber.e(e, "Unexpected response from the server: %s", responseStr);
                subscriber.onError(e);
            }
        });
    }

    public Observable<AccountAggregationTaskResponse> waitForExtractResponse(AccountAggregationTaskResponse task) {
        return waitForExtractResponse(task, EXTRACT_TIMEOUT_SECONDS);
    }

    public Observable<AccountAggregationTaskResponse> waitForExtractResponse(AccountAggregationTaskResponse task,
            int timeoutSeconds) {
        return Observable.interval(EXTRACT_POLL_TIME_SECONDS, TimeUnit.SECONDS).timeInterval().flatMap(time -> {
            AccountAggregationTaskResponse response = getExtractResponse(task).toBlocking().first();
            if (response.resultCode != AccountAggregationTaskResponse.RESULT_CODE_PROCESSING) {
                return Observable.just(response);
            } else {
                return Observable.empty();
            }
        }).timeout(timeoutSeconds, TimeUnit.SECONDS).first();
    }

    @Override
    public Observable<PrescriptionType> enrichPrescriptions(PrescriptionType... rxList) {
        return enrichPrescriptions(Arrays.asList(rxList));
    }

    @Override
    public Observable<PrescriptionType> enrichPrescriptions(List<PrescriptionType> rxList) {
        return subscribeIoObserveImmediate(subscriber -> {
            try {
                OkHttpClient client = PFNetworkManager.getPinnedPFHttpClient();
                Request req = new Request.Builder()
                        .post(RequestBody.create(MediaType.parse(HTTP_CONTENT_TYPE_JSON), gson.toJson(rxList)))
                        .url(PFServiceEndpoints.RX_ENRICH_URL).build();
                Response res = client.newCall(req).execute();
                List<PrescriptionType> enrichedRxList = gson.fromJson(res.body().charStream(), RX_LIST_TYPE);
                Observable.from(enrichedRxList).forEach(subscriber::onNext);
                subscriber.onCompleted();
            } catch (IOException ex) {
                Logger.getLogger(DefaultPrescriptionServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
                subscriber.onError(ex);
            }
        });
    }
}