or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-config.mdcore-model.mddependencies.mdindex.mdmodel-merging.mdprofiles.mdproject-metadata.mdrepositories.mdutility-classes.mdxml-io.md

model-merging.mddocs/

0

# Model Merging

1

2

Model inheritance and merging capabilities for parent-child POM relationships and profile integration. The ModelMerger class provides sophisticated merging logic that handles Maven's inheritance and composition patterns.

3

4

## Capabilities

5

6

### ModelMerger

7

8

The primary class responsible for merging Maven models, handling inheritance from parent POMs and profile integration.

9

10

```java { .api }

11

public class ModelMerger {

12

// Primary public merge method

13

public void merge(Model target, Model source, boolean sourceDominant, Map<?, ?> hints);

14

15

// Protected specific merge methods (for subclassing)

16

protected void mergeModel(Model target, Model source, boolean sourceDominant, Map<?, ?> hints);

17

protected void mergeModelBase(ModelBase target, ModelBase source, boolean sourceDominant, Map<?, ?> hints);

18

protected void mergeParent(Parent target, Parent source, boolean sourceDominant, Map<?, ?> hints);

19

protected void mergeBuild(Build target, Build source, boolean sourceDominant, Map<?, ?> hints);

20

protected void mergeBuildBase(BuildBase target, BuildBase source, boolean sourceDominant, Map<?, ?> hints);

21

protected void mergeProfile(Profile target, Profile source, boolean sourceDominant, Map<?, ?> hints);

22

23

// Protected dependency merging methods

24

protected void mergeDependency(Dependency target, Dependency source, boolean sourceDominant, Map<?, ?> hints);

25

protected void mergeDependencyManagement(DependencyManagement target, DependencyManagement source, boolean sourceDominant, Map<?, ?> hints);

26

27

// Protected plugin merging methods

28

protected void mergePlugin(Plugin target, Plugin source, boolean sourceDominant, Map<?, ?> hints);

29

protected void mergePluginManagement(PluginManagement target, PluginManagement source, boolean sourceDominant, Map<?, ?> hints);

30

protected void mergePluginExecution(PluginExecution target, PluginExecution source, boolean sourceDominant, Map<?, ?> hints);

31

32

// Protected repository merging methods

33

protected void mergeRepository(Repository target, Repository source, boolean sourceDominant, Map<?, ?> hints);

34

protected void mergeDistributionManagement(DistributionManagement target, DistributionManagement source, boolean sourceDominant, Map<?, ?> hints);

35

36

// Protected project information merging methods

37

protected void mergeOrganization(Organization target, Organization source, boolean sourceDominant, Map<?, ?> hints);

38

protected void mergeDeveloper(Developer target, Developer source, boolean sourceDominant, Map<?, ?> hints);

39

protected void mergeLicense(License target, License source, boolean sourceDominant, Map<?, ?> hints);

40

protected void mergeScm(Scm target, Scm source, boolean sourceDominant, Map<?, ?> hints);

41

42

// Protected activation merging methods

43

protected void mergeActivation(Activation target, Activation source, boolean sourceDominant, Map<?, ?> hints);

44

protected void mergeActivationProperty(ActivationProperty target, ActivationProperty source, boolean sourceDominant, Map<?, ?> hints);

45

protected void mergeActivationOS(ActivationOS target, ActivationOS source, boolean sourceDominant, Map<?, ?> hints);

46

protected void mergeActivationFile(ActivationFile target, ActivationFile source, boolean sourceDominant, Map<?, ?> hints);

47

}

48

```

49

50

**Note**: Most specific merge methods are `protected` and intended for subclassing the ModelMerger. For typical usage, developers should use the main public `merge()` method which internally calls the appropriate protected methods.

51

52

**Basic Usage Example:**

53

54

```java

55

import org.apache.maven.model.Model;

56

import org.apache.maven.model.merge.ModelMerger;

57

import java.util.HashMap;

58

import java.util.Map;

59

60

// Load parent and child models

61

Model parentModel = readParentPom();

62

Model childModel = readChildPom();

63

64

// Create merger and hints

65

ModelMerger merger = new ModelMerger();

66

Map<String, Object> hints = new HashMap<>();

67

68

// Merge parent into child (child properties take precedence)

69

merger.merge(childModel, parentModel, false, hints);

70

71

// Now childModel contains merged configuration

72

System.out.println("Merged project: " + childModel.getArtifactId());

73

```

74

75

### Merge Parameters

76

77

**`target`**: The model being merged into (typically the child model)

78

**`source`**: The model being merged from (typically the parent model)

79

**`sourceDominant`**: Controls merge precedence

80

- `false`: Target values take precedence (typical for child over parent)

81

- `true`: Source values take precedence (used for profile merging)

82

**`hints`**: Map providing merge customization options

83

84

### Parent-Child Inheritance

85

86

