Skip to content

Commit

Permalink
Merge pull request #22 from TechnologyBrewery/18-group-notifications
Browse files Browse the repository at this point in the history
✨ allow notifications to be group across modules into a single notification just before console output
  • Loading branch information
d-ryan-ashcraft authored Jun 29, 2023
2 parents 3f3c9d5 + d664263 commit a257e18
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public void execute() throws MojoExecutionException {

// store notifications in the target directory between plugin invocations so they can be output
// at the end of the build:
notificationService.recordNotifications(project);
notificationService.recordNotifications(getProject());

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public abstract class AbstractNotification implements Notification {

protected String key;

protected String group;

protected Set<String> items;

/**
Expand All @@ -17,11 +19,16 @@ public abstract class AbstractNotification implements Notification {
* @param key notification identifier
* @param items set of strings to use in the notification
*/
public AbstractNotification(String key, Set<String> items) {
protected AbstractNotification(String key, Set<String> items) {
this.key = key;
this.items = items;
}

protected AbstractNotification(String key, String group, Set<String> items) {
this(key, items);
this.group = group;
}

/**
* {@inheritDoc}
*/
Expand All @@ -30,6 +37,13 @@ public String getKey() {
return key;
}

/**
* {@inheritDoc}
*/
public String getGroup() {
return group;
}

/**
* {@inheritDoc}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ public interface Notification {
*/
String getKey();

/**
* Returns a grouping that this notification should be displayed in conjunction with.
* @return group
*/
String getGroup();

/**
* Returns the list of action items to request from the user.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.maven.AbstractMavenLifecycleParticipant;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.technologybrewery.fermenter.mda.generator.GenerationException;
Expand All @@ -16,10 +18,14 @@
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

Expand All @@ -31,7 +37,9 @@
public class NotificationService extends AbstractMavenLifecycleParticipant {

private static final Logger logger = LoggerFactory.getLogger(NotificationService.class);
private static final String NOTIFICATION_DIRECTORY_PATH = "target/manual-action-notifications/";
private static final String NOTIFICATION_DIR_NAME = "manual-action-notifications";
private static final String NOTIFICATION_DIRECTORY_PATH = "target/" + NOTIFICATION_DIR_NAME + "/";
public static final String GROUP = "group://";

private MavenSession session;

Expand Down Expand Up @@ -95,9 +103,10 @@ public void recordNotifications(MavenProject project) {
Map<String, Notification> notificationsForFile = entry.getValue();
int i = 0;
for (Map.Entry<String, Notification> subMapEntry : notificationsForFile.entrySet()) {
File outputFile = new File(projectParentFile, FilenameUtils.getName(fileName + "-" + i++ + ".txt"));
File notificationParentFile = getNotificationParentFile(projectParentFile, subMapEntry.getValue());
File outputFile = new File(notificationParentFile, FilenameUtils.getName(fileName + "-" + i++ + ".txt"));
try {
FileUtils.forceMkdir(projectParentFile);
FileUtils.forceMkdir(notificationParentFile);
FileUtils.write(outputFile, subMapEntry.getValue().getNotificationAsString(), Charset.defaultCharset());
manualActionCount++;
} catch (IOException e) {
Expand All @@ -115,27 +124,52 @@ public void recordNotifications(MavenProject project) {
NotificationCollector.cleanup();
}

/**
* Grouped notifications will be placed in a sub-folder of the group name.
*
* @param projectParentFile project parent file
* @param notification notifcation
* @return appropriate parent file location
*/
private File getNotificationParentFile(File projectParentFile, Notification notification) {
File result;
String group = notification.getGroup();
if (StringUtils.isBlank(group)) {
result = projectParentFile;
} else {
result = new File(projectParentFile, FilenameUtils.getName(group));
}

return result;
}

private void displayNotifications() throws IOException {
if (this.hideManualActions) {
logger.debug("Hiding manual actions");

} else if (logger.isWarnEnabled()) {
// Get all notifications, then display them by file being modified
Map<String, List<File>> notificationMap = findNotificationForDisplay();
Map<String, List<File>> groupedNotificationMap = groupNotifications(notificationMap);

if (MapUtils.isNotEmpty(notificationMap)) {
if (MapUtils.isNotEmpty(groupedNotificationMap)) {
int i = 1;
logger.warn("Manual action steps were detected by fermenter-mda in {} module(s)", notificationMap.size());
logger.warn("");
for (Map.Entry<String, List<File>> entry : notificationMap.entrySet()) {
logger.debug("Notifications for artifactId: {}", entry.getKey());

for (File notification : entry.getValue()) {
logger.warn("------------------------------------------------------------------------");
logger.warn("Manual Action #{}", i++);
logger.warn("------------------------------------------------------------------------");
logger.warn(FileUtils.readFileToString(notification, Charset.defaultCharset()));
for (Map.Entry<String, List<File>> entry : groupedNotificationMap.entrySet()) {
String key = entry.getKey();
if (key.startsWith(GROUP)) {
denoteNewManualAction(i);
outputGroupNotification(entry, key);

} else {
for (File notification : entry.getValue()) {
denoteNewManualAction(i);
logger.warn(FileUtils.readFileToString(notification, Charset.defaultCharset()));
}
}

i++;
}

logger.warn("To disable these messages, please use -Dfermenter.hide.manual.actions=true");
Expand All @@ -144,6 +178,12 @@ private void displayNotifications() throws IOException {
}
}

private static void denoteNewManualAction(int i) {
logger.warn("------------------------------------------------------------------------");
logger.warn("Manual Action #{}", i);
logger.warn("------------------------------------------------------------------------");
}

private Map<String, List<File>> findNotificationForDisplay() {
Map<String, List<File>> resultMap = new HashMap<>();
List<MavenProject> projects = this.session.getAllProjects();
Expand All @@ -153,7 +193,9 @@ private Map<String, List<File>> findNotificationForDisplay() {
if (projectNotificationDirectory.exists()) {
File[] fileArray = projectNotificationDirectory.listFiles();
if (fileArray != null) {
resultMap.put(project.getArtifactId(), Arrays.stream(fileArray).collect(Collectors.toList()));
Collection<File> files = FileUtils.listFiles(projectNotificationDirectory,
FileFilterUtils.trueFileFilter(), FileFilterUtils.directoryFileFilter());
resultMap.put(project.getArtifactId(), files.stream().collect(Collectors.toList()));
}
}
}
Expand All @@ -162,4 +204,30 @@ private Map<String, List<File>> findNotificationForDisplay() {

}

private Map<String, List<File>> groupNotifications(Map<String, List<File>> notificationMap) {
Map<String, List<File>> groupedNotificationMap = new HashMap<>();
for (Map.Entry<String, List<File>> entry : notificationMap.entrySet()) {
for (File file : entry.getValue()) {
String parentName = file.getParentFile().getName();
String key = Objects.equals(parentName, NOTIFICATION_DIR_NAME) ? file.getAbsolutePath() : GROUP + parentName;
List<File> fileList = groupedNotificationMap.computeIfAbsent(key, l -> new ArrayList<>());
fileList.add(file);
}
}

return groupedNotificationMap;
}

private static void outputGroupNotification(Map.Entry<String, List<File>> entry, String key) throws IOException {
String groupName = key.replace(GROUP, "");
String templateName = "templates/notifications/group-" + groupName + ".vm";
Set<String> groupItems = new HashSet<>();
for (File notification : entry.getValue()) {
groupItems.add(FileUtils.readFileToString(notification, Charset.defaultCharset()));
}

VelocityNotification groupNotification = new VelocityNotification(groupName, groupItems, templateName);
logger.warn(groupNotification.getNotificationAsString());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.codehaus.plexus.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.technologybrewery.fermenter.mda.generator.GenerationException;

import java.io.IOException;
Expand All @@ -19,6 +22,8 @@
*/
public class VelocityNotification extends AbstractNotification {

private static final Logger logger = LoggerFactory.getLogger(VelocityNotification.class);

protected String velocityTemplate;

protected VelocityContext context;
Expand All @@ -41,6 +46,17 @@ public class VelocityNotification extends AbstractNotification {
*/
public VelocityNotification(String key, Set<String> items, String velocityTemplate) {
super(key, items);
init(key, items, velocityTemplate);
}

public VelocityNotification(String key, String group, Set<String> items, String velocityTemplate) {
super(key, group, items);
init(key, items, velocityTemplate);

this.context.put("group", group);
}

private void init(String key, Set<String> items, String velocityTemplate) {
this.velocityTemplate = velocityTemplate;
this.context = new VelocityContext();

Expand All @@ -65,7 +81,14 @@ public void addToVelocityContext(String velocityContextKey, Object value) {
*/
@Override
public String getNotificationAsString() {
if (StringUtils.isBlank(velocityTemplate)) {
throw new GenerationException("Template location MUST be provided!");
}

Template template = velocityEngine.getTemplate(velocityTemplate);
if (template == null) {
logger.error("No template found at {}!", velocityTemplate);
}

try (Writer writer = new StringWriter()) {
template.merge(context, writer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<plugin>
<groupId>org.technologybrewery.habushu</groupId>
<artifactId>habushu-maven-plugin</artifactId>
<version>2.4.1</version>
<version>2.6.0</version>
<extensions>true</extensions>
</plugin>
</plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<plugin>
<groupId>org.technologybrewery.habushu</groupId>
<artifactId>habushu-maven-plugin</artifactId>
<version>2.4.1</version>
<version>2.6.0</version>
<extensions>true</extensions>
</plugin>
</plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,9 @@ Feature: Support the ability to create notifications that can be output at the e
Given one or more Maven modules that create manual action notifications in their "target/manual-action-notifications" folder
When the end of the Maven build is reached
Then the notifications for the Maven modules that were part of the build are emitted to the console

@manual
Scenario: Collect per-project written grouped manual action notifications and emit them at the end of the build as one notification per group
Given one or more Maven modules that create grouped manual action notifications in their "target/manual-action-notifications/group" folder
When the end of the Maven build is reached
Then the notifications for the Maven modules that were part of the build are emitted to the console as one notification per group
2 changes: 1 addition & 1 deletion test-primer/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<plugin>
<groupId>org.technologybrewery.habushu</groupId>
<artifactId>habushu-maven-plugin</artifactId>
<version>2.4.1</version>
<version>2.6.0</version>
<extensions>true</extensions>
</plugin>
</plugins>
Expand Down

0 comments on commit a257e18

Please sign in to comment.