diff --git a/smp-api/pom.xml b/smp-api/pom.xml index c692047d09de7eb3794edf9111f68ea9eda9e0da..644a8b9269d7442f23037023a1445d6cf2ffa175 100644 --- a/smp-api/pom.xml +++ b/smp-api/pom.xml @@ -34,6 +34,10 @@ <groupId>org.apache.cxf.xjc-utils</groupId> <artifactId>cxf-xjc-runtime</artifactId> </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + </dependency> <dependency> <groupId>pl.pragmatists</groupId> <artifactId>JUnitParams</artifactId> diff --git a/smp-api/src/main/java/eu/europa/ec/smp/api/Identifiers.java b/smp-api/src/main/java/eu/europa/ec/smp/api/Identifiers.java index e223e5b02746420c3934c0837370a35ff4cac823..9086b4f6847945b37ea9205e3ab079c1a64a5a26 100644 --- a/smp-api/src/main/java/eu/europa/ec/smp/api/Identifiers.java +++ b/smp-api/src/main/java/eu/europa/ec/smp/api/Identifiers.java @@ -18,11 +18,7 @@ import org.apache.commons.lang3.StringUtils; import org.oasis_open.docs.bdxr.ns.smp._2016._05.DocumentIdentifier; import org.oasis_open.docs.bdxr.ns.smp._2016._05.ParticipantIdentifierType; import org.oasis_open.docs.bdxr.ns.smp._2016._05.ProcessIdentifier; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import org.springframework.web.util.UriUtils; import static java.nio.charset.StandardCharsets.UTF_8; @@ -34,12 +30,11 @@ import static java.nio.charset.StandardCharsets.UTF_8; public class Identifiers { public static final String EBCORE_IDENTIFIER_PREFIX = "urn:oasis:names:tc:ebcore:partyid-type:"; - public static final String EBCORE_IDENTIFIER_FORMAT="%s:%s"; - public static final String EBCORE_IDENTIFIER_ISO6523_SCHEME="iso6523"; - public static final String DOUBLE_COLON_IDENTIFIER_FORMAT="%s::%s"; - - private static final String EMPTY_IDENTIFIER="Null/Empty"; + public static final String EBCORE_IDENTIFIER_FORMAT = "%s:%s"; + public static final String EBCORE_IDENTIFIER_ISO6523_SCHEME = "iso6523"; + public static final String DOUBLE_COLON_IDENTIFIER_FORMAT = "%s::%s"; + private static final String EMPTY_IDENTIFIER = "Null/Empty"; public static ParticipantIdentifierType asParticipantId(String participantIDentifier) { @@ -58,20 +53,20 @@ public class Identifiers { } public static String asString(ParticipantIdentifierType participantId) { - if(StringUtils.isBlank(participantId.getScheme())) { + if (StringUtils.isBlank(participantId.getScheme())) { // if scheme is empty just return value (for OASIS SMP 1.0 must start with :: ) - return (StringUtils.startsWithIgnoreCase(participantId.getScheme(), EBCORE_IDENTIFIER_PREFIX)? - "":"::") + participantId.getValue(); + return (StringUtils.startsWithIgnoreCase(participantId.getScheme(), EBCORE_IDENTIFIER_PREFIX) ? + "" : "::") + participantId.getValue(); } String format = - StringUtils.startsWithIgnoreCase(participantId.getScheme(), EBCORE_IDENTIFIER_PREFIX)? - EBCORE_IDENTIFIER_FORMAT:DOUBLE_COLON_IDENTIFIER_FORMAT; + StringUtils.startsWithIgnoreCase(participantId.getScheme(), EBCORE_IDENTIFIER_PREFIX) ? + EBCORE_IDENTIFIER_FORMAT : DOUBLE_COLON_IDENTIFIER_FORMAT; - return String.format(format, participantId.getScheme(), participantId.getValue()); + return String.format(format, participantId.getScheme(), participantId.getValue()); } public static String asString(DocumentIdentifier docId) { - return String.format(DOUBLE_COLON_IDENTIFIER_FORMAT, docId.getScheme()!=null?docId.getScheme():"", docId.getValue()); + return String.format(DOUBLE_COLON_IDENTIFIER_FORMAT, docId.getScheme() != null ? docId.getScheme() : "", docId.getValue()); } public static String asUrlEncodedString(ParticipantIdentifierType participantId) { @@ -83,20 +78,17 @@ public class Identifiers { } private static String urlEncode(String s) { - try { - return URLEncoder.encode(s, UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException(e); - } + return UriUtils.encode(s, UTF_8.name()); } + private static String[] splitParticipantIdentifier(String participantIdentifier) { String[] idResult; - if (StringUtils.isBlank(participantIdentifier)){ + if (StringUtils.isBlank(participantIdentifier)) { throw new MalformedIdentifierException(EMPTY_IDENTIFIER, null); } String identifier = participantIdentifier.trim(); - if(identifier.startsWith(EBCORE_IDENTIFIER_PREFIX) + if (identifier.startsWith(EBCORE_IDENTIFIER_PREFIX) || identifier.startsWith("::" + EBCORE_IDENTIFIER_PREFIX)) { idResult = splitEbCoreIdentifier(identifier); } else { @@ -110,25 +102,26 @@ public class Identifiers { /** * Method splits identifier at first occurrence of double colon :: and returns array size of 2. The first value is * schema and the second is identifier. If identifier is blank or with missing :: MalformedIdentifierException is thrown + * * @param doubleColonDelimitedId * @return array with two elements. First is schema and second is id */ private static String[] splitDoubleColonIdentifier(String doubleColonDelimitedId) { - if (StringUtils.isBlank(doubleColonDelimitedId)){ + if (StringUtils.isBlank(doubleColonDelimitedId)) { throw new MalformedIdentifierException(EMPTY_IDENTIFIER, null); } String[] idResult = new String[2]; int delimiterIndex = doubleColonDelimitedId.indexOf("::"); - if (delimiterIndex<0){ + if (delimiterIndex < 0) { throw new MalformedIdentifierException(doubleColonDelimitedId, null); } - idResult[0] = delimiterIndex==0?null:doubleColonDelimitedId.substring(0,delimiterIndex); - idResult[1] = doubleColonDelimitedId.substring(delimiterIndex+2); + idResult[0] = delimiterIndex == 0 ? null : doubleColonDelimitedId.substring(0, delimiterIndex); + idResult[1] = doubleColonDelimitedId.substring(delimiterIndex + 2); - if (StringUtils.isBlank(idResult[1])){ + if (StringUtils.isBlank(idResult[1])) { throw new MalformedIdentifierException(doubleColonDelimitedId, null); } @@ -136,26 +129,26 @@ public class Identifiers { } - public static String[] splitEbCoreIdentifier(final String partyId) { + public static String[] splitEbCoreIdentifier(final String partyId) { String partyIdPrivate = partyId.trim(); if (partyIdPrivate.startsWith("::")) { partyIdPrivate = StringUtils.removeStart(partyIdPrivate, "::"); } - if (!partyIdPrivate.startsWith(EBCORE_IDENTIFIER_PREFIX)){ + if (!partyIdPrivate.startsWith(EBCORE_IDENTIFIER_PREFIX)) { throw new MalformedIdentifierException(partyId, null); } - boolean isIso6523 = partyIdPrivate.startsWith(EBCORE_IDENTIFIER_PREFIX+EBCORE_IDENTIFIER_ISO6523_SCHEME +":"); + boolean isIso6523 = partyIdPrivate.startsWith(EBCORE_IDENTIFIER_PREFIX + EBCORE_IDENTIFIER_ISO6523_SCHEME + ":"); - int isSchemeDelimiter = partyIdPrivate.indexOf(':',EBCORE_IDENTIFIER_PREFIX.length()); - if (isSchemeDelimiter < 0){ + int isSchemeDelimiter = partyIdPrivate.indexOf(':', EBCORE_IDENTIFIER_PREFIX.length()); + if (isSchemeDelimiter < 0) { // invalid scheme - throw new IllegalArgumentException(String.format("Invalid ebCore id [%s] ebcoreId must have prefix 'urn:oasis:names:tc:ebcore:partyid-type', "+ + throw new IllegalArgumentException(String.format("Invalid ebCore id [%s] ebcoreId must have prefix 'urn:oasis:names:tc:ebcore:partyid-type', " + "and parts <catalog-identifier>, <scheme-in-catalog>, <scheme-specific-identifier> separated by colon. " + "Example: urn:oasis:names:tc:ebcore:partyid-type:<catalog-identifier>:(<scheme-in-catalog>)?:<scheme-specific-identifier>.", partyIdPrivate)); } - int isPartDelimiter = partyIdPrivate.indexOf(':',isSchemeDelimiter+1); + int isPartDelimiter = partyIdPrivate.indexOf(':', isSchemeDelimiter + 1); String[] result = new String[2]; if (isPartDelimiter < 0 && isIso6523) { // for iso scheme-in-catalog is mandatory @@ -163,10 +156,10 @@ public class Identifiers { throw new IllegalArgumentException(String.format("Invalid ebCore id [%s] ebcoreId must have prefix 'urn:oasis:names:tc:ebcore:partyid-type', " + "and parts <catalog-identifier>, <scheme-in-catalog>, <scheme-specific-identifier> separated by colon. " + "Example: urn:oasis:names:tc:ebcore:partyid-type:<catalog-identifier>:(<scheme-in-catalog>)?:<scheme-specific-identifier>.", partyIdPrivate)); - } else if (isPartDelimiter < 0){ + } else if (isPartDelimiter < 0) { result[0] = partyIdPrivate.substring(0, isSchemeDelimiter).trim(); result[1] = partyIdPrivate.substring(isSchemeDelimiter + 1).trim(); - }else { + } else { result[0] = partyIdPrivate.substring(0, isPartDelimiter).trim(); result[1] = partyIdPrivate.substring(isPartDelimiter + 1).trim(); } @@ -177,11 +170,8 @@ public class Identifiers { } //check if double colon was used for identifier separator in ebecoreid if (result[0].endsWith(":")) { - result[0] = StringUtils.removeEnd(result[0] , ":"); + result[0] = StringUtils.removeEnd(result[0], ":"); } return result; - } - - } diff --git a/smp-api/src/test/java/eu/europa/ec/smp/api/IdentifiersTest.java b/smp-api/src/test/java/eu/europa/ec/smp/api/IdentifiersTest.java index f353ad87226f7e1902e83dd9020e44b1fe32c893..58a2135e850faf7be3f45ab267328b3f1bc84168 100644 --- a/smp-api/src/test/java/eu/europa/ec/smp/api/IdentifiersTest.java +++ b/smp-api/src/test/java/eu/europa/ec/smp/api/IdentifiersTest.java @@ -174,7 +174,6 @@ public class IdentifiersTest { return res; } - @Test @Parameters(method = "participantIdentifierPositiveCases") @TestCaseName("{0}") @@ -248,7 +247,6 @@ public class IdentifiersTest { assertEquals(value, processId.getValue()); } - @Test @Parameters(method = "negativeCases") public void testProcessIdNegative(String negativeInput) { @@ -277,7 +275,6 @@ public class IdentifiersTest { fail(); } - private void negativeAssertions(String negativeInput, Exception e) { assertTrue(e instanceof MalformedIdentifierException); assertEquals(MALFORMED_INPUT_MSG + (StringUtils.isBlank(negativeInput) ? "Null/Empty" : negativeInput), e.getMessage()); @@ -292,6 +289,16 @@ public class IdentifiersTest { assertEquals("ehealth%3Aactorid%3Aqns%3A%3A0088%3Aconformance%3Asg01%23", Identifiers.asUrlEncodedString(participantId)); } + @Test + public void testUrlEncodingParticipantIdWithSpace() { + //given + ParticipantIdentifierType participantId = new ParticipantIdentifierType("GPR: 0088:conformance:sg01#", "ehealth:actorid:qns"); + + //when-then + //Because this is path segment spaces must be percent encoded (not with +)! + assertEquals("ehealth%3Aactorid%3Aqns%3A%3AGPR%3A%200088%3Aconformance%3Asg01%23", Identifiers.asUrlEncodedString(participantId)); + } + @Test public void testUrlEncodingDocumentId() { //given @@ -301,5 +308,14 @@ public class IdentifiersTest { assertEquals("busdox%3Adocid%3Aqns%3A%3Aurn%3A%3Aehealth%23%23services%3Aextended%3Aepsos01%3A%3A101", Identifiers.asUrlEncodedString(docId)); } + @Test + public void testUrlEncodingDocumentIdWithSpace() { + //given + DocumentIdentifier docId = new DocumentIdentifier("urn::ehealth##services:extended:epsos01:: 101", "busdox:docid:qns"); + + //when-then + //Because this is path segment spaces must be percent encoded (not with +)! + assertEquals("busdox%3Adocid%3Aqns%3A%3Aurn%3A%3Aehealth%23%23services%3Aextended%3Aepsos01%3A%3A%20101", Identifiers.asUrlEncodedString(docId)); + } }