View Javadoc
1   // =================== DO NOT EDIT THIS FILE ====================
2   //   Generated by Maven, any modifications will be overwritten.
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       * Merges the specified source object into the given target object.
32       *
33       * @param target The target object whose existing contents should be merged with the source, must not be
34       *            <code>null</code>.
35       * @param source The (read-only) source object that should be merged into the target object, may be
36       *            <code>null</code>.
37       * @param sourceDominant A flag indicating whether either the target object or the source object provides the
38       *            dominant data.
39       * @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific
40       *            information along, may be <code>null</code>.
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      * Use to compute keys for data structures
167      * @param <T> the data structure type
168      */
169     @FunctionalInterface
170     public interface KeyComputer<T> extends Function<T, Object>
171     {
172     }
173 
174     /**
175      * Merge two lists
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      * Merging list
206      * @param <V>
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 }