Skip to content

Commit 3236869

Browse files
committed
Rework report creation to simplify usage
1 parent 405a05b commit 3236869

File tree

10 files changed

+658
-10
lines changed

10 files changed

+658
-10
lines changed

components/sbm-core/src/main/java/org/springframework/sbm/properties/api/PropertiesSource.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,14 @@
2828
import org.openrewrite.properties.tree.Properties.Entry;
2929
import org.openrewrite.properties.tree.Properties.File;
3030

31+
import java.io.ByteArrayInputStream;
32+
import java.io.IOException;
33+
import java.nio.charset.StandardCharsets;
3134
import java.nio.file.Path;
3235
import java.util.List;
3336
import java.util.Optional;
3437
import java.util.Set;
38+
import java.util.stream.Collectors;
3539

3640
// TODO: fcoi RewriteSourceFileHolder as member ?!
3741
@Slf4j
@@ -79,6 +83,17 @@ public Optional<String> getProperty(String key) {
7983

8084
}
8185

86+
public java.util.Properties getProperties() {
87+
String collect = getSourceFile().getContent().stream().map(c -> c.toString()).collect(Collectors.joining());
88+
try {
89+
java.util.Properties properties = new java.util.Properties(collect.length());
90+
properties.load(new ByteArrayInputStream(collect.getBytes(StandardCharsets.UTF_8)));
91+
return properties;
92+
} catch (IOException e) {
93+
throw new RuntimeException(e);
94+
}
95+
}
96+
8297
private void apply(Recipe r) {
8398
File rewriteResource = getSourceFile();
8499
List<Result> results = r.run(List.of(rewriteResource), executionContext).getResults();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.sbm.boot.upgrade_27_30.report;
17+
18+
import lombok.Getter;
19+
import lombok.RequiredArgsConstructor;
20+
import org.springframework.sbm.boot.properties.api.SpringBootApplicationProperties;
21+
import org.springframework.sbm.boot.properties.search.SpringBootApplicationPropertiesResourceListFilter;
22+
import org.springframework.sbm.build.migration.conditions.NoDependencyExistMatchingRegex;
23+
import org.springframework.sbm.engine.context.ProjectContext;
24+
import org.springframework.sbm.engine.recipe.Condition;
25+
26+
import java.nio.file.Path;
27+
import java.util.ArrayList;
28+
import java.util.HashMap;
29+
import java.util.List;
30+
import java.util.Map;
31+
import java.util.stream.Collectors;
32+
33+
/**
34+
* @author Fabian Krüger
35+
*/
36+
public class ChangesToDataProperties implements Condition, SpringBootUpgradeReportAction.Helper<List<ChangesToDataProperties.Match>> {
37+
38+
private Map<String, List<Match>> data = new HashMap<>();
39+
40+
@Override
41+
public String getDescription() {
42+
return "";
43+
}
44+
45+
@Override
46+
public boolean evaluate(ProjectContext context) {
47+
boolean noDepExists = new NoDependencyExistMatchingRegex(List.of("org\\.springframework\\.data\\:.*")).evaluate(
48+
context);
49+
List<SpringBootApplicationProperties> search = context.search(
50+
new SpringBootApplicationPropertiesResourceListFilter());
51+
search.forEach(p -> {
52+
Path absolutePath = p.getAbsolutePath();
53+
List<Object> propertiesFound = p
54+
.getProperties()
55+
.keySet()
56+
.stream()
57+
.filter(k -> k.toString().startsWith("spring.data."))
58+
.collect(Collectors.toList());
59+
60+
if(data.containsKey("matches")) {
61+
data.get("matches").add(new Match(absolutePath.toString(), p.getSourcePath().toString(), propertiesFound));
62+
} else {
63+
List<Match> matches = new ArrayList<>();
64+
matches.add(new Match(absolutePath.toString(), p.getSourcePath().toString(), propertiesFound));
65+
data.put("matches", matches);
66+
}
67+
});
68+
return noDepExists && !data.isEmpty();
69+
}
70+
71+
@Override
72+
public Map<String, List<Match>> getData(ProjectContext context) {
73+
return data;
74+
}
75+
76+
@RequiredArgsConstructor
77+
@Getter
78+
public class Match {
79+
private final String absolutePath;
80+
private final String relativePath;
81+
private final List<Object> propertiesFound;
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.sbm.boot.upgrade_27_30.report;
17+
18+
import com.fasterxml.jackson.annotation.JsonIgnore;
19+
import freemarker.cache.StringTemplateLoader;
20+
import freemarker.core.ParseException;
21+
import freemarker.template.*;
22+
import lombok.Data;
23+
import lombok.Getter;
24+
import lombok.NoArgsConstructor;
25+
import lombok.Setter;
26+
import lombok.experimental.SuperBuilder;
27+
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.context.ApplicationEventPublisher;
29+
import org.springframework.sbm.engine.context.ProjectContext;
30+
import org.springframework.sbm.engine.recipe.Action;
31+
import org.springframework.sbm.engine.recipe.Condition;
32+
33+
import java.io.IOException;
34+
import java.io.StringWriter;
35+
import java.util.ArrayList;
36+
import java.util.HashMap;
37+
import java.util.List;
38+
import java.util.Map;
39+
40+
/**
41+
* @author Fabian Krüger
42+
*/
43+
@Setter
44+
@Getter
45+
@SuperBuilder
46+
@NoArgsConstructor
47+
public class SpringBootUpgradeReportAction implements Action {
48+
49+
private Condition condition;
50+
@JsonIgnore
51+
@Autowired
52+
private SpringBootUpgradeReportRenderer upgradeReportRenderer;
53+
@JsonIgnore
54+
private Configuration configuration;
55+
@JsonIgnore
56+
private StringTemplateLoader stringLoader;
57+
58+
@Data
59+
@NoArgsConstructor
60+
@Getter
61+
@Setter
62+
public class Section {
63+
String title;
64+
String info;
65+
String reason;
66+
String todos;
67+
@JsonIgnore
68+
Helper helper;
69+
70+
public String render(ProjectContext context) {
71+
if (getHelper().evaluate(context)) {
72+
Map<String, Object> params = new HashMap<>();
73+
if (getHelper() != null) {
74+
params = getHelper().getData(context);
75+
}
76+
77+
try (StringWriter writer = new StringWriter()) {
78+
stringLoader.putTemplate("section",
79+
"##" + getTitle() +
80+
"\n" +
81+
getInfo() +
82+
"\n" +
83+
getReason() +
84+
"\n" +
85+
getTodos());
86+
Template t = configuration.getTemplate("section");
87+
t.process(params, writer);
88+
String s = writer.toString();
89+
System.out.println(s);
90+
return s;
91+
} catch (TemplateException e) {
92+
throw new RuntimeException(e);
93+
} catch (TemplateNotFoundException e) {
94+
throw new RuntimeException(e);
95+
} catch (ParseException e) {
96+
throw new RuntimeException(e);
97+
} catch (MalformedTemplateNameException e) {
98+
throw new RuntimeException(e);
99+
} catch (IOException e) {
100+
throw new RuntimeException(e);
101+
}
102+
}
103+
return "";
104+
}
105+
// Condition condition;
106+
// DataProvider dataProvider;
107+
}
108+
109+
public interface Helper<T> extends Condition {
110+
<T> Map<String, T> getData(ProjectContext context);
111+
}
112+
113+
List<Section> sections;
114+
115+
@Override
116+
public String getDescription() {
117+
return "The description";
118+
}
119+
120+
@Override
121+
public String getDetailedDescription() {
122+
return "The detailed description";
123+
}
124+
125+
@Override
126+
public Condition getCondition() {
127+
return condition;
128+
}
129+
130+
@Override
131+
public void apply(ProjectContext context) {
132+
133+
List<String> renderedSections = new ArrayList<>();
134+
135+
Version version = new Version("2.3.0");
136+
configuration = new Configuration(version);
137+
stringLoader = new StringTemplateLoader();
138+
configuration.setTemplateLoader(stringLoader);
139+
140+
sections.stream().forEach(section -> {
141+
renderedSections.add(section.render(context));
142+
});
143+
renderReport(renderedSections, configuration, stringLoader);
144+
}
145+
146+
private void renderReport(List<String> sections, Configuration configuration, StringTemplateLoader stringLoader) {
147+
try (StringWriter writer = new StringWriter()) {
148+
String content = """
149+
<#list sections as changeSection>
150+
section: ${changeSection}
151+
</#list>
152+
""";
153+
stringLoader.putTemplate("report", content);
154+
Template report = configuration.getTemplate("report");// Template.getPlainTextTemplate("report", content, configuration);
155+
report.process(Map.of("sections", sections), writer);
156+
String s = writer.toString();
157+
System.out.println(s);
158+
upgradeReportRenderer.renderReport(s);
159+
} catch (IOException e) {
160+
throw new RuntimeException(e);
161+
} catch (TemplateException e) {
162+
throw new RuntimeException(e);
163+
}
164+
}
165+
166+
@Override
167+
public void applyInternal(ProjectContext context) {
168+
apply(context);
169+
}
170+
171+
@Override
172+
public ApplicationEventPublisher getEventPublisher() {
173+
return null;
174+
}
175+
176+
@Override
177+
public boolean isAutomated() {
178+
return false;
179+
}
180+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.sbm.boot.upgrade_27_30.report;
17+
18+
import com.fasterxml.jackson.databind.JsonNode;
19+
import com.fasterxml.jackson.databind.ObjectMapper;
20+
import com.fasterxml.jackson.databind.node.ArrayNode;
21+
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
22+
import org.springframework.sbm.engine.recipe.Action;
23+
import org.springframework.sbm.engine.recipe.ActionDeserializer;
24+
import org.springframework.stereotype.Component;
25+
26+
import java.lang.reflect.Constructor;
27+
import java.lang.reflect.InvocationTargetException;
28+
29+
/**
30+
* @author Fabian Krüger
31+
*/
32+
@Component
33+
public class SpringBootUpgradeReportActionDeserializer implements ActionDeserializer {
34+
@Override
35+
public Action deserialize(ObjectMapper tolerantObjectMapper, Class<? extends Action> actionClass, JsonNode node, AutowireCapableBeanFactory beanFactory) {
36+
try {
37+
SpringBootUpgradeReportAction action = (SpringBootUpgradeReportAction) tolerantObjectMapper.convertValue(node, actionClass);
38+
JsonNode sections = node.get("sections");
39+
if (sections != null) {
40+
if(ArrayNode.class.isInstance(sections)) {
41+
ArrayNode arrayNode = (ArrayNode) sections;
42+
for(int i=0; i < arrayNode.size(); i++) {
43+
JsonNode helper = arrayNode.get(i).get("helper");
44+
String type = helper.textValue();
45+
Class<?> aClass = Class.forName(type);
46+
Constructor<?> constructor = aClass.getConstructor(null);
47+
Object o = constructor.newInstance();
48+
SpringBootUpgradeReportAction.Helper cast = (SpringBootUpgradeReportAction.Helper) aClass.cast(o);
49+
action.getSections().get(i).setHelper(cast);
50+
}
51+
}
52+
// YamlResourceLoader yamlResourceLoader = new YamlResourceLoader(
53+
// new ByteArrayInputStream(sections.toString().getBytes(StandardCharsets.UTF_8)),
54+
// URI.create("recipe.yaml"), new Properties());
55+
// String type = sections.textValue();
56+
// ((MultiModuleHandler) o).setAction(action);
57+
} else {
58+
throw new IllegalArgumentException("Could not find required field 'sections' for SpringBootUpgradeReportAction with description '"+action.getDescription()+"'.");
59+
}
60+
return action;
61+
} catch (ClassNotFoundException e) {
62+
throw new RuntimeException(e);
63+
} catch (NoSuchMethodException e) {
64+
throw new RuntimeException(e);
65+
} catch (InvocationTargetException e) {
66+
throw new RuntimeException(e);
67+
} catch (InstantiationException e) {
68+
throw new RuntimeException(e);
69+
} catch (IllegalAccessException e) {
70+
throw new RuntimeException(e);
71+
}
72+
}
73+
74+
@Override
75+
public boolean canHandle(Class<? extends Action> key) {
76+
return SpringBootUpgradeReportAction.class.isAssignableFrom(key);
77+
}
78+
}

0 commit comments

Comments
 (0)