com.helger.peppol.sbdh.PeppolSBDHDocument Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of peppol-sbdh Show documentation
Show all versions of peppol-sbdh Show documentation
Library for reading and writing OASIS Standard Business Document Header (SBDH) documents conforming to the PEPPOL specifications
/**
* Copyright (C) 2014-2016 Philip Helger
* philip[at]helger[dot]com
*
* 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
*
* http://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.helger.peppol.sbdh;
import java.time.LocalDateTime;
import java.util.UUID;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import org.w3c.dom.Element;
import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.Nonempty;
import com.helger.commons.annotation.ReturnsMutableCopy;
import com.helger.commons.datetime.PDTFactory;
import com.helger.commons.equals.EqualsHelper;
import com.helger.commons.hashcode.HashCodeGenerator;
import com.helger.commons.string.StringHelper;
import com.helger.commons.string.ToStringGenerator;
import com.helger.peppol.identifier.generic.doctype.IDocumentTypeIdentifier;
import com.helger.peppol.identifier.generic.doctype.SimpleDocumentTypeIdentifier;
import com.helger.peppol.identifier.generic.participant.IParticipantIdentifier;
import com.helger.peppol.identifier.generic.participant.SimpleParticipantIdentifier;
import com.helger.peppol.identifier.generic.process.IProcessIdentifier;
import com.helger.peppol.identifier.generic.process.SimpleProcessIdentifier;
import com.helger.peppol.identifier.peppol.PeppolIdentifierHelper;
/**
* This class contains all the PEPPOL data per SBDH document in a syntax neutral
* way.
*
* @author Philip Helger
*/
@NotThreadSafe
public class PeppolSBDHDocument
{
// Sender
private String m_sSenderScheme;
private String m_sSenderValue;
// Receiver
private String m_sReceiverScheme;
private String m_sReceiverValue;
// BusinessScope
private String m_sDocumentTypeScheme;
private String m_sDocumentTypeValue;
private String m_sProcessScheme;
private String m_sProcessValue;
// DocumentIdentification
private String m_sStandard;
private String m_sTypeVersion;
private String m_sType;
private String m_sInstanceIdentifier;
private LocalDateTime m_aCreationDateAndTime;
// BusinessMessage
private Element m_aBusinessMessage;
public PeppolSBDHDocument ()
{}
/**
* Set the sender identifier.
*
* @param sScheme
* The PEPPOL identifier scheme. This is usually always
* {@link PeppolIdentifierHelper#DEFAULT_PARTICIPANT_SCHEME} . May neither be
* null
nor empty. This field is mapped to
* StandardBusinessDocumentHeader/Sender/Identifier/@Authority
* .
* @param sValue
* The sender identifier value. May neither be null
nor
* empty. This field is mapped to
* StandardBusinessDocumentHeader/Sender/Identifier/
.
* @return this
*/
@Nonnull
public PeppolSBDHDocument setSender (@Nonnull @Nonempty final String sScheme, @Nonnull @Nonempty final String sValue)
{
m_sSenderScheme = ValueEnforcer.notEmpty (sScheme, "Scheme");
m_sSenderValue = ValueEnforcer.notEmpty (sValue, "Value");
return this;
}
/**
* Set the sender identifier value using the default identifier
* scheme/authority {@link PeppolIdentifierHelper#DEFAULT_PARTICIPANT_SCHEME}.
*
* @param sValue
* The sender identifier value. May neither be null
nor
* empty. This field is mapped to
* StandardBusinessDocumentHeader/Sender/Identifier/
.
* @return this
*/
@Nonnull
public PeppolSBDHDocument setSenderWithDefaultScheme (@Nonnull @Nonempty final String sValue)
{
return setSender (PeppolIdentifierHelper.DEFAULT_PARTICIPANT_SCHEME, sValue);
}
/**
* @return The sender identifier scheme. May be null
if not
* initialized. This field is mapped to
* StandardBusinessDocumentHeader/Sender/Identifier/@Authority
* .
*/
@Nullable
public String getSenderScheme ()
{
return m_sSenderScheme;
}
/**
* @return The sender identifier value. May be null
if not
* initialized. This field is mapped to
* StandardBusinessDocumentHeader/Sender/Identifier/
.
*/
@Nullable
public String getSenderValue ()
{
return m_sSenderValue;
}
/**
* @return The sender identifier as a participant identifier or
* null
if certain information are missing or are
* invalid.
*/
@Nullable
public IParticipantIdentifier getSenderAsIdentifier ()
{
return new SimpleParticipantIdentifier (m_sSenderScheme, m_sSenderValue);
}
/**
* Set the receiver identifier.
*
* @param sScheme
* The PEPPOL identifier scheme. This is usually always
* {@link PeppolIdentifierHelper#DEFAULT_PARTICIPANT_SCHEME} . May neither be
* null
nor empty. This field is mapped to
* StandardBusinessDocumentHeader/Receiver/Identifier/@Authority
* .
* @param sValue
* The receiver identifier value. May neither be null
nor
* empty. This field is mapped to
* StandardBusinessDocumentHeader/Receiver/Identifier/
.
* @return this
*/
@Nonnull
public PeppolSBDHDocument setReceiver (@Nonnull @Nonempty final String sScheme,
@Nonnull @Nonempty final String sValue)
{
m_sReceiverScheme = ValueEnforcer.notEmpty (sScheme, "Scheme");
m_sReceiverValue = ValueEnforcer.notEmpty (sValue, "Value");
return this;
}
/**
* Set the receiver identifier value using the default identifier
* scheme/authority {@link PeppolIdentifierHelper#DEFAULT_PARTICIPANT_SCHEME}.
*
* @param sValue
* The sender identifier value. May neither be null
nor
* empty. This field is mapped to
* StandardBusinessDocumentHeader/Receiver/Identifier/
.
* @return this
*/
@Nonnull
public PeppolSBDHDocument setReceiverWithDefaultScheme (@Nonnull @Nonempty final String sValue)
{
return setReceiver (PeppolIdentifierHelper.DEFAULT_PARTICIPANT_SCHEME, sValue);
}
/**
* @return The receiver identifier scheme. May be null
if not
* initialized. This field is mapped to
* StandardBusinessDocumentHeader/Receiver/Identifier/@Authority
* .
*/
@Nullable
public String getReceiverScheme ()
{
return m_sReceiverScheme;
}
/**
* @return The receiver identifier value. May be null
if not
* initialized. This field is mapped to
* StandardBusinessDocumentHeader/Receiver/Identifier/
.
*/
@Nullable
public String getReceiverValue ()
{
return m_sReceiverValue;
}
/**
* @return The receiver identifier as a participant identifier or
* null
if certain information are missing or are
* invalid.
*/
@Nullable
public IParticipantIdentifier getReceiverAsIdentifier ()
{
return new SimpleParticipantIdentifier (m_sReceiverScheme, m_sReceiverValue);
}
/**
* Set the document type identifier.
*
* @param sScheme
* The document type identifier scheme. May neither be
* null
nor empty.
* @param sValue
* The document type identifier value. May neither be null
* nor empty. This field is mapped to
* StandardBusinessDocumentHeader/BusinessScope/Scope[Type/text()="DOCUMENTID"]/InstanceIdentifier
* .
* @return this
*/
@Nonnull
public PeppolSBDHDocument setDocumentType (@Nonnull @Nonempty final String sScheme,
@Nonnull @Nonempty final String sValue)
{
m_sDocumentTypeScheme = ValueEnforcer.notEmpty (sScheme, "Scheme");
m_sDocumentTypeValue = ValueEnforcer.notEmpty (sValue, "Value");
return this;
}
/**
* Set the document type identifier using the default identifier
* scheme/authority {@link PeppolIdentifierHelper#DEFAULT_DOCUMENT_TYPE_SCHEME} .
*
* @param sValue
* The document type identifier value. May neither be null
* nor empty. This field is mapped to
* StandardBusinessDocumentHeader/BusinessScope/Scope[Type/text()="DOCUMENTID"]/InstanceIdentifier
* .
* @return this
*/
@Nonnull
public PeppolSBDHDocument setDocumentTypeWithDefaultScheme (@Nonnull @Nonempty final String sValue)
{
return setDocumentType (PeppolIdentifierHelper.DEFAULT_DOCUMENT_TYPE_SCHEME, sValue);
}
/**
* @return The document type identifier scheme. May be null
if
* not initialized yet. This field is currently not mapped.
*/
@Nullable
public String getDocumentTypeScheme ()
{
return m_sDocumentTypeScheme;
}
/**
* @return The document type identifier value. May be null
if not
* initialized yet. This field is mapped to
* StandardBusinessDocumentHeader/BusinessScope/Scope[Type/text()="DOCUMENTID"]/InstanceIdentifier
* .
*/
@Nullable
public String getDocumentTypeValue ()
{
return m_sDocumentTypeValue;
}
/**
* @return The document type identifier as an object or null
if
* certain information are missing or are invalid.
*/
@Nullable
public IDocumentTypeIdentifier getDocumentTypeAsIdentifier ()
{
return new SimpleDocumentTypeIdentifier (m_sDocumentTypeScheme, m_sDocumentTypeValue);
}
/**
* Set the process identifier.
*
* @param sScheme
* The process identifier scheme. May neither be null
nor
* empty.
* @param sValue
* The process identifier. May neither be null
nor empty.
* This field is mapped to
* StandardBusinessDocumentHeader/BusinessScope/Scope[Type/text()="PROCESSID"]/InstanceIdentifier
* .
* @return this
*/
@Nonnull
public PeppolSBDHDocument setProcess (@Nonnull @Nonempty final String sScheme, @Nonnull @Nonempty final String sValue)
{
m_sProcessScheme = ValueEnforcer.notEmpty (sScheme, "Scheme");
m_sProcessValue = ValueEnforcer.notEmpty (sValue, "Value");
return this;
}
/**
* Set the document type identifier using the default identifier
* scheme/authority {@link PeppolIdentifierHelper#DEFAULT_PROCESS_SCHEME}.
*
* @param sValue
* The process identifier. May neither be null
nor empty.
* This field is mapped to
* StandardBusinessDocumentHeader/BusinessScope/Scope[Type/text()="PROCESSID"]/InstanceIdentifier
* .
* @return this
*/
@Nonnull
public PeppolSBDHDocument setProcessWithDefaultScheme (@Nonnull @Nonempty final String sValue)
{
return setProcess (PeppolIdentifierHelper.DEFAULT_PROCESS_SCHEME, sValue);
}
/**
* @return The process identifier scheme. May be null
if not
* initialized yet. This field is currently not mapped.
*/
@Nullable
public String getProcessScheme ()
{
return m_sProcessScheme;
}
/**
* @return The process identifier value. May be null
if not
* initialized yet. This field is mapped to
* StandardBusinessDocumentHeader/BusinessScope/Scope[Type/text()="PROCESSID"]/InstanceIdentifier
* .
*/
@Nullable
public String getProcessValue ()
{
return m_sProcessValue;
}
/**
* @return The process identifier as an object or null
if certain
* information are missing or are invalid.
*/
@Nullable
public IProcessIdentifier getProcessAsIdentifier ()
{
return new SimpleProcessIdentifier (m_sProcessScheme, m_sProcessValue);
}
/**
* Set the content of the fields that are mapped to
* StandardBusinessDocumentHeader/DocumentIdentification
.
*
* @param sStandard
* The standard of the enveloped business message, normally described
* by use of the XML namespace of the business message root element
* (such as urn:oasis:names:specification: ubl:schema:xsd:Order-2). May
* not be null
. This field is mapped to
* StandardBusinessDocumentHeader/DocumentIdentification/Standard
* .
* @param sTypeVersion
* The version number of the enveloped business message (such as the
* value "2.1" for OASIS UBL 2.1 or "2.0" for OASIS UBL 2.0). May not
* be null
. This field is mapped to
* StandardBusinessDocumentHeader/DocumentIdentification/TypeVersion
* .
* @param sType
* Message type - mandatory in SBDH. XML local element name of the
* root-element in the business message. May not be null
.
* This field is mapped to
* StandardBusinessDocumentHeader/DocumentIdentification/Type
* .
* @param sInstanceIdentifier
* An informative unique ID created by the issuer of the envelope. The
* InstanceIdentifier MUST be unique for each Business Message Envelope
* being created. This ID is not the same as the ID of the business
* message (such as the Invoice Number). It is not the same as a
* transmission Message ID generated by the application sending the
* message (as defined in AS2 or START).
* The InstanceIdentifier MUST be globally unique and it is RECOMMENDED
* to use UUID (such as 118e3040-51d2-11e3-8f96-0800200c9a66). May not
* be null
. This field is mapped to
* StandardBusinessDocumentHeader/DocumentIdentification/InstanceIdentifier
* .
* @param aCreationDateAndTime
* The date and time for when this envelope was created. It is NOT
* necessarily the same as the issue date of the business document
* (such as the invoice) being enveloped. It is NOT necessarily the
* date time for transmission.
* The format of the value of this MUST include timezone information.
* May not be null
. This field is mapped to
* StandardBusinessDocumentHeader/DocumentIdentification/CreationDateAndTime
* .
* @return this
*/
@Nonnull
public PeppolSBDHDocument setDocumentIdentification (@Nonnull final String sStandard,
@Nonnull final String sTypeVersion,
@Nonnull final String sType,
@Nonnull final String sInstanceIdentifier,
@Nonnull final LocalDateTime aCreationDateAndTime)
{
m_sStandard = ValueEnforcer.notNull (sStandard, "Standard");
m_sTypeVersion = ValueEnforcer.notNull (sTypeVersion, "TypeVersion");
m_sType = ValueEnforcer.notNull (sType, "Type");
m_sInstanceIdentifier = ValueEnforcer.notNull (sInstanceIdentifier, "InstanceIdentifier");
m_aCreationDateAndTime = ValueEnforcer.notNull (aCreationDateAndTime, "CreationDateAndTime");
return this;
}
/**
* The standard of the enveloped business message, normally described by use
* of the XML namespace of the business message root element (such as
* urn:oasis:names:specification:ubl:schema:xsd:Order-2). This field is mapped
* to
* StandardBusinessDocumentHeader/DocumentIdentification/Standard
* .
*
* @return The standard value. May be null
.
*/
@Nullable
public String getStandard ()
{
return m_sStandard;
}
/**
* The version number of the enveloped business message (such as the value
* "2.1" for OASIS UBL 2.1 or "2.0" for OASIS UBL 2.0). This field is mapped
* to
* StandardBusinessDocumentHeader/DocumentIdentification/TypeVersion
* .
*
* @return The type version. May be null
.
*/
@Nullable
public String getTypeVersion ()
{
return m_sTypeVersion;
}
/**
* Message type - mandatory in SBDH. XML local element name of the
* root-element in the business message. This field is mapped to
* StandardBusinessDocumentHeader/DocumentIdentification/Type
.
*
* @return Type value. May be null
.
*/
@Nullable
public String getType ()
{
return m_sType;
}
/**
* An informative unique ID created by the issuer of the envelope. The
* InstanceIdentifier MUST be unique for each Business Message Envelope being
* created. This ID is not the same as the ID of the business message (such as
* the Invoice Number). It is not the same as a transmission Message ID
* generated by the application sending the message (as defined in AS2 or
* START).
* The InstanceIdentifier MUST be globally unique and it is RECOMMENDED to use
* UUID (such as 118e3040-51d2-11e3-8f96-0800200c9a66). This field is mapped
* to
* StandardBusinessDocumentHeader/DocumentIdentification/InstanceIdentifier
* .
*
* @return The instance identifier. May be null
.
*/
@Nullable
public String getInstanceIdentifier ()
{
return m_sInstanceIdentifier;
}
/**
* The date and time for when this envelope was created. It is NOT necessarily
* the same as the issue date of the business document (such as the invoice)
* being enveloped. It is NOT necessarily the date time for transmission.
* The format of the value of this MUST include timezone information. This
* field is mapped to
* StandardBusinessDocumentHeader/DocumentIdentification/CreationDateAndTime
* .
*
* @return The creation date time. May be null
.
*/
@Nullable
public LocalDateTime getCreationDateAndTime ()
{
return m_aCreationDateAndTime;
}
/**
* Set the main business message that should be transmitted together with the
* SBDH.
*
* @param aBusinessMessage
* The business message to be set. May not be null
.
* Internally the passed element is cloned, so that further
* modifications outside of this method have no impact on the business
* message inside this object.
* @return this
*/
@Nonnull
public PeppolSBDHDocument setBusinessMessage (@Nonnull final Element aBusinessMessage)
{
ValueEnforcer.notNull (aBusinessMessage, "BusinessMessage");
// Create a deep copy of the element to avoid outside modifications
m_aBusinessMessage = (Element) aBusinessMessage.cloneNode (true);
return this;
}
/**
* Check if a business message is present without having the need to
* explicitly call {@link #getBusinessMessage()} which returns a cloned node
* and is therefore an expensive operation.
*
* @return true
if a business message is present,
* false
otherwise.
*/
public boolean hasBusinessMessage ()
{
return m_aBusinessMessage != null;
}
/**
* Get the contained business message.
*
* @return null
if no business message is present. A clone (deep
* copy) of the business message otherwise.
*/
@Nullable
@ReturnsMutableCopy
public Element getBusinessMessage ()
{
return m_aBusinessMessage == null ? null : (Element) m_aBusinessMessage.cloneNode (true);
}
/**
* @return true
if all mandatory fields required for creating an
* SBDH are present, false
if at least one field is not
* set.
*/
public boolean areAllFieldsSet ()
{
return StringHelper.hasText (m_sSenderScheme) &&
StringHelper.hasText (m_sSenderValue) &&
StringHelper.hasText (m_sReceiverScheme) &&
StringHelper.hasText (m_sReceiverValue) &&
StringHelper.hasText (m_sDocumentTypeScheme) &&
StringHelper.hasText (m_sDocumentTypeValue) &&
StringHelper.hasText (m_sProcessScheme) &&
StringHelper.hasText (m_sProcessValue) &&
m_sStandard != null &&
m_sTypeVersion != null &&
m_sType != null &&
m_sInstanceIdentifier != null &&
m_aCreationDateAndTime != null &&
m_aBusinessMessage != null;
}
@Override
public boolean equals (final Object o)
{
if (o == this)
return true;
if (o == null || !getClass ().equals (o.getClass ()))
return false;
final PeppolSBDHDocument rhs = (PeppolSBDHDocument) o;
return EqualsHelper.equals (m_sSenderScheme, rhs.m_sSenderScheme) &&
EqualsHelper.equals (m_sSenderValue, rhs.m_sSenderValue) &&
EqualsHelper.equals (m_sReceiverScheme, rhs.m_sReceiverScheme) &&
EqualsHelper.equals (m_sReceiverValue, rhs.m_sReceiverValue) &&
EqualsHelper.equals (m_sDocumentTypeScheme, rhs.m_sDocumentTypeScheme) &&
EqualsHelper.equals (m_sDocumentTypeValue, rhs.m_sDocumentTypeValue) &&
EqualsHelper.equals (m_sProcessScheme, rhs.m_sProcessScheme) &&
EqualsHelper.equals (m_sProcessValue, rhs.m_sProcessValue) &&
EqualsHelper.equals (m_sStandard, rhs.m_sStandard) &&
EqualsHelper.equals (m_sTypeVersion, rhs.m_sTypeVersion) &&
EqualsHelper.equals (m_sType, rhs.m_sType) &&
EqualsHelper.equals (m_sInstanceIdentifier, rhs.m_sInstanceIdentifier) &&
EqualsHelper.equals (m_aCreationDateAndTime, rhs.m_aCreationDateAndTime) &&
EqualsHelper.equals (m_aBusinessMessage, rhs.m_aBusinessMessage);
}
@Override
public int hashCode ()
{
return new HashCodeGenerator (this).append (m_sSenderScheme)
.append (m_sSenderValue)
.append (m_sReceiverScheme)
.append (m_sReceiverValue)
.append (m_sDocumentTypeScheme)
.append (m_sDocumentTypeValue)
.append (m_sProcessScheme)
.append (m_sProcessValue)
.append (m_sStandard)
.append (m_sTypeVersion)
.append (m_sType)
.append (m_sInstanceIdentifier)
.append (m_aCreationDateAndTime)
.append (m_aBusinessMessage)
.getHashCode ();
}
@Override
public String toString ()
{
return new ToStringGenerator (this).append ("senderScheme", m_sSenderScheme)
.append ("senderValue", m_sSenderValue)
.append ("receiverScheme", m_sReceiverScheme)
.append ("receiverValue", m_sReceiverValue)
.append ("documentTypeScheme", m_sDocumentTypeScheme)
.append ("documentTypeValue", m_sDocumentTypeValue)
.append ("processScheme", m_sProcessScheme)
.append ("processValue", m_sProcessValue)
.append ("standard", m_sStandard)
.append ("typeVersion", m_sTypeVersion)
.append ("type", m_sType)
.append ("instanceIdentifier", m_sInstanceIdentifier)
.append ("creationDateAndTime", m_aCreationDateAndTime)
.append ("businessMessage", m_aBusinessMessage)
.toString ();
}
/**
* Create a new {@link PeppolSBDHDocument} object for a business message. The
* resulting object has all required fields set, except for:
*
* - sender ID
* - receiver ID
* - document type ID
* - and process ID
*
*
* @param aBusinessMessage
* The XML business message. May not be null
.
* @return A pre-filled {@link PeppolSBDHDocument} object with some
* information still missing.
* @see #setSender(String, String)
* @see #setReceiver(String, String)
* @see #setDocumentType(String, String)
* @see #setProcess(String, String)
*/
@Nonnull
public static PeppolSBDHDocument create (@Nonnull final Element aBusinessMessage)
{
ValueEnforcer.notNull (aBusinessMessage, "BusinessMessage");
final PeppolSBDHDocument ret = new PeppolSBDHDocument ();
ret.setBusinessMessage (aBusinessMessage);
// 1. Always use UBL 2.1
// 2. Use a new UUID as the instance identifier
// 3. Use the current date time
ret.setDocumentIdentification (aBusinessMessage.getNamespaceURI (),
CPeppolSBDH.TYPE_VERSION_21,
aBusinessMessage.getLocalName (),
UUID.randomUUID ().toString (),
PDTFactory.getCurrentLocalDateTime ());
return ret;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy