Skip to content

Commit cb4f410

Browse files
committed
#979: Added changeRecorder to display-property-updates, display-parent-updates, display-dependency-updates, display-extension-updates
1 parent c8e6880 commit cb4f410

File tree

28 files changed

+418
-181
lines changed

28 files changed

+418
-181
lines changed

versions-api/src/main/java/org/codehaus/mojo/versions/api/recording/VersionChangeRecorderFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
public interface VersionChangeRecorderFactory {
1414

1515
/**
16-
* Creates a new {@link VersionChangeRecorder} instance.
16+
* Creates a new {@link VersionChangeRecorder} instance. Convenience method without any changeRendererOptions.
1717
*
1818
* @param mavenSession {@link MavenSession} instance
1919
* @param mojoExecution {@link MojoExecution} instance
20+
* @param log {@link Log} instance
2021
* @return a new {@link VersionChangeRecorder} instance
2122
*/
2223
default VersionChangeRecorder create(MavenSession mavenSession, MojoExecution mojoExecution, Log log) {
@@ -28,6 +29,7 @@ default VersionChangeRecorder create(MavenSession mavenSession, MojoExecution mo
2829
*
2930
* @param mavenSession {@link MavenSession} instance
3031
* @param mojoExecution {@link MojoExecution} instance
32+
* @param log {@link Log} instance
3133
* @param changeRendererOptions {@link Properties} custom properties to pass to the renderer
3234
* @return a new {@link VersionChangeRecorder} instance
3335
*/

versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvDeserializer.java

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
import org.codehaus.mojo.versions.model.ChangeRecorderLog;
1212
import org.codehaus.mojo.versions.model.DependencyChangeKind;
1313
import org.codehaus.mojo.versions.model.DependencyVersionChange;
14+
import org.codehaus.mojo.versions.model.ExtensionVersionChange;
1415
import org.codehaus.mojo.versions.model.ObjectFactory;
16+
import org.codehaus.mojo.versions.model.PluginVersionChange;
1517
import org.codehaus.mojo.versions.model.PropertyVersionChange;
1618
import org.codehaus.mojo.versions.model.VersionsExecution;
1719
import org.codehaus.mojo.versions.model.xjb.ZonedDateTimeXmlAdapter;
@@ -66,24 +68,48 @@ public ChangeRecorderLog deserialize(JsonParser p, DeserializationContext ctxt)
6668
exec.setDate(ZonedDateTimeXmlAdapter.parse(node.get("date").asText()));
6769
}
6870

69-
if (node.hasNonNull("kind") && !node.get("kind").asText().isEmpty()) {
71+
String updateClass = node.get("updateClass").asText();
72+
if ("dependency".equals(updateClass)) {
7073
DependencyVersionChange dep = objectFactory.createDependencyVersionChange();
71-
dep.setKind(DependencyChangeKind.valueOf(node.get("kind").asText()));
74+
dep.setKind(DependencyChangeKind.fromValue(node.get("kind").asText()));
7275
dep.setGroupId(node.get("groupId").asText());
7376
dep.setArtifactId(node.get("artifactId").asText());
74-
dep.setOldVersion(node.get("oldVersion").asText());
75-
dep.setNewVersion(node.get("newVersion").asText());
77+
if (node.hasNonNull("oldValue")) {
78+
dep.setOldVersion(node.get("oldValue").asText());
79+
}
80+
dep.setNewVersion(node.get("newValue").asText());
7681
exec.getVersionChanges().add(dep);
77-
} else if (node.hasNonNull("property")
78-
&& !node.get("property").asText().isEmpty()) {
82+
} else if ("extension".equals(updateClass)) {
83+
ExtensionVersionChange ext = objectFactory.createExtensionVersionChange();
84+
ext.setGroupId(node.get("groupId").asText());
85+
ext.setArtifactId(node.get("artifactId").asText());
86+
if (node.hasNonNull("oldValue")) {
87+
ext.setOldVersion(node.get("oldValue").asText());
88+
}
89+
ext.setNewVersion(node.get("newValue").asText());
90+
exec.getVersionChanges().add(ext);
91+
} else if ("plugin".equals(updateClass)) {
92+
PluginVersionChange plugin = objectFactory.createPluginVersionChange();
93+
plugin.setGroupId(node.get("groupId").asText());
94+
plugin.setArtifactId(node.get("artifactId").asText());
95+
if (node.hasNonNull("oldValue")) {
96+
plugin.setOldVersion(node.get("oldValue").asText());
97+
}
98+
plugin.setNewVersion(node.get("newValue").asText());
99+
if (node.hasNonNull("minMavenVersion")) {
100+
plugin.setMinimumMavenVersion(node.get("minMavenVersion").asText());
101+
}
102+
exec.getVersionChanges().add(plugin);
103+
} else if ("property".equals(updateClass)) {
79104
PropertyVersionChange prop = objectFactory.createPropertyVersionChange();
80105
prop.setProperty(node.get("property").asText());
81106
prop.setOldValue(node.get("oldValue").asText());
82107
prop.setNewValue(node.get("newValue").asText());
83108
exec.getVersionChanges().add(prop);
109+
} else {
110+
throw new IOException("Unknown updateClass: " + updateClass);
84111
}
85112
}
86-
87113
return changeRecorderLog;
88114
}
89115
}

versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/ChangeRecorderLogCsvSerializer.java

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import com.fasterxml.jackson.dataformat.csv.CsvGenerator;
1010
import org.codehaus.mojo.versions.model.ChangeRecorderLog;
1111
import org.codehaus.mojo.versions.model.DependencyVersionChange;
12+
import org.codehaus.mojo.versions.model.ExtensionVersionChange;
13+
import org.codehaus.mojo.versions.model.PluginVersionChange;
1214
import org.codehaus.mojo.versions.model.PropertyVersionChange;
1315
import org.codehaus.mojo.versions.model.VersionChange;
1416
import org.codehaus.mojo.versions.model.VersionsExecution;
@@ -34,41 +36,82 @@ public void serialize(ChangeRecorderLog changeRecorderLog, JsonGenerator gen, Se
3436
String executionId = UUID.randomUUID().toString();
3537
for (VersionChange change : execution.getVersionChanges()) {
3638
// Start a new row
37-
csvGen.writeStartObject();
3839

39-
// Common fields
40+
csvGen.writeStartObject();
4041
csvGen.writeStringField("execution", executionId);
4142
csvGen.writeStringField("goal", execution.getGoal());
4243
csvGen.writeStringField(
4344
"date", execution.getDate() != null ? ZonedDateTimeXmlAdapter.print(execution.getDate()) : "");
44-
4545
if (change instanceof DependencyVersionChange) {
46-
DependencyVersionChange dep = (DependencyVersionChange) change;
47-
csvGen.writeStringField("kind", dep.getKind().name());
48-
csvGen.writeStringField("groupId", dep.getGroupId());
49-
csvGen.writeStringField("artifactId", dep.getArtifactId());
50-
csvGen.writeStringField("oldVersion", dep.getOldVersion());
51-
csvGen.writeStringField("newVersion", dep.getNewVersion());
52-
// leave property fields empty
53-
csvGen.writeStringField("property", "");
54-
csvGen.writeStringField("oldValue", "");
55-
csvGen.writeStringField("newValue", "");
46+
writeDependency(csvGen, (DependencyVersionChange) change);
47+
} else if (change instanceof ExtensionVersionChange) {
48+
writeExtension(csvGen, (ExtensionVersionChange) change);
5649
} else if (change instanceof PropertyVersionChange) {
57-
PropertyVersionChange prop = (PropertyVersionChange) change;
58-
// leave dependency fields empty
59-
csvGen.writeStringField("kind", "");
60-
csvGen.writeStringField("groupId", "");
61-
csvGen.writeStringField("artifactId", "");
62-
csvGen.writeStringField("oldVersion", "");
63-
csvGen.writeStringField("newVersion", "");
64-
// property fields
65-
csvGen.writeStringField("property", prop.getProperty());
66-
csvGen.writeStringField("oldValue", prop.getOldValue());
67-
csvGen.writeStringField("newValue", prop.getNewValue());
50+
writeProperty(csvGen, (PropertyVersionChange) change);
51+
} else if (change instanceof PluginVersionChange) {
52+
writePlugin(csvGen, (PluginVersionChange) change);
53+
} else {
54+
throw new IOException("Unknown VersionChange subtype: "
55+
+ change.getClass().getName());
6856
}
69-
7057
csvGen.writeEndObject();
7158
}
7259
}
7360
}
61+
62+
private static void writePlugin(CsvGenerator csvGen, PluginVersionChange plugin) throws IOException {
63+
csvGen.writeStringField("updateClass", "plugin");
64+
csvGen.writeOmittedField("kind");
65+
csvGen.writeStringField("groupId", plugin.getGroupId());
66+
csvGen.writeStringField("artifactId", plugin.getArtifactId());
67+
csvGen.writeOmittedField("property");
68+
if (plugin.getOldVersion() != null) {
69+
csvGen.writeStringField("oldValue", plugin.getOldVersion());
70+
} else {
71+
csvGen.writeOmittedField("oldValue");
72+
}
73+
csvGen.writeStringField("newValue", plugin.getNewVersion());
74+
csvGen.writeStringField("minMavenVersion", plugin.getMinimumMavenVersion());
75+
}
76+
77+
private static void writeProperty(CsvGenerator csvGen, PropertyVersionChange prop) throws IOException {
78+
csvGen.writeStringField("updateClass", "property");
79+
csvGen.writeOmittedField("kind");
80+
csvGen.writeOmittedField("groupId");
81+
csvGen.writeOmittedField("artifactId");
82+
csvGen.writeStringField("property", prop.getProperty());
83+
csvGen.writeStringField("oldValue", prop.getOldValue());
84+
csvGen.writeStringField("newValue", prop.getNewValue());
85+
csvGen.writeOmittedField("minMavenVersion");
86+
}
87+
88+
private static void writeDependency(CsvGenerator csvGen, DependencyVersionChange dep) throws IOException {
89+
csvGen.writeStringField("updateClass", "dependency");
90+
csvGen.writeStringField("kind", dep.getKind().value());
91+
csvGen.writeStringField("groupId", dep.getGroupId());
92+
csvGen.writeStringField("artifactId", dep.getArtifactId());
93+
csvGen.writeOmittedField("property");
94+
if (dep.getOldVersion() != null) {
95+
csvGen.writeStringField("oldValue", dep.getOldVersion());
96+
} else {
97+
csvGen.writeOmittedField("oldValue");
98+
}
99+
csvGen.writeStringField("newValue", dep.getNewVersion());
100+
csvGen.writeOmittedField("minMavenVersion");
101+
}
102+
103+
private static void writeExtension(CsvGenerator csvGen, ExtensionVersionChange ext) throws IOException {
104+
csvGen.writeStringField("updateClass", "extension");
105+
csvGen.writeOmittedField("kind");
106+
csvGen.writeStringField("groupId", ext.getGroupId());
107+
csvGen.writeStringField("artifactId", ext.getArtifactId());
108+
csvGen.writeOmittedField("property");
109+
if (ext.getOldVersion() != null) {
110+
csvGen.writeStringField("oldValue", ext.getOldVersion());
111+
} else {
112+
csvGen.writeOmittedField("oldValue");
113+
}
114+
csvGen.writeStringField("newValue", ext.getNewVersion());
115+
csvGen.writeOmittedField("minMavenVersion");
116+
}
74117
}

