11package org .openapitools .openapidiff .core .compare ;
22
3- import io .swagger .v3 .oas .models .Operation ;
43import io .swagger .v3 .oas .models .PathItem ;
54import io .swagger .v3 .oas .models .Paths ;
6- import io .swagger .v3 .oas .models .parameters .Parameter ;
75import java .util .*;
86import java .util .regex .Matcher ;
97import java .util .regex .Pattern ;
10- import java .util .stream .IntStream ;
118import org .openapitools .openapidiff .core .model .Changed ;
129import org .openapitools .openapidiff .core .model .ChangedPaths ;
1310import org .openapitools .openapidiff .core .model .DiffContext ;
@@ -22,135 +19,62 @@ public PathsDiff(OpenApiDiff openApiDiff) {
2219 this .openApiDiff = openApiDiff ;
2320 }
2421
25- private static String normalizePath (String path ) {
26- return path .replaceAll (REGEX_PATH , "{}" );
27- }
28-
29- private static List <String > extractParameters (String path ) {
30- ArrayList <String > params = new ArrayList <>();
31- Pattern pattern = Pattern .compile (REGEX_PATH );
32- Matcher matcher = pattern .matcher (path );
33- while (matcher .find ()) {
34- params .add (matcher .group (1 ));
35- }
36- return params ;
37- }
38-
3922 public DeferredChanged <ChangedPaths > diff (
4023 final Map <String , PathItem > left , final Map <String , PathItem > right ) {
4124 DeferredBuilder <Changed > builder = new DeferredBuilder <>();
4225
4326 ChangedPaths changedPaths = new ChangedPaths (left , right , openApiDiff .getOptions ());
4427 changedPaths .getIncreased ().putAll (right );
4528
46- left .keySet ()
29+ left .entrySet ()
4730 .forEach (
48- ( String url ) -> {
49- PathItem leftPath = left . get ( url );
50- String template = normalizePath ( url );
31+ pathEntry -> {
32+ String leftUrl = pathEntry . getKey ( );
33+ PathItem leftPath = pathEntry . getValue ( );
5134 Optional <Map .Entry <String , PathItem >> result =
52- changedPaths .getIncreased ().entrySet ().stream ()
53- .filter (item -> normalizePath (item .getKey ()).equals (template ))
54- .min (
55- (a , b ) -> {
56- if (methodsAndParametersIntersect (a .getValue (), b .getValue ())) {
57- throw new IllegalArgumentException (
58- "Two path items have the same signature: " + template );
59- }
60- if (a .getKey ().equals (url )) {
61- return -1 ;
62- } else if (b .getKey ().equals ((url ))) {
63- return 1 ;
64- } else {
65- HashSet <PathItem .HttpMethod > methodsA =
66- new HashSet <>(a .getValue ().readOperationsMap ().keySet ());
67- methodsA .retainAll (leftPath .readOperationsMap ().keySet ());
68- HashSet <PathItem .HttpMethod > methodsB =
69- new HashSet <>(b .getValue ().readOperationsMap ().keySet ());
70- methodsB .retainAll (leftPath .readOperationsMap ().keySet ());
71- return Integer .compare (methodsB .size (), methodsA .size ());
72- }
73- });
35+ openApiDiff
36+ .getOptions ()
37+ .getPathMatcher ()
38+ .find (pathEntry , changedPaths .getIncreased ());
7439 if (result .isPresent ()) {
7540 String rightUrl = result .get ().getKey ();
7641 PathItem rightPath = changedPaths .getIncreased ().remove (rightUrl );
7742 Map <String , String > params = new LinkedHashMap <>();
78- if (!url .equals (rightUrl )) {
79- List <String > oldParams = extractParameters (url );
43+ if (!leftUrl .equals (rightUrl )) {
44+ List <String > oldParams = extractParameters (leftUrl );
8045 List <String > newParams = extractParameters (rightUrl );
8146 for (int i = 0 ; i < oldParams .size (); i ++) {
8247 params .put (oldParams .get (i ), newParams .get (i ));
8348 }
8449 }
8550 DiffContext context = new DiffContext (openApiDiff .getOptions ());
86- context .setUrl (url );
51+ context .setUrl (leftUrl );
8752 context .setParameters (params );
88- context .setLeftAndRightUrls (url , rightUrl );
53+ context .setLeftAndRightUrls (leftUrl , rightUrl );
8954 builder
9055 .with (openApiDiff .getPathDiff ().diff (leftPath , rightPath , context ))
9156 .ifPresent (path -> changedPaths .getChanged ().put (rightUrl , path ));
9257 } else {
93- changedPaths .getMissing ().put (url , leftPath );
58+ changedPaths .getMissing ().put (leftUrl , leftPath );
9459 }
9560 });
9661 return builder .buildIsChanged (changedPaths );
9762 }
9863
64+ private List <String > extractParameters (String path ) {
65+ ArrayList <String > params = new ArrayList <>();
66+ Pattern pattern = Pattern .compile (REGEX_PATH );
67+ Matcher matcher = pattern .matcher (path );
68+ while (matcher .find ()) {
69+ params .add (matcher .group (1 ));
70+ }
71+ return params ;
72+ }
73+
9974 public static Paths valOrEmpty (Paths path ) {
10075 if (path == null ) {
10176 path = new Paths ();
10277 }
10378 return path ;
10479 }
105-
106- /**
107- * @param a a path form the open api spec
108- * @param b another path from the same open api spec
109- * @return <code>true</code> in case both paths are of the same method AND their templated
110- * parameters are of the same type; <code>false</code> otherwise
111- */
112- private static boolean methodsAndParametersIntersect (PathItem a , PathItem b ) {
113- Set <PathItem .HttpMethod > methodsA = a .readOperationsMap ().keySet ();
114- for (PathItem .HttpMethod method : b .readOperationsMap ().keySet ()) {
115- if (methodsA .contains (method )) {
116- Operation left = a .readOperationsMap ().get (method );
117- Operation right = b .readOperationsMap ().get (method );
118- if (left .getParameters ().size () == right .getParameters ().size ()) {
119- return parametersIntersect (left .getParameters (), right .getParameters ());
120- }
121- return false ;
122- }
123- }
124- return false ;
125- }
126-
127- /**
128- * Checks if provided parameter pairs are equal by type and format
129- *
130- * @param left parameters from the first compared method
131- * @param right parameters from the second compared method
132- * @return <code>true</code> in case each parameter pair is of the same type; <code>false</code>
133- * otherwise
134- */
135- private static boolean parametersIntersect (List <Parameter > left , List <Parameter > right ) {
136- int parametersSize = left .size ();
137- long intersectedParameters =
138- IntStream .range (0 , left .size ())
139- .filter (i -> parametersTypeEquals (left .get (i ), right .get (i )))
140- .count ();
141- return parametersSize == intersectedParameters ;
142- }
143-
144- /**
145- * Checks if provided parameter pair is equal by type and format
146- *
147- * @param left parameter from the first compared method
148- * @param right parameter from the second compared method
149- * @return <code>true</code> in case parameter pair is of the same type; <code>false</code>
150- * otherwise
151- */
152- private static boolean parametersTypeEquals (Parameter left , Parameter right ) {
153- return Objects .equals (left .getSchema ().getType (), right .getSchema ().getType ())
154- && Objects .equals (left .getSchema ().getFormat (), right .getSchema ().getFormat ());
155- }
15680}
0 commit comments