Skip to content

Commit a0bde50

Browse files
committed
[MNG-8214] Improve model velocity template to support subclasses
This makes the constructor protected and takes the Builder as argument
1 parent 7e550ef commit a0bde50

File tree

3 files changed

+104
-64
lines changed

3 files changed

+104
-64
lines changed

api/maven-api-plugin/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ under the License.
3939
<groupId>org.apache.maven</groupId>
4040
<artifactId>maven-api-xml</artifactId>
4141
</dependency>
42+
<dependency>
43+
<groupId>org.junit.jupiter</groupId>
44+
<artifactId>junit-jupiter-api</artifactId>
45+
<scope>test</scope>
46+
</dependency>
4247
</dependencies>
4348

4449
<build>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.api.plugin.descriptor.another;
20+
21+
import org.apache.maven.api.plugin.descriptor.PluginDescriptor;
22+
import org.junit.jupiter.api.Test;
23+
24+
import static org.junit.jupiter.api.Assertions.assertEquals;
25+
26+
/**
27+
* Verifies that subclasses from generated model classes are possible.
28+
*/
29+
class ExtendedPluginDescriptorTest {
30+
31+
/**
32+
* A subclass of the generated class {@link PluginDescriptor} that adds an additional field.
33+
*/
34+
public static class ExtendedPluginDescriptor extends PluginDescriptor {
35+
36+
private final String additionalField;
37+
38+
protected ExtendedPluginDescriptor(Builder builder) {
39+
super(builder);
40+
this.additionalField = builder.additionalField;
41+
}
42+
43+
public String getAdditionalField() {
44+
return additionalField;
45+
}
46+
47+
public static class Builder extends PluginDescriptor.Builder {
48+
protected String additionalField;
49+
50+
public Builder() {
51+
super(false);
52+
}
53+
54+
public Builder additionalField(String additionalField) {
55+
this.additionalField = additionalField;
56+
return this;
57+
}
58+
59+
public ExtendedPluginDescriptor build() {
60+
return new ExtendedPluginDescriptor(this);
61+
}
62+
}
63+
}
64+
65+
@Test
66+
void testExtendedPluginDescriptor() {
67+
ExtendedPluginDescriptor.Builder builder = new ExtendedPluginDescriptor.Builder();
68+
// make sure to call the subclasses' builder methods first, otherwise fluent API would not work
69+
builder.additionalField("additional")
70+
.groupId("org.apache.maven")
71+
.artifactId("maven-plugin-api")
72+
.version("1.0.0");
73+
ExtendedPluginDescriptor descriptor = builder.build();
74+
assertEquals("additional", descriptor.getAdditionalField());
75+
assertEquals("org.apache.maven", descriptor.getGroupId());
76+
}
77+
}

src/mdo/model.vm

Lines changed: 22 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -145,55 +145,39 @@ public class ${class.name}
145145
#end
146146

