From cbc7024aab11df5bb5fb8dfc50e48b8295550cfd Mon Sep 17 00:00:00 2001 From: Philip Helger Date: Fri, 20 Dec 2024 00:43:01 +0100 Subject: [PATCH] Improved docs --- README.md | 2 + .../IPeppolDocumentTypeIdentifierParts.java | 2 +- .../PeppolDocumentTypeIdentifierParts.java | 87 ++++++++++++++++--- ...PeppolDocumentTypeIdentifierPartsTest.java | 12 +++ 4 files changed, 88 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 3f1e0854..d5de02f6 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,8 @@ They depend on several other libraries so I suggest you are going for the Maven # News and noteworthy +* v9.6.2 - work in progress + * Reworked the Peppol Document Type Identifier data model to handle non-XML syntax specific IDs as well * v9.6.1 - 2024-12-16 * Added new class `PeppolNaptrURLProvider` * Fixed the Peppol Directory URL of `EPeppolNetwork.PRODUCTION` diff --git a/peppol-id/src/main/java/com/helger/peppolid/peppol/doctype/IPeppolDocumentTypeIdentifierParts.java b/peppol-id/src/main/java/com/helger/peppolid/peppol/doctype/IPeppolDocumentTypeIdentifierParts.java index 4d62eb30..82aeee60 100644 --- a/peppol-id/src/main/java/com/helger/peppolid/peppol/doctype/IPeppolDocumentTypeIdentifierParts.java +++ b/peppol-id/src/main/java/com/helger/peppolid/peppol/doctype/IPeppolDocumentTypeIdentifierParts.java @@ -29,7 +29,7 @@ public interface IPeppolDocumentTypeIdentifierParts extends IPeppolGenericDocumentTypeIdentifierParts { /** - * Separator between namespace URI and local name + * Separator between XML root element namespace URI and local name */ String NAMESPACE_SEPARATOR = "::"; diff --git a/peppol-id/src/main/java/com/helger/peppolid/peppol/doctype/PeppolDocumentTypeIdentifierParts.java b/peppol-id/src/main/java/com/helger/peppolid/peppol/doctype/PeppolDocumentTypeIdentifierParts.java index 352a77ae..65720303 100644 --- a/peppol-id/src/main/java/com/helger/peppolid/peppol/doctype/PeppolDocumentTypeIdentifierParts.java +++ b/peppol-id/src/main/java/com/helger/peppolid/peppol/doctype/PeppolDocumentTypeIdentifierParts.java @@ -16,7 +16,10 @@ */ package com.helger.peppolid.peppol.doctype; +import java.util.function.BiConsumer; + import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import com.helger.commons.ValueEnforcer; @@ -24,6 +27,7 @@ import com.helger.commons.collection.impl.ICommonsList; import com.helger.commons.string.StringHelper; import com.helger.commons.string.ToStringGenerator; +import com.helger.commons.wrapper.Wrapper; import com.helger.peppolid.IDocumentTypeIdentifier; /** @@ -39,6 +43,20 @@ public class PeppolDocumentTypeIdentifierParts extends PeppolGenericDocumentType private final String m_sRootNS; private final String m_sLocalName; + /** + * Convert the XML specific syntax elements back to a single syntax specific + * ID + * + * @param sRootNS + * The XML root element namespace URI. May neither be null + * nor empty. + * @param sLocalName + * The XML root element local name. May neither be null + * nor empty. + * @return The combination of rootNS + :: + localName + */ + @Nonnull + @Nonempty public static String createSyntaxSpecificID (@Nonnull @Nonempty final String sRootNS, @Nonnull @Nonempty final String sLocalName) { @@ -95,22 +113,37 @@ public String toString () .getToString (); } + public static boolean isSyntaxSpecificIDLookingLikeXML (@Nullable final String sSyntaxSpecificID) + { + if (StringHelper.hasText (sSyntaxSpecificID)) + { + final int nIndex = sSyntaxSpecificID.indexOf (NAMESPACE_SEPARATOR); + if (nIndex >= 0) + { + // It's contains the separator and it's not the start and not the end + return nIndex > 0 && nIndex < sSyntaxSpecificID.length () - NAMESPACE_SEPARATOR.length (); + } + } + return false; + } + /** - * Parse an OpenPeppol Document Type Identifier using the XML syntax. + * Split the provided syntax specific ID into the XML root element namespace + * URI and the XML root element local name. * - * @param sDocTypeIDValue - * The document identifier value (without the scheme) to be split. May - * neither be null nor empty. - * @return The non-null Peppol identifier parts - * @throws IllegalArgumentException - * if the passed document identifier value does not match the - * specifications + * @param sSyntaxSpecificID + * The syntax specific ID to parse. May neither be null + * nor empty. + * @param aResultConsumer + * The consumer that takes root namespace URI and local name as a + * callback. + * @since 9.6.2 */ - @Nonnull - public static PeppolDocumentTypeIdentifierParts extractFromString (@Nonnull @Nonempty final String sDocTypeIDValue) + public static void extractXMLSyntaxSpecificID (@Nonnull @Nonempty final String sSyntaxSpecificID, + @Nonnull final BiConsumer aResultConsumer) { - final PeppolGenericDocumentTypeIdentifierParts aGenericParts = PeppolGenericDocumentTypeIdentifierParts.extractFromString (sDocTypeIDValue); - final String sSyntaxSpecificID = aGenericParts.getSyntaxSpecificID (); + ValueEnforcer.notEmpty (sSyntaxSpecificID, "SyntaxSpecificID"); + ValueEnforcer.notNull (aResultConsumer, "ResultConsumer"); final ICommonsList aFirst = StringHelper.getExploded (NAMESPACE_SEPARATOR, sSyntaxSpecificID, 2); if (aFirst.size () < 2) @@ -129,8 +162,34 @@ public static PeppolDocumentTypeIdentifierParts extractFromString (@Nonnull @Non sSyntaxSpecificID + "' contains an empty local name!"); - return new PeppolDocumentTypeIdentifierParts (sRootNS, - sLocalName, + aResultConsumer.accept (sRootNS, sLocalName); + } + + /** + * Parse an OpenPeppol Document Type Identifier using the XML syntax. + * + * @param sDocTypeIDValue + * The document identifier value (without the scheme) to be split. May + * neither be null nor empty. + * @return The non-null Peppol identifier parts + * @throws IllegalArgumentException + * if the passed document identifier value does not match the + * specifications + */ + @Nonnull + public static PeppolDocumentTypeIdentifierParts extractFromString (@Nonnull @Nonempty final String sDocTypeIDValue) + { + final PeppolGenericDocumentTypeIdentifierParts aGenericParts = PeppolGenericDocumentTypeIdentifierParts.extractFromString (sDocTypeIDValue); + + final Wrapper aRootNS = new Wrapper <> (); + final Wrapper aLocalName = new Wrapper <> (); + extractXMLSyntaxSpecificID (aGenericParts.getSyntaxSpecificID (), (ns, ln) -> { + aRootNS.set (ns); + aLocalName.set (ln); + }); + + return new PeppolDocumentTypeIdentifierParts (aRootNS.get (), + aLocalName.get (), aGenericParts.getCustomizationID (), aGenericParts.getVersion ()); } diff --git a/peppol-id/src/test/java/com/helger/peppolid/peppol/doctype/PeppolDocumentTypeIdentifierPartsTest.java b/peppol-id/src/test/java/com/helger/peppolid/peppol/doctype/PeppolDocumentTypeIdentifierPartsTest.java index da8db570..70309106 100644 --- a/peppol-id/src/test/java/com/helger/peppolid/peppol/doctype/PeppolDocumentTypeIdentifierPartsTest.java +++ b/peppol-id/src/test/java/com/helger/peppolid/peppol/doctype/PeppolDocumentTypeIdentifierPartsTest.java @@ -17,7 +17,9 @@ package com.helger.peppolid.peppol.doctype; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; @@ -181,4 +183,14 @@ public void testList () throws IOException }); } } + + @Test + public void testIsSyntaxSpecificIDLookingLikeXML () + { + assertTrue (PeppolDocumentTypeIdentifierParts.isSyntaxSpecificIDLookingLikeXML ("a::b")); + assertTrue (PeppolDocumentTypeIdentifierParts.isSyntaxSpecificIDLookingLikeXML ("root::local")); + assertFalse (PeppolDocumentTypeIdentifierParts.isSyntaxSpecificIDLookingLikeXML ("root:local")); + assertFalse (PeppolDocumentTypeIdentifierParts.isSyntaxSpecificIDLookingLikeXML ("::local")); + assertFalse (PeppolDocumentTypeIdentifierParts.isSyntaxSpecificIDLookingLikeXML ("root::")); + } }