dk.nsi.sdm4.ydelse.parser.SSRLineParser.java Source code

Java tutorial

Introduction

Here is the source code for dk.nsi.sdm4.ydelse.parser.SSRLineParser.java

Source

/**
 * The MIT License
 *
 * Original work sponsored and donated by National Board of e-Health (NSI), Denmark
 * (http://www.nsi.dk)
 *
 * Copyright (C) 2011 National Board of e-Health (NSI), Denmark (http://www.nsi.dk)
 *
 * 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 dk.nsi.sdm4.ydelse.parser;

import dk.nsi.sdm4.core.parser.ParserException;
import dk.nsi.sdm4.ydelse.common.splunk.SplunkLogger;
import dk.nsi.sdm4.ydelse.relation.model.DoctorOrganisationIdentifier;
import dk.nsi.sdm4.ydelse.relation.model.HashedCpr;
import dk.nsi.sdm4.ydelse.relation.model.SSR;
import org.joda.time.DateTime;
import org.joda.time.Interval;

import java.text.ParseException;
import java.text.SimpleDateFormat;

public class SSRLineParser {
    private static final SplunkLogger log = new SplunkLogger(SSRLineParser.class);

    private static final int EXPECTED_NUMBER_OF_FIELDS = 5;
    private static final String SEPARATOR = ",";
    private String[] fields;

    public static SsrAction parseLine(String line) throws ParserException {
        SSRLineParser parser = new SSRLineParser(line);
        return parser.parse();
    }

    private SSRLineParser(String line) throws ParserException {
        this.fields = getTokens(line, SEPARATOR, EXPECTED_NUMBER_OF_FIELDS);

        // strip whitespaces - the data from CSC can contain a varying amount of whitespaces
        for (int i = 0; i < EXPECTED_NUMBER_OF_FIELDS; i++) {
            this.fields[i] = this.fields[i].trim();
        }
    }

    private DoctorOrganisationIdentifier doctorOrganisationId;
    private String patientCpr;
    private Interval admittedInterval;
    private String ssrReference;

    private SsrAction parse() throws ParserException {
        if (everythingButExternalReferenceIsBlank()) {
            parseSsrReference();
            return SsrAction.createDeletion(ssrReference);
        } else if (!parseTreatmentInterval()) { // unfortunately CSC does not always add the dates, it has been decided (NSPSUPPORT-96) that we will ignore the fields with no date
            return SsrAction.createNOOP();
        } else {
            parseDoctorOrganisationId();
            parsePatientCpr();
            parseSsrReference();

            SSR ssr = SSR.createInstance(HashedCpr.buildFromHashedString(patientCpr), doctorOrganisationId,
                    admittedInterval, ssrReference);
            return SsrAction.createInsertion(ssr);
        }
    }

    private static final int DOCTOR_ORG_ID_FIELD = 0;
    private static final int PATIENT_CPR_FIELD = 1;
    private static final int TREATMENT_START_TIME_FIELD = 2;
    private static final int TREATMENT_END_TIME_FIELD = 3;
    private static final int SSR_REFERENCE_FIELD = 4;

    private boolean fieldIsMissing(int i) {
        return fields[i].trim().equals("");
    }

    private boolean everythingButExternalReferenceIsBlank() {
        return fieldIsMissing(DOCTOR_ORG_ID_FIELD) && fieldIsMissing(PATIENT_CPR_FIELD)
                && fieldIsMissing(TREATMENT_START_TIME_FIELD) && fieldIsMissing(TREATMENT_END_TIME_FIELD)
                && !fieldIsMissing(SSR_REFERENCE_FIELD);
    }

    private void parseDoctorOrganisationId() throws ParserException {
        if (fieldIsMissing(DOCTOR_ORG_ID_FIELD)) {
            throw new ParserException("Doctor organisation id (ydernummer) must be present");
        } else {
            try {
                doctorOrganisationId = DoctorOrganisationIdentifier.newInstance(fields[DOCTOR_ORG_ID_FIELD]);
            } catch (IllegalArgumentException e) {
                throw new ParserException(e.getMessage(), e);
            }
        }
    }

    private void parsePatientCpr() throws ParserException {
        if (fieldIsMissing(PATIENT_CPR_FIELD)) {
            throw new ParserException("Patient cpr must be present");
        } else {
            patientCpr = fields[PATIENT_CPR_FIELD];
        }
    }

    private boolean parseTreatmentInterval() throws ParserException {
        try {
            admittedInterval = parseIntervalFromTwoIdenticalDaysAsSpecifiedBySsr(fields, TREATMENT_START_TIME_FIELD,
                    TREATMENT_END_TIME_FIELD);
        } catch (ParserException ex) {
            log.error("Failed to parse line with reference " + fields[SSR_REFERENCE_FIELD] + ". Fault: "
                    + ex.getMessage());
            return false;
        }

        return true;
    }

    private void parseSsrReference() throws ParserException {
        if (fieldIsMissing(SSR_REFERENCE_FIELD)) {
            throw new ParserException("Reference to original ssr record must be present");
        } else {
            ssrReference = fields[SSR_REFERENCE_FIELD];

            // NSPSUPPORT-23 Data from SSR was observed to be of length 16, not 24 as previously specified.
            // We have decided to use space padding to overcome this.
            if (ssrReference.length() < SSR.REFERENCE_LENGTH) {
                ssrReference = ssrReference + spacePadding(SSR.REFERENCE_LENGTH - ssrReference.length());
            }
        }
    }

    private String spacePadding(int n) {
        String padding = "";
        for (int i = 0; i < n; i++) {
            padding += " ";
        }
        return padding;
    }

    private String[] getTokens(String line, String separator, int expectedNumberOfFields) throws ParserException {
        if (line.contains(System.getProperty("line.separator"))) {
            throw new ParserException("Line contains new-line character");
        }

        int asManyTimesAsPossible = -1;
        String[] tokens = line.split(separator, asManyTimesAsPossible);

        if (tokens.length < expectedNumberOfFields) {
            throw new ParserException("Too few fields on line: " + line);
        }

        if (tokens.length > expectedNumberOfFields) {
            throw new ParserException("Too many fields on line: " + line);
        }
        return tokens;
    }

    private boolean fieldIsMissing(String[] fields, int i) {
        return fields[i].equals("");
    }

    public Interval parseIntervalFromTwoIdenticalDaysAsSpecifiedBySsr(String[] fields, int treatmentStartTimeField,
            int treatmentEndTimeField) throws ParserException {
        if (fieldIsMissing(fields, treatmentStartTimeField)) {
            throw new ParserException("Treatment start time must be present");
        }

        if (fieldIsMissing(fields, treatmentEndTimeField)) {
            throw new ParserException("Treatment end time must be present");
        }

        DateTime admittedStart;
        try {
            admittedStart = parseDateAsSpecifiedBySsr(fields[treatmentStartTimeField]);
        } catch (ParseException e) {
            throw new ParserException("Treatment start time is malformed: " + fields[treatmentStartTimeField]);
        }

        DateTime admittedEnd;
        try {
            admittedEnd = parseDateAsSpecifiedBySsr(fields[treatmentEndTimeField]);
        } catch (ParseException e) {
            throw new ParserException("Treatment end time is malformed: " + fields[treatmentEndTimeField]);
        }

        if (!admittedStart.equals(admittedEnd)) {
            throw new ParserException("Treatment end time must be the same day as the treatment start time");
        }

        admittedEnd = admittedEnd.plusDays(1);

        return new Interval(admittedStart, admittedEnd);
    }

    private final static SimpleDateFormat ssrFormat = new SimpleDateFormat("yyyyMMdd");

    static {
        ssrFormat.setLenient(false);
    }

    private DateTime parseDateAsSpecifiedBySsr(String s) throws ParseException {
        return new DateTime(ssrFormat.parse(s));
    }
}