147147
/**
148-
* Constructor for this class, package protected.
148+
* Constructor for this class, to be called from its subclasses and {@link Builder}.
149149
* @see Builder#build()
150150
*/
151-
${class.name}(
152-
#if ( $class == $root )
153-
String namespaceUri,
154-
String modelEncoding,
155-
#end
156-
#foreach ( $field in $allFields )
157-
#set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" )
158-
#set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} )
159-
#if ( $type.startsWith("List<") )
160-
#set ( $type = ${type.replace('List<','Collection<')} )
161-
#end
162-
$type $field.name${sep}
163-
#end
164-
#if ( $locationTracking )
165-
Map<Object, InputLocation> locations,
166-
InputLocation importedFrom
167-
#end
168-
) {
151+
protected ${class.name}(Builder builder) {
169152
#if ( $class.superClass )
170-
super(
171-
#foreach ( $field in $inheritedFields )
172-
#set ( $sep = "#if(${locationTracking}||$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" )
173-
${field.name}${sep}
174-
#end
175-
#if ( $locationTracking )
176-
locations,
177-
importedFrom
178-
#end
179-
);
153+
super(builder);
180154
#end
181155
#if ( $class == $root )
182-
this.namespaceUri = namespaceUri;
183-
this.modelEncoding = modelEncoding;
156+
this.namespaceUri = builder.namespaceUri != null ? builder.namespaceUri : (builder.base != null ? builder.base.namespaceUri : null);
157+
this.modelEncoding = builder.modelEncoding != null ? builder.modelEncoding : (builder.base != null ? builder.base.modelEncoding : "UTF-8");
184158
#end
185159
#foreach ( $field in $class.getFields($version) )
186160
#if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" || $field.type == "java.util.Map" )
187-
this.${field.name} = ImmutableCollections.copy(${field.name});
161+
this.${field.name} = ImmutableCollections.copy(builder.${field.name} != null ? builder.${field.name} : (builder.base != null ? builder.base.${field.name} : null));
188162
#else
189-
this.${field.name} = ${field.name};
163+
#if ( $field.type == "boolean" || $field.type == "int" )
164+
this.${field.name} = builder.${field.name} != null ? builder.${field.name} : (builder.base != null ? builder.base.${field.name} : ${field.defaultValue});
165+
#else
166+
this.${field.name} = builder.${field.name} != null ? builder.${field.name} : (builder.base != null ? builder.base.${field.name} : null);
167+
#end
190168
#end
191169
#end
192170
#if ( $locationTracking )
171+
Map<Object, InputLocation> newlocs = builder.locations != null ? builder.locations : Collections.emptyMap();
172+
Map<Object, InputLocation> oldlocs = builder.base != null && builder.base.locations != null ? builder.base.locations : Collections.emptyMap();
193173
#if ( ! $class.superClass )
194-
this.locations = ImmutableCollections.copy(locations);
195-
this.importedFrom = importedFrom;
174+
this.locations = new HashMap<>();
175+
this.importedFrom = builder.importedFrom;
176+
this.locations.put("", newlocs.containsKey("") ? newlocs.get("") : oldlocs.get(""));
196177
#end
178+
#foreach ( $field in $class.getFields($version) )
179+
this.locations.put("${field.name}", newlocs.containsKey("${field.name}") ? newlocs.get("${field.name}") : oldlocs.get("${field.name}"));
180+
#end
197181
#end
198182
}
199183

@@ -406,7 +390,7 @@ public class ${class.name}
406390
InputLocation importedFrom;
407391
#end
408392

409-
Builder(boolean withDefaults) {
393+
protected Builder(boolean withDefaults) {
410394
#if ( $class.superClass )
411395
super(withDefaults);
412396
#end
@@ -424,7 +408,7 @@ public class ${class.name}
424408
}
425409
}
426410

427-
Builder(${class.name} base, boolean forceCopy) {
411+
protected Builder(${class.name} base, boolean forceCopy) {
428412
#if ( $class.superClass )
429413
super(base, forceCopy);
430414
#end
@@ -500,33 +484,7 @@ public class ${class.name}
500484
) {
501485
return base;
502486
}
503-
#if ( $locationTracking )
504-
Map<Object, InputLocation> newlocs = this.locations != null ? this.locations : Collections.emptyMap();
505-
Map<Object, InputLocation> oldlocs = this.base != null && this.base.locations != null ? this.base.locations : Collections.emptyMap();
506-
Map<Object, InputLocation> locations = new HashMap<>();
507-
locations.put("", newlocs.containsKey("") ? newlocs.get("") : oldlocs.get(""));
508-
#foreach ( $field in $allFields )
509-
locations.put("${field.name}", newlocs.containsKey("${field.name}") ? newlocs.get("${field.name}") : oldlocs.get("${field.name}"));
510-
#end
511-
#end
512-
return new ${class.name}(
513-
#if ( $class == $root )
514-
namespaceUri != null ? namespaceUri : (base != null ? base.namespaceUri : ""),
515-
modelEncoding != null ? modelEncoding : (base != null ? base.modelEncoding : "UTF-8"),
516-
#end
517-
#foreach ( $field in $allFields )
518-
#set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" )
519-
#if ( $field.type == "boolean" || $field.type == "int" )
520-
${field.name} != null ? ${field.name} : (base != null ? base.${field.name} : ${field.defaultValue})${sep}
521-
#else
522-
${field.name} != null ? ${field.name} : (base != null ? base.${field.name} : null)${sep}
523-
#end
524-
#end
525-
#if ( $locationTracking )
526-
locations,
527-
importedFrom
528-
#end
529-
);
487+
return new ${class.name}(this);
530488
}
531489
}
532490

0 commit comments

Comments
 (0)