[MNG-7598] Fix compatibility issues with toolchains and settings (#971)

* Split the header on two lines
* Properly delegates equals/hashCode to the v4 models
* Introduce object tracking in settings / toolchains
* Get back to a single template for v3 models
* Switch settings / toolchains mergers to deep merge
* Fix binary compatibility with 3.x
This commit is contained in:
Guillaume Nodet 2023-01-27 15:56:16 +01:00 committed by GitHub
parent 74cf7eae8f
commit f153ac134c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 821 additions and 712 deletions

View File

@ -2527,6 +2527,13 @@
return groupId + ":" + artifactId;
}
]]>
</code>
</codeSegment>
<codeSegment>
<version>4.2.0+</version>
<code>
<![CDATA[
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@ -3240,7 +3247,7 @@
</fields>
<codeSegments>
<codeSegment>
<version>4.0.0+</version>
<version>4.2.0+</version>
<code>
<![CDATA[
/**

View File

@ -825,6 +825,8 @@
<field>
<name>id</name>
<version>1.0.0+</version>
<required>true</required>
<identifier>true</identifier>
<description>
<![CDATA[
A unique identifier for a repository.
@ -865,7 +867,7 @@
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0+</version>
<version>1.0.0/1.1.0</version>
<code>
<![CDATA[
/**
@ -920,7 +922,7 @@
<!-- prevent Modello generation of an incorrect equals method. Could be avoided by using <identity/> tags to mark ID as the only identity field -->
<codeSegments>
<codeSegment>
<version>1.0.0+</version>
<version>1.0.0/1.1.0</version>
<code>
<![CDATA[
/**

View File

@ -50,7 +50,7 @@ under the License.
<goal>velocity</goal>
</goals>
<configuration>
<version>1.1.0</version>
<version>1.2.0</version>
<velocityBasedir>${project.basedir}/../../src/mdo</velocityBasedir>
<models>
<model>src/main/mdo/toolchains.mdo</model>

View File

@ -176,7 +176,7 @@
</fields>
<codeSegments>
<codeSegment>
<version>1.1.0+</version>
<version>1.2.0+</version>
<comment>Generated hashCode() and equals() based on identifier also calls its super, which breaks comparison</comment>
<code>
<![CDATA[

View File

@ -279,6 +279,30 @@ under the License.
<artifactId>japicmp-maven-plugin</artifactId>
<configuration>
<parameter>
<includes>
<include>org.apache.maven.artifact</include>
<include>org.apache.maven.classrealm</include>
<include>org.apache.maven.cli</include>
<include>org.apache.maven.configuration</include>
<include>org.apache.maven.exception</include>
<include>org.apache.maven.execution</include>
<include>org.apache.maven.execution.scope</include>
<include>org.apache.maven.feature</include>
<include>org.apache.maven.graph</include>
<include>org.apache.maven.lifecycle</include>
<include>org.apache.maven.model</include>
<include>org.apache.maven.monitor</include>
<include>org.apache.maven.plugin</include>
<include>org.apache.maven.profiles</include>
<include>org.apache.maven.project</include>
<include>org.apache.maven.reporting</include>
<include>org.apache.maven.repository</include>
<include>org.apache.maven.rtinfo</include>
<include>org.apache.maven.rtinfo.internal</include>
<include>org.apache.maven.settings</include>
<include>org.apache.maven.toolchain</include>
<include>org.apache.maven.usability</include>
</includes>
<!-- allowed non-binary backwards compatible changes -->
<excludes>
<!-- START default constructor on Plexus/JSR 330 components -->

View File

@ -108,6 +108,68 @@ under the License.
<groupId>org.eclipse.sisu</groupId>
<artifactId>sisu-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
<configuration>
<oldVersion>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${maven.baseline}</version>
</dependency>
</oldVersion>
<parameter>
<excludes>
<exclude>org.apache.maven.model.building.DefaultModelBuilder#DefaultModelBuilder():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.building.DefaultModelProcessor#setModelLocator(org.apache.maven.model.locator.ModelLocator):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.building.DefaultModelProcessor#setModelReader(org.apache.maven.model.io.ModelReader):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.building.DefaultModelProcessor#DefaultModelProcessor():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.building.ModelCache#get(org.apache.maven.building.Source,java.lang.String):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#get(org.apache.maven.building.Source,org.apache.maven.model.building.ModelCacheTag):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#get(java.lang.String,java.lang.String,java.lang.String,org.apache.maven.model.building.ModelCacheTag):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#put(org.apache.maven.building.Source,java.lang.String,java.lang.Object):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#put(org.apache.maven.building.Source,org.apache.maven.model.building.ModelCacheTag,java.lang.Object):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#put(java.lang.String,java.lang.String,java.lang.String,org.apache.maven.model.building.ModelCacheTag,java.lang.Object):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.composition.DependencyManagementImporter#importManagement(org.apache.maven.model.Model,java.util.List,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.composition.DefaultDependencyManagementImporter#importManagement(org.apache.maven.model.Model,java.util.List,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.inheritance.DefaultInheritanceAssembler</exclude>
<exclude>org.apache.maven.model.inheritance.InheritanceAssembler#assembleModelInheritance(org.apache.maven.model.Model,org.apache.maven.model.Model,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.interpolation.AbstractStringBasedModelInterpolator</exclude>
<exclude>org.apache.maven.model.interpolation.StringSearchModelInterpolator</exclude>
<exclude>org.apache.maven.model.interpolation.StringVisitorModelInterpolator</exclude>
<exclude>org.apache.maven.model.io.DefaultModelReader#DefaultModelReader():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.management.DefaultDependencyManagementInjector$ManagementModelMerger</exclude>
<exclude>org.apache.maven.model.management.DefaultPluginManagementInjector$ManagementModelMerger</exclude>
<exclude>org.apache.maven.model.merge.MavenModelMerger</exclude>
<exclude>org.apache.maven.model.normalization.DefaultModelNormalizer$DuplicateMerger#mergePlugin(org.apache.maven.model.Plugin,org.apache.maven.model.Plugin):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.normalization.DefaultModelNormalizer$DuplicateMerger:METHOD_REMOVED_IN_SUPERCLASS</exclude>
<exclude>org.apache.maven.model.path.DefaultModelPathTranslator#setPathTranslator(org.apache.maven.model.path.PathTranslator):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.path.DefaultModelPathTranslator#DefaultModelPathTranslator():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.path.DefaultModelUrlNormalizer#setUrlNormalizer(org.apache.maven.model.path.UrlNormalizer):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.path.DefaultModelUrlNormalizer#DefaultModelUrlNormalizer():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.path.ProfileActivationFilePathInterpolator#setPathTranslator(org.apache.maven.model.path.PathTranslator):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.path.ProfileActivationFilePathInterpolator#ProfileActivationFilePathInterpolator():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.profile.activation.FileProfileActivator#setProfileActivationFilePathInterpolator(org.apache.maven.model.path.ProfileActivationFilePathInterpolator):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.profile.activation.FileProfileActivator#FileProfileActivator():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.profile.DefaultProfileInjector</exclude>
<exclude>org.apache.maven.model.resolution.InvalidRepositoryException#getRepository():METHOD_RETURN_TYPE_CHANGED</exclude>
<exclude>org.apache.maven.model.resolution.InvalidRepositoryException#InvalidRepositoryException(java.lang.String,org.apache.maven.model.Repository,java.lang.Throwable):CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.resolution.InvalidRepositoryException#InvalidRepositoryException(java.lang.String,org.apache.maven.model.Repository):CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.resolution.ModelResolver#addRepository(org.apache.maven.api.model.Repository):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.resolution.ModelResolver#addRepository(org.apache.maven.api.model.Repository,boolean):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.resolution.ModelResolver#resolveModel(org.apache.maven.api.model.Parent,java.util.concurrent.atomic.AtomicReference):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.resolution.ModelResolver#resolveModel(org.apache.maven.api.model.Dependency,java.util.concurrent.atomic.AtomicReference):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.superpom.DefaultSuperPomProvider#getSuperModel(java.lang.String):METHOD_RETURN_TYPE_CHANGED</exclude>
<exclude>org.apache.maven.model.superpom.DefaultSuperPomProvider#setModelProcessor(org.apache.maven.model.building.ModelProcessor):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.superpom.DefaultSuperPomProvider#DefaultSuperPomProvider():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.superpom.SuperPomProvider#getSuperModel(java.lang.String):METHOD_RETURN_TYPE_CHANGED</exclude>
<exclude>org.apache.maven.model.validation.DefaultModelValidator#validateDependencyVersion(org.apache.maven.model.building.ModelProblemCollector,org.apache.maven.model.Dependency,java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.validation.ModelValidator#validateFileModel(org.apache.maven.model.Model,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_NEW_DEFAULT</exclude>
</excludes>
</parameter>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -20,7 +20,7 @@ package org.apache.maven.model.interpolation;
import java.io.File;
import org.apache.maven.api.model.Model;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelProblemCollector;
@ -46,8 +46,8 @@ public interface ModelInterpolator {
*/
Model interpolateModel(Model model, File projectDir, ModelBuildingRequest request, ModelProblemCollector problems);
org.apache.maven.model.Model interpolateModel(
org.apache.maven.model.Model model,
org.apache.maven.api.model.Model interpolateModel(
org.apache.maven.api.model.Model model,
File projectDir,
ModelBuildingRequest request,
ModelProblemCollector problems);

View File

@ -23,6 +23,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.apache.maven.api.model.BuildBase;
@ -66,6 +67,39 @@ public class MavenModelMerger extends MavenMerger {
*/
public static final String ARTIFACT_ID = "artifact-id";
public MavenModelMerger() {
super(false);
}
/**
* Merges the specified source object into the given target object.
*
* @param target The target object whose existing contents should be merged with the source, must not be
* <code>null</code>.
* @param source The (read-only) source object that should be merged into the target object, may be
* <code>null</code>.
* @param sourceDominant A flag indicating whether either the target object or the source object provides the
* dominant data.
* @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific
* information along, may be <code>null</code>.
*/
public void merge(
org.apache.maven.model.Model target,
org.apache.maven.model.Model source,
boolean sourceDominant,
Map<?, ?> hints) {
Objects.requireNonNull(target, "target cannot be null");
if (source == null) {
return;
}
target.update(merge(target.getDelegate(), source.getDelegate(), sourceDominant, hints));
}
@Override
public Model merge(Model target, Model source, boolean sourceDominant, Map<?, ?> hints) {
return super.merge(target, source, sourceDominant, hints);
}
@Override
protected Model mergeModel(Model target, Model source, boolean sourceDominant, Map<Object, Object> context) {
context.put(ARTIFACT_ID, target.getArtifactId());

View File

@ -48,6 +48,18 @@ public class DefaultModelNormalizer implements ModelNormalizer {
private DuplicateMerger merger = new DuplicateMerger();
@Override
public void mergeDuplicates(
org.apache.maven.model.Model model, ModelBuildingRequest request, ModelProblemCollector problems) {
model.update(mergeDuplicates(model.getDelegate(), request, problems));
}
@Override
public void injectDefaultValues(
org.apache.maven.model.Model model, ModelBuildingRequest request, ModelProblemCollector problems) {
model.update(injectDefaultValues(model.getDelegate(), request, problems));
}
@Override
public Model mergeDuplicates(Model model, ModelBuildingRequest request, ModelProblemCollector problems) {
Model.Builder builder = Model.newBuilder(model);
@ -127,9 +139,7 @@ public class DefaultModelNormalizer implements ModelNormalizer {
private Dependency injectDependency(Dependency d) {
// we cannot set this directly in the MDO due to the interactions with dependency management
return StringUtils.isEmpty(d.getScope())
? Dependency.newBuilder(d).scope("compile").build()
: d;
return StringUtils.isEmpty(d.getScope()) ? d.withScope("compile") : d;
}
/**

View File

@ -18,7 +18,7 @@
*/
package org.apache.maven.model.normalization;
import org.apache.maven.api.model.Model;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelProblemCollector;
@ -37,7 +37,7 @@ public interface ModelNormalizer {
* @param request The model building request that holds further settings, must not be {@code null}.
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
*/
Model mergeDuplicates(Model model, ModelBuildingRequest request, ModelProblemCollector problems);
void mergeDuplicates(Model model, ModelBuildingRequest request, ModelProblemCollector problems);
/**
* Sets default values in the specified model that for technical reasons cannot be set directly in the Modello
@ -47,5 +47,11 @@ public interface ModelNormalizer {
* @param request The model building request that holds further settings, must not be {@code null}.
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
*/
Model injectDefaultValues(Model model, ModelBuildingRequest request, ModelProblemCollector problems);
void injectDefaultValues(Model model, ModelBuildingRequest request, ModelProblemCollector problems);
org.apache.maven.api.model.Model mergeDuplicates(
org.apache.maven.api.model.Model model, ModelBuildingRequest request, ModelProblemCollector problems);
org.apache.maven.api.model.Model injectDefaultValues(
org.apache.maven.api.model.Model model, ModelBuildingRequest request, ModelProblemCollector problems);
}

View File

@ -81,7 +81,7 @@ under the License.
<configuration>
<version>4.1.0</version>
<templates>
<template>model-v3-modified.vm</template>
<template>model-v3.vm</template>
</templates>
</configuration>
</execution>
@ -114,6 +114,40 @@ under the License.
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
<configuration>
<parameter>
<excludes>
<exclude>org.apache.maven.model.*#setOtherLocation(java.lang.Object,org.apache.maven.model.InputLocation):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.ConfigurationContainer#isInheritanceApplied():METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.ConfigurationContainer#setInherited(boolean):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.ConfigurationContainer#unsetInheritanceApplied():METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Contributor#addProperty(java.lang.String,java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Dependency#clearManagementKey():METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.ModelBase#addProperty(java.lang.String,java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.ModelBase#getReports():METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.ModelBase#setReports(java.lang.Object):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Notifier#addConfiguration(java.lang.String,java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Plugin#getGoals():METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Plugin#setGoals(java.lang.Object):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Reporting#flushReportPluginMap():METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Reporting#getReportPluginsAsMap():METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Resource#initMergeId():METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Scm#setChildScmConnectionInheritAppendPath(boolean):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Scm#setChildScmDeveloperConnectionInheritAppendPath(boolean):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Scm#setChildScmUrlInheritAppendPath(boolean):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.Site#setChildSiteUrlInheritAppendPath(boolean):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.io.xpp3.MavenXpp3Reader#contentTransformer</exclude>
<exclude>org.apache.maven.model.io.xpp3.MavenXpp3ReaderEx#contentTransformer</exclude>
<exclude>org.apache.maven.model.io.xpp3.MavenXpp3WriterEx#toString(org.apache.maven.model.InputLocation):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.io.xpp3.MavenXpp3WriterEx#writeXpp3DomToSerializer(org.codehaus.plexus.util.xml.Xpp3Dom,org.codehaus.plexus.util.xml.pull.XmlSerializer):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.merge.ModelMerger</exclude>
</excludes>
</parameter>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -104,6 +104,37 @@ under the License.
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
<configuration>
<parameter>
<excludes>
<exclude>org.apache.maven.monitor.logging.DefaultLog</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#addGoal(java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#getConfiguration():METHOD_RETURN_TYPE_CHANGED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#removeGoal(java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#setConfiguration(java.lang.Object):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#setGoals(java.util.List):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Execution#Execution():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.io.xpp3.LifecycleMappingsXpp3Reader#contentTransformer</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Lifecycle#addPhase(org.apache.maven.plugin.lifecycle.Phase):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Lifecycle#removePhase(org.apache.maven.plugin.lifecycle.Phase):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Lifecycle#setId(java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Lifecycle#setPhases(java.util.List):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Lifecycle#Lifecycle():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#addLifecycle(org.apache.maven.plugin.lifecycle.Lifecycle):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#removeLifecycle(org.apache.maven.plugin.lifecycle.Lifecycle):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#setLifecycles(java.util.List):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#setModelEncoding(java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#LifecycleConfiguration():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#addExecution(org.apache.maven.plugin.lifecycle.Execution):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#getConfiguration():METHOD_RETURN_TYPE_CHANGED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#removeExecution(org.apache.maven.plugin.lifecycle.Execution):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#setConfiguration(java.lang.Object):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#setExecutions(java.util.List):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#setId(java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.plugin.lifecycle.Phase#Phase():CONSTRUCTOR_REMOVED</exclude>
</excludes>
</parameter>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -75,6 +75,11 @@ under the License.
<groupId>org.eclipse.sisu</groupId>
<artifactId>sisu-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
<configuration />
</plugin>
</plugins>
</build>

View File

@ -30,9 +30,9 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.building.FileSource;
import org.apache.maven.building.Source;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.TrackableBase;
import org.apache.maven.settings.io.SettingsParseException;
import org.apache.maven.settings.io.SettingsReader;
@ -95,7 +95,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
Source userSettingsSource = getSettingsSource(request.getUserSettingsFile(), request.getUserSettingsSource());
Settings userSettings = readSettings(userSettingsSource, request, problems);
userSettings = settingsMerger.merge(userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL);
settingsMerger.merge(userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL);
problems.setSource("");
@ -106,7 +106,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
if (localRepository != null && localRepository.length() > 0) {
File file = new File(localRepository);
if (!file.isAbsolute() && file.getPath().startsWith(File.separator)) {
userSettings = userSettings.withLocalRepository(file.getAbsolutePath());
userSettings.setLocalRepository(file.getAbsolutePath());
}
}
@ -114,8 +114,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
throw new SettingsBuildingException(problems.getProblems());
}
return new DefaultSettingsBuildingResult(
new org.apache.maven.settings.Settings(userSettings), problems.getProblems());
return new DefaultSettingsBuildingResult(userSettings, problems.getProblems());
}
private boolean hasErrors(List<SettingsProblem> problems) {
@ -142,7 +141,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
private Settings readSettings(
Source settingsSource, SettingsBuildingRequest request, DefaultSettingsProblemCollector problems) {
if (settingsSource == null) {
return Settings.newInstance();
return new Settings();
}
problems.setSource(settingsSource.getLocation());
@ -169,7 +168,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
e.getLineNumber(),
e.getColumnNumber(),
e);
return Settings.newInstance();
return new Settings();
} catch (IOException e) {
problems.add(
SettingsProblem.Severity.FATAL,
@ -177,7 +176,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder {
-1,
-1,
e);
return Settings.newInstance();
return new Settings();
}
settingsValidator.validate(settings, problems);

View File

@ -28,7 +28,7 @@ import java.io.Reader;
import java.util.Map;
import java.util.Objects;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.v4.SettingsXpp3Reader;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@ -54,7 +54,7 @@ public class DefaultSettingsReader implements SettingsReader {
Objects.requireNonNull(input, "input cannot be null");
try (Reader in = input) {
return new SettingsXpp3Reader().read(in, isStrict(options));
return new Settings(new SettingsXpp3Reader().read(in, isStrict(options)));
} catch (XmlPullParserException e) {
throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
}
@ -65,7 +65,7 @@ public class DefaultSettingsReader implements SettingsReader {
Objects.requireNonNull(input, "input cannot be null");
try (InputStream in = input) {
return new SettingsXpp3Reader().read(in, isStrict(options));
return new Settings(new SettingsXpp3Reader().read(in, isStrict(options)));
} catch (XmlPullParserException e) {
throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
}

View File

@ -29,7 +29,7 @@ import java.io.Writer;
import java.util.Map;
import java.util.Objects;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.v4.SettingsXpp3Writer;
import org.codehaus.plexus.util.WriterFactory;
@ -58,7 +58,7 @@ public class DefaultSettingsWriter implements SettingsWriter {
Objects.requireNonNull(settings, "settings cannot be null");
try (Writer out = output) {
new SettingsXpp3Writer().write(out, settings);
new SettingsXpp3Writer().write(out, settings.getDelegate());
}
}

View File

@ -24,7 +24,7 @@ import java.io.InputStream;
import java.io.Reader;
import java.util.Map;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.Settings;
/**
* Handles deserialization of settings from some kind of textual format like XML.

View File

@ -24,7 +24,7 @@ import java.io.OutputStream;
import java.io.Writer;
import java.util.Map;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.Settings;
/**
* Handles serialization of settings into some kind of textual format like XML.

View File

@ -19,16 +19,12 @@
package org.apache.maven.settings.merge;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.maven.api.settings.IdentifiableBase;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.IdentifiableBase;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.util.StringUtils;
/**
@ -44,44 +40,54 @@ public class MavenSettingsMerger {
* @param recessive
* @param recessiveSourceLevel
*/
public Settings merge(Settings dominant, Settings recessive, String recessiveSourceLevel) {
if (dominant == null) {
return recessive;
} else if (recessive == null) {
return dominant;
public void merge(Settings dominant, Settings recessive, String recessiveSourceLevel) {
if (dominant == null || recessive == null) {
return;
}
recessive.setSourceLevel(recessiveSourceLevel);
Settings.Builder merged = Settings.newBuilder(dominant);
List<String> dominantActiveProfiles = dominant.getActiveProfiles();
List<String> recessiveActiveProfiles = recessive.getActiveProfiles();
List<String> mergedActiveProfiles = Stream.of(dominantActiveProfiles, recessiveActiveProfiles)
.flatMap(Collection::stream)
.distinct()
.collect(Collectors.toList());
merged.activeProfiles(mergedActiveProfiles);
if (recessiveActiveProfiles != null) {
if (dominantActiveProfiles == null) {
dominantActiveProfiles = new ArrayList<>();
dominant.setActiveProfiles(dominantActiveProfiles);
}
for (String profileId : recessiveActiveProfiles) {
if (!dominantActiveProfiles.contains(profileId)) {
dominantActiveProfiles.add(profileId);
}
}
}
List<String> dominantPluginGroupIds = dominant.getPluginGroups();
List<String> recessivePluginGroupIds = recessive.getPluginGroups();
List<String> mergedPluginGroupIds = Stream.of(dominantPluginGroupIds, recessivePluginGroupIds)
.flatMap(Collection::stream)
.distinct()
.collect(Collectors.toList());
merged.pluginGroups(mergedPluginGroupIds);
String localRepository = StringUtils.isEmpty(dominant.getLocalRepository())
? recessive.getLocalRepository()
: dominant.getLocalRepository();
merged.localRepository(localRepository);
if (recessivePluginGroupIds != null) {
if (dominantPluginGroupIds == null) {
dominantPluginGroupIds = new ArrayList<>();
dominant.setPluginGroups(dominantPluginGroupIds);
}
merged.mirrors(shallowMergeById(dominant.getMirrors(), recessive.getMirrors(), recessiveSourceLevel));
merged.servers(shallowMergeById(dominant.getServers(), recessive.getServers(), recessiveSourceLevel));
merged.proxies(shallowMergeById(dominant.getProxies(), recessive.getProxies(), recessiveSourceLevel));
merged.profiles(shallowMergeById(dominant.getProfiles(), recessive.getProfiles(), recessiveSourceLevel));
for (String pluginGroupId : recessivePluginGroupIds) {
if (!dominantPluginGroupIds.contains(pluginGroupId)) {
dominantPluginGroupIds.add(pluginGroupId);
}
}
}
return merged.build();
if (StringUtils.isEmpty(dominant.getLocalRepository())) {
dominant.setLocalRepository(recessive.getLocalRepository());
}
shallowMergeById(dominant.getMirrors(), recessive.getMirrors(), recessiveSourceLevel);
shallowMergeById(dominant.getServers(), recessive.getServers(), recessiveSourceLevel);
shallowMergeById(dominant.getProxies(), recessive.getProxies(), recessiveSourceLevel);
shallowMergeById(dominant.getProfiles(), recessive.getProfiles(), recessiveSourceLevel);
}
/**
@ -89,18 +95,20 @@ public class MavenSettingsMerger {
* @param recessive
* @param recessiveSourceLevel
*/
private static <T extends IdentifiableBase> List<T> shallowMergeById(
private static <T extends IdentifiableBase> void shallowMergeById(
List<T> dominant, List<T> recessive, String recessiveSourceLevel) {
Set<String> dominantIds = dominant.stream().map(IdentifiableBase::getId).collect(Collectors.toSet());
final List<T> merged = new ArrayList<>(dominant.size() + recessive.size());
merged.addAll(dominant);
Map<String, T> dominantById = mapById(dominant);
final List<T> identifiables = new ArrayList<>(recessive.size());
for (T identifiable : recessive) {
if (!dominantIds.contains(identifiable.getId())) {
if (!dominantById.containsKey(identifiable.getId())) {
identifiable.setSourceLevel(recessiveSourceLevel);
merged.add(identifiable);
identifiables.add(identifiable);
}
}
return merged;
dominant.addAll(0, identifiables);
}
/**

View File

@ -25,12 +25,12 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.maven.api.settings.Mirror;
import org.apache.maven.api.settings.Profile;
import org.apache.maven.api.settings.Proxy;
import org.apache.maven.api.settings.Repository;
import org.apache.maven.api.settings.Server;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.Mirror;
import org.apache.maven.settings.Profile;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Repository;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.building.SettingsProblem.Severity;
import org.apache.maven.settings.building.SettingsProblemCollector;
import org.codehaus.plexus.util.StringUtils;

View File

@ -18,7 +18,7 @@
*/
package org.apache.maven.settings.validation;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.building.SettingsProblemCollector;
/**

View File

@ -19,16 +19,14 @@
package org.apache.maven.settings.validation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.maven.api.settings.Mirror;
import org.apache.maven.api.settings.Profile;
import org.apache.maven.api.settings.Proxy;
import org.apache.maven.api.settings.Repository;
import org.apache.maven.api.settings.Server;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.Mirror;
import org.apache.maven.settings.Profile;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Repository;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.building.SettingsProblem.Severity;
import org.apache.maven.settings.building.SettingsProblemCollector;
import org.junit.jupiter.api.AfterEach;
@ -61,29 +59,26 @@ public class DefaultSettingsValidatorTest {
@Test
public void testValidate() {
Profile prof = Profile.newInstance().withId("xxx");
Settings model = Settings.newInstance().withProfiles(Collections.singletonList(prof));
Settings model = new Settings();
Profile prof = new Profile();
prof.setId("xxx");
model.addProfile(prof);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(model, problems);
assertEquals(0, problems.messages.size());
Repository repo = Repository.newInstance();
prof = prof.withRepositories(Collections.singletonList(repo));
model = model.withProfiles(Collections.singletonList(prof));
Repository repo = new Repository();
prof.addRepository(repo);
problems = new SimpleProblemCollector();
validator.validate(model, problems);
assertEquals(2, problems.messages.size());
repo = repo.withUrl("http://xxx.xxx.com");
prof = prof.withRepositories(Collections.singletonList(repo));
model = model.withProfiles(Collections.singletonList(prof));
repo.setUrl("http://xxx.xxx.com");
problems = new SimpleProblemCollector();
validator.validate(model, problems);
assertEquals(1, problems.messages.size());
repo = repo.withId("xxx");
prof = prof.withRepositories(Collections.singletonList(repo));
model = model.withProfiles(Collections.singletonList(prof));
repo.setId("xxx");
problems = new SimpleProblemCollector();
validator.validate(model, problems);
assertEquals(0, problems.messages.size());
@ -91,14 +86,15 @@ public class DefaultSettingsValidatorTest {
@Test
public void testValidateMirror() throws Exception {
Mirror mirror1 = Mirror.newBuilder().id("local").build();
Mirror mirror2 = Mirror.newBuilder()
.id("illegal\\:/chars")
.url("http://void")
.mirrorOf("void")
.build();
Settings settings =
Settings.newBuilder().mirrors(Arrays.asList(mirror1, mirror2)).build();
Settings settings = new Settings();
Mirror mirror = new Mirror();
mirror.setId("local");
settings.addMirror(mirror);
mirror = new Mirror();
mirror.setId("illegal\\:/chars");
mirror.setUrl("http://void");
mirror.setMirrorOf("void");
settings.addMirror(mirror);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
@ -111,16 +107,16 @@ public class DefaultSettingsValidatorTest {
@Test
public void testValidateRepository() throws Exception {
Repository repo1 = Repository.newBuilder().id("local").build();
Repository repo2 = Repository.newBuilder()
.id("illegal\\:/chars")
.url("http://void")
.build();
Profile profile =
Profile.newBuilder().repositories(Arrays.asList(repo1, repo2)).build();
Settings settings = Settings.newBuilder()
.profiles(Collections.singletonList(profile))
.build();
Profile profile = new Profile();
Repository repo = new Repository();
repo.setId("local");
profile.addRepository(repo);
repo = new Repository();
repo.setId("illegal\\:/chars");
repo.setUrl("http://void");
profile.addRepository(repo);
Settings settings = new Settings();
settings.addProfile(profile);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
@ -137,10 +133,13 @@ public class DefaultSettingsValidatorTest {
@Test
public void testValidateUniqueServerId() throws Exception {
Server server1 = Server.newBuilder().id("test").build();
Server server2 = Server.newBuilder().id("test").build();
Settings settings =
Settings.newBuilder().servers(Arrays.asList(server1, server2)).build();
Settings settings = new Settings();
Server server1 = new Server();
server1.setId("test");
settings.addServer(server1);
Server server2 = new Server();
server2.setId("test");
settings.addServer(server2);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
@ -151,11 +150,13 @@ public class DefaultSettingsValidatorTest {
@Test
public void testValidateUniqueProfileId() throws Exception {
Profile profile1 = Profile.newBuilder().id("test").build();
Profile profile2 = Profile.newBuilder().id("test").build();
Settings settings = Settings.newBuilder()
.profiles(Arrays.asList(profile1, profile2))
.build();
Settings settings = new Settings();
Profile profile1 = new Profile();
profile1.setId("test");
settings.addProfile(profile1);
Profile profile2 = new Profile();
profile2.setId("test");
settings.addProfile(profile2);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
@ -167,17 +168,18 @@ public class DefaultSettingsValidatorTest {
@Test
public void testValidateUniqueRepositoryId() throws Exception {
Repository repo1 =
Repository.newBuilder().id("test").url("http://apache.org/").build();
Repository repo2 =
Repository.newBuilder().id("test").url("http://apache.org/").build();
Profile profile = Profile.newBuilder()
.id("pro")
.repositories(Arrays.asList(repo1, repo2))
.build();
Settings settings = Settings.newBuilder()
.profiles(Collections.singletonList(profile))
.build();
Settings settings = new Settings();
Profile profile = new Profile();
profile.setId("pro");
settings.addProfile(profile);
Repository repo1 = new Repository();
repo1.setUrl("http://apache.org/");
repo1.setId("test");
profile.addRepository(repo1);
Repository repo2 = new Repository();
repo2.setUrl("http://apache.org/");
repo2.setId("test");
profile.addRepository(repo2);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
@ -190,37 +192,27 @@ public class DefaultSettingsValidatorTest {
@Test
public void testValidateUniqueProxyId() throws Exception {
Proxy proxy = Proxy.newBuilder().id("foo").host("www.example.com").build();
Settings settings =
Settings.newBuilder().proxies(Arrays.asList(proxy, proxy)).build();
Settings settings = new Settings();
Proxy proxy = new Proxy();
String id = "foo";
proxy.setId(id);
proxy.setHost("www.example.com");
settings.addProxy(proxy);
settings.addProxy(proxy);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
assertEquals(1, problems.messages.size());
assertContains(
problems.messages.get(0),
"'proxies.proxy.id' must be unique" + " but found duplicate proxy with id foo");
}
@Test
public void testValidateUniqueProxyNullId() throws Exception {
Proxy proxy = Proxy.newBuilder(false).host("www.example.com").build();
Settings settings =
Settings.newBuilder().proxies(Arrays.asList(proxy, proxy)).build();
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);
assertEquals(1, problems.messages.size());
assertContains(
problems.messages.get(0),
"'proxies.proxy.id' must be unique" + " but found duplicate proxy with id null");
"'proxies.proxy.id' must be unique" + " but found duplicate proxy with id " + id);
}
@Test
public void testValidateProxy() throws Exception {
Proxy proxy = Proxy.newBuilder().build();
Settings settings =
Settings.newBuilder().proxies(Collections.singletonList(proxy)).build();
Settings settings = new Settings();
Proxy proxy1 = new Proxy();
settings.addProxy(proxy1);
SimpleProblemCollector problems = new SimpleProblemCollector();
validator.validate(settings, problems);

View File

@ -84,6 +84,19 @@ under the License.
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
<configuration>
<parameter>
<excludes>
<exclude>org.apache.maven.settings.io.xpp3.SettingsXpp3Reader#contentTransformer</exclude>
<exclude>org.apache.maven.settings.RuntimeInfo</exclude>
<exclude>org.apache.maven.settings.Settings#setModelEncoding(java.lang.String):METHOD_REMOVED</exclude>
</excludes>
</parameter>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.settings;
import java.io.Serializable;
public abstract class BaseObject implements Serializable, Cloneable {
protected transient ChildrenTracking childrenTracking;
protected Object delegate;
public BaseObject() {}
public BaseObject(Object delegate, BaseObject parent) {
this.delegate = delegate;
this.childrenTracking = parent != null ? parent::replace : null;
}
public BaseObject(Object delegate, ChildrenTracking parent) {
this.delegate = delegate;
this.childrenTracking = parent;
}
public Object getDelegate() {
return delegate;
}
public void update(Object newDelegate) {
if (delegate != newDelegate) {
if (childrenTracking != null) {
childrenTracking.replace(delegate, newDelegate);
}
delegate = newDelegate;
}
}
protected boolean replace(Object oldDelegate, Object newDelegate) {
return false;
}
@FunctionalInterface
protected interface ChildrenTracking {
boolean replace(Object oldDelegate, Object newDelegate);
}
}

View File

@ -64,6 +64,32 @@ under the License.
<groupId>org.eclipse.sisu</groupId>
<artifactId>sisu-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
<configuration>
<parameter>
<includes>
<include>org.apache.maven.toolchain.building</include>
<include>org.apache.maven.toolchain.io</include>
<include>org.apache.maven.toolchain.io.xpp3</include>
<include>org.apache.maven.toolchain.merge</include>
</includes>
<excludes>
<exclude>org.apache.maven.toolchain.building.DefaultToolchainsBuilder#DefaultToolchainsBuilder():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.toolchain.merge.MavenToolchainMerger#getToolchainModelKey(org.apache.maven.toolchain.model.ToolchainModel):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.toolchain.merge.MavenToolchainMerger#mergeToolchainModelConfiguration(org.apache.maven.toolchain.model.ToolchainModel,org.apache.maven.toolchain.model.ToolchainModel):METHOD_REMOVED</exclude>
</excludes>
</parameter>
<oldVersion>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.baseline}</version>
</dependency>
</oldVersion>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -29,8 +29,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.api.toolchain.TrackableBase;
import org.apache.maven.building.Problem;
import org.apache.maven.building.ProblemCollector;
import org.apache.maven.building.ProblemCollectorFactory;
@ -39,6 +37,8 @@ import org.apache.maven.toolchain.io.ToolchainsParseException;
import org.apache.maven.toolchain.io.ToolchainsReader;
import org.apache.maven.toolchain.io.ToolchainsWriter;
import org.apache.maven.toolchain.merge.MavenToolchainMerger;
import org.apache.maven.toolchain.model.PersistedToolchains;
import org.apache.maven.toolchain.model.TrackableBase;
import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
import org.codehaus.plexus.interpolation.InterpolationException;
import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
@ -69,19 +69,17 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
PersistedToolchains userToolchains = readToolchains(request.getUserToolchainsSource(), request, problems);
PersistedToolchains merged =
toolchainsMerger.merge(userToolchains, globalToolchains, TrackableBase.GLOBAL_LEVEL);
toolchainsMerger.merge(userToolchains, globalToolchains, TrackableBase.GLOBAL_LEVEL);
problems.setSource("");
merged = interpolate(merged, problems);
userToolchains = interpolate(userToolchains, problems);
if (hasErrors(problems.getProblems())) {
throw new ToolchainsBuildingException(problems.getProblems());
}
return new DefaultToolchainsBuildingResult(
new org.apache.maven.toolchain.model.PersistedToolchains(merged), problems.getProblems());
return new DefaultToolchainsBuildingResult(userToolchains, problems.getProblems());
}
private PersistedToolchains interpolate(PersistedToolchains toolchains, ProblemCollector problems) {
@ -143,7 +141,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
private PersistedToolchains readToolchains(
Source toolchainsSource, ToolchainsBuildingRequest request, ProblemCollector problems) {
if (toolchainsSource == null) {
return PersistedToolchains.newInstance();
return new PersistedToolchains();
}
PersistedToolchains toolchains;
@ -167,7 +165,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
e.getLineNumber(),
e.getColumnNumber(),
e);
return PersistedToolchains.newInstance();
return new PersistedToolchains();
} catch (IOException e) {
problems.add(
Problem.Severity.FATAL,
@ -175,7 +173,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder {
-1,
-1,
e);
return PersistedToolchains.newInstance();
return new PersistedToolchains();
}
return toolchains;

View File

@ -28,7 +28,7 @@ import java.io.Reader;
import java.util.Map;
import java.util.Objects;
import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.toolchain.model.PersistedToolchains;
import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@ -55,7 +55,7 @@ public class DefaultToolchainsReader implements ToolchainsReader {
Objects.requireNonNull(input, "input cannot be null");
try (Reader in = input) {
return new MavenToolchainsXpp3Reader().read(in, isStrict(options));
return new PersistedToolchains(new MavenToolchainsXpp3Reader().read(in, isStrict(options)));
} catch (XmlPullParserException e) {
throw new ToolchainsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
}
@ -66,7 +66,7 @@ public class DefaultToolchainsReader implements ToolchainsReader {
Objects.requireNonNull(input, "input cannot be null");
try (InputStream in = input) {
return new MavenToolchainsXpp3Reader().read(in, isStrict(options));
return new PersistedToolchains(new MavenToolchainsXpp3Reader().read(in, isStrict(options)));
} catch (XmlPullParserException e) {
throw new ToolchainsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
}

View File

@ -26,7 +26,7 @@ import java.io.Writer;
import java.util.Map;
import java.util.Objects;
import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.toolchain.model.PersistedToolchains;
import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Writer;
/**
@ -45,7 +45,7 @@ public class DefaultToolchainsWriter implements ToolchainsWriter {
Objects.requireNonNull(toolchains, "toolchains cannot be null");
try (Writer out = output) {
new MavenToolchainsXpp3Writer().write(out, toolchains);
new MavenToolchainsXpp3Writer().write(out, toolchains.getDelegate());
}
}
}

View File

@ -24,7 +24,7 @@ import java.io.InputStream;
import java.io.Reader;
import java.util.Map;
import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.toolchain.model.PersistedToolchains;
/**
* Handles deserialization of toolchains from some kind of textual format like XML.

View File

@ -22,7 +22,7 @@ import java.io.IOException;
import java.io.Writer;
import java.util.Map;
import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.toolchain.model.PersistedToolchains;
/**
* Handles serialization of toolchains into some kind of textual format like XML.

View File

@ -18,14 +18,7 @@
*/
package org.apache.maven.toolchain.merge;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.api.toolchain.ToolchainModel;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.toolchain.model.PersistedToolchains;
/**
*
@ -34,51 +27,14 @@ import org.apache.maven.api.xml.XmlNode;
*/
public class MavenToolchainMerger {
public PersistedToolchains merge(
PersistedToolchains dominant, PersistedToolchains recessive, String recessiveSourceLevel) {
public void merge(PersistedToolchains dominant, PersistedToolchains recessive, String recessiveSourceLevel) {
if (dominant == null || recessive == null) {
return dominant;
return;
}
recessive.setSourceLevel(recessiveSourceLevel);
return shallowMerge(dominant.getToolchains(), recessive.getToolchains(), recessiveSourceLevel);
}
private PersistedToolchains shallowMerge(
List<ToolchainModel> dominant, List<ToolchainModel> recessive, String recessiveSourceLevel) {
Map<Object, ToolchainModel> merged = new LinkedHashMap<>();
for (ToolchainModel dominantModel : dominant) {
Object key = getToolchainModelKey(dominantModel);
merged.put(key, dominantModel);
}
for (ToolchainModel recessiveModel : recessive) {
Object key = getToolchainModelKey(recessiveModel);
ToolchainModel dominantModel = merged.get(key);
if (dominantModel == null) {
recessiveModel.setSourceLevel(recessiveSourceLevel);
merged.put(key, recessiveModel);
} else {
merged.put(key, mergeToolchainModelConfiguration(dominantModel, recessiveModel));
}
}
return PersistedToolchains.newBuilder()
.toolchains(new ArrayList<>(merged.values()))
.build();
}
protected ToolchainModel mergeToolchainModelConfiguration(ToolchainModel target, ToolchainModel source) {
XmlNode src = source.getConfiguration();
XmlNode tgt = target.getConfiguration();
XmlNode merged = XmlNode.merge(tgt, src);
return target.withConfiguration(merged);
}
protected Object getToolchainModelKey(ToolchainModel model) {
return model;
dominant.update(new org.apache.maven.toolchain.v4.MavenToolchainsMerger()
.merge(dominant.getDelegate(), recessive.getDelegate(), true, null));
}
}

View File

@ -23,15 +23,16 @@ import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.api.toolchain.ToolchainModel;
import org.apache.maven.building.StringSource;
import org.apache.maven.internal.xml.XmlNodeImpl;
import org.apache.maven.toolchain.io.DefaultToolchainsReader;
import org.apache.maven.toolchain.io.DefaultToolchainsWriter;
import org.apache.maven.toolchain.io.ToolchainsParseException;
import org.apache.maven.toolchain.model.PersistedToolchains;
import org.apache.maven.toolchain.model.ToolchainModel;
import org.codehaus.plexus.interpolation.os.OperatingSystemUtils;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
@ -81,13 +82,13 @@ public class DefaultToolchainsBuilderTest {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(""));
Map<String, String> props = new HashMap<>();
Properties props = new Properties();
props.put("key", "user_value");
ToolchainModel toolchain =
ToolchainModel.newBuilder().type("TYPE").provides(props).build();
PersistedToolchains userResult = PersistedToolchains.newBuilder()
.toolchains(Collections.singletonList(toolchain))
.build();
ToolchainModel toolchain = new ToolchainModel();
toolchain.setType("TYPE");
toolchain.setProvides(props);
PersistedToolchains userResult = new PersistedToolchains();
userResult.setToolchains(Collections.singletonList(toolchain));
doReturn(userResult)
.when(toolchainsReader)
.read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
@ -113,13 +114,13 @@ public class DefaultToolchainsBuilderTest {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setGlobalToolchainsSource(new StringSource(""));
Map<String, String> props = new HashMap<>();
Properties props = new Properties();
props.put("key", "global_value");
ToolchainModel toolchain =
ToolchainModel.newBuilder().type("TYPE").provides(props).build();
PersistedToolchains globalResult = PersistedToolchains.newBuilder()
.toolchains(Collections.singletonList(toolchain))
.build();
ToolchainModel toolchain = new ToolchainModel();
toolchain.setType("TYPE");
toolchain.setProvides(props);
PersistedToolchains globalResult = new PersistedToolchains();
globalResult.setToolchains(Collections.singletonList(toolchain));
doReturn(globalResult)
.when(toolchainsReader)
.read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap());
@ -146,20 +147,21 @@ public class DefaultToolchainsBuilderTest {
request.setGlobalToolchainsSource(new StringSource(""));
request.setUserToolchainsSource(new StringSource(""));
Map<String, String> props = new HashMap<>();
Properties props = new Properties();
props.put("key", "user_value");
ToolchainModel toolchain =
ToolchainModel.newBuilder().type("TYPE").provides(props).build();
PersistedToolchains userResult = PersistedToolchains.newBuilder()
.toolchains(Collections.singletonList(toolchain))
.build();
ToolchainModel toolchain = new ToolchainModel();
toolchain.setType("TYPE");
toolchain.setProvides(props);
PersistedToolchains userResult = new PersistedToolchains();
userResult.setToolchains(Collections.singletonList(toolchain));
props = new HashMap<>();
props = new Properties();
props.put("key", "global_value");
toolchain = ToolchainModel.newBuilder().type("TYPE").provides(props).build();
PersistedToolchains globalResult = PersistedToolchains.newBuilder()
.toolchains(Collections.singletonList(toolchain))
.build();
toolchain = new ToolchainModel();
toolchain.setType("TYPE");
toolchain.setProvides(props);
PersistedToolchains globalResult = new PersistedToolchains();
globalResult.setToolchains(Collections.singletonList(toolchain));
doReturn(globalResult)
.doReturn(userResult)
@ -234,19 +236,18 @@ public class DefaultToolchainsBuilderTest {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(""));
Map<String, String> props = new HashMap<>();
Properties props = new Properties();
props.put("key", "${env.testKey}");
XmlNodeImpl configurationChild = new XmlNodeImpl("jdkHome", "${env.testKey}", null, null, null);
XmlNodeImpl configuration =
new XmlNodeImpl("configuration", null, null, Collections.singletonList(configurationChild), null);
ToolchainModel toolchain = ToolchainModel.newBuilder()
.type("TYPE")
.provides(props)
.configuration(configuration)
.build();
PersistedToolchains persistedToolchains = PersistedToolchains.newBuilder()
.toolchains(Collections.singletonList(toolchain))
.build();
Xpp3Dom configurationChild = new Xpp3Dom("jdkHome");
configurationChild.setValue("${env.testKey}");
Xpp3Dom configuration = new Xpp3Dom("configuration");
configuration.addChild(configurationChild);
ToolchainModel toolchain = new ToolchainModel();
toolchain.setType("TYPE");
toolchain.setProvides(props);
toolchain.setConfiguration(configuration);
PersistedToolchains persistedToolchains = new PersistedToolchains();
persistedToolchains.setToolchains(Collections.singletonList(toolchain));
doReturn(persistedToolchains)
.when(toolchainsReader)
@ -274,13 +275,13 @@ public class DefaultToolchainsBuilderTest {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(""));
Map<String, String> props = new HashMap<>();
Properties props = new Properties();
props.put("key", "${env.testNonExistingKey}");
ToolchainModel toolchain =
ToolchainModel.newBuilder().type("TYPE").provides(props).build();
PersistedToolchains persistedToolchains = PersistedToolchains.newBuilder()
.toolchains(Collections.singletonList(toolchain))
.build();
ToolchainModel toolchain = new ToolchainModel();
toolchain.setType("TYPE");
toolchain.setProvides(props);
PersistedToolchains persistedToolchains = new PersistedToolchains();
persistedToolchains.setToolchains(Collections.singletonList(toolchain));
doReturn(persistedToolchains)
.when(toolchainsReader)
@ -303,13 +304,13 @@ public class DefaultToolchainsBuilderTest {
ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest();
request.setUserToolchainsSource(new StringSource(""));
Map<String, String> props = new HashMap<>();
Properties props = new Properties();
props.put("key", "${env.testSpecialCharactersKey}");
ToolchainModel toolchain =
ToolchainModel.newBuilder().type("TYPE").provides(props).build();
PersistedToolchains persistedToolchains = PersistedToolchains.newBuilder()
.toolchains(Collections.singletonList(toolchain))
.build();
ToolchainModel toolchain = new ToolchainModel();
toolchain.setType("TYPE");
toolchain.setProvides(props);
PersistedToolchains persistedToolchains = new PersistedToolchains();
persistedToolchains.setToolchains(Collections.singletonList(toolchain));
doReturn(persistedToolchains)
.when(toolchainsReader)

View File

@ -18,12 +18,14 @@
*/
package org.apache.maven.toolchain.merge;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.api.toolchain.TrackableBase;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader;
import org.apache.maven.toolchain.io.DefaultToolchainsReader;
import org.apache.maven.toolchain.model.PersistedToolchains;
import org.apache.maven.toolchain.model.TrackableBase;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -31,95 +33,97 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class MavenToolchainMergerTest {
private MavenToolchainMerger merger = new MavenToolchainMerger();
private MavenToolchainsXpp3Reader reader = new MavenToolchainsXpp3Reader();
private DefaultToolchainsReader reader = new DefaultToolchainsReader();
@Test
public void testMergeNulls() {
merger.merge(null, null, null);
PersistedToolchains pt = PersistedToolchains.newInstance();
PersistedToolchains pt = new PersistedToolchains();
merger.merge(pt, null, null);
merger.merge(null, pt, null);
}
@Test
public void testMergeJdk() throws Exception {
try (InputStream isDominant = getClass().getResourceAsStream("toolchains-jdks.xml");
InputStream isRecessive = getClass().getResourceAsStream("toolchains-jdks.xml")) {
PersistedToolchains dominant = reader.read(isDominant);
PersistedToolchains recessive = reader.read(isRecessive);
try (InputStream isDominant = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml");
InputStream isRecessive = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml")) {
PersistedToolchains dominant = read(isDominant);
PersistedToolchains recessive = read(isRecessive);
assertEquals(2, dominant.getToolchains().size());
PersistedToolchains merged = merger.merge(dominant, recessive, TrackableBase.USER_LEVEL);
assertEquals(2, merged.getToolchains().size());
merger.merge(dominant, recessive, TrackableBase.USER_LEVEL);
assertEquals(2, dominant.getToolchains().size());
}
}
@Test
public void testMergeJdkExtra() throws Exception {
try (InputStream jdksIS = getClass().getResourceAsStream("toolchains-jdks.xml");
InputStream jdksExtraIS = getClass().getResourceAsStream("toolchains-jdks-extra.xml")) {
PersistedToolchains jdks = reader.read(jdksIS);
PersistedToolchains jdksExtra = reader.read(jdksExtraIS);
try (InputStream jdksIS = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml");
InputStream jdksExtraIS =
MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks-extra.xml")) {
PersistedToolchains jdks = read(jdksIS);
PersistedToolchains jdksExtra = read(jdksExtraIS);
assertEquals(2, jdks.getToolchains().size());
assertEquals(2, jdksExtra.getToolchains().size());
PersistedToolchains merged = merger.merge(jdks, jdksExtra, TrackableBase.USER_LEVEL);
assertEquals(4, merged.getToolchains().size());
assertEquals(2, jdks.getToolchains().size());
merger.merge(jdks, jdksExtra, TrackableBase.USER_LEVEL);
assertEquals(4, jdks.getToolchains().size());
assertEquals(2, jdksExtra.getToolchains().size());
}
try (InputStream jdksIS = getClass().getResourceAsStream("toolchains-jdks.xml");
InputStream jdksExtraIS = getClass().getResourceAsStream("toolchains-jdks-extra.xml")) {
PersistedToolchains jdks = reader.read(jdksIS);
PersistedToolchains jdksExtra = reader.read(jdksExtraIS);
try (InputStream jdksIS = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml");
InputStream jdksExtraIS =
MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks-extra.xml")) {
PersistedToolchains jdks = read(jdksIS);
PersistedToolchains jdksExtra = read(jdksExtraIS);
assertEquals(2, jdks.getToolchains().size());
assertEquals(2, jdksExtra.getToolchains().size());
// switch dominant with recessive
PersistedToolchains merged = merger.merge(jdksExtra, jdks, TrackableBase.USER_LEVEL);
assertEquals(4, merged.getToolchains().size());
merger.merge(jdksExtra, jdks, TrackableBase.USER_LEVEL);
assertEquals(4, jdksExtra.getToolchains().size());
assertEquals(2, jdks.getToolchains().size());
assertEquals(2, jdksExtra.getToolchains().size());
}
}
@Test
public void testMergeJdkExtend() throws Exception {
try (InputStream jdksIS = getClass().getResourceAsStream("toolchains-jdks.xml");
InputStream jdksExtendIS = getClass().getResourceAsStream("toolchains-jdks-extend.xml")) {
PersistedToolchains jdks = reader.read(jdksIS);
PersistedToolchains jdksExtend = reader.read(jdksExtendIS);
try (InputStream jdksIS = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml");
InputStream jdksExtendIS =
MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks-extend.xml")) {
PersistedToolchains jdks = read(jdksIS);
PersistedToolchains jdksExtend = read(jdksExtendIS);
assertEquals(2, jdks.getToolchains().size());
PersistedToolchains merged = merger.merge(jdks, jdksExtend, TrackableBase.USER_LEVEL);
assertEquals(2, merged.getToolchains().size());
XmlNode config0 = merged.getToolchains().get(0).getConfiguration();
assertEquals("lib/tools.jar", config0.getChild("toolsJar").getValue());
assertEquals(2, config0.getChildren().size());
XmlNode config1 = merged.getToolchains().get(1).getConfiguration();
assertEquals(2, config1.getChildren().size());
assertEquals("lib/classes.jar", config1.getChild("toolsJar").getValue());
merger.merge(jdks, jdksExtend, TrackableBase.USER_LEVEL);
assertEquals(2, jdks.getToolchains().size());
Xpp3Dom config0 = (Xpp3Dom) jdks.getToolchains().get(0).getConfiguration();
assertEquals("lib/tools.jar", config0.getChild("toolsJar").getValue());
assertEquals(2, config0.getChildCount());
Xpp3Dom config1 = (Xpp3Dom) jdks.getToolchains().get(1).getConfiguration();
assertEquals(2, config1.getChildCount());
assertEquals("lib/classes.jar", config1.getChild("toolsJar").getValue());
assertEquals(2, jdksExtend.getToolchains().size());
}
try (InputStream jdksIS = getClass().getResourceAsStream("toolchains-jdks.xml");
InputStream jdksExtendIS = getClass().getResourceAsStream("toolchains-jdks-extend.xml")) {
PersistedToolchains jdks = reader.read(jdksIS);
PersistedToolchains jdksExtend = reader.read(jdksExtendIS);
try (InputStream jdksIS = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml");
InputStream jdksExtendIS =
MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks-extend.xml")) {
PersistedToolchains jdks = read(jdksIS);
PersistedToolchains jdksExtend = read(jdksExtendIS);
assertEquals(2, jdks.getToolchains().size());
// switch dominant with recessive
PersistedToolchains merged = merger.merge(jdksExtend, jdks, TrackableBase.USER_LEVEL);
assertEquals(2, merged.getToolchains().size());
XmlNode config0 = merged.getToolchains().get(0).getConfiguration();
merger.merge(jdksExtend, jdks, TrackableBase.USER_LEVEL);
assertEquals(2, jdksExtend.getToolchains().size());
Xpp3Dom config0 = (Xpp3Dom) jdksExtend.getToolchains().get(0).getConfiguration();
assertEquals("lib/tools.jar", config0.getChild("toolsJar").getValue());
assertEquals(2, config0.getChildren().size());
XmlNode config1 = merged.getToolchains().get(1).getConfiguration();
assertEquals(2, config1.getChildren().size());
assertEquals(2, config0.getChildCount());
Xpp3Dom config1 = (Xpp3Dom) jdksExtend.getToolchains().get(1).getConfiguration();
assertEquals(2, config1.getChildCount());
assertEquals("lib/classes.jar", config1.getChild("toolsJar").getValue());
assertEquals(2, jdks.getToolchains().size());
assertEquals(2, jdksExtend.getToolchains().size());
}
}
private PersistedToolchains read(InputStream is) throws IOException {
return reader.read(is, Collections.emptyMap());
}
}

View File

@ -83,6 +83,28 @@ under the License.
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
<configuration>
<parameter>
<includes>
<include>org.apache.maven.toolchain.model</include>
</includes>
<excludes>
<exclude>org.apache.maven.toolchain.model.PersistedToolchains#setModelEncoding(java.lang.String):METHOD_REMOVED</exclude>
</excludes>
<includeExclusively>true</includeExclusively>
</parameter>
<oldVersion>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.baseline}</version>
</dependency>
</oldVersion>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.toolchain.model;
import java.io.Serializable;
public abstract class BaseObject implements Serializable, Cloneable {
protected transient ChildrenTracking childrenTracking;
protected Object delegate;
public BaseObject() {}
public BaseObject(Object delegate, BaseObject parent) {
this.delegate = delegate;
this.childrenTracking = parent != null ? parent::replace : null;
}
public BaseObject(Object delegate, ChildrenTracking parent) {
this.delegate = delegate;
this.childrenTracking = parent;
}
public Object getDelegate() {
return delegate;
}
public void update(Object newDelegate) {
if (delegate != newDelegate) {
if (childrenTracking != null) {
childrenTracking.replace(delegate, newDelegate);
}
delegate = newDelegate;
}
}
protected boolean replace(Object oldDelegate, Object newDelegate) {
return false;
}
@FunctionalInterface
protected interface ChildrenTracking {
boolean replace(Object oldDelegate, Object newDelegate);
}
}

30
pom.xml
View File

@ -170,6 +170,7 @@ under the License.
<slf4jVersion>1.7.36</slf4jVersion>
<xmlunitVersion>2.6.4</xmlunitVersion>
<maven.test.redirectTestOutputToFile>true</maven.test.redirectTestOutputToFile>
<maven.baseline>3.8.7</maven.baseline>
<!-- Control the name of the distribution and information output by mvn -->
<distributionId>apache-maven</distributionId>
<distributionShortName>Maven</distributionShortName>
@ -556,36 +557,11 @@ under the License.
<configuration>
<parameter>
<!-- baseline is 3.8.6 for Maven 4 -->
<oldVersionPattern>3.8.6</oldVersionPattern>
<oldVersionPattern>${maven.baseline}</oldVersionPattern>
<breakBuildOnBinaryIncompatibleModifications>true</breakBuildOnBinaryIncompatibleModifications>
<onlyBinaryIncompatible>true</onlyBinaryIncompatible>
<!-- only exported packages from maven-core/META-INF/maven/extension.xml matter -->
<includes>
<include>org.apache.maven.artifact</include>
<include>org.apache.maven.classrealm</include>
<include>org.apache.maven.cli</include>
<include>org.apache.maven.configuration</include>
<include>org.apache.maven.exception</include>
<include>org.apache.maven.execution</include>
<include>org.apache.maven.execution.scope</include>
<include>org.apache.maven.feature</include>
<include>org.apache.maven.graph</include>
<include>org.apache.maven.lifecycle</include>
<include>org.apache.maven.model</include>
<include>org.apache.maven.monitor</include>
<include>org.apache.maven.plugin</include>
<include>org.apache.maven.profiles</include>
<include>org.apache.maven.project</include>
<include>org.apache.maven.reporting</include>
<include>org.apache.maven.repository</include>
<include>org.apache.maven.rtinfo</include>
<include>org.apache.maven.rtinfo.internal</include>
<include>org.apache.maven.settings</include>
<include>org.apache.maven.toolchain</include>
<include>org.apache.maven.usability</include>
</includes>
<includeExclusively>true</includeExclusively>
<!-- don't include subpackages -->
<includeExclusively>true</includeExclusively>
</parameter>
</configuration>
</execution>

View File

@ -25,7 +25,8 @@
#
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} template, any modifications will be overwritten.
// Generated by Modello Velocity from ${template}
// template, any modifications will be overwritten.
// ==============================================================
package ${package};
@ -53,6 +54,16 @@ import ${packageModelV4}.${class.Name};
public class ${className}
{
private final boolean deepMerge;
public ${className}() {
this(true);
}
public ${className}(boolean deepMerge) {
this.deepMerge = deepMerge;
}
/**
* Merges the specified source object into the given target object.
*
@ -169,7 +180,12 @@ public class ${className}
}
}
#elseif ( $field.to && $field.multiplicity == "*" )
builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) );
if (deepMerge) {
builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), get${field.to}Key(),
( t, s ) -> merge${field.to}( t, s, sourceDominant, context ) ) );
} else {
builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) );
}
#elseif ( $field.type == "DOM" )
XmlNode src = source.getConfiguration();
if ( src != null )

View File

@ -1,319 +0,0 @@
#*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*#
#parse ( "common.vm" )
#
#set ( $package = "${packageModelV3}" )
#
#set ( $root = $model.getClass( $model.getRoot($version), $version ) )
#
#foreach ( $class in $model.allClasses )
#set ( $ancestors = $Helper.ancestors( $class ) )
#set ( $allFields = [] )
#set ( $inheritedFields = [] )
#foreach ( $cl in $ancestors )
#if ( $cl != $class )
#set ( $dummy = $inheritedFields.addAll( $cl.allFields ) )
#end
#set ( $dummy = $allFields.addAll( $cl.allFields ) )
#end
#set ( $className = "${class.name}" )
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
#if ( $class.name != "InputLocation" && $class.name != "InputSource" )
#set ( $types = { } )
#set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() )
#set ( $dummy = $imports.add( "java.io.Serializable" ) )
#set ( $dummy = $imports.add( "java.util.AbstractList" ) )
#set ( $dummy = $imports.add( "java.util.Collections" ) )
#set ( $dummy = $imports.add( "java.util.HashMap" ) )
#set ( $dummy = $imports.add( "java.util.List" ) )
#set ( $dummy = $imports.add( "java.util.Map" ) )
#set ( $dummy = $imports.add( "java.util.Objects" ) )
#set ( $dummy = $imports.add( "java.util.stream.Collectors" ) )
#set ( $dummy = $imports.add( "java.util.stream.Stream" ) )
#set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) )
#set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) )
#foreach ( $field in $allFields )
#if ( $field.type == "java.util.List" )
#set ( $dummy = $imports.add( "java.util.ArrayList" ) )
#set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) )
#elseif ( $field.type == "DOM" )
#set ( $dummy = $imports.add( "org.codehaus.plexus.util.xml.Xpp3Dom" ) )
#set ( $dummy = $types.put( $field, "Object" ) )
#else
#set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} )
#set ( $idx = $fieldType.lastIndexOf('.') )
#if ( $idx > 0 )
#set ( $dummy = $imports.add( $fieldType ) )
#set ( $dummy = $types.put( $fieldType, $fieldType.substring( $idx + 1 ) ) )
#end
#end
#end
#set ( $eq = "" )
#set ( $hc = "" )
#foreach ( $field in $allFields )
#if ( $field.identifier )
#set ( $dummy = $imports.add( "java.util.Objects" ) )
#set ( $dummy = $identifiers.add( $field ) )
#if ( $eq == "" )
#set ( $eq = "Objects.equals( this.${field.name}, that.${field.name} )" )
#else
#set ( $eq = "$eq && Objects.equals( this.${field.name}, that.${field.name} )" )
#end
#if ( $hc == "" )
#set ( $hc = "${field.name}" )
#else
#set ( $hc = "$hc, this.${field.name}" )
#end
#end
#end
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} template, any modifications will be overwritten.
// ==============================================================
package ${package};
#foreach ( $imp in $imports )
import $imp;
#end
@Generated
public class ${class.name}
#if ( $class.superClass )
extends ${class.superClass}
implements Serializable, Cloneable
#else
extends BaseObject
#end
{
public ${class.name}()
{
this( ${packageModelV4}.${class.name}.newInstance() );
}
public ${class.name}( ${packageModelV4}.${class.name} delegate )
{
this( delegate, null );
}
public ${class.name}( ${packageModelV4}.${class.name} delegate, BaseObject parent )
{
super( delegate, parent );
}
public ${class.name} clone()
{
return new ${class.name}( getDelegate() );
}
#if ( $class.superClass )
@Override
#end
public ${packageModelV4}.${class.name} getDelegate()
{
return ( ${packageModelV4}.${class.name} ) super.getDelegate();
}
#if ( ! $eq.empty )
@Override
public boolean equals( Object o )
{
if ( this == o )
{
return true;
}
if ( o == null || !( o instanceof ${class.name} ) )
{
return false;
}
${class.name} that = ( ${class.name} ) o;
return Objects.equals( this.delegate, that.delegate );
}
@Override
public int hashCode()
{
return getDelegate().hashCode();
}
#end
#if ( $class == $root )
public String getModelEncoding()
{
return getDelegate().getModelEncoding();
}
#end
#foreach ( $field in $class.getFields($version) )
#set ( $cap = $Helper.capitalise( $field.name ) )
#set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} )
#if ( $type == "boolean" || $type == "Boolean" )
#set ( $pfx = "is" )
#else
#set ( $pfx = "get" )
#end
#if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" )
@Nonnull
#end
public ${type} ${pfx}${cap}()
{
#if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
return new WrapperList<${field.to}, ${packageModelV4}.${field.to}>(
() -> getDelegate().get${cap}(), l -> update( getDelegate().with${cap}( l ) ),
d -> new ${field.to}( d, this ), ${field.to}::getDelegate );
#elseif ( $field.to == "String" && $field.type == "java.util.Properties" && $field.multiplicity == "*" )
return new WrapperProperties( () -> getDelegate().get${cap}(), this::set${cap} );
#elseif ( $field.to == "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
return new WrapperList<String, ${field.to}>( () -> getDelegate().get${cap}(), this::set${cap}, s -> s, s -> s );
#elseif ( $field.to )
return getDelegate().${pfx}${cap}() != null ? new ${field.to}( getDelegate().${pfx}${cap}(), this ) : null;
#elseif ( $field.type == "DOM" )
return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}(), this::replace ) : null;
#else
return getDelegate().${pfx}${cap}();
#end
}
public void set${cap}( ${type} ${field.name} )
{
#if ( $field.type == "DOM" )
if ( ! Objects.equals( ( ( Xpp3Dom ) ${field.name} ).getDom(), getDelegate().${pfx}${cap}() ) )
{
update( getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ) );
( ( Xpp3Dom ) ${field.name} ).setChildrenTracking( this::replace );
}
#elseif( $field.type == "java.util.Properties" )
Map<String, String> map = ${field.name}.entrySet().stream()
.collect( Collectors.toMap( e -> e.getKey().toString(), e -> e.getValue().toString() ) );
if ( !Objects.equals( map, getDelegate().get${cap}() ) )
{
update( getDelegate().with${cap}( map ) );
}
#else
if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) )
{
#if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
update( getDelegate().with${cap}(
${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) ) );
${field.name}.forEach( e -> e.childrenTracking = this::replace );
#elseif ( $field.to && $field.to != "String" )
update( getDelegate().with${cap}( ${field.name}.getDelegate() ) );
${field.name}.childrenTracking = this::replace;
#else
update( getDelegate().with${cap}( ${field.name} ) );
#end
}
#end
}
#if ( $field.type == "java.util.List" && $field.multiplicity == "*" )
#set ( $v = $Helper.singular( ${field.name} ) )
#set ( $scap = $Helper.capitalise( $v ) )
public void add${scap}( ${field.to} ${v} )
{
#if ( $field.to == "String" )
update( getDelegate().with${cap}(
Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v} ) )
.collect( Collectors.toList() ) ) );
#else
update( getDelegate().with${cap}(
Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) )
.collect( Collectors.toList() ) ) );
${v}.childrenTracking = this::replace;
#end
}
public void remove${scap}( ${field.to} ${v} )
{
#if ( $field.to == "String" )
update( getDelegate().with${cap}(
getDelegate().get${cap}().stream()
.filter( e -> !Objects.equals( e, ${v} ) )
.collect( Collectors.toList() ) ) );
#else
update( getDelegate().with${cap}(
getDelegate().get${cap}().stream()
.filter( e -> !Objects.equals( e, ${v} ) )
.collect( Collectors.toList() ) ) );
${v}.childrenTracking = null;
#end
}
#end
#end
public InputLocation getLocation( Object key )
{
${packageModelV4}.InputLocation loc = getDelegate().getLocation( key );
return loc != null ? new InputLocation( loc ) : null;
}
public void setLocation( Object key, InputLocation location )
{
update( ${packageModelV4}.${class.name}.newBuilder( getDelegate(), true )
.location( key, location.toApiLocation() ).build() );
}
protected boolean replace( Object oldDelegate, Object newDelegate )
{
if ( super.replace( oldDelegate, newDelegate ) )
{
return true;
}
#foreach ( $field in $class.getFields($version) )
#set ( $cap = $Helper.capitalise( $field.name ) )
#set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} )
#if ( $field.to && $field.multiplicity != "*" )
if ( oldDelegate == getDelegate().get${cap}() )
{
update( getDelegate().with${cap}( ( ${packageModelV4}.${field.to} ) newDelegate ) );
return true;
}
#elseif ( $field.type == "java.util.List" && $field.to != "String" )
if ( getDelegate().get${cap}().contains( oldDelegate ) )
{
List<${packageModelV4}.${field.to}> list = new ArrayList<>( getDelegate().get${cap}() );
list.replaceAll( d -> d == oldDelegate ? ( ${packageModelV4}.${field.to} ) newDelegate : d );
update( getDelegate().with${cap}( list ) );
return true;
}
#elseif ( $field.type == "DOM" )
if ( getDelegate().get${cap}() == oldDelegate )
{
update( getDelegate().with${cap}( ( org.apache.maven.api.xml.XmlNode ) newDelegate ) );
}
#end
#end
return false;
}
public static List<${packageModelV4}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list )
{
return list != null ? new WrapperList<>( list, ${class.name}::getDelegate, ${class.name}::new ) : null;
}
public static List<${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV3( List<${packageModelV4}.${class.name}> list )
{
return list != null ? new WrapperList<>( list, ${class.name}::new, ${class.name}::getDelegate ) : null;
}
#foreach ( $cs in $class.getCodeSegments($version) )
$cs.code
#end
}
#end
#end

View File

@ -43,6 +43,7 @@
#set ( $dummy = $imports.add( "java.util.HashMap" ) )
#set ( $dummy = $imports.add( "java.util.List" ) )
#set ( $dummy = $imports.add( "java.util.Map" ) )
#set ( $dummy = $imports.add( "java.util.Objects" ) )
#set ( $dummy = $imports.add( "java.util.stream.Collectors" ) )
#set ( $dummy = $imports.add( "java.util.stream.Stream" ) )
#set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) )
@ -82,7 +83,8 @@
#end
#end
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} template, any modifications will be overwritten.
// Generated by Modello Velocity from ${template}
// template, any modifications will be overwritten.
// ==============================================================
package ${package};
@ -94,13 +96,11 @@ import $imp;
public class ${class.name}
#if ( $class.superClass )
extends ${class.superClass}
#end
implements Serializable, Cloneable
{
#if ( ! $class.superClass )
${packageModelV4}.${class.name} delegate;
#else
extends BaseObject
#end
{
public ${class.name}()
{
@ -109,11 +109,12 @@ public class ${class.name}
public ${class.name}( ${packageModelV4}.${class.name} delegate )
{
#if ( $class.superClass )
super( delegate );
#else
this.delegate = delegate;
#end
this( delegate, null );
}
public ${class.name}( ${packageModelV4}.${class.name} delegate, BaseObject parent )
{
super( delegate, parent );
}
public ${class.name} clone()
@ -126,14 +127,9 @@ public class ${class.name}
#end
public ${packageModelV4}.${class.name} getDelegate()
{
#if ( $class.superClass )
return ( ${packageModelV4}.${class.name} ) delegate;
#else
return delegate;
#end
return ( ${packageModelV4}.${class.name} ) super.getDelegate();
}
#if ( ! $eq.empty )
@Override
public boolean equals( Object o )
{
@ -155,7 +151,6 @@ public class ${class.name}
return getDelegate().hashCode();
}
#end
#if ( $class == $root )
public String getModelEncoding()
{
@ -178,16 +173,16 @@ public class ${class.name}
{
#if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
return new WrapperList<${field.to}, ${packageModelV4}.${field.to}>(
getDelegate()::get${cap}, l -> delegate = getDelegate().with${cap}( l ),
${field.to}::new, ${field.to}::getDelegate );
() -> getDelegate().get${cap}(), l -> update( getDelegate().with${cap}( l ) ),
d -> new ${field.to}( d, this ), ${field.to}::getDelegate );
#elseif ( $field.to == "String" && $field.type == "java.util.Properties" && $field.multiplicity == "*" )
return new WrapperProperties( getDelegate()::get${cap}, this::set${cap} );
return new WrapperProperties( () -> getDelegate().get${cap}(), this::set${cap} );
#elseif ( $field.to == "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
return new WrapperList<String, ${field.to}>( getDelegate()::get${cap}, this::set${cap}, s -> s, s -> s );
return new WrapperList<String, ${field.to}>( () -> getDelegate().get${cap}(), this::set${cap}, s -> s, s -> s );
#elseif ( $field.to )
return getDelegate().${pfx}${cap}() != null ? new ${field.to}( getDelegate().${pfx}${cap}() ) : null;
return getDelegate().${pfx}${cap}() != null ? new ${field.to}( getDelegate().${pfx}${cap}(), this ) : null;
#elseif ( $field.type == "DOM" )
return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}() ) : null;
return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}(), this::replace ) : null;
#else
return getDelegate().${pfx}${cap}();
#end
@ -196,18 +191,32 @@ public class ${class.name}
public void set${cap}( ${type} ${field.name} )
{
#if ( $field.type == "DOM" )
delegate = getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() );
if ( ! Objects.equals( ( ( Xpp3Dom ) ${field.name} ).getDom(), getDelegate().${pfx}${cap}() ) )
{
update( getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ) );
( ( Xpp3Dom ) ${field.name} ).setChildrenTracking( this::replace );
}
#elseif( $field.type == "java.util.Properties" )
Map<String, String> map = ${field.name}.entrySet().stream()
.collect( Collectors.toMap( e -> e.getKey().toString(), e -> e.getValue().toString() ) );
delegate = getDelegate().with${cap}( map );
#elseif ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
delegate = getDelegate().with${cap}(
${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) );
#elseif ( $field.to && $field.to != "String" )
delegate = getDelegate().with${cap}( ${field.name}.getDelegate() );
if ( !Objects.equals( map, getDelegate().get${cap}() ) )
{
update( getDelegate().with${cap}( map ) );
}
#else
delegate = getDelegate().with${cap}( ${field.name} );
if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) )
{
#if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
update( getDelegate().with${cap}(
${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) ) );
${field.name}.forEach( e -> e.childrenTracking = this::replace );
#elseif ( $field.to && $field.to != "String" )
update( getDelegate().with${cap}( ${field.name}.getDelegate() ) );
${field.name}.childrenTracking = this::replace;
#else
update( getDelegate().with${cap}( ${field.name} ) );
#end
}
#end
}
@ -217,13 +226,30 @@ public class ${class.name}
public void add${scap}( ${field.to} ${v} )
{
#if ( $field.to == "String" )
delegate = getDelegate().with${cap}(
update( getDelegate().with${cap}(
Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v} ) )
.collect( Collectors.toList() ) );
.collect( Collectors.toList() ) ) );
#else
delegate = getDelegate().with${cap}(
update( getDelegate().with${cap}(
Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) )
.collect( Collectors.toList() ) );
.collect( Collectors.toList() ) ) );
${v}.childrenTracking = this::replace;
#end
}
public void remove${scap}( ${field.to} ${v} )
{
#if ( $field.to == "String" )
update( getDelegate().with${cap}(
getDelegate().get${cap}().stream()
.filter( e -> !Objects.equals( e, ${v} ) )
.collect( Collectors.toList() ) ) );
#else
update( getDelegate().with${cap}(
getDelegate().get${cap}().stream()
.filter( e -> !Objects.equals( e, ${v} ) )
.collect( Collectors.toList() ) ) );
${v}.childrenTracking = null;
#end
}
@ -237,6 +263,53 @@ public class ${class.name}
#end
#end
#if ( $locationTracking )
public InputLocation getLocation( Object key )
{
${packageModelV4}.InputLocation loc = getDelegate().getLocation( key );
return loc != null ? new InputLocation( loc ) : null;
}
public void setLocation( Object key, InputLocation location )
{
update( ${packageModelV4}.${class.name}.newBuilder( getDelegate(), true )
.location( key, location.toApiLocation() ).build() );
}
#end
protected boolean replace( Object oldDelegate, Object newDelegate )
{
if ( super.replace( oldDelegate, newDelegate ) )
{
return true;
}
#foreach ( $field in $class.getFields($version) )
#set ( $cap = $Helper.capitalise( $field.name ) )
#set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} )
#if ( $field.to && $field.multiplicity != "*" )
if ( oldDelegate == getDelegate().get${cap}() )
{
update( getDelegate().with${cap}( ( ${packageModelV4}.${field.to} ) newDelegate ) );
return true;
}
#elseif ( $field.type == "java.util.List" && $field.to != "String" )
if ( getDelegate().get${cap}().contains( oldDelegate ) )
{
List<${packageModelV4}.${field.to}> list = new ArrayList<>( getDelegate().get${cap}() );
list.replaceAll( d -> d == oldDelegate ? ( ${packageModelV4}.${field.to} ) newDelegate : d );
update( getDelegate().with${cap}( list ) );
return true;
}
#elseif ( $field.type == "DOM" )
if ( getDelegate().get${cap}() == oldDelegate )
{
update( getDelegate().with${cap}( ( org.apache.maven.api.xml.XmlNode ) newDelegate ) );
}
#end
#end
return false;
}
public static List<${packageModelV4}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list )
{
return list != null ? new WrapperList<>( list, ${class.name}::getDelegate, ${class.name}::new ) : null;

View File

@ -85,7 +85,8 @@
#end
#end
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} template, any modifications will be overwritten.
// Generated by Modello Velocity from ${template}
// template, any modifications will be overwritten.
// ==============================================================
package ${package};

View File

@ -29,7 +29,8 @@
#
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} template, any modifications will be overwritten.
// Generated by Modello Velocity from ${template}
// template, any modifications will be overwritten.
// ==============================================================
package ${package};

View File

@ -29,7 +29,8 @@
#
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} template, any modifications will be overwritten.
// Generated by Modello Velocity from ${template}
// template, any modifications will be overwritten.
// ==============================================================
package ${package};

View File

@ -29,7 +29,8 @@
#
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} template, any modifications will be overwritten.
// Generated by Modello Velocity from ${template}
// template, any modifications will be overwritten.
// ==============================================================
package ${package};

View File

@ -23,7 +23,8 @@
#
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} template, any modifications will be overwritten.
// Generated by Modello Velocity from ${template}
// template, any modifications will be overwritten.
// ==============================================================
package ${package};

View File

@ -29,7 +29,8 @@
#
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} template, any modifications will be overwritten.
// Generated by Modello Velocity from ${template}
// template, any modifications will be overwritten.
// ==============================================================
package ${package};

View File

@ -29,7 +29,8 @@
#
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
// =================== DO NOT EDIT THIS FILE ====================
// Generated by Modello Velocity from ${template} template, any modifications will be overwritten.
// Generated by Modello Velocity from ${template}
// template, any modifications will be overwritten.
// ==============================================================
package ${package};