versions-common/src/main/java/org/codehaus/mojo/versions/recording/csv/CsvVersionChangeRenderer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,14 @@ public CsvVersionChangeRenderer(ObjectFactory objectFactory) {
5353
.addColumn("execution")
5454
.addColumn("goal")
5555
.addColumn("date")
56+
.addColumn("updateClass")
5657
.addColumn("kind")
5758
.addColumn("groupId")
5859
.addColumn("artifactId")
59-
.addColumn("oldVersion")
60-
.addColumn("newVersion")
6160
.addColumn("property")
6261
.addColumn("oldValue")
6362
.addColumn("newValue")
63+
.addColumn("minMavenVersion")
6464
.setColumnSeparator(';')
6565
.disableQuoteChar()
6666
.build()
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.codehaus.mojo.versions.recording.json;
2+
3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
5+
/**
6+
* Mix-in to instruct Jackson to omit null-valued properties during serialization.
7+
*/
8+
@JsonInclude(JsonInclude.Include.NON_NULL)
9+
public abstract class JsonIncludeNonNullMixIn {}

versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeModule.java

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22

33
import java.io.IOException;
44

5+
import com.fasterxml.jackson.core.JsonGenerator;
56
import com.fasterxml.jackson.core.JsonParser;
6-
import com.fasterxml.jackson.core.ObjectCodec;
77
import com.fasterxml.jackson.databind.DeserializationContext;
88
import com.fasterxml.jackson.databind.JsonDeserializer;
99
import com.fasterxml.jackson.databind.JsonMappingException;
10-
import com.fasterxml.jackson.databind.JsonNode;
10+
import com.fasterxml.jackson.databind.JsonSerializer;
11+
import com.fasterxml.jackson.databind.SerializerProvider;
12+
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
1113
import com.fasterxml.jackson.databind.module.SimpleModule;
12-
import org.codehaus.mojo.versions.model.DependencyVersionChange;
13-
import org.codehaus.mojo.versions.model.PropertyVersionChange;
14+
import com.fasterxml.jackson.databind.module.SimpleSerializers;
15+
import org.codehaus.mojo.versions.model.DependencyChangeKind;
1416
import org.codehaus.mojo.versions.model.VersionChange;
1517

1618
/**
@@ -23,21 +25,42 @@ public class JsonVersionChangeModule extends SimpleModule {
2325
/**
2426
* Creates a new module.
2527
*/
26-
public JsonVersionChangeModule() {
27-
addDeserializer(VersionChange.class, new JsonDeserializer<VersionChange>() {
28-
@Override
29-
public VersionChange deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
30-
ObjectCodec codec = p.getCodec();
31-
JsonNode node = codec.readTree(p);
32-
33-
if (node.has("kind")) {
34-
return codec.treeToValue(node, DependencyVersionChange.class);
35-
} else if (node.has("property")) {
36-
return codec.treeToValue(node, PropertyVersionChange.class);
37-
} else {
38-
throw new JsonMappingException(p, "Unknown VersionChange subtype: " + node.toString());
39-
}
28+
public JsonVersionChangeModule() {}
29+
30+
@Override
31+
public void setupModule(SetupContext context) {
32+
super.setupModule(context);
33+
34+
SimpleSerializers serializers = new SimpleSerializers();
35+
serializers.addSerializer(DependencyChangeKind.class, new DependencyChangeKindSerializer());
36+
context.addSerializers(serializers);
37+
38+
SimpleDeserializers deserializers = new SimpleDeserializers();
39+
deserializers.addDeserializer(DependencyChangeKind.class, new DependencyChangeKindDeserializer());
40+
context.addDeserializers(deserializers);
41+
}
42+
43+
private static final class DependencyChangeKindSerializer extends JsonSerializer<DependencyChangeKind> {
44+
@Override
45+
public void serialize(DependencyChangeKind value, JsonGenerator gen, SerializerProvider serializers)
46+
throws IOException {
47+
if (value == null) {
48+
gen.writeNull();
49+
} else {
50+
gen.writeString(value.value());
51+
}
52+
}
53+
}
54+
55+
private static final class DependencyChangeKindDeserializer extends JsonDeserializer<DependencyChangeKind> {
56+
@Override
57+
public DependencyChangeKind deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
58+
String text = p.getValueAsString();
59+
try {
60+
return DependencyChangeKind.fromValue(text);
61+
} catch (IllegalArgumentException e) {
62+
throw JsonMappingException.from(p, "Unknown DependencyChangeKind: " + text, e);
4063
}
41-
});
64+
}
4265
}
4366
}

