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

com.alextherapeutics.diga.implementation.DigaCodeDefaultParser Maven / Gradle / Ivy

/*
 * Copyright 2021-2021 Alex Therapeutics AB and individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *
 */

package com.alextherapeutics.diga.implementation;

import com.alextherapeutics.diga.DigaCodeParser;
import com.alextherapeutics.diga.DigaCodeValidationException;
import com.alextherapeutics.diga.DigaHealthInsuranceDirectory;
import com.alextherapeutics.diga.model.DigaBillingInformation;
import com.alextherapeutics.diga.model.DigaCodeInformation;
import com.alextherapeutics.diga.model.DigaInvoiceMethod;
import de.bitmarck.bms.base32.Base32Check1;
import lombok.AllArgsConstructor;
import lombok.Builder;

/** Parses a DiGA Code */
@AllArgsConstructor
public class DigaCodeDefaultParser implements DigaCodeParser {
  private final DigaHealthInsuranceDirectory healthInsuranceDirectory;

  @Override
  public DigaCodeInformation parseCodeForValidation(String code)
      throws DigaCodeValidationException {
    var parsedCode = parseCode(code);
    var healthInsuranceInformation =
        healthInsuranceDirectory.getInformation(parsedCode.healthInsuranceCode);
    // TODO null check and throw exception?
    return DigaCodeInformation.builder()
        .endpoint(healthInsuranceInformation.getEndpunktKommunikationsstelle())
        .insuranceCompanyIKNumber(healthInsuranceInformation.getKostentraegerkennung())
        .clearingCenterIKNumber(healthInsuranceInformation.getIKAbrechnungsstelle())
        .insuranceCompanyName(healthInsuranceInformation.getNameDesKostentraegers())
        .fullDigaCode(code)
        .personalDigaCode(parsedCode.healthInsuranceIndividualCode)
        .build();
  }

  @Override
  public DigaBillingInformation parseCodeForBilling(String code)
      throws DigaCodeValidationException {
    var parsedCode = parseCode(code);
    var healthInsuranceInformation =
        healthInsuranceDirectory.getInformation(parsedCode.healthInsuranceCode);
    return DigaBillingInformation.builder()
        .endpoint(healthInsuranceInformation.getEndpunktKommunikationsstelle())
        .insuranceCompanyIKNumber(healthInsuranceInformation.getKostentraegerkennung())
        .clearingCenterIKNumber(healthInsuranceInformation.getIKAbrechnungsstelle())
        .buyerCompanyCreditorIk(healthInsuranceInformation.getIKDesRechnungsempfaengers())
        .insuranceCompanyName(healthInsuranceInformation.getNameDesKostentraegers())
        .buyerCompanyPostalCode(
            healthInsuranceInformation.getPLZ() != null
                ? healthInsuranceInformation.getPLZ()
                : DigaBillingInformation.INFORMATION_MISSING)
        .buyerCompanyAddressLine(
            healthInsuranceInformation.getStrassePostfach() != null
                ? healthInsuranceInformation.getStrassePostfach()
                    + " "
                    + healthInsuranceInformation.getHausnummerPostfachnummer()
                : DigaBillingInformation.INFORMATION_MISSING)
        .buyerCompanyCity(
            healthInsuranceInformation.getOrt() != null
                ? healthInsuranceInformation.getOrt()
                : DigaBillingInformation.INFORMATION_MISSING)
        .buyerInvoicingMethod(
            DigaInvoiceMethod.fromIdentifier(healthInsuranceInformation.getVersandart().intValue()))
        .buyerInvoicingEmail(healthInsuranceInformation.getEMailKostentraeger())
        .build();
  }

  // according to
  // https://www.gkv-datenaustausch.de/media/dokumente/leistungserbringer_1/digitale_gesundheitsanwendungen/technische_anlagen_aktuell_7/Anlage_1_Technische_Anlage_zur_RL_V1.0.pdf
  private ParsedDigaCode parseCodeString(String codeString) {
    return ParsedDigaCode.builder()
        .healthInsuranceCode(codeString.substring(0, 2))
        .version(Character.toString(codeString.charAt(2)))
        .healthInsuranceIndividualCode(codeString.substring(3, 15))
        .checksum(Character.toString(codeString.charAt(15)))
        .build();
  }

  private boolean validateDigaCodeStructure(String code) {
    if (code != null && code.length() == 16) {
      var codeToCheck = code.substring(0, code.length() - 1);
      var extractedChecksum = code.substring(code.length() - 1);
      var base32Instance = Base32Check1.getInstance();

      try {
        var calculatedChecksum = base32Instance.compute(codeToCheck);

        if (base32Instance.validate(codeToCheck + calculatedChecksum)) {
          return extractedChecksum.equals(String.valueOf(calculatedChecksum));
        }
      } catch (IndexOutOfBoundsException | IllegalArgumentException e) {
        return false;
      }
    }

    return false;
  }

  private DigaCodeDefaultParser.ParsedDigaCode parseCode(String code)
      throws DigaCodeValidationException {
    if (!validateDigaCodeStructure(code)) {
      throw new DigaCodeValidationException("Invalid DiGA code");
    }
    return parseCodeString(code);
  }

  @Builder
  private static class ParsedDigaCode {
    private final String healthInsuranceCode;
    private final String version;
    private final String healthInsuranceIndividualCode;
    private final String checksum;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy