19
19
package com .amartus .sonata .blender .cmd ;
20
20
21
21
import com .amartus .sonata .blender .impl .ProductSpecReader ;
22
- import com .amartus .sonata .blender .impl .util .Pair ;
23
22
import com .amartus .sonata .blender .impl .util .PathResolver ;
24
23
import com .amartus .sonata .blender .parser .DeserializerProvider ;
25
24
import com . .rvesse .airline .annotations .Option ;
26
25
import com . .rvesse .airline .annotations .restrictions .MutuallyExclusiveWith ;
27
26
import com . .rvesse .airline .annotations .restrictions .Once ;
28
27
import io .swagger .v3 .oas .models .media .Schema ;
28
+ import org .apache .commons .lang3 .StringUtils ;
29
+ import org .apache .commons .lang3 .tuple .Pair ;
30
+ import org .apache .commons .lang3 .tuple .Triple ;
29
31
import org .slf4j .Logger ;
30
32
import org .slf4j .LoggerFactory ;
31
33
34
36
import java .util .ArrayList ;
35
37
import java .util .List ;
36
38
import java .util .Map ;
39
+ import java .util .function .Function ;
37
40
import java .util .stream .Collectors ;
38
41
import java .util .stream .Stream ;
39
42
@@ -95,14 +98,78 @@ public abstract class AbstractBlend {
95
98
protected Map <String , Schema > toProductSpecifications () {
96
99
var config = new ProductSpecReader .Options (modelToAugment , autodiscover );
97
100
98
- return toSchemaPaths (blendingSchemas ())
99
- .flatMap (schema -> new ProductSpecReader (config , schema .first (), schema .second (), new DeserializerProvider (), ProductSpecReader .defaultOptions ()).readSchemas ().entrySet ().stream ())
101
+ var foundSchemas = toSchemaPaths (blendingSchemas ())
102
+ .map (schema -> {
103
+ var resolved = new ProductSpecReader (config ,
104
+ schema .getLeft (), schema .getRight (),
105
+ new DeserializerProvider (), ProductSpecReader .defaultOptions ())
106
+ .readSchemas ();
107
+ return Pair .of (schema , resolved );
108
+ })
109
+ .collect (Collectors .toList ());
110
+
111
+ validateResolvedSchemas (foundSchemas );
112
+
113
+ var allSchemas = foundSchemas .stream ().flatMap (it -> it .getRight ().entrySet ().stream ());
114
+
115
+ return allSchemas
100
116
.collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue , (a , b ) -> {
101
117
if (a .equals (b )) return a ;
102
118
throw new IllegalArgumentException (String .format ("Object for the same key does not match %s %s" , a , b ));
103
119
}));
104
120
}
105
121
122
+ Function <Pair <Path , String >, String > toPointer = it -> {
123
+ var path = it .getLeft ().toAbsolutePath ().toString ();
124
+ var schema = it .getRight ();
125
+ return StringUtils .isBlank (schema ) ? path : path + "#" + schema ;
126
+ };
127
+
128
+ private void validateResolvedSchemas (List <Pair <Pair <Path , String >, Map <String , Schema <?>>>> foundSchemas ) {
129
+ var byKeys = foundSchemas .stream ()
130
+ .flatMap (it -> {
131
+ var key = it .getLeft ();
132
+ return it .getRight ().entrySet ().stream ()
133
+ .map (e -> Triple .of (e .getKey (), e .getValue (), key ));
134
+ }).collect (Collectors .groupingBy (Triple ::getLeft ));
135
+
136
+ List <String > messages = byKeys .entrySet ().stream ()
137
+ .filter (it -> it .getValue ().size () > 1 )
138
+ .map (it -> {
139
+ var groups = it .getValue ().stream ().collect (Collectors .groupingBy (
140
+ Triple ::getMiddle ,
141
+ Collectors .mapping (t -> toPointer .apply ((Pair <Path , String >) t .getRight ()), Collectors .toList ())
142
+ ));
143
+
144
+ var strings = groups .values ().stream ().map (list -> String .join ("\n " , list )).collect (Collectors .toList ());
145
+ return Pair .of (it .getKey (), strings );
146
+ })
147
+ .peek (this ::logReferencingFiles )
148
+ .filter (it -> ((List <String >)it .getValue ()).size () > 1 )
149
+ .map (it -> {
150
+ var groupsCount = it .getValue ().size ();
151
+ StringBuilder sb = new StringBuilder ();
152
+ var idx = 1 ;
153
+
154
+ for (var group : it .getValue ()) {
155
+ sb .append (String .format ("Group %d:\n %s\n " , idx ++, group ));
156
+ }
157
+
158
+ return String .format ("Schema %s defined %d times and referenced from files groups:\n %s" ,
159
+ it .getKey (), groupsCount ,
160
+ sb );
161
+ })
162
+ .collect (Collectors .toList ());
163
+ if (messages .isEmpty ()) return ;
164
+
165
+ throw new IllegalArgumentException (String .format ("Found conflicting schema definitions\n %s" , String .join ("\n " , messages )));
166
+ }
167
+
168
+ private void logReferencingFiles (Pair <String , List <String >> it ) {
169
+ var files = String .join ("\n " , ((List <String >) it .getValue ()));
170
+ log .debug ("Schema {} found in files:\n {}" , it .getKey (), files );
171
+ }
172
+
106
173
protected Stream <Pair <Path , String >> toSchemaPaths (Stream <String > path ) {
107
174
return new PathResolver (specificationsRootDir ).toSchemaPaths (path );
108
175
}
@@ -112,7 +179,7 @@ protected Stream<String> blendingSchemas() {
112
179
113
180
protected void validateProductSpecs () {
114
181
var incorrectFilesExists = toSchemaPaths (blendingSchemas ())
115
- .map (Pair ::first )
182
+ .map (Pair ::getLeft )
116
183
.filter (p -> !Files .isRegularFile (p ))
117
184
.peek (p -> log .warn ("{} is not a file" , p ))
118
185
.count () > 0 ;
0 commit comments