diff options
| author | Christof Rabensteiner <christof.rabensteiner@iaik.tugraz.at> | 2019-05-08 09:41:37 +0200 | 
|---|---|---|
| committer | Christof Rabensteiner <christof.rabensteiner@iaik.tugraz.at> | 2019-05-08 09:41:37 +0200 | 
| commit | 1aaec2e6127b9b2261a97749daa15c23f0af7be1 (patch) | |
| tree | 1f52ca9d17ae9ff7853a7fbbafa3c179ec022081 /src/main/java | |
| parent | fefde1ad7592412007b9efed2b62cb403d3f6cac (diff) | |
| download | moa-zs-1aaec2e6127b9b2261a97749daa15c23f0af7be1.tar.gz moa-zs-1aaec2e6127b9b2261a97749daa15c23f0af7be1.tar.bz2 moa-zs-1aaec2e6127b9b2261a97749daa15c23f0af7be1.zip | |
Implement Pipeline Flow and mzs2msg Conversion
- Implement and test conversion from mzs:DeliveryRequest to
  msg:DeliveryRequest with the "convert-pojos-by-hand"-strategy.
  Reason: The chosen strategy benefits from JAXB's strong typing,
  which is useful in this scenario: Differences between msg and mzs
  are nuanced and easy to overlook. The chosen strategy is,
  unfortunately, verbose and could become expensive to maintain.
- Update SameThreadDeliveryPipeline: Integrate tnvz query, conversion,
  and msg query.
- Add MsgClient stub.
tnvz:
- Change TnvzClient stub interface.
- Implement mimetype mismatch check from tnvz Response.
- Put p:Identification from tnvz response into msg:DeliveryRequest.
MZS Schema changes:
- Replace DeliveryRequest/Sender/Person with CorporateBody (because
  thats the only sender that is allowed by zusemsg) and add a
  SenderProfile choice.
- Add ID Attribute to DeliveryRequest/Sender because
  msg/DeliveryRequest/Sender/AbstractSenderPersonType also has an id
  attribute.
