View Javadoc
1   package org.apache.maven.model.merge;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.AbstractList;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.LinkedHashMap;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.Objects;
31  import java.util.Properties;
32  
33  import org.apache.maven.model.Activation;
34  import org.apache.maven.model.Build;
35  import org.apache.maven.model.BuildBase;
36  import org.apache.maven.model.CiManagement;
37  import org.apache.maven.model.ConfigurationContainer;
38  import org.apache.maven.model.Contributor;
39  import org.apache.maven.model.Dependency;
40  import org.apache.maven.model.DependencyManagement;
41  import org.apache.maven.model.DeploymentRepository;
42  import org.apache.maven.model.Developer;
43  import org.apache.maven.model.DistributionManagement;
44  import org.apache.maven.model.Exclusion;
45  import org.apache.maven.model.Extension;
46  import org.apache.maven.model.FileSet;
47  import org.apache.maven.model.InputLocation;
48  import org.apache.maven.model.IssueManagement;
49  import org.apache.maven.model.License;
50  import org.apache.maven.model.MailingList;
51  import org.apache.maven.model.Model;
52  import org.apache.maven.model.ModelBase;
53  import org.apache.maven.model.Notifier;
54  import org.apache.maven.model.Organization;
55  import org.apache.maven.model.Parent;
56  import org.apache.maven.model.PatternSet;
57  import org.apache.maven.model.Plugin;
58  import org.apache.maven.model.PluginConfiguration;
59  import org.apache.maven.model.PluginContainer;
60  import org.apache.maven.model.PluginExecution;
61  import org.apache.maven.model.PluginManagement;
62  import org.apache.maven.model.Prerequisites;
63  import org.apache.maven.model.Profile;
64  import org.apache.maven.model.Relocation;
65  import org.apache.maven.model.ReportPlugin;
66  import org.apache.maven.model.ReportSet;
67  import org.apache.maven.model.Reporting;
68  import org.apache.maven.model.Repository;
69  import org.apache.maven.model.RepositoryBase;
70  import org.apache.maven.model.RepositoryPolicy;
71  import org.apache.maven.model.Resource;
72  import org.apache.maven.model.Scm;
73  import org.apache.maven.model.Site;
74  import org.codehaus.plexus.util.xml.Xpp3Dom;
75  
76  /**
77   * This is a hand-crafted prototype of the default model merger that should eventually be generated by Modello by a new
78   * Java plugin. Code structure to merge source (read-only) object into the target object is:<ul>
79   * <li><code>merge<i>Classname</i>( <i>Classname</i> target, <i>Classname</i> source, boolean sourceDominant,
80   * Map&lt;Object, Object&gt; context )</code> for each model class</li>
81   * <li><code>merge<i>Classname</i>_<i>FieldName</i>( <i>Classname</i> target, <i>Classname</i> source, boolean
82   * sourceDominant, Map&lt;Object, Object&gt; context )</code> for each field of each model class</li>
83   * <li><code>Object get<i>Classname</i>Key( <i>Classname</i> <i>classname</i> )</code>
84   * for each class that is used in a list</li>
85   * </ul>
86   * Code is written like it could be generated, with default behaviour to be overridden when necessary.
87   * This is particularly the case for <code>Object get<i>Classname</i>Key( <i>Classname</i> <i>classname</i> )</code>
88   * method, which by default return the object itself and is expected to be overridden to calculate better suited key
89   * value.
90   *
91   * @author Benjamin Bentmann
92   */
93  @SuppressWarnings( { "checkstyle:methodname" } )
94  public class ModelMerger
95  {
96  
97      /**
98       * Merges the specified source object into the given target object.
99       *
100      * @param target The target object whose existing contents should be merged with the source, must not be
101      *            <code>null</code>.
102      * @param source The (read-only) source object that should be merged into the target object, may be
103      *            <code>null</code>.
104      * @param sourceDominant A flag indicating whether either the target object or the source object provides the
105      *            dominant data.
106      * @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific
107      *            information along, may be <code>null</code>.
108      */
109     public void merge( Model target, Model source, boolean sourceDominant, Map<?, ?> hints )
110     {
111         Objects.requireNonNull( target, "target cannot be null" );
112 
113         if ( source == null )
114         {
115             return;
116         }
117 
118         Map<Object, Object> context = new HashMap<>();
119         if ( hints != null )
120         {
121             context.putAll( hints );
122         }
123 
124         mergeModel( target, source, sourceDominant, context );
125     }
126 
127     protected void mergeModel( Model target, Model source, boolean sourceDominant, Map<Object, Object> context )
128     {
129         mergeModelBase( target, source, sourceDominant, context );
130 
131         mergeModel_ChildProjectUrlInheritAppendPath( target, source, sourceDominant, context );
132         mergeModel_ModelVersion( target, source, sourceDominant, context );
133         mergeModel_Parent( target, source, sourceDominant, context );
134         mergeModel_GroupId( target, source, sourceDominant, context );
135         mergeModel_ArtifactId( target, source, sourceDominant, context );
136         mergeModel_Version( target, source, sourceDominant, context );
137         mergeModel_Packaging( target, source, sourceDominant, context );
138         mergeModel_Name( target, source, sourceDominant, context );
139         mergeModel_Description( target, source, sourceDominant, context );
140         mergeModel_Url( target, source, sourceDominant, context );
141         mergeModel_InceptionYear( target, source, sourceDominant, context );
142         mergeModel_Organization( target, source, sourceDominant, context );
143         mergeModel_Licenses( target, source, sourceDominant, context );
144         mergeModel_MailingLists( target, source, sourceDominant, context );
145         mergeModel_Developers( target, source, sourceDominant, context );
146         mergeModel_Contributors( target, source, sourceDominant, context );
147         mergeModel_IssueManagement( target, source, sourceDominant, context );
148         mergeModel_Scm( target, source, sourceDominant, context );
149         mergeModel_CiManagement( target, source, sourceDominant, context );
150         mergeModel_Prerequisites( target, source, sourceDominant, context );
151         mergeModel_Build( target, source, sourceDominant, context );
152         mergeModel_Profiles( target, source, sourceDominant, context );
153     }
154 
155     protected void mergeModel_ModelVersion( Model target, Model source, boolean sourceDominant,
156                                             Map<Object, Object> context )
157     {
158         String src = source.getModelVersion();
159         if ( src != null )
160         {
161             if ( sourceDominant || target.getModelVersion() == null )
162             {
163                 target.setModelVersion( src );
164                 target.setLocation( "modelVersion", source.getLocation( "modelVersion" ) );
165             }
166         }
167     }
168 
169     protected void mergeModel_Parent( Model target, Model source, boolean sourceDominant, Map<Object, Object> context )
170     {
171         Parent src = source.getParent();
172         if ( src != null )
173         {
174             Parent tgt = target.getParent();
175             if ( tgt == null )
176             {
177                 tgt = new Parent();
178                 tgt.setRelativePath( null );
179                 target.setParent( tgt );
180             }
181             mergeParent( tgt, src, sourceDominant, context );
182         }
183     }
184 
185     protected void mergeModel_GroupId( Model target, Model source, boolean sourceDominant,
186                                        Map<Object, Object> context )
187     {
188         String src = source.getGroupId();
189         if ( src != null )
190         {
191             if ( sourceDominant || target.getGroupId() == null )
192             {
193                 target.setGroupId( src );
194                 target.setLocation( "groupId", source.getLocation( "groupId" ) );
195             }
196         }
197     }
198 
199     protected void mergeModel_ArtifactId( Model target, Model source, boolean sourceDominant,
200                                           Map<Object, Object> context )
201     {
202         String src = source.getArtifactId();
203         if ( src != null )
204         {
205             if ( sourceDominant || target.getArtifactId() == null )
206             {
207                 target.setArtifactId( src );
208                 target.setLocation( "artifactId", source.getLocation( "artifactId" ) );
209             }
210         }
211     }
212 
213     protected void mergeModel_ChildProjectUrlInheritAppendPath( Model target, Model source, boolean sourceDominant,
214                                                                 Map<Object, Object> context )
215     {
216         String src = source.getChildProjectUrlInheritAppendPath();
217         if ( src != null )
218         {
219             if ( sourceDominant || target.getChildProjectUrlInheritAppendPath() == null )
220             {
221                 target.setChildProjectUrlInheritAppendPath( src );
222                 target.setLocation( "child.project.url.inherit.append.path",
223                                     source.getLocation( "child.project.url.inherit.append.path" ) );
224             }
225         }
226     }
227 
228     protected void mergeModel_Version( Model target, Model source, boolean sourceDominant,
229                                        Map<Object, Object> context )
230     {
231         String src = source.getVersion();
232         if ( src != null )
233         {
234             if ( sourceDominant || target.getVersion() == null )
235             {
236                 target.setVersion( src );
237                 target.setLocation( "version", source.getLocation( "version" ) );
238             }
239         }
240     }
241 
242     protected void mergeModel_Packaging( Model target, Model source, boolean sourceDominant,
243                                          Map<Object, Object> context )
244     {
245         String src = source.getPackaging();
246         if ( src != null )
247         {
248             if ( sourceDominant || target.getPackaging() == null )
249             {
250                 target.setPackaging( src );
251                 target.setLocation( "packaging", source.getLocation( "packaging" ) );
252             }
253         }
254     }
255 
256     protected void mergeModel_Name( Model target, Model source, boolean sourceDominant, Map<Object, Object> context )
257     {
258         String src = source.getName();
259         if ( src != null )
260         {
261             if ( sourceDominant || target.getName() == null )
262             {
263                 target.setName( src );
264                 target.setLocation( "name", source.getLocation( "name" ) );
265             }
266         }
267     }
268 
269     protected void mergeModel_Description( Model target, Model source, boolean sourceDominant,
270                                            Map<Object, Object> context )
271     {
272         String src = source.getDescription();
273         if ( src != null )
274         {
275             if ( sourceDominant || target.getDescription() == null )
276             {
277                 target.setDescription( src );
278                 target.setLocation( "description", source.getLocation( "description" ) );
279             }
280         }
281     }
282 
283     protected void mergeModel_Url( Model target, Model source, boolean sourceDominant, Map<Object, Object> context )
284     {
285         String src = source.getUrl();
286         if ( src != null )
287         {
288             if ( sourceDominant || target.getUrl() == null )
289             {
290                 target.setUrl( src );
291                 target.setLocation( "url", source.getLocation( "url" ) );
292             }
293         }
294     }
295 
296     protected void mergeModel_InceptionYear( Model target, Model source, boolean sourceDominant,
297                                              Map<Object, Object> context )
298     {
299         String src = source.getInceptionYear();
300         if ( src != null )
301         {
302             if ( sourceDominant || target.getInceptionYear() == null )
303             {
304                 target.setInceptionYear( src );
305                 target.setLocation( "inceptionYear", source.getLocation( "inceptionYear" ) );
306             }
307         }
308     }
309 
310     protected void mergeModel_Organization( Model target, Model source, boolean sourceDominant,
311                                             Map<Object, Object> context )
312     {
313         Organization src = source.getOrganization();
314         if ( src != null )
315         {
316             Organization tgt = target.getOrganization();
317             if ( tgt == null )
318             {
319                 tgt = new Organization();
320                 target.setOrganization( tgt );
321             }
322             mergeOrganization( tgt, src, sourceDominant, context );
323         }
324     }
325 
326     protected void mergeModel_Licenses( Model target, Model source, boolean sourceDominant,
327                                         Map<Object, Object> context )
328     {
329         target.setLicenses( merge( target.getLicenses(), source.getLicenses(),
330                                     sourceDominant, new LicenseKeyComputer() ) );
331     }
332 
333     protected void mergeModel_MailingLists( Model target, Model source, boolean sourceDominant,
334                                             Map<Object, Object> context )
335     {
336         target.setMailingLists( merge( target.getMailingLists(), source.getMailingLists(),
337                                        sourceDominant, new MailingListKeyComputer() ) );
338     }
339 
340     protected void mergeModel_Developers( Model target, Model source, boolean sourceDominant,
341                                           Map<Object, Object> context )
342     {
343         target.setDevelopers( merge( target.getDevelopers(), source.getDevelopers(),
344                 sourceDominant, new DeveloperKeyComputer() ) );
345     }
346 
347     protected void mergeModel_Contributors( Model target, Model source, boolean sourceDominant,
348                                             Map<Object, Object> context )
349     {
350         target.setContributors( merge( target.getContributors(), source.getContributors(),
351                 sourceDominant, new ContributorKeyComputer() ) );
352     }
353 
354     protected void mergeModel_IssueManagement( Model target, Model source, boolean sourceDominant,
355                                                Map<Object, Object> context )
356     {
357         IssueManagement src = source.getIssueManagement();
358         if ( src != null )
359         {
360             IssueManagement tgt = target.getIssueManagement();
361             if ( tgt == null )
362             {
363                 tgt = new IssueManagement();
364                 target.setIssueManagement( tgt );
365             }
366             mergeIssueManagement( tgt, src, sourceDominant, context );
367         }
368     }
369 
370     protected void mergeModel_Scm( Model target, Model source, boolean sourceDominant, Map<Object, Object> context )
371     {
372         Scm src = source.getScm();
373         if ( src != null )
374         {
375             Scm tgt = target.getScm();
376             if ( tgt == null )
377             {
378                 tgt = new Scm();
379                 tgt.setTag( null );
380                 target.setScm( tgt );
381             }
382             mergeScm( tgt, src, sourceDominant, context );
383         }
384     }
385 
386     protected void mergeModel_CiManagement( Model target, Model source, boolean sourceDominant,
387                                             Map<Object, Object> context )
388     {
389         CiManagement src = source.getCiManagement();
390         if ( src != null )
391         {
392             CiManagement tgt = target.getCiManagement();
393             if ( tgt == null )
394             {
395                 tgt = new CiManagement();
396                 target.setCiManagement( tgt );
397             }
398             mergeCiManagement( tgt, src, sourceDominant, context );
399         }
400     }
401 
402     protected void mergeModel_Prerequisites( Model target, Model source, boolean sourceDominant,
403                                              Map<Object, Object> context )
404     {
405         Prerequisites src = source.getPrerequisites();
406         if ( src != null )
407         {
408             Prerequisites tgt = target.getPrerequisites();
409             if ( tgt == null )
410             {
411                 tgt = new Prerequisites();
412                 tgt.setMaven( null );
413                 target.setPrerequisites( tgt );
414             }
415             mergePrerequisites( tgt, src, sourceDominant, context );
416         }
417     }
418 
419     protected void mergeModel_Build( Model target, Model source, boolean sourceDominant, Map<Object, Object> context )
420     {
421         Build src = source.getBuild();
422         if ( src != null )
423         {
424             Build tgt = target.getBuild();
425             if ( tgt == null )
426             {
427                 tgt = new Build();
428                 target.setBuild( tgt );
429             }
430             mergeBuild( tgt, src, sourceDominant, context );
431         }
432     }
433 
434     protected void mergeModel_Profiles( Model target, Model source, boolean sourceDominant,
435                                         Map<Object, Object> context )
436     {
437         target.setProfiles( merge( target.getProfiles(), source.getProfiles(),
438                 sourceDominant, new ProfileKeyComputer() ) );
439     }
440 
441     protected void mergeModelBase( ModelBase target, ModelBase source, boolean sourceDominant,
442                                    Map<Object, Object> context )
443     {
444         mergeModelBase_DistributionManagement( target, source, sourceDominant, context );
445         mergeModelBase_Modules( target, source, sourceDominant, context );
446         mergeModelBase_Repositories( target, source, sourceDominant, context );
447         mergeModelBase_PluginRepositories( target, source, sourceDominant, context );
448         mergeModelBase_Dependencies( target, source, sourceDominant, context );
449         mergeModelBase_Reporting( target, source, sourceDominant, context );
450         mergeModelBase_DependencyManagement( target, source, sourceDominant, context );
451         mergeModelBase_Properties( target, source, sourceDominant, context );
452     }
453 
454     protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boolean sourceDominant,
455                                            Map<Object, Object> context )
456     {
457         List<String> src = source.getModules();
458         if ( !src.isEmpty() )
459         {
460             List<String> tgt = target.getModules();
461             List<String> merged = new ArrayList<>( tgt.size() + src.size() );
462             merged.addAll( tgt );
463             merged.addAll( src );
464             target.setModules( merged );
465         }
466     }
467 
468     protected void mergeModelBase_Dependencies( ModelBase target, ModelBase source, boolean sourceDominant,
469                                                 Map<Object, Object> context )
470     {
471         target.setDependencies( merge( target.getDependencies(), source.getDependencies(),
472                 sourceDominant, new DependencyKeyComputer() ) );
473     }
474 
475     protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, boolean sourceDominant,
476                                                 Map<Object, Object> context )
477     {
478         target.setRepositories( merge( target.getRepositories(), source.getRepositories(),
479                 sourceDominant, new RepositoryKeyComputer() ) );
480     }
481 
482     protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase source, boolean sourceDominant,
483                                                       Map<Object, Object> context )
484     {
485         target.setPluginRepositories( merge( target.getPluginRepositories(), source.getPluginRepositories(),
486                 sourceDominant, new RepositoryKeyComputer() ) );
487     }
488 
489     protected void mergeModelBase_DistributionManagement( ModelBase target, ModelBase source, boolean sourceDominant,
490                                                           Map<Object, Object> context )
491     {
492         DistributionManagement src = source.getDistributionManagement();
493         if ( src != null )
494         {
495             DistributionManagement tgt = target.getDistributionManagement();
496             if ( tgt == null )
497             {
498                 tgt = new DistributionManagement();
499                 target.setDistributionManagement( tgt );
500             }
501             mergeDistributionManagement( tgt, src, sourceDominant, context );
502         }
503     }
504 
505     protected void mergeModelBase_Reporting( ModelBase target, ModelBase source, boolean sourceDominant,
506                                              Map<Object, Object> context )
507     {
508         Reporting src = source.getReporting();
509         if ( src != null )
510         {
511             Reporting tgt = target.getReporting();
512             if ( tgt == null )
513             {
514                 tgt = new Reporting();
515                 target.setReporting( tgt );
516             }
517             mergeReporting( tgt, src, sourceDominant, context );
518         }
519     }
520 
521     protected void mergeModelBase_DependencyManagement( ModelBase target, ModelBase source, boolean sourceDominant,
522                                                         Map<Object, Object> context )
523     {
524         DependencyManagement src = source.getDependencyManagement();
525         if ( src != null )
526         {
527             DependencyManagement tgt = target.getDependencyManagement();
528             if ( tgt == null )
529             {
530                 tgt = new DependencyManagement();
531                 target.setDependencyManagement( tgt );
532             }
533             mergeDependencyManagement( tgt, src, sourceDominant, context );
534         }
535     }
536 
537     protected void mergeModelBase_Properties( ModelBase target, ModelBase source, boolean sourceDominant,
538                                               Map<Object, Object> context )
539     {
540         Properties merged = new Properties();
541         if ( sourceDominant )
542         {
543             merged.putAll( target.getProperties() );
544             merged.putAll( source.getProperties() );
545         }
546         else
547         {
548             merged.putAll( source.getProperties() );
549             merged.putAll( target.getProperties() );
550         }
551         target.setProperties( merged );
552         target.setLocation( "properties", InputLocation.merge( target.getLocation( "properties" ),
553                                                                source.getLocation( "properties" ), sourceDominant ) );
554     }
555 
556     protected void mergeDistributionManagement( DistributionManagement target, DistributionManagement source,
557                                                 boolean sourceDominant, Map<Object, Object> context )
558     {
559         mergeDistributionManagement_Repository( target, source, sourceDominant, context );
560         mergeDistributionManagement_SnapshotRepository( target, source, sourceDominant, context );
561         mergeDistributionManagement_Site( target, source, sourceDominant, context );
562         mergeDistributionManagement_Status( target, source, sourceDominant, context );
563         mergeDistributionManagement_DownloadUrl( target, source, sourceDominant, context );
564     }
565 
566     protected void mergeDistributionManagement_Repository( DistributionManagement target,
567                                                            DistributionManagement source, boolean sourceDominant,
568                                                            Map<Object, Object> context )
569     {
570         DeploymentRepository src = source.getRepository();
571         if ( src != null )
572         {
573             DeploymentRepository tgt = target.getRepository();
574             if ( tgt == null )
575             {
576                 tgt = new DeploymentRepository();
577                 target.setRepository( tgt );
578             }
579             mergeDeploymentRepository( tgt, src, sourceDominant, context );
580         }
581     }
582 
583     protected void mergeDistributionManagement_SnapshotRepository( DistributionManagement target,
584                                                                    DistributionManagement source,
585                                                                    boolean sourceDominant,
586                                                                    Map<Object, Object> context )
587     {
588         DeploymentRepository src = source.getSnapshotRepository();
589         if ( src != null )
590         {
591             DeploymentRepository tgt = target.getSnapshotRepository();
592             if ( tgt == null )
593             {
594                 tgt = new DeploymentRepository();
595                 target.setSnapshotRepository( tgt );
596             }
597             mergeDeploymentRepository( tgt, src, sourceDominant, context );
598         }
599     }
600 
601     protected void mergeDistributionManagement_Site( DistributionManagement target, DistributionManagement source,
602                                                      boolean sourceDominant, Map<Object, Object> context )
603     {
604         Site src = source.getSite();
605         if ( src != null )
606         {
607             Site tgt = target.getSite();
608             if ( tgt == null )
609             {
610                 tgt = new Site();
611                 target.setSite( tgt );
612             }
613             mergeSite( tgt, src, sourceDominant, context );
614         }
615     }
616 
617     protected void mergeDistributionManagement_Status( DistributionManagement target, DistributionManagement source,
618                                                        boolean sourceDominant, Map<Object, Object> context )
619     {
620         String src = source.getStatus();
621         if ( src != null )
622         {
623             if ( sourceDominant || target.getStatus() == null )
624             {
625                 target.setStatus( src );
626                 target.setLocation( "status", source.getLocation( "status" ) );
627             }
628         }
629     }
630 
631     protected void mergeDistributionManagement_DownloadUrl( DistributionManagement target,
632                                                             DistributionManagement source, boolean sourceDominant,
633                                                             Map<Object, Object> context )
634     {
635         String src = source.getDownloadUrl();
636         if ( src != null )
637         {
638             if ( sourceDominant || target.getDownloadUrl() == null )
639             {
640                 target.setDownloadUrl( src );
641                 target.setLocation( "downloadUrl", source.getLocation( "downloadUrl" ) );
642             }
643         }
644     }
645 
646     protected void mergeRelocation( Relocation target, Relocation source, boolean sourceDominant,
647                                     Map<Object, Object> context )
648     {
649         mergeRelocation_GroupId( target, source, sourceDominant, context );
650         mergeRelocation_ArtifactId( target, source, sourceDominant, context );
651         mergeRelocation_Version( target, source, sourceDominant, context );
652         mergeRelocation_Message( target, source, sourceDominant, context );
653     }
654 
655     protected void mergeRelocation_GroupId( Relocation target, Relocation source, boolean sourceDominant,
656                                             Map<Object, Object> context )
657     {
658         String src = source.getGroupId();
659         if ( src != null )
660         {
661             if ( sourceDominant || target.getGroupId() == null )
662             {
663                 target.setGroupId( src );
664                 target.setLocation( "groupId", source.getLocation( "groupId" ) );
665             }
666         }
667     }
668 
669     protected void mergeRelocation_ArtifactId( Relocation target, Relocation source, boolean sourceDominant,
670                                                Map<Object, Object> context )
671     {
672         String src = source.getArtifactId();
673         if ( src != null )
674         {
675             if ( sourceDominant || target.getArtifactId() == null )
676             {
677                 target.setArtifactId( src );
678                 target.setLocation( "artifactId", source.getLocation( "artifactId" ) );
679             }
680         }
681     }
682 
683     protected void mergeRelocation_Version( Relocation target, Relocation source, boolean sourceDominant,
684                                             Map<Object, Object> context )
685     {
686         String src = source.getVersion();
687         if ( src != null )
688         {
689             if ( sourceDominant || target.getVersion() == null )
690             {
691                 target.setVersion( src );
692                 target.setLocation( "version", source.getLocation( "version" ) );
693             }
694         }
695     }
696 
697     protected void mergeRelocation_Message( Relocation target, Relocation source, boolean sourceDominant,
698                                             Map<Object, Object> context )
699     {
700         String src = source.getMessage();
701         if ( src != null )
702         {
703             if ( sourceDominant || target.getMessage() == null )
704             {
705                 target.setMessage( src );
706                 target.setLocation( "message", source.getLocation( "message" ) );
707             }
708         }
709     }
710 
711     protected void mergeDeploymentRepository( DeploymentRepository target, DeploymentRepository source,
712                                               boolean sourceDominant, Map<Object, Object> context )
713     {
714         mergeRepository( target, source, sourceDominant, context );
715         mergeDeploymentRepository_UniqueVersion( target, source, sourceDominant, context );
716     }
717 
718     protected void mergeDeploymentRepository_UniqueVersion( DeploymentRepository target, DeploymentRepository source,
719                                                             boolean sourceDominant, Map<Object, Object> context )
720     {
721         if ( sourceDominant )
722         {
723             target.setUniqueVersion( source.isUniqueVersion() );
724             target.setLocation( "uniqueVersion", source.getLocation( "uniqueVersion" ) );
725         }
726     }
727 
728     protected void mergeSite( Site target, Site source, boolean sourceDominant, Map<Object, Object> context )
729     {
730         mergeSite_ChildSiteUrlInheritAppendPath( target, source, sourceDominant, context );
731         mergeSite_Id( target, source, sourceDominant, context );
732         mergeSite_Name( target, source, sourceDominant, context );
733         mergeSite_Url( target, source, sourceDominant, context );
734     }
735 
736     protected void mergeSite_ChildSiteUrlInheritAppendPath( Site target, Site source, boolean sourceDominant,
737                                                             Map<Object, Object> context )
738     {
739         String src = source.getChildSiteUrlInheritAppendPath();
740         if ( src != null )
741         {
742             if ( sourceDominant || target.getChildSiteUrlInheritAppendPath() == null )
743             {
744                 target.setChildSiteUrlInheritAppendPath( src );
745                 target.setLocation( "child.site.url.inherit.append.path",
746                                     source.getLocation( "child.site.url.inherit.append.path" ) );
747             }
748         }
749     }
750 
751     protected void mergeSite_Id( Site target, Site source, boolean sourceDominant, Map<Object, Object> context )
752     {
753         String src = source.getId();
754         if ( src != null )
755         {
756             if ( sourceDominant || target.getId() == null )
757             {
758                 target.setId( src );
759                 target.setLocation( "id", source.getLocation( "id" ) );
760             }
761         }
762     }
763 
764     protected void mergeSite_Name( Site target, Site source, boolean sourceDominant, Map<Object, Object> context )
765     {
766         String src = source.getName();
767         if ( src != null )
768         {
769             if ( sourceDominant || target.getName() == null )
770             {
771                 target.setName( src );
772                 target.setLocation( "name", source.getLocation( "name" ) );
773             }
774         }
775     }
776 
777     protected void mergeSite_Url( Site target, Site source, boolean sourceDominant, Map<Object, Object> context )
778     {
779         String src = source.getUrl();
780         if ( src != null )
781         {
782             if ( sourceDominant || target.getUrl() == null )
783             {
784                 target.setUrl( src );
785                 target.setLocation( "url", source.getLocation( "url" ) );
786             }
787         }
788     }
789 
790     protected void mergeRepository( Repository target, Repository source, boolean sourceDominant,
791                                     Map<Object, Object> context )
792     {
793         mergeRepositoryBase( target, source, sourceDominant, context );
794         mergeRepository_Releases( target, source, sourceDominant, context );
795         mergeRepository_Snapshots( target, source, sourceDominant, context );
796     }
797 
798     protected void mergeRepository_Releases( Repository target, Repository source, boolean sourceDominant,
799                                              Map<Object, Object> context )
800     {
801         RepositoryPolicy src = source.getReleases();
802         if ( src != null )
803         {
804             RepositoryPolicy tgt = target.getReleases();
805             if ( tgt == null )
806             {
807                 tgt = new RepositoryPolicy();
808                 target.setReleases( tgt );
809             }
810             mergeRepositoryPolicy( tgt, src, sourceDominant, context );
811         }
812     }
813 
814     protected void mergeRepository_Snapshots( Repository target, Repository source, boolean sourceDominant,
815                                               Map<Object, Object> context )
816     {
817         RepositoryPolicy src = source.getSnapshots();
818         if ( src != null )
819         {
820             RepositoryPolicy tgt = target.getSnapshots();
821             if ( tgt == null )
822             {
823                 tgt = new RepositoryPolicy();
824                 target.setSnapshots( tgt );
825             }
826             mergeRepositoryPolicy( tgt, src, sourceDominant, context );
827         }
828     }
829 
830     protected void mergeRepositoryBase( RepositoryBase target, RepositoryBase source, boolean sourceDominant,
831                                         Map<Object, Object> context )
832     {
833         mergeRepositoryBase_Id( target, source, sourceDominant, context );
834         mergeRepositoryBase_Name( target, source, sourceDominant, context );
835         mergeRepositoryBase_Url( target, source, sourceDominant, context );
836         mergeRepositoryBase_Layout( target, source, sourceDominant, context );
837     }
838 
839     protected void mergeRepositoryBase_Id( RepositoryBase target, RepositoryBase source, boolean sourceDominant,
840                                            Map<Object, Object> context )
841     {
842         String src = source.getId();
843         if ( src != null )
844         {
845             if ( sourceDominant || target.getId() == null )
846             {
847                 target.setId( src );
848                 target.setLocation( "id", source.getLocation( "id" ) );
849             }
850         }
851     }
852 
853     protected void mergeRepositoryBase_Url( RepositoryBase target, RepositoryBase source, boolean sourceDominant,
854                                             Map<Object, Object> context )
855     {
856         String src = source.getUrl();
857         if ( src != null )
858         {
859             if ( sourceDominant || target.getUrl() == null )
860             {
861                 target.setUrl( src );
862                 target.setLocation( "url", source.getLocation( "url" ) );
863             }
864         }
865     }
866 
867     protected void mergeRepositoryBase_Name( RepositoryBase target, RepositoryBase source, boolean sourceDominant,
868                                              Map<Object, Object> context )
869     {
870         String src = source.getName();
871         if ( src != null )
872         {
873             if ( sourceDominant || target.getName() == null )
874             {
875                 target.setName( src );
876                 target.setLocation( "name", source.getLocation( "name" ) );
877             }
878         }
879     }
880 
881     protected void mergeRepositoryBase_Layout( RepositoryBase target, RepositoryBase source, boolean sourceDominant,
882                                                Map<Object, Object> context )
883     {
884         String src = source.getLayout();
885         if ( src != null )
886         {
887             if ( sourceDominant || target.getLayout() == null )
888             {
889                 target.setLayout( src );
890                 target.setLocation( "layout", source.getLocation( "layout" ) );
891             }
892         }
893     }
894 
895     protected void mergeRepositoryPolicy( RepositoryPolicy target, RepositoryPolicy source, boolean sourceDominant,
896                                           Map<Object, Object> context )
897     {
898         mergeRepositoryPolicy_Enabled( target, source, sourceDominant, context );
899         mergeRepositoryPolicy_UpdatePolicy( target, source, sourceDominant, context );
900         mergeRepositoryPolicy_ChecksumPolicy( target, source, sourceDominant, context );
901     }
902 
903     protected void mergeRepositoryPolicy_Enabled( RepositoryPolicy target, RepositoryPolicy source,
904                                                   boolean sourceDominant, Map<Object, Object> context )
905     {
906         String src = source.getEnabled();
907         if ( src != null )
908         {
909             if ( sourceDominant || target.getEnabled() == null )
910             {
911                 target.setEnabled( src );
912                 target.setLocation( "enabled", source.getLocation( "enabled" ) );
913             }
914         }
915     }
916 
917     protected void mergeRepositoryPolicy_UpdatePolicy( RepositoryPolicy target, RepositoryPolicy source,
918                                                        boolean sourceDominant, Map<Object, Object> context )
919     {
920         String src = source.getUpdatePolicy();
921         if ( src != null )
922         {
923             if ( sourceDominant || target.getUpdatePolicy() == null )
924             {
925                 target.setUpdatePolicy( src );
926                 target.setLocation( "updatePolicy", source.getLocation( "updatePolicy" ) );
927             }
928         }
929     }
930 
931     protected void mergeRepositoryPolicy_ChecksumPolicy( RepositoryPolicy target, RepositoryPolicy source,
932                                                          boolean sourceDominant, Map<Object, Object> context )
933     {
934         String src = source.getChecksumPolicy();
935         if ( src != null )
936         {
937             if ( sourceDominant || target.getChecksumPolicy() == null )
938             {
939                 target.setChecksumPolicy( src );
940                 target.setLocation( "checksumPolicy", source.getLocation( "checksumPolicy" ) );
941             }
942         }
943     }
944 
945     protected void mergeDependency( Dependency target, Dependency source, boolean sourceDominant,
946                                     Map<Object, Object> context )
947     {
948         mergeDependency_GroupId( target, source, sourceDominant, context );
949         mergeDependency_ArtifactId( target, source, sourceDominant, context );
950         mergeDependency_Version( target, source, sourceDominant, context );
951         mergeDependency_Type( target, source, sourceDominant, context );
952         mergeDependency_Classifier( target, source, sourceDominant, context );
953         mergeDependency_Scope( target, source, sourceDominant, context );
954         mergeDependency_SystemPath( target, source, sourceDominant, context );
955         mergeDependency_Optional( target, source, sourceDominant, context );
956         mergeDependency_Exclusions( target, source, sourceDominant, context );
957     }
958 
959     protected void mergeDependency_GroupId( Dependency target, Dependency source, boolean sourceDominant,
960                                             Map<Object, Object> context )
961     {
962         String src = source.getGroupId();
963         if ( src != null )
964         {
965             if ( sourceDominant || target.getGroupId() == null )
966             {
967                 target.setGroupId( src );
968                 target.setLocation( "groupId", source.getLocation( "groupId" ) );
969             }
970         }
971     }
972 
973     protected void mergeDependency_ArtifactId( Dependency target, Dependency source, boolean sourceDominant,
974                                                Map<Object, Object> context )
975     {
976         String src = source.getArtifactId();
977         if ( src != null )
978         {
979             if ( sourceDominant || target.getArtifactId() == null )
980             {
981                 target.setArtifactId( src );
982                 target.setLocation( "artifactId", source.getLocation( "artifactId" ) );
983             }
984         }
985     }
986 
987     protected void mergeDependency_Version( Dependency target, Dependency source, boolean sourceDominant,
988                                             Map<Object, Object> context )
989     {
990         String src = source.getVersion();
991         if ( src != null )
992         {
993             if ( sourceDominant || target.getVersion() == null )
994             {
995                 target.setVersion( src );
996                 target.setLocation( "version", source.getLocation( "version" ) );
997             }
998         }
999     }
1000 
1001     protected void mergeDependency_Type( Dependency target, Dependency source, boolean sourceDominant,
1002                                          Map<Object, Object> context )
1003     {
1004         String src = source.getType();
1005         if ( src != null )
1006         {
1007             if ( sourceDominant || target.getType() == null )
1008             {
1009                 target.setType( src );
1010                 target.setLocation( "type", source.getLocation( "type" ) );
1011             }
1012         }
1013     }
1014 
1015     protected void mergeDependency_Classifier( Dependency target, Dependency source, boolean sourceDominant,
1016                                                Map<Object, Object> context )
1017     {
1018         String src = source.getClassifier();
1019         if ( src != null )
1020         {
1021             if ( sourceDominant || target.getClassifier() == null )
1022             {
1023                 target.setClassifier( src );
1024                 target.setLocation( "classifier", source.getLocation( "classifier" ) );
1025             }
1026         }
1027     }
1028 
1029     protected void mergeDependency_Scope( Dependency target, Dependency source, boolean sourceDominant,
1030                                           Map<Object, Object> context )
1031     {
1032         String src = source.getScope();
1033         if ( src != null )
1034         {
1035             if ( sourceDominant || target.getScope() == null )
1036             {
1037                 target.setScope( src );
1038                 target.setLocation( "scope", source.getLocation( "scope" ) );
1039             }
1040         }
1041     }
1042 
1043     protected void mergeDependency_SystemPath( Dependency target, Dependency source, boolean sourceDominant,
1044                                                Map<Object, Object> context )
1045     {
1046         String src = source.getSystemPath();
1047         if ( src != null )
1048         {
1049             if ( sourceDominant || target.getSystemPath() == null )
1050             {
1051                 target.setSystemPath( src );
1052                 target.setLocation( "systemPath", source.getLocation( "systemPath" ) );
1053             }
1054         }
1055     }
1056 
1057     protected void mergeDependency_Optional( Dependency target, Dependency source, boolean sourceDominant,
1058                                              Map<Object, Object> context )
1059     {
1060         String src = source.getOptional();
1061         if ( src != null )
1062         {
1063             if ( sourceDominant || target.getOptional() == null )
1064             {
1065                 target.setOptional( src );
1066                 target.setLocation( "optional", source.getLocation( "optional" ) );
1067             }
1068         }
1069     }
1070 
1071     protected void mergeDependency_Exclusions( Dependency target, Dependency source, boolean sourceDominant,
1072                                                Map<Object, Object> context )
1073     {
1074         target.setExclusions( merge( target.getExclusions(), source.getExclusions(),
1075                 sourceDominant, new ExclusionKeyComputer() ) );
1076     }
1077 
1078     protected void mergeExclusion( Exclusion target, Exclusion source, boolean sourceDominant,
1079                                    Map<Object, Object> context )
1080     {
1081         mergeExclusion_GroupId( target, source, sourceDominant, context );
1082         mergeExclusion_ArtifactId( target, source, sourceDominant, context );
1083     }
1084 
1085     protected void mergeExclusion_GroupId( Exclusion target, Exclusion source, boolean sourceDominant,
1086                                            Map<Object, Object> context )
1087     {
1088         String src = source.getGroupId();
1089         if ( src != null )
1090         {
1091             if ( sourceDominant || target.getGroupId() == null )
1092             {
1093                 target.setGroupId( src );
1094                 target.setLocation( "groupId", source.getLocation( "groupId" ) );
1095             }
1096         }
1097     }
1098 
1099     protected void mergeExclusion_ArtifactId( Exclusion target, Exclusion source, boolean sourceDominant,
1100                                               Map<Object, Object> context )
1101     {
1102         String src = source.getArtifactId();
1103         if ( src != null )
1104         {
1105             if ( sourceDominant || target.getArtifactId() == null )
1106             {
1107                 target.setArtifactId( src );
1108                 target.setLocation( "artifactId", source.getLocation( "artifactId" ) );
1109             }
1110         }
1111     }
1112 
1113     protected void mergeReporting( Reporting target, Reporting source, boolean sourceDominant,
1114                                    Map<Object, Object> context )
1115     {
1116         mergeReporting_OutputDirectory( target, source, sourceDominant, context );
1117         mergeReporting_ExcludeDefaults( target, source, sourceDominant, context );
1118         mergeReporting_Plugins( target, source, sourceDominant, context );
1119     }
1120 
1121     protected void mergeReporting_OutputDirectory( Reporting target, Reporting source, boolean sourceDominant,
1122                                                    Map<Object, Object> context )
1123     {
1124         String src = source.getOutputDirectory();
1125         if ( src != null )
1126         {
1127             if ( sourceDominant || target.getOutputDirectory() == null )
1128             {
1129                 target.setOutputDirectory( src );
1130                 target.setLocation( "outputDirectory", source.getLocation( "outputDirectory" ) );
1131             }
1132         }
1133     }
1134 
1135     protected void mergeReporting_ExcludeDefaults( Reporting target, Reporting source, boolean sourceDominant,
1136                                                    Map<Object, Object> context )
1137     {
1138         String src = source.getExcludeDefaults();
1139         if ( src != null )
1140         {
1141             if ( sourceDominant || target.getExcludeDefaults() == null )
1142             {
1143                 target.setExcludeDefaults( src );
1144                 target.setLocation( "excludeDefaults", source.getLocation( "excludeDefaults" ) );
1145             }
1146         }
1147     }
1148 
1149     protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant,
1150                                            Map<Object, Object> context )
1151     {
1152         target.setPlugins( merge( target.getPlugins(), source.getPlugins(),
1153                 sourceDominant, new ReportPluginKeyComputer() ) );
1154     }
1155 
1156     protected void mergeReportPlugin( ReportPlugin target, ReportPlugin source, boolean sourceDominant,
1157                                       Map<Object, Object> context )
1158     {
1159         mergeConfigurationContainer( target, source, sourceDominant, context );
1160         mergeReportPlugin_GroupId( target, source, sourceDominant, context );
1161         mergeReportPlugin_ArtifactId( target, source, sourceDominant, context );
1162         mergeReportPlugin_Version( target, source, sourceDominant, context );
1163         mergeReportPlugin_ReportSets( target, source, sourceDominant, context );
1164     }
1165 
1166     protected void mergeReportPlugin_GroupId( ReportPlugin target, ReportPlugin source, boolean sourceDominant,
1167                                               Map<Object, Object> context )
1168     {
1169         String src = source.getGroupId();
1170         if ( src != null )
1171         {
1172             if ( sourceDominant || target.getGroupId() == null )
1173             {
1174                 target.setGroupId( src );
1175                 target.setLocation( "groupId", source.getLocation( "groupId" ) );
1176             }
1177         }
1178     }
1179 
1180     protected void mergeReportPlugin_ArtifactId( ReportPlugin target, ReportPlugin source, boolean sourceDominant,
1181                                                  Map<Object, Object> context )
1182     {
1183         String src = source.getArtifactId();
1184         if ( src != null )
1185         {
1186             if ( sourceDominant || target.getArtifactId() == null )
1187             {
1188                 target.setArtifactId( src );
1189                 target.setLocation( "artifactId", source.getLocation( "artifactId" ) );
1190             }
1191         }
1192     }
1193 
1194     protected void mergeReportPlugin_Version( ReportPlugin target, ReportPlugin source, boolean sourceDominant,
1195                                               Map<Object, Object> context )
1196     {
1197         String src = source.getVersion();
1198         if ( src != null )
1199         {
1200             if ( sourceDominant || target.getVersion() == null )
1201             {
1202                 target.setVersion( src );
1203                 target.setLocation( "version", source.getLocation( "version" ) );
1204             }
1205         }
1206     }
1207 
1208     protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant,
1209                                                  Map<Object, Object> context )
1210     {
1211         target.setReportSets( merge( target.getReportSets(), source.getReportSets(),
1212                 sourceDominant, new ReportSetKeyComputer() ) );
1213     }
1214 
1215     protected void mergeReportSet( ReportSet target, ReportSet source, boolean sourceDominant,
1216                                    Map<Object, Object> context )
1217     {
1218         mergeConfigurationContainer( target, source, sourceDominant, context );
1219         mergeReportSet_Id( target, source, sourceDominant, context );
1220         mergeReportSet_Reports( target, source, sourceDominant, context );
1221     }
1222 
1223     protected void mergeReportSet_Id( ReportSet target, ReportSet source, boolean sourceDominant,
1224                                       Map<Object, Object> context )
1225     {
1226         String src = source.getId();
1227         if ( src != null )
1228         {
1229             if ( sourceDominant || target.getId() == null )
1230             {
1231                 target.setId( src );
1232                 target.setLocation( "id", source.getLocation( "id" ) );
1233             }
1234         }
1235     }
1236 
1237     protected void mergeReportSet_Reports( ReportSet target, ReportSet source, boolean sourceDominant,
1238                                            Map<Object, Object> context )
1239     {
1240         List<String> src = source.getReports();
1241         if ( !src.isEmpty() )
1242         {
1243             List<String> tgt = target.getReports();
1244             List<String> merged = new ArrayList<>( tgt.size() + src.size() );
1245             merged.addAll( tgt );
1246             merged.addAll( src );
1247             target.setReports( merged );
1248 
1249             InputLocation sourceLocation = source.getLocation( "reports" );
1250             if ( sourceLocation != null )
1251             {
1252                 InputLocation targetLocation = target.getLocation( "reports" );
1253                 if ( targetLocation == null )
1254                 {
1255                     target.setLocation( "reports", sourceLocation );
1256                 }
1257                 else
1258                 {
1259                     for ( int i = 0; i < src.size(); i++ )
1260                     {
1261                         targetLocation.setLocation( Integer.valueOf( tgt.size() + i ),
1262                                                     sourceLocation.getLocation( Integer.valueOf( i ) ) );
1263                     }
1264                 }
1265             }
1266         }
1267     }
1268 
1269     protected void mergeDependencyManagement( DependencyManagement target, DependencyManagement source,
1270                                               boolean sourceDominant, Map<Object, Object> context )
1271     {
1272         mergeDependencyManagement_Dependencies( target, source, sourceDominant, context );
1273     }
1274 
1275     protected void mergeDependencyManagement_Dependencies( DependencyManagement target, DependencyManagement source,
1276                                                            boolean sourceDominant, Map<Object, Object> context )
1277     {
1278         target.setDependencies( merge( target.getDependencies(), source.getDependencies(),
1279                                        sourceDominant, new DependencyKeyComputer() ) );
1280     }
1281 
1282     protected void mergeParent( Parent target, Parent source, boolean sourceDominant, Map<Object, Object> context )
1283     {
1284         mergeParent_GroupId( target, source, sourceDominant, context );
1285         mergeParent_ArtifactId( target, source, sourceDominant, context );
1286         mergeParent_Version( target, source, sourceDominant, context );
1287         mergeParent_RelativePath( target, source, sourceDominant, context );
1288     }
1289 
1290     protected void mergeParent_GroupId( Parent target, Parent source, boolean sourceDominant,
1291                                         Map<Object, Object> context )
1292     {
1293         String src = source.getGroupId();
1294         if ( src != null )
1295         {
1296             if ( sourceDominant || target.getGroupId() == null )
1297             {
1298                 target.setGroupId( src );
1299                 target.setLocation( "groupId", source.getLocation( "groupId" ) );
1300             }
1301         }
1302     }
1303 
1304     protected void mergeParent_ArtifactId( Parent target, Parent source, boolean sourceDominant,
1305                                            Map<Object, Object> context )
1306     {
1307         String src = source.getArtifactId();
1308         if ( src != null )
1309         {
1310             if ( sourceDominant || target.getArtifactId() == null )
1311             {
1312                 target.setArtifactId( src );
1313                 target.setLocation( "artifactId", source.getLocation( "artifactId" ) );
1314             }
1315         }
1316     }
1317 
1318     protected void mergeParent_Version( Parent target, Parent source, boolean sourceDominant,
1319                                         Map<Object, Object> context )
1320     {
1321         String src = source.getVersion();
1322         if ( src != null )
1323         {
1324             if ( sourceDominant || target.getVersion() == null )
1325             {
1326                 target.setVersion( src );
1327                 target.setLocation( "version", source.getLocation( "version" ) );
1328             }
1329         }
1330     }
1331 
1332     protected void mergeParent_RelativePath( Parent target, Parent source, boolean sourceDominant,
1333                                              Map<Object, Object> context )
1334     {
1335         String src = source.getRelativePath();
1336         if ( src != null )
1337         {
1338             if ( sourceDominant || target.getRelativePath() == null )
1339             {
1340                 target.setRelativePath( src );
1341                 target.setLocation( "relativePath", source.getLocation( "relativePath" ) );
1342             }
1343         }
1344     }
1345 
1346     protected void mergeOrganization( Organization target, Organization source, boolean sourceDominant,
1347                                       Map<Object, Object> context )
1348     {
1349         mergeOrganization_Name( target, source, sourceDominant, context );
1350         mergeOrganization_Url( target, source, sourceDominant, context );
1351     }
1352 
1353     protected void mergeOrganization_Name( Organization target, Organization source, boolean sourceDominant,
1354                                            Map<Object, Object> context )
1355     {
1356         String src = source.getName();
1357         if ( src != null )
1358         {
1359             if ( sourceDominant || target.getName() == null )
1360             {
1361                 target.setName( src );
1362                 target.setLocation( "name", source.getLocation( "name" ) );
1363             }
1364         }
1365     }
1366 
1367     protected void mergeOrganization_Url( Organization target, Organization source, boolean sourceDominant,
1368                                           Map<Object, Object> context )
1369     {
1370         String src = source.getUrl();
1371         if ( src != null )
1372         {
1373             if ( sourceDominant || target.getUrl() == null )
1374             {
1375                 target.setUrl( src );
1376                 target.setLocation( "url", source.getLocation( "url" ) );
1377             }
1378         }
1379     }
1380 
1381     protected void mergeLicense( License target, License source, boolean sourceDominant, Map<Object, Object> context )
1382     {
1383         mergeLicense_Name( target, source, sourceDominant, context );
1384         mergeLicense_Url( target, source, sourceDominant, context );
1385         mergeLicense_Distribution( target, source, sourceDominant, context );
1386         mergeLicense_Comments( target, source, sourceDominant, context );
1387     }
1388 
1389     protected void mergeLicense_Name( License target, License source, boolean sourceDominant,
1390                                       Map<Object, Object> context )
1391     {
1392         String src = source.getName();
1393         if ( src != null )
1394         {
1395             if ( sourceDominant || target.getName() == null )
1396             {
1397                 target.setName( src );
1398                 target.setLocation( "name", source.getLocation( "name" ) );
1399             }
1400         }
1401     }
1402 
1403     protected void mergeLicense_Url( License target, License source, boolean sourceDominant,
1404                                      Map<Object, Object> context )
1405     {
1406         String src = source.getUrl();
1407         if ( src != null )
1408         {
1409             if ( sourceDominant || target.getUrl() == null )
1410             {
1411                 target.setUrl( src );
1412                 target.setLocation( "url", source.getLocation( "url" ) );
1413             }
1414         }
1415     }
1416 
1417     protected void mergeLicense_Distribution( License target, License source, boolean sourceDominant,
1418                                               Map<Object, Object> context )
1419     {
1420         String src = source.getDistribution();
1421         if ( src != null )
1422         {
1423             if ( sourceDominant || target.getDistribution() == null )
1424             {
1425                 target.setDistribution( src );
1426                 target.setLocation( "distribution", source.getLocation( "distribution" ) );
1427             }
1428         }
1429     }
1430 
1431     protected void mergeLicense_Comments( License target, License source, boolean sourceDominant,
1432                                           Map<Object, Object> context )
1433     {
1434         String src = source.getComments();
1435         if ( src != null )
1436         {
1437             if ( sourceDominant || target.getComments() == null )
1438             {
1439                 target.setComments( src );
1440                 target.setLocation( "comments", source.getLocation( "comments" ) );
1441             }
1442         }
1443     }
1444 
1445     protected void mergeMailingList( MailingList target, MailingList source, boolean sourceDominant,
1446                                      Map<Object, Object> context )
1447     {
1448         mergeMailingList_Name( target, source, sourceDominant, context );
1449         mergeMailingList_Subscribe( target, source, sourceDominant, context );
1450         mergeMailingList_Unsubscribe( target, source, sourceDominant, context );
1451         mergeMailingList_Post( target, source, sourceDominant, context );
1452         mergeMailingList_OtherArchives( target, source, sourceDominant, context );
1453     }
1454 
1455     protected void mergeMailingList_Name( MailingList target, MailingList source, boolean sourceDominant,
1456                                           Map<Object, Object> context )
1457     {
1458         String src = source.getName();
1459         if ( src != null )
1460         {
1461             if ( sourceDominant || target.getName() == null )
1462             {
1463                 target.setName( src );
1464                 target.setLocation( "name", source.getLocation( "name" ) );
1465             }
1466         }
1467     }
1468 
1469     protected void mergeMailingList_Subscribe( MailingList target, MailingList source, boolean sourceDominant,
1470                                                Map<Object, Object> context )
1471     {
1472         String src = source.getSubscribe();
1473         if ( src != null )
1474         {
1475             if ( sourceDominant || target.getSubscribe() == null )
1476             {
1477                 target.setSubscribe( src );
1478                 target.setLocation( "subscribe", source.getLocation( "subscribe" ) );
1479             }
1480         }
1481     }
1482 
1483     protected void mergeMailingList_Unsubscribe( MailingList target, MailingList source, boolean sourceDominant,
1484                                                  Map<Object, Object> context )
1485     {
1486         String src = source.getUnsubscribe();
1487         if ( src != null )
1488         {
1489             if ( sourceDominant || target.getUnsubscribe() == null )
1490             {
1491                 target.setUnsubscribe( src );
1492                 target.setLocation( "unsubscribe", source.getLocation( "unsubscribe" ) );
1493             }
1494         }
1495     }
1496 
1497     protected void mergeMailingList_Post( MailingList target, MailingList source, boolean sourceDominant,
1498                                           Map<Object, Object> context )
1499     {
1500         String src = source.getPost();
1501         if ( src != null )
1502         {
1503             if ( sourceDominant || target.getPost() == null )
1504             {
1505                 target.setPost( src );
1506                 target.setLocation( "post", source.getLocation( "post" ) );
1507             }
1508         }
1509     }
1510 
1511     protected void mergeMailingList_Archive( MailingList target, MailingList source, boolean sourceDominant,
1512                                              Map<Object, Object> context )
1513     {
1514         String src = source.getArchive();
1515         if ( src != null )
1516         {
1517             if ( sourceDominant || target.getArchive() == null )
1518             {
1519                 target.setArchive( src );
1520                 target.setLocation( "archive", source.getLocation( "archive" ) );
1521             }
1522         }
1523     }
1524 
1525     protected void mergeMailingList_OtherArchives( MailingList target, MailingList source, boolean sourceDominant,
1526                                                    Map<Object, Object> context )
1527     {
1528         List<String> src = source.getOtherArchives();
1529         if ( !src.isEmpty() )
1530         {
1531             List<String> tgt = target.getOtherArchives();
1532             List<String> merged = new ArrayList<>( tgt.size() + src.size() );
1533             merged.addAll( tgt );
1534             merged.addAll( src );
1535             target.setOtherArchives( merged );
1536         }
1537     }
1538 
1539     protected void mergeDeveloper( Developer target, Developer source, boolean sourceDominant,
1540                                    Map<Object, Object> context )
1541     {
1542         mergeContributor( target, source, sourceDominant, context );
1543         mergeDeveloper_Id( target, source, sourceDominant, context );
1544     }
1545 
1546     protected void mergeDeveloper_Id( Developer target, Developer source, boolean sourceDominant,
1547                                       Map<Object, Object> context )
1548     {
1549         String src = source.getId();
1550         if ( src != null )
1551         {
1552             if ( sourceDominant || target.getId() == null )
1553             {
1554                 target.setId( src );
1555                 target.setLocation( "id", source.getLocation( "id" ) );
1556             }
1557         }
1558     }
1559 
1560     protected void mergeContributor( Contributor target, Contributor source, boolean sourceDominant,
1561                                      Map<Object, Object> context )
1562     {
1563         mergeContributor_Name( target, source, sourceDominant, context );
1564         mergeContributor_Email( target, source, sourceDominant, context );
1565         mergeContributor_Url( target, source, sourceDominant, context );
1566         mergeContributor_Organization( target, source, sourceDominant, context );
1567         mergeContributor_OrganizationUrl( target, source, sourceDominant, context );
1568         mergeContributor_Timezone( target, source, sourceDominant, context );
1569         mergeContributor_Roles( target, source, sourceDominant, context );
1570         mergeContributor_Properties( target, source, sourceDominant, context );
1571     }
1572 
1573     protected void mergeContributor_Name( Contributor target, Contributor source, boolean sourceDominant,
1574                                           Map<Object, Object> context )
1575     {
1576         String src = source.getName();
1577         if ( src != null )
1578         {
1579             if ( sourceDominant || target.getName() == null )
1580             {
1581                 target.setName( src );
1582                 target.setLocation( "name", source.getLocation( "name" ) );
1583             }
1584         }
1585     }
1586 
1587     protected void mergeContributor_Email( Contributor target, Contributor source, boolean sourceDominant,
1588                                            Map<Object, Object> context )
1589     {
1590         String src = source.getEmail();
1591         if ( src != null )
1592         {
1593             if ( sourceDominant || target.getEmail() == null )
1594             {
1595                 target.setEmail( src );
1596                 target.setLocation( "email", source.getLocation( "email" ) );
1597             }
1598         }
1599     }
1600 
1601     protected void mergeContributor_Url( Contributor target, Contributor source, boolean sourceDominant,
1602                                          Map<Object, Object> context )
1603     {
1604         String src = source.getUrl();
1605         if ( src != null )
1606         {
1607             if ( sourceDominant || target.getUrl() == null )
1608             {
1609                 target.setUrl( src );
1610                 target.setLocation( "url", source.getLocation( "url" ) );
1611             }
1612         }
1613     }
1614 
1615     protected void mergeContributor_Organization( Contributor target, Contributor source, boolean sourceDominant,
1616                                                   Map<Object, Object> context )
1617     {
1618         String src = source.getOrganization();
1619         if ( src != null )
1620         {
1621             if ( sourceDominant || target.getOrganization() == null )
1622             {
1623                 target.setOrganization( src );
1624                 target.setLocation( "organization", source.getLocation( "organization" ) );
1625             }
1626         }
1627     }
1628 
1629     protected void mergeContributor_OrganizationUrl( Contributor target, Contributor source, boolean sourceDominant,
1630                                                      Map<Object, Object> context )
1631     {
1632         String src = source.getOrganizationUrl();
1633         if ( src != null )
1634         {
1635             if ( sourceDominant || target.getOrganizationUrl() == null )
1636             {
1637                 target.setOrganizationUrl( src );
1638                 target.setLocation( "organizationUrl", source.getLocation( "organizationUrl" ) );
1639             }
1640         }
1641     }
1642 
1643     protected void mergeContributor_Timezone( Contributor target, Contributor source, boolean sourceDominant,
1644                                               Map<Object, Object> context )
1645     {
1646         String src = source.getTimezone();
1647         if ( src != null )
1648         {
1649             if ( sourceDominant || target.getTimezone() == null )
1650             {
1651                 target.setTimezone( src );
1652                 target.setLocation( "timezone", source.getLocation( "timezone" ) );
1653             }
1654         }
1655     }
1656 
1657     protected void mergeContributor_Roles( Contributor target, Contributor source, boolean sourceDominant,
1658                                            Map<Object, Object> context )
1659     {
1660         List<String> src = source.getRoles();
1661         if ( !src.isEmpty() )
1662         {
1663             List<String> tgt = target.getRoles();
1664             List<String> merged = new ArrayList<>( tgt.size() + src.size() );
1665             merged.addAll( tgt );
1666             merged.addAll( src );
1667             target.setRoles( merged );
1668         }
1669     }
1670 
1671     protected void mergeContributor_Properties( Contributor target, Contributor source, boolean sourceDominant,
1672                                                 Map<Object, Object> context )
1673     {
1674         Properties merged = new Properties();
1675         if ( sourceDominant )
1676         {
1677             merged.putAll( target.getProperties() );
1678             merged.putAll( source.getProperties() );
1679         }
1680         else
1681         {
1682             merged.putAll( source.getProperties() );
1683             merged.putAll( target.getProperties() );
1684         }
1685         target.setProperties( merged );
1686         target.setLocation( "properties", InputLocation.merge( target.getLocation( "properties" ),
1687                                                                source.getLocation( "properties" ), sourceDominant ) );
1688     }
1689 
1690     protected void mergeIssueManagement( IssueManagement target, IssueManagement source, boolean sourceDominant,
1691                                          Map<Object, Object> context )
1692     {
1693         mergeIssueManagement_Url( target, source, sourceDominant, context );
1694         mergeIssueManagement_System( target, source, sourceDominant, context );
1695     }
1696 
1697     protected void mergeIssueManagement_System( IssueManagement target, IssueManagement source, boolean sourceDominant,
1698                                                 Map<Object, Object> context )
1699     {
1700         String src = source.getSystem();
1701         if ( src != null )
1702         {
1703             if ( sourceDominant || target.getSystem() == null )
1704             {
1705                 target.setSystem( src );
1706                 target.setLocation( "system", source.getLocation( "system" ) );
1707             }
1708         }
1709     }
1710 
1711     protected void mergeIssueManagement_Url( IssueManagement target, IssueManagement source, boolean sourceDominant,
1712                                              Map<Object, Object> context )
1713     {
1714         String src = source.getUrl();
1715         if ( src != null )
1716         {
1717             if ( sourceDominant || target.getUrl() == null )
1718             {
1719                 target.setUrl( src );
1720                 target.setLocation( "url", source.getLocation( "url" ) );
1721             }
1722         }
1723     }
1724 
1725     protected void mergeScm( Scm target, Scm source, boolean sourceDominant, Map<Object, Object> context )
1726     {
1727         mergeScm_ChildScmConnectionInheritAppendPath( target, source, sourceDominant, context );
1728         mergeScm_ChildScmDeveloperConnectionInheritAppendPath( target, source, sourceDominant, context );
1729         mergeScm_ChildScmUrlInheritAppendPath( target, source, sourceDominant, context );
1730         mergeScm_Url( target, source, sourceDominant, context );
1731         mergeScm_Connection( target, source, sourceDominant, context );
1732         mergeScm_DeveloperConnection( target, source, sourceDominant, context );
1733         mergeScm_Tag( target, source, sourceDominant, context );
1734     }
1735 
1736     protected void mergeScm_ChildScmConnectionInheritAppendPath( Scm target, Scm source, boolean sourceDominant,
1737                                                                  Map<Object, Object> context )
1738     {
1739         String src = source.getChildScmConnectionInheritAppendPath();
1740         if ( src != null )
1741         {
1742             if ( sourceDominant || target.getChildScmConnectionInheritAppendPath() == null )
1743             {
1744                 target.setChildScmConnectionInheritAppendPath( src );
1745                 target.setLocation( "child.scm.connection.inherit.append.path",
1746                                     source.getLocation( "child.scm.connection.inherit.append.path" ) );
1747             }
1748         }
1749     }
1750 
1751     protected void mergeScm_ChildScmDeveloperConnectionInheritAppendPath( Scm target, Scm source,
1752                                                                           boolean sourceDominant,
1753                                                                           Map<Object, Object> context )
1754     {
1755         String src = source.getChildScmDeveloperConnectionInheritAppendPath();
1756         if ( src != null )
1757         {
1758             if ( sourceDominant || target.getChildScmDeveloperConnectionInheritAppendPath() == null )
1759             {
1760                 target.setChildScmDeveloperConnectionInheritAppendPath( src );
1761                 target.setLocation( "child.scm.developerConnection.inherit.append.path",
1762                                     source.getLocation( "child.scm.developerConnection.inherit.append.path" ) );
1763             }
1764         }
1765     }
1766 
1767     protected void mergeScm_ChildScmUrlInheritAppendPath( Scm target, Scm source, boolean sourceDominant,
1768                                                           Map<Object, Object> context )
1769     {
1770         String src = source.getChildScmUrlInheritAppendPath();
1771         if ( src != null )
1772         {
1773             if ( sourceDominant || target.getChildScmUrlInheritAppendPath() == null )
1774             {
1775                 target.setChildScmUrlInheritAppendPath( src );
1776                 target.setLocation( "child.scm.url.inherit.append.path",
1777                                     source.getLocation( "child.scm.url.inherit.append.path" ) );
1778             }
1779         }
1780     }
1781 
1782     protected void mergeScm_Url( Scm target, Scm source, boolean sourceDominant, Map<Object, Object> context )
1783     {
1784         String src = source.getUrl();
1785         if ( src != null )
1786         {
1787             if ( sourceDominant || target.getUrl() == null )
1788             {
1789                 target.setUrl( src );
1790                 target.setLocation( "url", source.getLocation( "url" ) );
1791             }
1792         }
1793     }
1794 
1795     protected void mergeScm_Connection( Scm target, Scm source, boolean sourceDominant, Map<Object, Object> context )
1796     {
1797         String src = source.getConnection();
1798         if ( src != null )
1799         {
1800             if ( sourceDominant || target.getConnection() == null )
1801             {
1802                 target.setConnection( src );
1803                 target.setLocation( "connection", source.getLocation( "connection" ) );
1804             }
1805         }
1806     }
1807 
1808     protected void mergeScm_DeveloperConnection( Scm target, Scm source, boolean sourceDominant,
1809                                                  Map<Object, Object> context )
1810     {
1811         String src = source.getDeveloperConnection();
1812         if ( src != null )
1813         {
1814             if ( sourceDominant || target.getDeveloperConnection() == null )
1815             {
1816                 target.setDeveloperConnection( src );
1817                 target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) );
1818             }
1819         }
1820     }
1821 
1822     protected void mergeScm_Tag( Scm target, Scm source, boolean sourceDominant, Map<Object, Object> context )
1823     {
1824         String src = source.getTag();
1825         if ( src != null )
1826         {
1827             if ( sourceDominant || target.getTag() == null )
1828             {
1829                 target.setTag( src );
1830                 target.setLocation( "tag", source.getLocation( "tag" ) );
1831             }
1832         }
1833     }
1834 
1835     protected void mergeCiManagement( CiManagement target, CiManagement source, boolean sourceDominant,
1836                                       Map<Object, Object> context )
1837     {
1838         mergeCiManagement_System( target, source, sourceDominant, context );
1839         mergeCiManagement_Url( target, source, sourceDominant, context );
1840         mergeCiManagement_Notifiers( target, source, sourceDominant, context );
1841     }
1842 
1843     protected void mergeCiManagement_System( CiManagement target, CiManagement source, boolean sourceDominant,
1844                                              Map<Object, Object> context )
1845     {
1846         String src = source.getSystem();
1847         if ( src != null )
1848         {
1849             if ( sourceDominant || target.getSystem() == null )
1850             {
1851                 target.setSystem( src );
1852                 target.setLocation( "system", source.getLocation( "system" ) );
1853             }
1854         }
1855     }
1856 
1857     protected void mergeCiManagement_Url( CiManagement target, CiManagement source, boolean sourceDominant,
1858                                           Map<Object, Object> context )
1859     {
1860         String src = source.getUrl();
1861         if ( src != null )
1862         {
1863             if ( sourceDominant || target.getUrl() == null )
1864             {
1865                 target.setUrl( src );
1866                 target.setLocation( "url", source.getLocation( "url" ) );
1867             }
1868         }
1869     }
1870 
1871     protected void mergeCiManagement_Notifiers( CiManagement target, CiManagement source, boolean sourceDominant,
1872                                                 Map<Object, Object> context )
1873     {
1874         target.setNotifiers( merge( target.getNotifiers(), source.getNotifiers(),
1875                                     sourceDominant, new NotifierKeyComputer() ) );
1876     }
1877 
1878     protected void mergeNotifier( Notifier target, Notifier source, boolean sourceDominant,
1879                                   Map<Object, Object> context )
1880     {
1881         mergeNotifier_Type( target, source, sourceDominant, context );
1882         mergeNotifier_Address( target, source, sourceDominant, context );
1883         mergeNotifier_Configuration( target, source, sourceDominant, context );
1884         mergeNotifier_SendOnError( target, source, sourceDominant, context );
1885         mergeNotifier_SendOnFailure( target, source, sourceDominant, context );
1886         mergeNotifier_SendOnSuccess( target, source, sourceDominant, context );
1887         mergeNotifier_SendOnWarning( target, source, sourceDominant, context );
1888     }
1889 
1890     protected void mergeNotifier_Type( Notifier target, Notifier source, boolean sourceDominant,
1891                                        Map<Object, Object> context )
1892     {
1893         String src = source.getType();
1894         if ( src != null )
1895         {
1896             if ( sourceDominant || target.getType() == null )
1897             {
1898                 target.setType( src );
1899             }
1900         }
1901     }
1902 
1903     protected void mergeNotifier_Address( Notifier target, Notifier source, boolean sourceDominant,
1904                                           Map<Object, Object> context )
1905     {
1906         String src = source.getAddress();
1907         if ( src != null )
1908         {
1909             if ( sourceDominant || target.getAddress() == null )
1910             {
1911                 target.setAddress( src );
1912             }
1913         }
1914     }
1915 
1916     protected void mergeNotifier_Configuration( Notifier target, Notifier source, boolean sourceDominant,
1917                                                 Map<Object, Object> context )
1918     {
1919         Properties merged = new Properties();
1920         if ( sourceDominant )
1921         {
1922             merged.putAll( target.getConfiguration() );
1923             merged.putAll( source.getConfiguration() );
1924         }
1925         else
1926         {
1927             merged.putAll( source.getConfiguration() );
1928             merged.putAll( target.getConfiguration() );
1929         }
1930         target.setConfiguration( merged );
1931     }
1932 
1933     protected void mergeNotifier_SendOnError( Notifier target, Notifier source, boolean sourceDominant,
1934                                               Map<Object, Object> context )
1935     {
1936         if ( sourceDominant )
1937         {
1938             target.setSendOnError( source.isSendOnError() );
1939         }
1940     }
1941 
1942     protected void mergeNotifier_SendOnFailure( Notifier target, Notifier source, boolean sourceDominant,
1943                                                 Map<Object, Object> context )
1944     {
1945         if ( sourceDominant )
1946         {
1947             target.setSendOnFailure( source.isSendOnFailure() );
1948         }
1949     }
1950 
1951     protected void mergeNotifier_SendOnSuccess( Notifier target, Notifier source, boolean sourceDominant,
1952                                                 Map<Object, Object> context )
1953     {
1954         if ( sourceDominant )
1955         {
1956             target.setSendOnSuccess( source.isSendOnSuccess() );
1957         }
1958     }
1959 
1960     protected void mergeNotifier_SendOnWarning( Notifier target, Notifier source, boolean sourceDominant,
1961                                                 Map<Object, Object> context )
1962     {
1963         if ( sourceDominant )
1964         {
1965             target.setSendOnWarning( source.isSendOnWarning() );
1966         }
1967     }
1968 
1969     protected void mergePrerequisites( Prerequisites target, Prerequisites source, boolean sourceDominant,
1970                                        Map<Object, Object> context )
1971     {
1972         mergePrerequisites_Maven( target, source, sourceDominant, context );
1973     }
1974 
1975     protected void mergePrerequisites_Maven( Prerequisites target, Prerequisites source, boolean sourceDominant,
1976                                              Map<Object, Object> context )
1977     {
1978         String src = source.getMaven();
1979         if ( src != null )
1980         {
1981             if ( sourceDominant || target.getMaven() == null )
1982             {
1983                 target.setMaven( src );
1984                 target.setLocation( "maven", source.getLocation( "maven" ) );
1985             }
1986         }
1987     }
1988 
1989     protected void mergeBuild( Build target, Build source, boolean sourceDominant, Map<Object, Object> context )
1990     {
1991         mergeBuildBase( target, source, sourceDominant, context );
1992         mergeBuild_SourceDirectory( target, source, sourceDominant, context );
1993         mergeBuild_ScriptSourceDirectory( target, source, sourceDominant, context );
1994         mergeBuild_TestSourceDirectory( target, source, sourceDominant, context );
1995         mergeBuild_OutputDirectory( target, source, sourceDominant, context );
1996         mergeBuild_TestOutputDirectory( target, source, sourceDominant, context );
1997         mergeBuild_Extensions( target, source, sourceDominant, context );
1998     }
1999 
2000     protected void mergeBuild_SourceDirectory( Build target, Build source, boolean sourceDominant,
2001                                                Map<Object, Object> context )
2002     {
2003         String src = source.getSourceDirectory();
2004         if ( src != null )
2005         {
2006             if ( sourceDominant || target.getSourceDirectory() == null )
2007             {
2008                 target.setSourceDirectory( src );
2009                 target.setLocation( "sourceDirectory", source.getLocation( "sourceDirectory" ) );
2010             }
2011         }
2012     }
2013 
2014     protected void mergeBuild_ScriptSourceDirectory( Build target, Build source, boolean sourceDominant,
2015                                                      Map<Object, Object> context )
2016     {
2017         String src = source.getScriptSourceDirectory();
2018         if ( src != null )
2019         {
2020             if ( sourceDominant || target.getScriptSourceDirectory() == null )
2021             {
2022                 target.setScriptSourceDirectory( src );
2023                 target.setLocation( "scriptSourceDirectory", source.getLocation( "scriptSourceDirectory" ) );
2024             }
2025         }
2026     }
2027 
2028     protected void mergeBuild_TestSourceDirectory( Build target, Build source, boolean sourceDominant,
2029                                                    Map<Object, Object> context )
2030     {
2031         String src = source.getTestSourceDirectory();
2032         if ( src != null )
2033         {
2034             if ( sourceDominant || target.getTestSourceDirectory() == null )
2035             {
2036                 target.setTestSourceDirectory( src );
2037                 target.setLocation( "testSourceDirectory", source.getLocation( "testSourceDirectory" ) );
2038             }
2039         }
2040     }
2041 
2042     protected void mergeBuild_OutputDirectory( Build target, Build source, boolean sourceDominant,
2043                                                Map<Object, Object> context )
2044     {
2045         String src = source.getOutputDirectory();
2046         if ( src != null )
2047         {
2048             if ( sourceDominant || target.getOutputDirectory() == null )
2049             {
2050                 target.setOutputDirectory( src );
2051                 target.setLocation( "outputDirectory", source.getLocation( "outputDirectory" ) );
2052             }
2053         }
2054     }
2055 
2056     protected void mergeBuild_TestOutputDirectory( Build target, Build source, boolean sourceDominant,
2057                                                    Map<Object, Object> context )
2058     {
2059         String src = source.getTestOutputDirectory();
2060         if ( src != null )
2061         {
2062             if ( sourceDominant || target.getTestOutputDirectory() == null )
2063             {
2064                 target.setTestOutputDirectory( src );
2065                 target.setLocation( "testOutputDirectory", source.getLocation( "testOutputDirectory" ) );
2066             }
2067         }
2068     }
2069 
2070     protected void mergeBuild_Extensions( Build target, Build source, boolean sourceDominant,
2071                                           Map<Object, Object> context )
2072     {
2073         target.setExtensions( merge( target.getExtensions(), source.getExtensions(),
2074                                      sourceDominant, new ExtensionKeyComputer() ) );
2075     }
2076 
2077     protected void mergeExtension( Extension target, Extension source, boolean sourceDominant,
2078                                    Map<Object, Object> context )
2079     {
2080         mergeExtension_GroupId( target, source, sourceDominant, context );
2081         mergeExtension_ArtifactId( target, source, sourceDominant, context );
2082         mergeExtension_Version( target, source, sourceDominant, context );
2083     }
2084 
2085     protected void mergeExtension_GroupId( Extension target, Extension source, boolean sourceDominant,
2086                                            Map<Object, Object> context )
2087     {
2088         String src = source.getGroupId();
2089         if ( src != null )
2090         {
2091             if ( sourceDominant || target.getGroupId() == null )
2092             {
2093                 target.setGroupId( src );
2094                 target.setLocation( "groupId", source.getLocation( "groupId" ) );
2095             }
2096         }
2097     }
2098 
2099     protected void mergeExtension_ArtifactId( Extension target, Extension source, boolean sourceDominant,
2100                                               Map<Object, Object> context )
2101     {
2102         String src = source.getArtifactId();
2103         if ( src != null )
2104         {
2105             if ( sourceDominant || target.getArtifactId() == null )
2106             {
2107                 target.setArtifactId( src );
2108                 target.setLocation( "artifactId", source.getLocation( "artifactId" ) );
2109             }
2110         }
2111     }
2112 
2113     protected void mergeExtension_Version( Extension target, Extension source, boolean sourceDominant,
2114                                            Map<Object, Object> context )
2115     {
2116         String src = source.getVersion();
2117         if ( src != null )
2118         {
2119             if ( sourceDominant || target.getVersion() == null )
2120             {
2121                 target.setVersion( src );
2122                 target.setLocation( "version", source.getLocation( "version" ) );
2123             }
2124         }
2125     }
2126 
2127     protected void mergeBuildBase( BuildBase target, BuildBase source, boolean sourceDominant,
2128                                    Map<Object, Object> context )
2129     {
2130         mergePluginConfiguration( target, source, sourceDominant, context );
2131         mergeBuildBase_DefaultGoal( target, source, sourceDominant, context );
2132         mergeBuildBase_FinalName( target, source, sourceDominant, context );
2133         mergeBuildBase_Directory( target, source, sourceDominant, context );
2134         mergeBuildBase_Resources( target, source, sourceDominant, context );
2135         mergeBuildBase_TestResources( target, source, sourceDominant, context );
2136         mergeBuildBase_Filters( target, source, sourceDominant, context );
2137     }
2138 
2139     protected void mergeBuildBase_DefaultGoal( BuildBase target, BuildBase source, boolean sourceDominant,
2140                                                Map<Object, Object> context )
2141     {
2142         String src = source.getDefaultGoal();
2143         if ( src != null )
2144         {
2145             if ( sourceDominant || target.getDefaultGoal() == null )
2146             {
2147                 target.setDefaultGoal( src );
2148                 target.setLocation( "defaultGoal", source.getLocation( "defaultGoal" ) );
2149             }
2150         }
2151     }
2152 
2153     protected void mergeBuildBase_Directory( BuildBase target, BuildBase source, boolean sourceDominant,
2154                                              Map<Object, Object> context )
2155     {
2156         String src = source.getDirectory();
2157         if ( src != null )
2158         {
2159             if ( sourceDominant || target.getDirectory() == null )
2160             {
2161                 target.setDirectory( src );
2162                 target.setLocation( "directory", source.getLocation( "directory" ) );
2163             }
2164         }
2165     }
2166 
2167     protected void mergeBuildBase_FinalName( BuildBase target, BuildBase source, boolean sourceDominant,
2168                                              Map<Object, Object> context )
2169     {
2170         String src = source.getFinalName();
2171         if ( src != null )
2172         {
2173             if ( sourceDominant || target.getFinalName() == null )
2174             {
2175                 target.setFinalName( src );
2176                 target.setLocation( "finalName", source.getLocation( "finalName" ) );
2177             }
2178         }
2179     }
2180 
2181     protected void mergeBuildBase_Filters( BuildBase target, BuildBase source, boolean sourceDominant,
2182                                            Map<Object, Object> context )
2183     {
2184         List<String> src = source.getFilters();
2185         if ( !src.isEmpty() )
2186         {
2187             List<String> tgt = target.getFilters();
2188             List<String> merged = new ArrayList<>( tgt.size() + src.size() );
2189             merged.addAll( tgt );
2190             merged.addAll( src );
2191             target.setFilters( merged );
2192         }
2193     }
2194 
2195     protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant,
2196                                              Map<Object, Object> context )
2197     {
2198         target.setResources( merge( target.getResources(), source.getResources(),
2199                                     sourceDominant, new ResourceKeyComputer() ) );
2200     }
2201 
2202     protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant,
2203                                                  Map<Object, Object> context )
2204     {
2205         target.setTestResources( merge( target.getTestResources(), source.getTestResources(),
2206                                         sourceDominant, new ResourceKeyComputer() ) );
2207     }
2208 
2209     protected void mergePluginConfiguration( PluginConfiguration target, PluginConfiguration source,
2210                                              boolean sourceDominant, Map<Object, Object> context )
2211     {
2212         mergePluginContainer( target, source, sourceDominant, context );
2213         mergePluginConfiguration_PluginManagement( target, source, sourceDominant, context );
2214     }
2215 
2216     protected void mergePluginConfiguration_PluginManagement( PluginConfiguration target, PluginConfiguration source,
2217                                                               boolean sourceDominant, Map<Object, Object> context )
2218     {
2219         PluginManagement src = source.getPluginManagement();
2220         if ( src != null )
2221         {
2222             PluginManagement tgt = target.getPluginManagement();
2223             if ( tgt == null )
2224             {
2225                 tgt = new PluginManagement();
2226                 target.setPluginManagement( tgt );
2227             }
2228             mergePluginManagement( tgt, src, sourceDominant, context );
2229         }
2230     }
2231 
2232     protected void mergePluginContainer( PluginContainer target, PluginContainer source,
2233                                          boolean sourceDominant, Map<Object, Object> context )
2234     {
2235         mergePluginContainer_Plugins( target, source, sourceDominant, context );
2236     }
2237 
2238     protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source,
2239                                                  boolean sourceDominant, Map<Object, Object> context )
2240     {
2241         target.setPlugins( merge( target.getPlugins(), source.getPlugins(),
2242                                   sourceDominant, new PluginKeyComputer() ) );
2243     }
2244 
2245     protected void mergePluginManagement( PluginManagement target, PluginManagement source, boolean sourceDominant,
2246                                           Map<Object, Object> context )
2247     {
2248         mergePluginContainer( target, source, sourceDominant, context );
2249     }
2250 
2251     protected void mergePlugin( Plugin target, Plugin source, boolean sourceDominant, Map<Object, Object> context )
2252     {
2253         mergeConfigurationContainer( target, source, sourceDominant, context );
2254         mergePlugin_GroupId( target, source, sourceDominant, context );
2255         mergePlugin_ArtifactId( target, source, sourceDominant, context );
2256         mergePlugin_Version( target, source, sourceDominant, context );
2257         mergePlugin_Extensions( target, source, sourceDominant, context );
2258         mergePlugin_Dependencies( target, source, sourceDominant, context );
2259         mergePlugin_Executions( target, source, sourceDominant, context );
2260     }
2261 
2262     protected void mergePlugin_GroupId( Plugin target, Plugin source, boolean sourceDominant,
2263                                         Map<Object, Object> context )
2264     {
2265         String src = source.getGroupId();
2266         if ( src != null )
2267         {
2268             if ( sourceDominant || target.getGroupId() == null )
2269             {
2270                 target.setGroupId( src );
2271                 target.setLocation( "groupId", source.getLocation( "groupId" ) );
2272             }
2273         }
2274     }
2275 
2276     protected void mergePlugin_ArtifactId( Plugin target, Plugin source, boolean sourceDominant,
2277                                            Map<Object, Object> context )
2278     {
2279         String src = source.getArtifactId();
2280         if ( src != null )
2281         {
2282             if ( sourceDominant || target.getArtifactId() == null )
2283             {
2284                 target.setArtifactId( src );
2285                 target.setLocation( "artifactId", source.getLocation( "artifactId" ) );
2286             }
2287         }
2288     }
2289 
2290     protected void mergePlugin_Version( Plugin target, Plugin source, boolean sourceDominant,
2291                                         Map<Object, Object> context )
2292     {
2293         String src = source.getVersion();
2294         if ( src != null )
2295         {
2296             if ( sourceDominant || target.getVersion() == null )
2297             {
2298                 target.setVersion( src );
2299                 target.setLocation( "version", source.getLocation( "version" ) );
2300             }
2301         }
2302     }
2303 
2304     protected void mergePlugin_Extensions( Plugin target, Plugin source, boolean sourceDominant,
2305                                            Map<Object, Object> context )
2306     {
2307         String src = source.getExtensions();
2308         if ( src != null )
2309         {
2310             if ( sourceDominant || target.getExtensions() == null )
2311             {
2312                 target.setExtensions( src );
2313                 target.setLocation( "extensions", source.getLocation( "extensions" ) );
2314             }
2315         }
2316     }
2317 
2318     protected void mergePlugin_Dependencies( Plugin target, Plugin source, boolean sourceDominant,
2319                                              Map<Object, Object> context )
2320     {
2321         target.setDependencies( merge( target.getDependencies(), source.getDependencies(),
2322                                        sourceDominant, new DependencyKeyComputer() ) );
2323     }
2324 
2325     protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant,
2326                                            Map<Object, Object> context )
2327     {
2328         target.setExecutions( merge( target.getExecutions(), source.getExecutions(),
2329                                      sourceDominant, new ExecutionKeyComputer() ) );
2330     }
2331 
2332     protected void mergeConfigurationContainer( ConfigurationContainer target, ConfigurationContainer source,
2333                                                 boolean sourceDominant, Map<Object, Object> context )
2334     {
2335         mergeConfigurationContainer_Inherited( target, source, sourceDominant, context );
2336         mergeConfigurationContainer_Configuration( target, source, sourceDominant, context );
2337     }
2338 
2339     protected void mergeConfigurationContainer_Inherited( ConfigurationContainer target, ConfigurationContainer source,
2340                                                           boolean sourceDominant, Map<Object, Object> context )
2341     {
2342         String src = source.getInherited();
2343         if ( src != null )
2344         {
2345             if ( sourceDominant || target.getInherited() == null )
2346             {
2347                 target.setInherited( src );
2348                 target.setLocation( "inherited", source.getLocation( "inherited" ) );
2349             }
2350         }
2351     }
2352 
2353     protected void mergeConfigurationContainer_Configuration( ConfigurationContainer target,
2354                                                               ConfigurationContainer source, boolean sourceDominant,
2355                                                               Map<Object, Object> context )
2356     {
2357         Xpp3Dom src = (Xpp3Dom) source.getConfiguration();
2358         if ( src != null )
2359         {
2360             Xpp3Dom tgt = (Xpp3Dom) target.getConfiguration();
2361             if ( sourceDominant || tgt == null )
2362             {
2363                 tgt = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( src ), tgt );
2364             }
2365             else
2366             {
2367                 tgt = Xpp3Dom.mergeXpp3Dom( tgt, src );
2368             }
2369             target.setConfiguration( tgt );
2370         }
2371     }
2372 
2373     protected void mergePluginExecution( PluginExecution target, PluginExecution source, boolean sourceDominant,
2374                                          Map<Object, Object> context )
2375     {
2376         mergeConfigurationContainer( target, source, sourceDominant, context );
2377         mergePluginExecution_Id( target, source, sourceDominant, context );
2378         mergePluginExecution_Phase( target, source, sourceDominant, context );
2379         mergePluginExecution_Goals( target, source, sourceDominant, context );
2380     }
2381 
2382     protected void mergePluginExecution_Id( PluginExecution target, PluginExecution source, boolean sourceDominant,
2383                                             Map<Object, Object> context )
2384     {
2385         String src = source.getId();
2386         if ( src != null )
2387         {
2388             if ( sourceDominant || target.getId() == null )
2389             {
2390                 target.setId( src );
2391                 target.setLocation( "id", source.getLocation( "id" ) );
2392             }
2393         }
2394     }
2395 
2396     protected void mergePluginExecution_Phase( PluginExecution target, PluginExecution source, boolean sourceDominant,
2397                                                Map<Object, Object> context )
2398     {
2399         String src = source.getPhase();
2400         if ( src != null )
2401         {
2402             if ( sourceDominant || target.getPhase() == null )
2403             {
2404                 target.setPhase( src );
2405                 target.setLocation( "phase", source.getLocation( "phase" ) );
2406             }
2407         }
2408     }
2409 
2410     protected void mergePluginExecution_Goals( PluginExecution target, PluginExecution source, boolean sourceDominant,
2411                                                Map<Object, Object> context )
2412     {
2413         List<String> src = source.getGoals();
2414         if ( !src.isEmpty() )
2415         {
2416             List<String> tgt = target.getGoals();
2417             List<String> merged = new ArrayList<>( tgt.size() + src.size() );
2418             merged.addAll( tgt );
2419             merged.addAll( src );
2420             target.setGoals( merged );
2421         }
2422     }
2423 
2424     protected void mergeResource( Resource target, Resource source, boolean sourceDominant,
2425                                   Map<Object, Object> context )
2426     {
2427         mergeFileSet( target, source, sourceDominant, context );
2428         mergeResource_TargetPath( target, source, sourceDominant, context );
2429         mergeResource_Filtering( target, source, sourceDominant, context );
2430         mergeResource_MergeId( target, source, sourceDominant, context );
2431     }
2432 
2433     protected void mergeResource_TargetPath( Resource target, Resource source, boolean sourceDominant,
2434                                              Map<Object, Object> context )
2435     {
2436         String src = source.getTargetPath();
2437         if ( src != null )
2438         {
2439             if ( sourceDominant || target.getTargetPath() == null )
2440             {
2441                 target.setTargetPath( src );
2442                 target.setLocation( "targetPath", source.getLocation( "targetPath" ) );
2443             }
2444         }
2445     }
2446 
2447     protected void mergeResource_Filtering( Resource target, Resource source, boolean sourceDominant,
2448                                             Map<Object, Object> context )
2449     {
2450         String src = source.getFiltering();
2451         if ( src != null )
2452         {
2453             if ( sourceDominant || target.getFiltering() == null )
2454             {
2455                 target.setFiltering( src );
2456                 target.setLocation( "filtering", source.getLocation( "filtering" ) );
2457             }
2458         }
2459     }
2460 
2461     protected void mergeResource_MergeId( Resource target, Resource source, boolean sourceDominant,
2462                                           Map<Object, Object> context )
2463     {
2464         String src = source.getMergeId();
2465         if ( src != null )
2466         {
2467             if ( sourceDominant || target.getMergeId() == null )
2468             {
2469                 target.setMergeId( src );
2470             }
2471         }
2472     }
2473 
2474     protected void mergeFileSet( FileSet target, FileSet source, boolean sourceDominant, Map<Object, Object> context )
2475     {
2476         mergePatternSet( target, source, sourceDominant, context );
2477         mergeFileSet_Directory( target, source, sourceDominant, context );
2478     }
2479 
2480     protected void mergeFileSet_Directory( FileSet target, FileSet source, boolean sourceDominant,
2481                                            Map<Object, Object> context )
2482     {
2483         String src = source.getDirectory();
2484         if ( src != null )
2485         {
2486             if ( sourceDominant || target.getDirectory() == null )
2487             {
2488                 target.setDirectory( src );
2489                 target.setLocation( "directory", source.getLocation( "directory" ) );
2490             }
2491         }
2492     }
2493 
2494     protected void mergePatternSet( PatternSet target, PatternSet source, boolean sourceDominant,
2495                                     Map<Object, Object> context )
2496     {
2497         mergePatternSet_Includes( target, source, sourceDominant, context );
2498         mergePatternSet_Excludes( target, source, sourceDominant, context );
2499     }
2500 
2501     protected void mergePatternSet_Includes( PatternSet target, PatternSet source, boolean sourceDominant,
2502                                              Map<Object, Object> context )
2503     {
2504         List<String> src = source.getIncludes();
2505         if ( !src.isEmpty() )
2506         {
2507             List<String> tgt = target.getIncludes();
2508             List<String> merged = new ArrayList<>( tgt.size() + src.size() );
2509             merged.addAll( tgt );
2510             merged.addAll( src );
2511             target.setIncludes( merged );
2512         }
2513     }
2514 
2515     protected void mergePatternSet_Excludes( PatternSet target, PatternSet source, boolean sourceDominant,
2516                                              Map<Object, Object> context )
2517     {
2518         List<String> src = source.getExcludes();
2519         if ( !src.isEmpty() )
2520         {
2521             List<String> tgt = target.getExcludes();
2522             List<String> merged = new ArrayList<>( tgt.size() + src.size() );
2523             merged.addAll( tgt );
2524             merged.addAll( src );
2525             target.setExcludes( merged );
2526         }
2527     }
2528 
2529     protected void mergeProfile( Profile target, Profile source, boolean sourceDominant, Map<Object, Object> context )
2530     {
2531         mergeModelBase( target, source, sourceDominant, context );
2532         // TODO
2533     }
2534 
2535     protected void mergeActivation( Activation target, Activation source, boolean sourceDominant,
2536                                     Map<Object, Object> context )
2537     {
2538         // TODO
2539     }
2540 
2541     protected Object getDependencyKey( Dependency dependency )
2542     {
2543         return dependency;
2544     }
2545 
2546     protected Object getPluginKey( Plugin plugin )
2547     {
2548         return plugin;
2549     }
2550 
2551     protected Object getPluginExecutionKey( PluginExecution pluginExecution )
2552     {
2553         return pluginExecution;
2554     }
2555 
2556     protected Object getReportPluginKey( ReportPlugin reportPlugin )
2557     {
2558         return reportPlugin;
2559     }
2560 
2561     protected Object getReportSetKey( ReportSet reportSet )
2562     {
2563         return reportSet;
2564     }
2565 
2566     protected Object getLicenseKey( License license )
2567     {
2568         return license;
2569     }
2570 
2571     protected Object getMailingListKey( MailingList mailingList )
2572     {
2573         return mailingList;
2574     }
2575 
2576     protected Object getDeveloperKey( Developer developer )
2577     {
2578         return developer;
2579     }
2580 
2581     protected Object getContributorKey( Contributor contributor )
2582     {
2583         return contributor;
2584     }
2585 
2586     protected Object getProfileKey( Profile profile )
2587     {
2588         return profile;
2589     }
2590 
2591     protected Object getRepositoryKey( Repository repository )
2592     {
2593         return getRepositoryBaseKey( repository );
2594     }
2595 
2596     protected Object getRepositoryBaseKey( RepositoryBase repositoryBase )
2597     {
2598         return repositoryBase;
2599     }
2600 
2601     protected Object getNotifierKey( Notifier notifier )
2602     {
2603         return notifier;
2604     }
2605 
2606     protected Object getResourceKey( Resource resource )
2607     {
2608         return resource;
2609     }
2610 
2611     protected Object getExtensionKey( Extension extension )
2612     {
2613         return extension;
2614     }
2615 
2616     protected Object getExclusionKey( Exclusion exclusion )
2617     {
2618         return exclusion;
2619     }
2620 
2621     /**
2622      * Use to compute keys for data structures
2623      * @param <T>
2624      */
2625     private interface KeyComputer<T>
2626     {
2627         Object key( T t );
2628     }
2629 
2630     /**
2631      * Remapping function
2632      * @param <T>
2633      */
2634     private interface Remapping<T>
2635     {
2636         T merge( T u, T v );
2637     }
2638 
2639     /**
2640      * KeyComputer for Dependency
2641      */
2642     private final class DependencyKeyComputer implements KeyComputer<Dependency>
2643     {
2644         @Override
2645         public Object key( Dependency dependency )
2646         {
2647             return getDependencyKey( dependency );
2648         }
2649     }
2650 
2651     /**
2652      * KeyComputer for License
2653      */
2654     private class LicenseKeyComputer implements KeyComputer<License>
2655     {
2656         @Override
2657         public Object key( License license )
2658         {
2659             return getLicenseKey( license );
2660         }
2661     }
2662 
2663     /**
2664      * KeyComputer for MailingList
2665      */
2666     private class MailingListKeyComputer implements KeyComputer<MailingList>
2667     {
2668         @Override
2669         public Object key( MailingList mailingList )
2670         {
2671             return getMailingListKey( mailingList );
2672         }
2673     }
2674 
2675     /**
2676      * KeyComputer for Developer
2677      */
2678     private class DeveloperKeyComputer implements KeyComputer<Developer>
2679     {
2680         @Override
2681         public Object key( Developer developer )
2682         {
2683             return getDeveloperKey( developer );
2684         }
2685     }
2686 
2687     /**
2688      * KeyComputer for Contributor
2689      */
2690     private class ContributorKeyComputer implements KeyComputer<Contributor>
2691     {
2692         @Override
2693         public Object key( Contributor contributor )
2694         {
2695             return getContributorKey( contributor );
2696         }
2697     }
2698 
2699     /**
2700      * KeyComputer for Profile
2701      */
2702     private class ProfileKeyComputer implements KeyComputer<Profile>
2703     {
2704         @Override
2705         public Object key( Profile profile )
2706         {
2707             return getProfileKey( profile );
2708         }
2709     }
2710 
2711     /**
2712      * KeyComputer for Repository
2713      */
2714     private class RepositoryKeyComputer implements KeyComputer<Repository>
2715     {
2716         @Override
2717         public Object key( Repository repository )
2718         {
2719             return getRepositoryKey( repository );
2720         }
2721     }
2722 
2723     /**
2724      * KeyComputer for ReportPlugin
2725      */
2726     private class ReportPluginKeyComputer implements KeyComputer<ReportPlugin>
2727     {
2728         @Override
2729         public Object key( ReportPlugin plugin )
2730         {
2731             return getReportPluginKey( plugin );
2732         }
2733     }
2734 
2735     /**
2736      * KeyComputer for Plugin
2737      */
2738     private class PluginKeyComputer implements KeyComputer<Plugin>
2739     {
2740         @Override
2741         public Object key( Plugin plugin )
2742         {
2743             return getPluginKey( plugin );
2744         }
2745     }
2746 
2747     /**
2748      * KeyComputer for ReportSet
2749      */
2750     private class ReportSetKeyComputer implements KeyComputer<ReportSet>
2751     {
2752         @Override
2753         public Object key( ReportSet reportSet )
2754         {
2755             return getReportSetKey( reportSet );
2756         }
2757     }
2758 
2759     /**
2760      * KeyComputer for Notifier
2761      */
2762     private class NotifierKeyComputer implements KeyComputer<Notifier>
2763     {
2764         @Override
2765         public Object key( Notifier notifier )
2766         {
2767             return getNotifierKey( notifier );
2768         }
2769     }
2770 
2771     /**
2772      * KeyComputer for Extension
2773      */
2774     private class ExtensionKeyComputer implements KeyComputer<Extension>
2775     {
2776         @Override
2777         public Object key( Extension extension )
2778         {
2779             return getExtensionKey( extension );
2780         }
2781     }
2782 
2783     /**
2784      * KeyComputer for Resource
2785      */
2786     private class ResourceKeyComputer implements KeyComputer<Resource>
2787     {
2788         @Override
2789         public Object key( Resource resource )
2790         {
2791             return getResourceKey( resource );
2792         }
2793     }
2794 
2795     /**
2796      * KeyComputer for PluginExecution
2797      */
2798     private class ExecutionKeyComputer implements KeyComputer<PluginExecution>
2799     {
2800         @Override
2801         public Object key( PluginExecution pluginExecution )
2802         {
2803             return getPluginExecutionKey( pluginExecution );
2804         }
2805     }
2806 
2807     /**
2808      * KeyComputer for Exclusion
2809      */
2810     private class ExclusionKeyComputer implements KeyComputer<Exclusion>
2811     {
2812         @Override
2813         public Object key( Exclusion exclusion )
2814         {
2815             return getExclusionKey( exclusion );
2816         }
2817     }
2818 
2819     /**
2820      * Return the second value if <code>sourceDominant</code> is true, the first one otherwise.
2821      * @param <T>
2822      */
2823     private static class SourceDominant<T> implements Remapping<T>
2824     {
2825         private final boolean sourceDominant;
2826 
2827         SourceDominant( boolean sourceDominant )
2828         {
2829             this.sourceDominant = sourceDominant;
2830         }
2831 
2832         @Override
2833         public T merge( T u, T v )
2834         {
2835             return sourceDominant ? v : u;
2836         }
2837     }
2838 
2839     /**
2840      * Merge two lists
2841      */
2842     private static <T> List<T> merge( List<T> tgt, List<T> src, boolean sourceDominant, KeyComputer<T> computer )
2843     {
2844         return merge( tgt, src, computer, new SourceDominant<T>( sourceDominant ) );
2845     }
2846 
2847     private static <T> List<T> merge( List<T> tgt, List<T> src, KeyComputer<T> computer, Remapping<T> remapping )
2848     {
2849         if ( src.isEmpty() )
2850         {
2851             return tgt;
2852         }
2853 
2854         MergingList<T> list;
2855         if ( tgt instanceof MergingList )
2856         {
2857             list = (MergingList<T>) tgt;
2858         }
2859         else
2860         {
2861             list = new MergingList<>( computer, src.size() + tgt.size() );
2862             list.mergeAll( tgt, new SourceDominant<T>( true ) );
2863         }
2864 
2865         list.mergeAll( src, remapping );
2866         return list;
2867     }
2868 
2869     /**
2870      * Merging list
2871      * @param <V>
2872      */
2873     private static class MergingList<V> extends AbstractList<V>
2874     {
2875         private final KeyComputer<V> keyComputer;
2876         private Map<Object, V> map;
2877         private List<V> list;
2878 
2879         MergingList( KeyComputer<V> keyComputer, int initialCapacity )
2880         {
2881             this.map = new LinkedHashMap<>( initialCapacity );
2882             this.keyComputer = keyComputer;
2883         }
2884 
2885         @Override
2886         public Iterator<V> iterator()
2887         {
2888             if ( map != null )
2889             {
2890                 return map.values().iterator();
2891             }
2892             else
2893             {
2894                 return list.iterator();
2895             }
2896         }
2897 
2898         void mergeAll( Collection<V> vs, Remapping<V> remapping )
2899         {
2900             if ( map == null )
2901             {
2902                 map = new LinkedHashMap<>( list.size() + vs.size() );
2903                 for ( V v : list )
2904                 {
2905                     map.put( keyComputer.key( v ), v );
2906                 }
2907                 list = null;
2908             }
2909             if ( vs instanceof MergingList && ( (MergingList) vs ).map != null )
2910             {
2911                 for ( Map.Entry<Object, V> e : ( (MergingList<V>) vs ).map.entrySet() )
2912                 {
2913                     Object key = e.getKey();
2914                     V oldValue = map.get( key );
2915                     // JDK8: this should be a call to map.merge( key, v, remapping )
2916                     V newValue = ( oldValue == null ) ? e.getValue() : remapping.merge( oldValue, e.getValue() );
2917                     if ( newValue == null )
2918                     {
2919                         remove( key );
2920                     }
2921                     else if ( newValue != oldValue )
2922                     {
2923                         map.put( key, newValue );
2924                     }
2925                 }
2926             }
2927             else
2928             {
2929                 for ( V v : vs )
2930                 {
2931                     Object key = keyComputer.key( v );
2932                     // JDK8: this should be a call to map.merge( key, v, remapping )
2933                     V oldValue = map.get( key );
2934                     V newValue = ( oldValue == null ) ? v : remapping.merge( oldValue, v );
2935                     if ( newValue == null )
2936                     {
2937                         remove( key );
2938                     }
2939                     else
2940                     {
2941                         map.put( key, newValue );
2942                     }
2943                 }
2944             }
2945         }
2946 
2947         @Override
2948         public boolean contains( Object o )
2949         {
2950             if ( map != null )
2951             {
2952                 return map.containsValue( o );
2953             }
2954             else
2955             {
2956                 return list.contains( o );
2957             }
2958         }
2959 
2960         private List<V> asList()
2961         {
2962             if ( list == null )
2963             {
2964                 list = new ArrayList<>( map.values() );
2965                 map = null;
2966             }
2967             return list;
2968         }
2969 
2970         @Override
2971         public void add( int index, V element )
2972         {
2973             asList().add( index, element );
2974         }
2975 
2976         @Override
2977         public V remove( int index )
2978         {
2979             return asList().remove( index );
2980         }
2981 
2982         @Override
2983         public V get( int index )
2984         {
2985             return asList().get( index );
2986         }
2987 
2988         @Override
2989         public int size()
2990         {
2991             if ( map != null )
2992             {
2993                 return map.size();
2994             }
2995             else
2996             {
2997                 return list.size();
2998             }
2999         }
3000     }
3001 }