11package com .apicatalog .did ;
22
3- import java .net .MalformedURLException ;
43import java .net .URI ;
54import java .net .URISyntaxException ;
6- import java .net .URL ;
75import java .util .Objects ;
86
97public class DidUrl extends Did {
108
119 private static final long serialVersionUID = 5752880077497569763L ;
12-
10+
1311 protected final String path ;
1412 protected final String query ;
1513 protected final String fragment ;
@@ -27,49 +25,119 @@ public static DidUrl from(Did did, String path, String query, String fragment) {
2725
2826 public static DidUrl from (final URI uri ) {
2927
30- if (!isDidUrl (uri )) {
31- throw new IllegalArgumentException ("The URI [" + uri + "] is not valid DID URL, does not start with 'did:'." );
28+ if (uri == null ) {
29+ throw new IllegalArgumentException ("The DID URL must not be null." );
30+ }
31+
32+ if (!Did .SCHEME .equalsIgnoreCase (uri .getScheme ())) {
33+ throw new IllegalArgumentException ("The URI [" + uri + "] is not valid DID URL, must start with 'did:' prefix." );
34+ }
35+
36+ final String [] didParts = uri .getSchemeSpecificPart ().split (":" , 2 );
37+
38+ if (didParts .length != 2 ) {
39+ throw new IllegalArgumentException ("The URI [" + uri + "] is not valid DID, must be in form 'did:method:method-specific-id'." );
40+ }
41+
42+ return from (uri , didParts [0 ], didParts [1 ], uri .getFragment ());
43+ }
44+
45+ public static DidUrl from (final String uri ) {
46+
47+ if (uri == null || uri .length () == 0 ) {
48+ throw new IllegalArgumentException ("The DID must not be null or blank string." );
49+ }
50+
51+ final String [] parts = uri .split (":" , 3 );
52+
53+ if (parts .length != 3 ) {
54+ throw new IllegalArgumentException ("The URI [" + uri + "] is not valid DID, must be in form 'did:method:method-specific-id'." );
55+ }
56+
57+ if (!Did .SCHEME .equalsIgnoreCase (parts [0 ])) {
58+ throw new IllegalArgumentException ("The URI [" + uri + "] is not valid DID, must start with 'did:' prefix." );
3259 }
33-
34- Did did = from (uri , uri .getSchemeSpecificPart ().split (":" , 2 ));
3560
36- return new DidUrl (did , uri .getPath (), uri .getQuery (), uri .getFragment ());
61+ String rest = parts [2 ];
62+ String fragment = null ;
63+
64+ int fragmentIndex = rest .indexOf ('#' );
65+ if (fragmentIndex != -1 ) {
66+ fragment = rest .substring (fragmentIndex + 1 );
67+ rest = rest .substring (0 , fragmentIndex );
68+ }
69+
70+ return from (uri , parts [1 ], rest , fragment );
3771 }
3872
73+ protected static DidUrl from (Object uri , final String method , final String rest , final String fragment ) {
74+ String specificId = rest ;
75+
76+ String path = null ;
77+ String query = null ;
78+
79+ int urlPartIndex = specificId .indexOf ('?' );
80+ if (urlPartIndex != -1 ) {
81+ query = specificId .substring (urlPartIndex + 1 );
82+ specificId = specificId .substring (0 , urlPartIndex );
83+ }
84+
85+ urlPartIndex = specificId .indexOf ('/' );
86+ if (urlPartIndex != -1 ) {
87+ path = specificId .substring (urlPartIndex );
88+ specificId = specificId .substring (0 , urlPartIndex );
89+ }
90+
91+ Did did = from (uri , method , specificId );
92+
93+ return new DidUrl (did , path , query , fragment );
94+ }
3995
4096 public static boolean isDidUrl (final URI uri ) {
41- return Did .SCHEME .equals (uri .getScheme ());
97+ if (!Did .SCHEME .equalsIgnoreCase (uri .getScheme ())
98+ || isBlank (uri .getSchemeSpecificPart ())
99+ || isNotBlank (uri .getAuthority ())
100+ || isNotBlank (uri .getUserInfo ())
101+ || isNotBlank (uri .getHost ())) {
102+ return false ;
103+ }
104+
105+ final String [] parts = uri .getSchemeSpecificPart ().split (":" , 2 );
106+
107+ return parts .length == 2
108+ && parts [0 ].length () > 0
109+ && parts [1 ].length () > 0
110+ && parts [0 ].codePoints ().allMatch (METHOD_CHAR );
42111 }
43112
44113 public static boolean isDidUrl (final String uri ) {
45- if (Did . isBlank ( uri ) ) {
114+ if (uri == null ) {
46115 return false ;
47116 }
48117
49- final String [] parts = uri .split (":" );
118+ final String [] parts = uri .split (":" , 3 );
50119
51- return ( parts .length == 3 || parts . length == 4 )
120+ return parts .length == 3
52121 && Did .SCHEME .equalsIgnoreCase (parts [0 ])
53- ;
122+ && parts [1 ].length () > 0
123+ && parts [2 ].length () > 0
124+ && parts [1 ].codePoints ().allMatch (METHOD_CHAR );
54125 }
55126
56127 @ Override
57128 public URI toUri () {
58129 try {
59- return new URI (SCHEME , method + ":" + specificId , path , query , fragment );
130+ return new URI (SCHEME ,
131+ appendPathQuery (new StringBuilder ()
132+ .append (method )
133+ .append (':' )
134+ .append (specificId )).toString (),
135+ fragment );
60136 } catch (URISyntaxException e ) {
61137 throw new IllegalStateException (e );
62138 }
63139 }
64140
65- public URL toUrl () {
66- try {
67- return toUri ().toURL ();
68- } catch (MalformedURLException e ) {
69- throw new IllegalStateException (e );
70- }
71- }
72-
73141 @ Override
74142 public boolean isDidUrl () {
75143 return true ;
@@ -84,28 +152,39 @@ public DidUrl asDidUrl() {
84152 public String toString () {
85153 final StringBuilder builder = new StringBuilder (super .toString ());
86154
87- if (Did .isNotBlank (path )) {
88- if (path .charAt (0 ) != '/' ) {
89- builder .append ('/' );
155+ appendPathQuery (builder );
156+
157+ if (fragment != null ) {
158+ if (fragment .length () == 0 || fragment .charAt (0 ) != '#' ) {
159+ builder .append ('#' );
160+ }
161+ if (fragment .length () > 0 ) {
162+ builder .append (fragment );
90163 }
91- builder .append (path );
92164 }
93165
94- if (Did .isNotBlank (query )) {
95- if (query .charAt (0 ) != '?' ) {
96- builder .append ('?' );
166+ return builder .toString ();
167+ }
168+
169+ protected StringBuilder appendPathQuery (final StringBuilder builder ) {
170+ if (path != null ) {
171+ if (path .length () == 0 || path .charAt (0 ) != '/' ) {
172+ builder .append ('/' );
173+ }
174+ if (path .length () > 0 ) {
175+ builder .append (path );
97176 }
98- builder .append (query );
99177 }
100178
101- if (Did .isNotBlank (fragment )) {
102- if (fragment .charAt (0 ) != '#' ) {
103- builder .append ('#' );
179+ if (query != null ) {
180+ if (query .length () == 0 || query .charAt (0 ) != '?' ) {
181+ builder .append ('?' );
182+ }
183+ if (query .length () > 0 ) {
184+ builder .append (query );
104185 }
105- builder .append (fragment );
106186 }
107-
108- return builder .toString ();
187+ return builder ;
109188 }
110189
111190 @ Override
0 commit comments