- Remove PersonDataType because it's dead code.
Diffstat (limited to 'src/main/java')
4 files changed, 420 insertions, 11 deletions
| diff --git a/src/main/java/at/gv/egiz/moazs/MsgClient.java b/src/main/java/at/gv/egiz/moazs/MsgClient.java new file mode 100644 index 0000000..3a6b5ce --- /dev/null +++ b/src/main/java/at/gv/egiz/moazs/MsgClient.java @@ -0,0 +1,26 @@ +package at.gv.egiz.moazs; + +import at.gv.zustellung.msg.xsd.DeliveryRequestStatusType; +import at.gv.zustellung.msg.xsd.DeliveryRequestType; +import org.springframework.stereotype.Component; + +import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.Success.successBuilder; +import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.deliveryRequestStatusTypeBuilder; + +@Component +public class MsgClient { + +    public DeliveryRequestStatusType send(DeliveryRequestType msgRequest) { + +        //stub implementation +        var success = successBuilder() +                .withAppDeliveryID(msgRequest.getMetaData().getAppDeliveryID()) +                .build(); + +        return deliveryRequestStatusTypeBuilder() +                .withSuccess(success) +                .build(); + +    } + +} diff --git a/src/main/java/at/gv/egiz/moazs/Mzs2MsgConverter.java b/src/main/java/at/gv/egiz/moazs/Mzs2MsgConverter.java new file mode 100644 index 0000000..b517f39 --- /dev/null +++ b/src/main/java/at/gv/egiz/moazs/Mzs2MsgConverter.java @@ -0,0 +1,321 @@ +package at.gv.egiz.moazs; + +import at.gv.zustellung.msg.xsd.*; +import at.gv.zustellung.msg.xsd.DeliveryRequestType.DeliveryRequestTypeBuilder; +import at.gv.zustellung.msg.xsd.persondata.*; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +import javax.xml.bind.JAXBElement; +import java.util.List; + +import static at.gv.zustellung.msg.xsd.AttachmentType.attachmentTypeBuilder; +import static at.gv.zustellung.msg.xsd.AttachmentsType.attachmentsTypeBuilder; +import static at.gv.zustellung.msg.xsd.ConfirmationAddress.confirmationAddressBuilder; +import static at.gv.zustellung.msg.xsd.DeliveryRequestType.deliveryRequestTypeBuilder; +import static at.gv.zustellung.msg.xsd.Receiver.receiverBuilder; +import static at.gv.zustellung.msg.xsd.Sender.senderBuilder; +import static at.gv.zustellung.msg.xsd.SenderCorporateBodyType.senderCorporateBodyTypeBuilder; +import static at.gv.zustellung.msg.xsd.WebserviceURL.webserviceURLBuilder; +import static at.gv.zustellung.msg.xsd.persondata.CorporateBodyType.corporateBodyTypeBuilder; +import static at.gv.zustellung.msg.xsd.persondata.IdentificationType.Value.valueBuilder; +import static at.gv.zustellung.msg.xsd.persondata.IdentificationType.identificationTypeBuilder; +import static at.gv.zustellung.msg.xsd.persondata.InternetAddressType.internetAddressTypeBuilder; +import static at.gv.zustellung.msg.xsd.persondata.PersonNameType.*; +import static at.gv.zustellung.msg.xsd.persondata.PersonNameType.Affix.affixBuilder; +import static at.gv.zustellung.msg.xsd.persondata.PersonNameType.FamilyName.familyNameBuilder; +import static at.gv.zustellung.msg.xsd.persondata.PhysicalPersonType.physicalPersonTypeBuilder; +import static at.gv.zustellung.msg.xsd.persondata.PostalAddressType.DeliveryAddress.deliveryAddressBuilder; +import static at.gv.zustellung.msg.xsd.persondata.PostalAddressType.postalAddressTypeBuilder; +import static at.gv.zustellung.msg.xsd.persondata.TelephoneAddressType.telephoneAddressTypeBuilder; +import static java.lang.String.format; +import static java.util.stream.Collectors.toList; + + +@Component +public class Mzs2MsgConverter { + +    private final at.gv.zustellung.msg.xsd.ObjectFactory msgFactory = new at.gv.zustellung.msg.xsd.ObjectFactory(); +    private final at.gv.zustellung.msg.xsd.persondata.ObjectFactory personFactory = new at.gv.zustellung.msg.xsd.persondata.ObjectFactory(); + +    public DeliveryRequestType convert(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType mzsRequest) { +        return setupBuilder(mzsRequest) +                .withReceiver(convert(mzsRequest.getReceiver())) +                .build(); +    } + +    public DeliveryRequestType convert(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType mzsRequest, +                                                                IdentificationType identification) { +        return setupBuilder(mzsRequest) +                .withReceiver(convert(mzsRequest.getReceiver(), identification)) +                .build(); +    } + +    private DeliveryRequestTypeBuilder setupBuilder(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType mzsRequest) { +        return deliveryRequestTypeBuilder() +                .withVersion("2.0.0") +                .withSender(convert(mzsRequest.getSender())) +                .withMetaData(mzsRequest.getMetaData()) +                .withAttachments(convertPayloads(mzsRequest.getPayload())); +    } + +    //------------- SENDER ------------------ + +    private Sender convert(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Sender sender) { +        return senderBuilder() +                .withSenderPerson(extractSenderPerson(sender)) +                .withLogo(sender.getLogo()) +                .withAdditionalCriteria(sender.getAdditionalCriteria()) +                .withConfirmationAddress(convertConfirmationAddress(sender)) +                .build(); +    } + +    private JAXBElement<? extends AbstractSenderPersonType> extractSenderPerson(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Sender sender) { + +        Assert.isTrue(sender.getSenderProfile() != null || sender.getCorporateBody() != null, +                "Neither SenderProfile nor CorporateBody are given"); + +        var builder = senderCorporateBodyTypeBuilder(); + +        if(sender.getSenderProfile() != null) { +            builder.withSenderProfile(sender.getSenderProfile()); +        } else { +            var identification = sender.getCorporateBody().getIdentification().get(0); +            builder.withCorporateBody(convert(sender.getCorporateBody())) +                    .withIdentification(convert(identification)); +        } + +        builder.withId(sender.getId()); + +        return msgFactory.createSenderCorporateBody(builder.build()); + +    } + +    private ConfirmationAddress convertConfirmationAddress(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Sender sender) { + +        var builder = confirmationAddressBuilder(); + +        if(sender.getEMailAddress() != null) { +            builder.withEmail(convert(sender.getEMailAddress())) +                    .withType(sender.getEMailAddress().getType()); +        } else { +            builder.withWebserviceURL(convert(sender.getWebserviceURL())) +                    .withType(sender.getWebserviceURL().getType()); +        } + +        return builder.build(); +    } + +    private InternetAddressType convert(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Sender.EMailAddress eMailAddress) { +        return internetAddressTypeBuilder() +                .withAddress(eMailAddress.getValue()) +                .build(); +    } + +    private WebserviceURL convert(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Sender.WebserviceURL webserviceURL) { +        return webserviceURLBuilder() +                .withAddress(webserviceURL.getValue()) +                .withAlternativeEmail(webserviceURL.getAlternativeEmail()) +                .build(); +    } + + +    //------------- RECEIVER ------------------ + +    private at.gv.zustellung.msg.xsd.Receiver convert(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Receiver receiver) { +        return setupReceiverBuilder(receiver).build(); +    } + +    private at.gv.zustellung.msg.xsd.Receiver convert(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Receiver receiver, +                                                      IdentificationType identificationType) { +        return setupReceiverBuilder(receiver) +                .withIdentification(identificationType) +                .build(); +    } + +    private Receiver.ReceiverBuilder setupReceiverBuilder(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Receiver receiver) { +        var builder = receiverBuilder() +                .withPreAdviceNote(receiver.getPreAdviceNote()) +                .withAdditionalCriteria(receiver.getAdditionalCriteria()) +                .withPerson(convert(receiver.getPerson())) +                .withAddress(convertAddresses(receiver.getAddress())); + +        if (receiver.getIdentification() != null) builder.withIdentification(convert(receiver.getIdentification())); + +        return builder; + +    } + +    //------------- ADDRESSES ------------------ + +    private List<JAXBElement<? extends AbstractAddressType>> convertAddresses( +            List<JAXBElement<? extends at.gv.zustellung.app2mzs.xsd.persondata.AbstractAddressType>> addresses) { +        return addresses.stream() +                .map(JAXBElement::getValue) +                .map(this::convert) +                .map(personFactory::createAddress) +                .collect(toList()); +    } + +    private AbstractAddressType convert(at.gv.zustellung.app2mzs.xsd.persondata.AbstractAddressType address) { +        if        (address instanceof at.gv.zustellung.app2mzs.xsd.persondata.InternetAddressType ) { return convert((at.gv.zustellung.app2mzs.xsd.persondata.InternetAddressType)  address); +        } else if (address instanceof at.gv.zustellung.app2mzs.xsd.persondata.PostalAddressType   ) { return convert((at.gv.zustellung.app2mzs.xsd.persondata.PostalAddressType)    address); +        } else if (address instanceof at.gv.zustellung.app2mzs.xsd.persondata.TelephoneAddressType) { return convert((at.gv.zustellung.app2mzs.xsd.persondata.TelephoneAddressType) address); +        } else { +            throw new IllegalArgumentException(format("No conversion strategy of address of type {0}", address.getClass().toGenericString())); +        } +    } + +    private InternetAddressType convert(at.gv.zustellung.app2mzs.xsd.persondata.InternetAddressType address) { +        return internetAddressTypeBuilder() +                .withAddress(address.getAddress()) +                .withId(address.getId()) +                .build(); +    } + +    private PostalAddressType convert(at.gv.zustellung.app2mzs.xsd.persondata.PostalAddressType address) { +        return postalAddressTypeBuilder() +                .withCountryCode(address.getCountryCode()) +                .withDeliveryAddress(convert(address.getDeliveryAddress())) +                .withId(address.getId()) +                .withMunicipality(address.getMunicipality()) +                .withMunicipalityNumber(address.getMunicipalityNumber()) +                .withPostalCode(address.getPostalCode()) +                .withType(address.getType()) +                .build(); +    } + +    private PostalAddressType.DeliveryAddress convert(at.gv.zustellung.app2mzs.xsd.persondata.PostalAddressType.DeliveryAddress deliveryAddress) { +        return deliveryAddressBuilder() +                .withBuildingNumber(deliveryAddress.getBuildingNumber()) +                .withDoorNumber(deliveryAddress.getDoorNumber()) +                .withStreetName(deliveryAddress.getStreetName()) +                .withUnit(deliveryAddress.getUnit()) +                .build(); +    } + +    private TelephoneAddressType convert(at.gv.zustellung.app2mzs.xsd.persondata.TelephoneAddressType address) { +        return telephoneAddressTypeBuilder() +                .withId(address.getId()) +                .withMessengerService(address.getMessengerService()) +                .withNumber(address.getNumber().getFormattedNumber()) +                .build(); +    } + + +    //------------- ATTACHMENTS ------------------ + +    private AttachmentsType convertPayloads(List<at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Payload> payloadList) { +        var builder = attachmentsTypeBuilder(); + +        payloadList.stream() +                .map(this::convert) +                .forEach(builder::addAttachment); + +        return builder.build(); +    } + +    private AttachmentType convert(at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Payload payload) { + +        return attachmentTypeBuilder() +                .withFileName(payload.getFileName()) +                .withContent(payload.getBinaryDocument()) +                .withCheckSum(payload.getCheckSum()) +                .withURL(payload.getDocumentReference()) +                .withDocumentClass(payload.getDocumentClass()) +                .withMimeType(payload.getMIMEType()) +                .withSize(payload.getSize()) +                .build(); +    } + +    //------------- IDENTIFICATION TYPE ------------- + +    private IdentificationType convert(at.gv.zustellung.app2mzs.xsd.persondata.IdentificationType identification) { +        return identificationTypeBuilder() +                .withId(identification.getId()) +                .withType(identification.getType()) +                .withValue(convert(identification.getValue())) +                .build(); +    } + +    private IdentificationType.Value convert(at.gv.zustellung.app2mzs.xsd.persondata.IdentificationType.Value value) { +        return valueBuilder() +                .withId(value.getId()) +                .withValue(value.getValue()) +                .build(); +    } + +    //------------ PERSONS -------------------- + +    private JAXBElement<? extends AbstractPersonType> convert( +            JAXBElement<? extends at.gv.zustellung.app2mzs.xsd.persondata.AbstractPersonType> jaxbPerson) { + +        var mzsPerson = jaxbPerson.getValue(); + +        Assert.isTrue(personIsPhysical(mzsPerson) || personIsCorporateBody(mzsPerson), +                "Person is neither a PhysicalPerson nor a CorporateBody."); + +        var msgPerson = (personIsPhysical(mzsPerson)) +                ? convert((at.gv.zustellung.app2mzs.xsd.persondata.PhysicalPersonType) mzsPerson) +                : convert((at.gv.zustellung.app2mzs.xsd.persondata.CorporateBodyType) mzsPerson); + +        return personFactory.createPerson(msgPerson); + +    } + +    private boolean personIsPhysical(at.gv.zustellung.app2mzs.xsd.persondata.AbstractPersonType person) { +        return person instanceof at.gv.zustellung.app2mzs.xsd.persondata.PhysicalPersonType; +    } + +    private boolean personIsCorporateBody(at.gv.zustellung.app2mzs.xsd.persondata.AbstractPersonType person) { +        return person instanceof at.gv.zustellung.app2mzs.xsd.persondata.CorporateBodyType; +    } + +    private CorporateBodyType convert(at.gv.zustellung.app2mzs.xsd.persondata.CorporateBodyType corporateBody) { +        return corporateBodyTypeBuilder() +                .withFullName(corporateBody.getFullName()) +                .withId(corporateBody.getId()) +                .withOrganization(corporateBody.getOrganization()) +                .withTarget(corporateBody.getTarget()) +                .build(); +    } + +    private PhysicalPersonType convert(at.gv.zustellung.app2mzs.xsd.persondata.PhysicalPersonType physicalPerson) { +        return physicalPersonTypeBuilder() +                .withDateOfBirth(physicalPerson.getDateOfBirth()) +                .withId(physicalPerson.getId()) +                .withName(convert(physicalPerson.getName())) +                .build(); +    } + +    private PersonNameType convert(at.gv.zustellung.app2mzs.xsd.persondata.PersonNameType name) { +        return personNameTypeBuilder() +                .withGivenName(name.getGivenName()) +                .withFamilyName(convert(name.getFamilyName())) +                .withAffix(convertAffixes(name.getAffix())) +                .build(); +    } + +    private FamilyName convert(at.gv.zustellung.app2mzs.xsd.persondata.PersonNameType.FamilyName familyName) { +        return familyNameBuilder() +                .withPrefix(familyName.getPrefix()) +                .withPrimary(familyName.getPrimary()) +                .withValue(familyName.getValue()) +                .build(); +    } + +    private List<Affix> convertAffixes(List<at.gv.zustellung.app2mzs.xsd.persondata.PersonNameType.Affix> affix) { +        return affix.stream() +                .map(mzsAffix -> convert(mzsAffix)) +                .collect(toList()); +    } + +    private Affix convert(at.gv.zustellung.app2mzs.xsd.persondata.PersonNameType.Affix affix) { +        return affixBuilder() +                .withPosition(affix.getPosition()) +                .withType(affix.getType()) +                .withValue(affix.getValue()) +                .build(); +    } + +} diff --git a/src/main/java/at/gv/egiz/moazs/TnvzClient.java b/src/main/java/at/gv/egiz/moazs/TnvzClient.java index 7b4e3f6..7aa6344 100644 --- a/src/main/java/at/gv/egiz/moazs/TnvzClient.java +++ b/src/main/java/at/gv/egiz/moazs/TnvzClient.java @@ -2,13 +2,17 @@ package at.gv.egiz.moazs;  import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Sender;  import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Receiver; +import at.gv.zustellung.tnvz.xsd.PersonResultSuccessType; +import at.gv.zustellung.tnvz.xsd.PersonResultType; +import at.gv.zustellung.tnvz.xsd.PersonResultType.PersonResultTypeBuilder;  import org.springframework.stereotype.Component;  @Component  public class TnvzClient { -    public boolean queryPerson(Sender sender, Receiver receiver) { -        return true; +    public PersonResultType queryPerson(Sender sender, Receiver receiver) { +        PersonResultSuccessType success = new PersonResultSuccessType.PersonResultSuccessTypeBuilder().build(); +        return new PersonResultTypeBuilder().withSuccess(success).build();      }  } diff --git a/src/main/java/at/gv/egiz/moazs/pipeline/SameThreadDeliveryPipeline.java b/src/main/java/at/gv/egiz/moazs/pipeline/SameThreadDeliveryPipeline.java index b309434..e2b219a 100644 --- a/src/main/java/at/gv/egiz/moazs/pipeline/SameThreadDeliveryPipeline.java +++ b/src/main/java/at/gv/egiz/moazs/pipeline/SameThreadDeliveryPipeline.java @@ -1,40 +1,98 @@  package at.gv.egiz.moazs.pipeline; +import at.gv.egiz.moazs.MsgClient; +import at.gv.egiz.moazs.Mzs2MsgConverter;  import at.gv.egiz.moazs.TnvzClient;  import at.gv.egiz.moazs.repository.DeliveryRepository;  import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType; +import at.gv.zustellung.msg.xsd.persondata.IdentificationType; +import at.gv.zustellung.tnvz.xsd.PersonResultType;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.context.annotation.Profile;  import org.springframework.stereotype.Component; +import java.util.Collection; +import java.util.List; + +import static java.lang.String.format; +import static java.lang.String.join; +import static java.util.stream.Collectors.toSet; +  @Component  @Profile("!cluster")  public class SameThreadDeliveryPipeline implements DeliveryPipeline {      private final DeliveryRepository repository;      private final TnvzClient tnvzClient; +    private final Mzs2MsgConverter converter; +    private final MsgClient msgClient; -    public SameThreadDeliveryPipeline(@Autowired DeliveryRepository repository, TnvzClient tnvzClient) { +    public SameThreadDeliveryPipeline(@Autowired DeliveryRepository repository, +                                      @Autowired TnvzClient tnvzClient, +                                      @Autowired Mzs2MsgConverter converter, +                                      @Autowired MsgClient msgClient) {          this.repository = repository;          this.tnvzClient = tnvzClient; +        this.converter = converter; +        this.msgClient = msgClient;      }      @Override      public void processRequest(String appDeliveryId) { -        var request = repository.getDeliveryRequest(appDeliveryId).orElseThrow(); -        checkAddressability(request); +        var mzsRequest = repository.getDeliveryRequest(appDeliveryId).orElseThrow(); +        var msgRequest = (mzsRequest.getConfig().isPerformQueryPersonRequest()) +                ? converter.convert(mzsRequest, queryPerson(mzsRequest)) +                : converter.convert(mzsRequest); + +        var status = msgClient.send(msgRequest); +        repository.add(status); +    } + +    private IdentificationType queryPerson(DeliveryRequestType request) { +        var result = tnvzClient.queryPerson(request.getSender(), request.getReceiver()); + +        if (result.getError() != null) { +            var error = result.getError(); +            var info = error.getErrorInfo(); +            var noteSent = format("Preadvice note was {0}sent", (error.getPreAdviceNoteSent() != null) ? "" : "not "); +            var message = format("Receiver is not addressable. Code: {0} ; Text: {1}; {2}", +                    info.getCode(), info.getText(), noteSent); +            throw new RuntimeException(message); +        } + +        var mismatchedTypes = findMimeTypeMismatches(result, request); -        //store response to repository +        if (!mismatchedTypes.isEmpty()) { +            var template = "Request contains attachment of type(s) {0}, but receiver only accepts attachments of type(s) {1}"; +            var acceptedTypesString = join(",", getAcceptedTypes(result)); +            var mismatchedTypesString = join(",", mismatchedTypes); +            var message = format(template, mismatchedTypesString, acceptedTypesString); +            throw new RuntimeException(message); +        } + +        return result.getSuccess().getIdentification();      } -    private void checkAddressability(DeliveryRequestType request) { -        if (request.getConfig().isPerformQueryPersonRequest()) { -            if (!tnvzClient.queryPerson(request.getReceiver())) { -                throw new RuntimeException("Receiver is not addressable."); -            } +    private Collection<String> findMimeTypeMismatches(PersonResultType result, DeliveryRequestType request) { +        var acceptedTypes = getAcceptedTypes(result); + +        if (acceptedTypes.contains("*/*")) { +            return List.of();          } + +        var typesInRequest = request.getPayload().stream() +                .map(payload -> payload.getMIMEType()) +                .collect(toSet()); + +        typesInRequest.removeAll(acceptedTypes); + +        return typesInRequest; +    } + +    private List<String> getAcceptedTypes(PersonResultType result) { +        return result.getSuccess().getMimeTypeList().getMimeType();      }  } | 
