1
2
3
4 package org.apache.maven.toolchain.v4;
5
6 import java.io.ObjectStreamException;
7 import java.util.AbstractList;
8 import java.util.ArrayList;
9 import java.util.Collection;
10 import java.util.HashMap;
11 import java.util.Iterator;
12 import java.util.LinkedHashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Objects;
16 import java.util.function.BinaryOperator;
17 import java.util.function.Function;
18 import java.util.stream.Collectors;
19
20 import org.apache.maven.api.annotations.Generated;
21 import org.apache.maven.api.xml.Dom;
22 import org.apache.maven.api.toolchain.TrackableBase;
23 import org.apache.maven.api.toolchain.PersistedToolchains;
24 import org.apache.maven.api.toolchain.ToolchainModel;
25
26 @Generated
27 public class MavenToolchainsMerger
28 {
29
30
31
32
33
34
35
36
37
38
39
40
41
42 public PersistedToolchains merge( PersistedToolchains target, PersistedToolchains source, boolean sourceDominant, Map<?, ?> hints )
43 {
44 Objects.requireNonNull( target, "target cannot be null" );
45 if ( source == null )
46 {
47 return target;
48 }
49 Map<Object, Object> context = new HashMap<>();
50 if ( hints != null )
51 {
52 context.putAll( hints );
53 }
54 return mergePersistedToolchains( target, source, sourceDominant, context );
55 }
56
57 protected TrackableBase mergeTrackableBase( TrackableBase target, TrackableBase source, boolean sourceDominant, Map<Object, Object> context )
58 {
59 TrackableBase.Builder builder = TrackableBase.newBuilder( target );
60 mergeTrackableBase( builder, target, source, sourceDominant, context );
61 return builder.build();
62 }
63
64 protected void mergeTrackableBase( TrackableBase.Builder builder, TrackableBase target, TrackableBase source, boolean sourceDominant, Map<Object, Object> context )
65 {
66 }
67
68
69 protected PersistedToolchains mergePersistedToolchains( PersistedToolchains target, PersistedToolchains source, boolean sourceDominant, Map<Object, Object> context )
70 {
71 PersistedToolchains.Builder builder = PersistedToolchains.newBuilder( target );
72 mergePersistedToolchains( builder, target, source, sourceDominant, context );
73 return builder.build();
74 }
75
76 protected void mergePersistedToolchains( PersistedToolchains.Builder builder, PersistedToolchains target, PersistedToolchains source, boolean sourceDominant, Map<Object, Object> context )
77 {
78 mergeTrackableBase( builder, target ,source, sourceDominant, context );
79 mergePersistedToolchains_Toolchains( builder, target, source, sourceDominant, context );
80 }
81
82 protected void mergePersistedToolchains_Toolchains( PersistedToolchains.Builder builder, PersistedToolchains target, PersistedToolchains source, boolean sourceDominant, Map<Object, Object> context )
83 {
84 builder.toolchains( merge( target.getToolchains(), source.getToolchains(), sourceDominant, getToolchainModelKey() ) );
85 }
86
87 protected ToolchainModel mergeToolchainModel( ToolchainModel target, ToolchainModel source, boolean sourceDominant, Map<Object, Object> context )
88 {
89 ToolchainModel.Builder builder = ToolchainModel.newBuilder( target );
90 mergeToolchainModel( builder, target, source, sourceDominant, context );
91 return builder.build();
92 }
93
94 protected void mergeToolchainModel( ToolchainModel.Builder builder, ToolchainModel target, ToolchainModel source, boolean sourceDominant, Map<Object, Object> context )
95 {
96 mergeTrackableBase( builder, target ,source, sourceDominant, context );
97 mergeToolchainModel_Type( builder, target, source, sourceDominant, context );
98 mergeToolchainModel_Provides( builder, target, source, sourceDominant, context );
99 mergeToolchainModel_Configuration( builder, target, source, sourceDominant, context );
100 }
101
102 protected void mergeToolchainModel_Type( ToolchainModel.Builder builder, ToolchainModel target, ToolchainModel source, boolean sourceDominant, Map<Object, Object> context )
103 {
104 String src = source.getType();
105 String tgt = target.getType();
106 if ( src != null && ( sourceDominant || tgt == null ) )
107 {
108 builder.type( src );
109 }
110 }
111 protected void mergeToolchainModel_Provides( ToolchainModel.Builder builder, ToolchainModel target, ToolchainModel source, boolean sourceDominant, Map<Object, Object> context )
112 {
113 Map<String, String> src = source.getProvides();
114 if ( !src.isEmpty() )
115 {
116 Map<String, String> tgt = target.getProvides();
117 if ( tgt.isEmpty() )
118 {
119 builder.provides( src );
120 }
121 else
122 {
123 Map<String, String> merged = new HashMap<>();
124 merged.putAll( sourceDominant ? target.getProvides() : source.getProvides() );
125 merged.putAll( sourceDominant ? source.getProvides() : target.getProvides() );
126 builder.provides( merged );
127 }
128 }
129 }
130 protected void mergeToolchainModel_Configuration( ToolchainModel.Builder builder, ToolchainModel target, ToolchainModel source, boolean sourceDominant, Map<Object, Object> context )
131 {
132 Dom src = source.getConfiguration();
133 if ( src != null )
134 {
135 Dom tgt = target.getConfiguration();
136 if ( tgt == null )
137 {
138 builder.configuration( src );
139 }
140 else if ( sourceDominant )
141 {
142 builder.configuration( src.merge( tgt ) );
143 }
144 else
145 {
146 builder.configuration( tgt.merge( src ) );
147 }
148 }
149 }
150
151
152 protected KeyComputer<TrackableBase> getTrackableBaseKey()
153 {
154 return v -> v;
155 }
156 protected KeyComputer<PersistedToolchains> getPersistedToolchainsKey()
157 {
158 return v -> v;
159 }
160 protected KeyComputer<ToolchainModel> getToolchainModelKey()
161 {
162 return v -> v;
163 }
164
165
166
167
168
169 @FunctionalInterface
170 public interface KeyComputer<T> extends Function<T, Object>
171 {
172 }
173
174
175
176
177 public static <T> List<T> merge( List<T> tgt, List<T> src, boolean sourceDominant, KeyComputer<T> computer )
178 {
179 return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t );
180 }
181
182 public static <T> List<T> merge( List<T> tgt, List<T> src, KeyComputer<T> computer, BinaryOperator<T> remapping )
183 {
184 if ( src.isEmpty() )
185 {
186 return tgt;
187 }
188
189 MergingList<T> list;
190 if ( tgt instanceof MergingList )
191 {
192 list = (MergingList<T>) tgt;
193 }
194 else
195 {
196 list = new MergingList<>( computer, src.size() + tgt.size() );
197 list.mergeAll( tgt, ( t, s ) -> s );
198 }
199
200 list.mergeAll( src, remapping );
201 return list;
202 }
203
204
205
206
207
208 private static class MergingList<V> extends AbstractList<V> implements java.io.Serializable
209 {
210
211 private final KeyComputer<V> keyComputer;
212 private Map<Object, V> map;
213 private List<V> list;
214
215 MergingList( KeyComputer<V> keyComputer, int initialCapacity )
216 {
217 this.map = new LinkedHashMap<>( initialCapacity );
218 this.keyComputer = keyComputer;
219 }
220
221 Object writeReplace() throws ObjectStreamException
222 {
223 return new ArrayList<>( this );
224 }
225
226 @Override
227 public Iterator<V> iterator()
228 {
229 if ( map != null )
230 {
231 return map.values().iterator();
232 }
233 else
234 {
235 return list.iterator();
236 }
237 }
238
239 void mergeAll( Collection<V> vs, BinaryOperator<V> remapping )
240 {
241 if ( map == null )
242 {
243 map = list.stream().collect( Collectors.toMap( keyComputer,
244 Function.identity(),
245 null,
246 LinkedHashMap::new ) );
247
248 list = null;
249 }
250
251 if ( vs instanceof MergingList && ( (MergingList<V>) vs ).map != null )
252 {
253 for ( Map.Entry<Object, V> e : ( (MergingList<V>) vs ).map.entrySet() )
254 {
255 Object key = e.getKey();
256 V v = e.getValue();
257 map.merge( key, v, remapping );
258 }
259 }
260 else
261 {
262 for ( V v : vs )
263 {
264 Object key = keyComputer.apply( v );
265
266 map.merge( key, v, remapping );
267 }
268 }
269 }
270
271 @Override
272 public boolean contains( Object o )
273 {
274 if ( map != null )
275 {
276 return map.containsValue( o );
277 }
278 else
279 {
280 return list.contains( o );
281 }
282 }
283
284 private List<V> asList()
285 {
286 if ( list == null )
287 {
288 list = new ArrayList<>( map.values() );
289 map = null;
290 }
291 return list;
292 }
293
294 @Override
295 public void add( int index, V element )
296 {
297 asList().add( index, element );
298 }
299
300 @Override
301 public V remove( int index )
302 {
303 return asList().remove( index );
304 }
305
306 @Override
307 public V get( int index )
308 {
309 return asList().get( index );
310 }
311
312 @Override
313 public int size()
314 {
315 if ( map != null )
316 {
317 return map.size();
318 }
319 else
320 {
321 return list.size();
322 }
323 }
324 }
325 }