```java

87

// Typical parent-child POM inheritance

88

public void mergeParentInternal(Model child, Model parent) {

89

ModelMerger merger = new ModelMerger();

90

Map<String, Object> hints = new HashMap<>();

91

92

// Child overrides parent (sourceDominant = false)

93

merger.merge(child, parent, false, hints);

94

95

// Handle coordinate inheritance

96

if (child.getGroupId() == null) {

97

child.setGroupId(parent.getGroupId());

98

}

99

if (child.getVersion() == null) {

100

child.setVersion(parent.getVersion());

101

}

102

}

103

```

104

105

### Profile Merging

106

107

```java

108

// Merge active profiles into main model

109

public void mergeActiveProfiles(Model model, List<Profile> activeProfiles) {

110

ModelMerger merger = new ModelMerger();

111

Map<String, Object> hints = new HashMap<>();

112

113

for (Profile profile : activeProfiles) {

114

// Profile values override model values (sourceDominant = true)

115

merger.mergeModelBase(model, profile, true, hints);

116

117

// Merge profile build into model build

118

if (profile.getBuild() != null) {

119

if (model.getBuild() == null) {

120

model.setBuild(new Build());

121

}

122

merger.mergeBuildBase(model.getBuild(), profile.getBuild(), true, hints);

123

}

124

}

125

}

126

```

127

128

### Advanced Merging Options

129

130

The hints map can control specific merge behaviors:

131

132

```java

133

Map<String, Object> hints = new HashMap<>();

134

135

// Custom merge strategies for specific elements

136

hints.put("merge.dependencies", "append"); // Append rather than replace

137

hints.put("merge.plugins", "combine"); // Combine configurations

138

hints.put("merge.properties", "override"); // Override properties

139

140

ModelMerger merger = new ModelMerger();

141

merger.merge(target, source, false, hints);

142

```

143

144

### Merge Strategies

145

146

Different elements use different merge strategies:

147

148

**Override Strategy** (default for most scalar values):

149

- Target value used if present, otherwise source value

150

151

**Append Strategy** (used for lists like dependencies):

152

- Items from both target and source are combined

153

- Duplicates handled based on element key (e.g., groupId:artifactId for dependencies)

154

155

**Combine Strategy** (used for plugin configurations):

156

- XML configurations are merged at the DOM level

157

- Child elements override parent elements with same name

158

159

### Error Handling

160

161

```java

162

try {

163

ModelMerger merger = new ModelMerger();

164

merger.merge(childModel, parentModel, false, hints);

165

} catch (Exception e) {

166

// Handle merge conflicts or errors

167

System.err.println("Model merge failed: " + e.getMessage());

168

// Usually indicates circular inheritance or malformed models

169

}

170

```

171

172

### Complete Integration Example

173

174

```java

175

import org.apache.maven.model.Model;

176

import org.apache.maven.model.Profile;

177

import org.apache.maven.model.merge.ModelMerger;

178

import org.apache.maven.model.io.xpp3.MavenXpp3Reader;

179

import java.util.*;

180

181

public class ModelMergeExample {

182

183

public void performCompleteInheritance(String childPomPath, String parentPomPath,

184

List<String> activeProfileIds) throws Exception {

185

186

MavenXpp3Reader reader = new MavenXpp3Reader();

187

ModelMerger merger = new ModelMerger();

188

189

// Read models

190

Model childModel = reader.read(new FileReader(childPomPath));

191

Model parentModel = reader.read(new FileReader(parentPomPath));

192

193

// 1. Merge parent into child

194

Map<String, Object> hints = new HashMap<>();

195

merger.merge(childModel, parentModel, false, hints);

196

197

// 2. Handle coordinate inheritance

198

if (childModel.getGroupId() == null) {

199

childModel.setGroupId(parentModel.getGroupId());

200

}

201

if (childModel.getVersion() == null) {

202

childModel.setVersion(parentModel.getVersion());

203

}

204

205

// 3. Merge active profiles

206

for (Profile profile : childModel.getProfiles()) {

207

if (activeProfileIds.contains(profile.getId())) {

208

merger.mergeModelBase(childModel, profile, true, hints);

209

210

if (profile.getBuild() != null) {

211

if (childModel.getBuild() == null) {

212

childModel.setBuild(new Build());

213

}

214

merger.mergeBuildBase(childModel.getBuild(), profile.getBuild(), true, hints);

215

}

216

}

217

}

218

219

// Result: childModel now contains complete effective POM

220

System.out.println("Effective POM created for: " + childModel.getId());

221

}

222

}

223

```

224

225

### Key Merge Rules

226

227

1. **Scalar Values**: Child overrides parent unless child value is null

228

2. **Lists**: Combined with duplicates removed based on element key

229

3. **Maps/Properties**: Child properties override parent properties

230

4. **Plugin Configurations**: DOM-level merging with child elements taking precedence

231

5. **Profiles**: Profile values override model values when active

232

6. **Coordinates**: groupId and version inherited from parent if not specified in child