diff --git a/phase4-dbnalliance-client/src/main/java/com/helger/phase4/dbnalliance/Phase4DBNAllianceSender.java b/phase4-dbnalliance-client/src/main/java/com/helger/phase4/dbnalliance/Phase4DBNAllianceSender.java
index 81971cf04..c341111a9 100644
--- a/phase4-dbnalliance-client/src/main/java/com/helger/phase4/dbnalliance/Phase4DBNAllianceSender.java
+++ b/phase4-dbnalliance-client/src/main/java/com/helger/phase4/dbnalliance/Phase4DBNAllianceSender.java
@@ -26,6 +26,7 @@
import javax.annotation.Nullable;
import javax.annotation.OverridingMethodsMustInvokeSuper;
import javax.annotation.concurrent.Immutable;
+import javax.annotation.concurrent.NotThreadSafe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,6 +34,8 @@
import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.Nonempty;
+import com.helger.commons.mime.CMimeType;
+import com.helger.commons.mime.IMimeType;
import com.helger.commons.state.ESuccess;
import com.helger.peppol.smp.ESMPTransportProfile;
import com.helger.peppol.utils.PeppolCertificateHelper;
@@ -43,6 +46,8 @@
import com.helger.peppolid.IParticipantIdentifier;
import com.helger.peppolid.IProcessIdentifier;
import com.helger.peppolid.factory.BDXR2IdentifierFactory;
+import com.helger.peppolid.simple.doctype.SimpleDocumentTypeIdentifier;
+import com.helger.peppolid.simple.process.SimpleProcessIdentifier;
import com.helger.phase4.CAS4;
import com.helger.phase4.attachment.AS4OutgoingAttachment;
import com.helger.phase4.crypto.ICryptoSessionKeyProvider;
@@ -59,6 +64,7 @@
import com.helger.xhe.v10.CXHE10;
import com.helger.xhe.v10.XHE10Marshaller;
import com.helger.xhe.v10.XHE10XHEType;
+import com.helger.xhe.v10.cac.XHE10PayloadType;
/**
* This class contains all the specifics to send AS4 messages with the
@@ -72,7 +78,9 @@
public final class Phase4DBNAllianceSender
{
public static final BDXR2IdentifierFactory IF = BDXR2IdentifierFactory.INSTANCE;
+
private static final Logger LOGGER = LoggerFactory.getLogger (Phase4DBNAllianceSender.class);
+ private static final IMimeType MIME_TYPE = CMimeType.APPLICATION_XML;
private Phase4DBNAllianceSender ()
{}
@@ -93,7 +101,7 @@ private static XHE10XHEType _createXHE (@Nonnull final IParticipantIdentifier aS
final DBNAlliancePayload aPayload = new DBNAlliancePayload (IF);
// Content type code is mandatory
- aPayload.setContentTypeCode ("application/xml");
+ aPayload.setContentTypeCode (MIME_TYPE.getAsString ());
aPayload.setCustomizationID (null, aDocTypeID.getValue ());
aPayload.setProfileID (aProcID.getScheme (), aProcID.getValue ());
@@ -123,6 +131,17 @@ public static DBNAllianceUserMessageBuilder builder ()
return new DBNAllianceUserMessageBuilder ();
}
+ /**
+ * @return Create a new Builder for AS4 messages if the XHE message is
+ * present. Never null
.
+ * @since 3.0.0
+ */
+ @Nonnull
+ public static DBNAllianceUserMessageXHEBuilder xheBuilder ()
+ {
+ return new DBNAllianceUserMessageXHEBuilder ();
+ }
+
/**
* Abstract DBNAlliance UserMessage builder class with sanity methods.
*
@@ -574,11 +593,122 @@ protected ESuccess finishFields () throws Phase4Exception
// Now we have the main payload
payload (AS4OutgoingAttachment.builder ()
.data (aXHEBytes)
- .compressionGZIP ()
.mimeTypeXML ()
+ .compressionGZIP ()
.charset (StandardCharsets.UTF_8));
return ESuccess.SUCCESS;
}
}
+
+ /**
+ * A builder class for sending AS4 messages using DBNAlliance specifics. Use
+ * {@link #sendMessage()} or {@link #sendMessageAndCheckForReceipt()} to
+ * trigger the main transmission.
+ * This builder class assumes, that the XHE was created outside, therefore no
+ * validation can occur.
+ *
+ * @author Philip Helger
+ * @since 3.0.0
+ */
+ @NotThreadSafe
+ public static class DBNAllianceUserMessageXHEBuilder extends
+ AbstractDBNAllianceUserMessageBuilder
+ {
+ private byte [] m_aPayloadBytes;
+
+ /**
+ * Create a new builder with the defaults from
+ * {@link AbstractDBNAllianceUserMessageBuilder#AbstractDBNAllianceUserMessageBuilder()}
+ */
+ public DBNAllianceUserMessageXHEBuilder ()
+ {}
+
+ /**
+ * Set the XHE payload to be used as a byte array. This means, that you need
+ * to pass in all other mandatory fields manually (sender participant ID,
+ * receiver participant ID, document Type ID and process ID).
+ *
+ * @param aXHEBytes
+ * The XHE bytes to be used. May not be null
.
+ * @return this for chaining
+ * @see #senderParticipantID(IParticipantIdentifier)
+ * @see #receiverParticipantID(IParticipantIdentifier)
+ */
+ @Nonnull
+ public DBNAllianceUserMessageXHEBuilder payload (@Nonnull final byte [] aXHEBytes)
+ {
+ ValueEnforcer.notNull (aXHEBytes, "XHEBytes");
+ m_aPayloadBytes = aXHEBytes;
+ return this;
+ }
+
+ /**
+ * Set the payload, the sender participant ID, the receiver participant ID,
+ * the document type ID and the process ID.
+ *
+ * @param aXHE
+ * The XHE to use. May not be null
.
+ * @return this for chaining
+ * @see #payload(byte[])
+ * @see #senderParticipantID(IParticipantIdentifier)
+ * @see #receiverParticipantID(IParticipantIdentifier)
+ */
+ @Nonnull
+ public DBNAllianceUserMessageXHEBuilder payloadAndMetadata (@Nonnull final DBNAllianceXHEData aXHE)
+ {
+ ValueEnforcer.notNull (aXHE, "SBDH");
+
+ // Check with logging
+ if (!aXHE.areAllFieldsSet (true))
+ throw new IllegalArgumentException ("The provided DBNAlliance XHE data is incomplete. See logs for details.");
+
+ final XHE10XHEType aJaxbXHE = aXHE.getAsXHEDocument ();
+ final XHE10PayloadType aJaxbPayload = aJaxbXHE.getPayloads ().hasPayloadEntries () ? aJaxbXHE.getPayloads ()
+ .getPayloadAtIndex (0)
+ : null;
+
+ senderParticipantID (aXHE.getFromPartyAsIdentifier ()).receiverParticipantID (aXHE.getToPartyAsIdentifier ());
+ if (aJaxbPayload != null)
+ {
+ if (aJaxbPayload.getCustomizationID () != null)
+ documentTypeID (new SimpleDocumentTypeIdentifier (null, aJaxbPayload.getCustomizationID ().getValue ()));
+
+ if (aJaxbPayload.getProfileID () != null)
+ processID (new SimpleProcessIdentifier (aJaxbPayload.getProfileID ().getSchemeID (),
+ aJaxbPayload.getProfileID ().getValue ()));
+ }
+ return payload (new XHE10Marshaller ().getAsBytes (aJaxbXHE));
+ }
+
+ @Override
+ @OverridingMethodsMustInvokeSuper
+ public boolean isEveryRequiredFieldSet ()
+ {
+ if (!super.isEveryRequiredFieldSet ())
+ return false;
+
+ if (m_aPayloadBytes == null)
+ {
+ LOGGER.warn ("The field 'payloadBytes' is not set");
+ return false;
+ }
+ // All valid
+ return true;
+ }
+
+ @Override
+ @OverridingMethodsMustInvokeSuper
+ protected ESuccess finishFields () throws Phase4Exception
+ {
+ // Perform SMP lookup
+ if (super.finishFields ().isFailure ())
+ return ESuccess.FAILURE;
+
+ // Now we have the main payload
+ payload (AS4OutgoingAttachment.builder ().data (m_aPayloadBytes).mimeTypeXML ().compressionGZIP ());
+
+ return ESuccess.SUCCESS;
+ }
+ }
}