versions-common/src/main/java/org/codehaus/mojo/versions/recording/json/JsonVersionChangeRenderer.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,18 @@
1919
import java.nio.file.Files;
2020
import java.nio.file.Path;
2121

22+
import com.fasterxml.jackson.annotation.JsonInclude;
2223
import com.fasterxml.jackson.core.exc.StreamReadException;
2324
import com.fasterxml.jackson.core.exc.StreamWriteException;
2425
import com.fasterxml.jackson.core.type.TypeReference;
2526
import com.fasterxml.jackson.databind.DatabindException;
2627
import com.fasterxml.jackson.databind.ObjectMapper;
27-
import com.fasterxml.jackson.databind.SerializationFeature;
2828
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
2929
import org.codehaus.mojo.versions.model.ChangeRecorderLog;
3030
import org.codehaus.mojo.versions.recording.ChangeRecorderRenderer;
3131

32+
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS;
33+
3234
/**
3335
* A JSON renderer for the {@link ChangeRecorderLog}
3436
*/
@@ -40,11 +42,24 @@ public class JsonVersionChangeRenderer implements ChangeRecorderRenderer {
4042
*/
4143
public JsonVersionChangeRenderer() {
4244
mapper = new ObjectMapper();
45+
// Do not serialize null-valued properties so attributes like oldVersion are omitted
46+
// from the JSON output when they are null. Register a mix-in annotated with
47+
// @JsonInclude(Include.NON_NULL) to avoid using deprecated or unavailable APIs.
48+
mapper.addMixIn(Object.class, JsonIncludeNonNullMixIn.class);
49+
// Register polymorphic mix-in for VersionChange so Jackson writes/reads
50+
// the "updateClass" discriminator automatically.
51+
mapper.addMixIn(
52+
org.codehaus.mojo.versions.model.VersionChange.class,
53+
org.codehaus.mojo.versions.recording.json.VersionChangeMixin.class);
4354
mapper.registerModule(new JavaTimeModule());
4455
mapper.registerModule(new JsonVersionChangeModule());
45-
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
56+
mapper.disable(WRITE_DATES_AS_TIMESTAMPS);
4657
}
4758

59+
// Local mix-in to exclude null-valued properties without touching generated models.
60+
@JsonInclude(JsonInclude.Include.NON_NULL)
61+
private abstract static class JsonIncludeNonNullMixIn {}
62+
4863
@Override
4964
public ChangeRecorderLog read(Path path) throws IOException {
5065
if (path == null || !Files.exists(path) || Files.size(path) == 0) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.codehaus.mojo.versions.recording.json;
2+
3+
import com.fasterxml.jackson.annotation.JsonSubTypes;
4+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
5+
import org.codehaus.mojo.versions.model.DependencyVersionChange;
6+
import org.codehaus.mojo.versions.model.ExtensionVersionChange;
7+
import org.codehaus.mojo.versions.model.PluginVersionChange;
8+
import org.codehaus.mojo.versions.model.PropertyVersionChange;
9+
10+
/**
11+
* Jackson mix-in to enable polymorphic (de)serialization of {@code VersionChange}
12+
* using an external discriminator property named "updateClass".
13+
*/
14+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "updateClass")
15+
@JsonSubTypes({
16+
@JsonSubTypes.Type(value = DependencyVersionChange.class, name = "dependency"),
17+
@JsonSubTypes.Type(value = PropertyVersionChange.class, name = "property"),
18+
@JsonSubTypes.Type(value = PluginVersionChange.class, name = "plugin"),
19+
@JsonSubTypes.Type(value = ExtensionVersionChange.class, name = "extension")
20+
})
21+
public abstract class VersionChangeMixin {}

0 commit comments

Comments
 (0)