From d443be1abfa255bf82df43c67084fd3c723fc9a1 Mon Sep 17 00:00:00 2001 From: Caleb Bird Date: Fri, 6 Mar 2026 17:11:57 +0000 Subject: [PATCH 1/9] initial development of entity based changelogs --- .../changelog/ChangelogStatementConsumer.java | 47 +-- .../morf/changelog/ConsumerUtils.java | 51 +++ .../EntityHumanReadableStatementConsumer.java | 87 ++++++ .../upgrade/EntityKnowledgeMapBuilder.java | 295 ++++++++++++++++++ .../EntityKnowledgeMapUpgradeStep.java | 21 ++ .../HumanReadableStatementDataEditor.java | 23 ++ .../upgrade/HumanReadableStatementHelper.java | 26 ++ .../HumanReadableStatementProducer.java | 184 +++-------- .../HumanReadableStatementSchemaEditor.java | 155 +++++++++ ...dEntityHumanReadableStatementConsumer.java | 82 +++++ ...tBackedHumanReadableStatementConsumer.java | 82 +++++ .../TestEntityHumanReadableStatements.java | 159 ++++++++++ .../upgrade/TestHumanReadableStatements.java | 77 ----- 13 files changed, 1031 insertions(+), 258 deletions(-) create mode 100644 morf-core/src/main/java/org/alfasoftware/morf/changelog/ConsumerUtils.java create mode 100644 morf-core/src/main/java/org/alfasoftware/morf/changelog/EntityHumanReadableStatementConsumer.java create mode 100644 morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java create mode 100644 morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapUpgradeStep.java create mode 100644 morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementDataEditor.java create mode 100644 morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementSchemaEditor.java create mode 100644 morf-core/src/test/java/org/alfasoftware/morf/upgrade/ListBackedEntityHumanReadableStatementConsumer.java create mode 100644 morf-core/src/test/java/org/alfasoftware/morf/upgrade/ListBackedHumanReadableStatementConsumer.java create mode 100644 morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestEntityHumanReadableStatements.java diff --git a/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogStatementConsumer.java b/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogStatementConsumer.java index 150df2390..7c2c9addc 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogStatementConsumer.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogStatementConsumer.java @@ -19,7 +19,6 @@ import org.alfasoftware.morf.upgrade.HumanReadableStatementConsumer; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.text.WordUtils; /** * Class to consume strings produced by the human readable statement generator and @@ -29,48 +28,14 @@ */ class ChangelogStatementConsumer implements HumanReadableStatementConsumer { - /** - * Line width to apply wrapping at. - */ - private static final int LINE_LENGTH = 132; + private final PrintWriter outputStream; + private final ConsumerUtils utils; ChangelogStatementConsumer(PrintWriter outputStream) { this.outputStream = outputStream; - } - - - /** - * Writes one or more lines of text, applying line wrapping. - */ - private void writeWrapped(final String text) { - - // Handle the case of multiple lines - if (text.contains(System.lineSeparator())) { - for (String line : text.split(System.lineSeparator())) { - writeWrapped(line); - } - return; - } - - // Write anything below the wrapping limit - if (text.length() < LINE_LENGTH) { - outputStream.println(text); - return; - } - - // Measure the indent to use on the split lines - int indent = 0; - while (indent < text.length() && text.charAt(indent) == ' ') { - indent++; - } - indent += 2; - - // Split the line, preserving the indent on new lines - final String firstLineIndent = text.substring(0, indent); - final String lineSeparator = System.lineSeparator() + StringUtils.repeat(" ", indent); - outputStream.println(firstLineIndent + WordUtils.wrap(text.substring(indent), LINE_LENGTH - indent, lineSeparator, false)); + utils = new ConsumerUtils(outputStream); } @@ -83,13 +48,13 @@ public void versionStart(String versionNumber) { @Override public void upgradeStepStart(String name, String description, String jiraId) { - writeWrapped("* " + jiraId + ": " + description); + utils.writeWrapped("* " + jiraId + ": " + description); } @Override public void schemaChange(String description) { - writeWrapped(" o " + description); + utils.writeWrapped(" o " + description); } @@ -107,7 +72,7 @@ public void versionEnd(String versionNumber) { @Override public void dataChange(final String description) { - writeWrapped(" o " + description); + utils.writeWrapped(" o " + description); } } diff --git a/morf-core/src/main/java/org/alfasoftware/morf/changelog/ConsumerUtils.java b/morf-core/src/main/java/org/alfasoftware/morf/changelog/ConsumerUtils.java new file mode 100644 index 000000000..be9834c08 --- /dev/null +++ b/morf-core/src/main/java/org/alfasoftware/morf/changelog/ConsumerUtils.java @@ -0,0 +1,51 @@ +package org.alfasoftware.morf.changelog; + +import java.io.PrintWriter; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.text.WordUtils; + +public class ConsumerUtils { + + /** + * Line width to apply wrapping at. + */ + private static final int LINE_LENGTH = 132;; + private final PrintWriter outputStream; + + public ConsumerUtils(PrintWriter outputStream) { + this.outputStream = outputStream; + } + + public void writeWrapped(String text) { + String output = ""; + // Handle the case of multiple lines + if (text.contains(System.lineSeparator())) { + for (String line : text.split(System.lineSeparator())) { + writeWrapped(line); + } + return; + } + + // Write anything below the wrapping limit + if (text.length() < LINE_LENGTH) { + output = text; + outputStream.println(output); + return; + } + + // Measure the indent to use on the split lines + int indent = 0; + while (indent < text.length() && text.charAt(indent) == ' ') { + indent++; + } + indent += 2; + + // Split the line, preserving the indent on new lines + final String firstLineIndent = text.substring(0, indent); + final String lineSeparator = System.lineSeparator() + StringUtils.repeat(" ", indent); + output = firstLineIndent + WordUtils.wrap(text.substring(indent), LINE_LENGTH - indent, lineSeparator, false); + outputStream.println(output); + } + +} diff --git a/morf-core/src/main/java/org/alfasoftware/morf/changelog/EntityHumanReadableStatementConsumer.java b/morf-core/src/main/java/org/alfasoftware/morf/changelog/EntityHumanReadableStatementConsumer.java new file mode 100644 index 000000000..69bd76d30 --- /dev/null +++ b/morf-core/src/main/java/org/alfasoftware/morf/changelog/EntityHumanReadableStatementConsumer.java @@ -0,0 +1,87 @@ +package org.alfasoftware.morf.changelog; + +import java.io.PrintWriter; + +import org.alfasoftware.morf.upgrade.HumanReadableStatementConsumer; +import org.apache.commons.lang3.StringUtils; + +/** + * Class to consume strings produced by the entity human readable statement generator and + * passes them to the target output stream after applying word-wrapping logic. + * + * @author Copyright (c) Alfa Financial Software 2026 + */ +public class EntityHumanReadableStatementConsumer implements HumanReadableStatementConsumer { + private final ConsumerUtils utils; + private final PrintWriter outputStream; + private final String versionStart; + + + public EntityHumanReadableStatementConsumer(String versionStart, PrintWriter outputStream) { + utils = new ConsumerUtils(outputStream); + this.versionStart = versionStart; + this.outputStream = outputStream; + } + + public String getVersionStart() { + return versionStart; + } + + public void entityStart(String entityStart) { + outputStream.println(entityStart); + outputStream.println(StringUtils.repeat("=", entityStart.length())); + } + + public void entityEnd(String entityEnd) { + // nothing to write + } + + /** + * @see HumanReadableStatementConsumer#upgradeStepStart(String, String, String) + */ + @Override + public void upgradeStepStart(String name, String description, String jiraId) { + utils.writeWrapped("* " + jiraId + ": " + description); + } + + /** + * @see HumanReadableStatementConsumer#upgradeStepEnd(String) + */ + @Override + public void upgradeStepEnd(String name) { + outputStream.println(); + } + + /** + * @see HumanReadableStatementConsumer#schemaChange(String) + */ + @Override + public void schemaChange(String description) { + utils.writeWrapped(" o " + description); + } + + /** + * @see HumanReadableStatementConsumer#dataChange(String) + */ + @Override + public void dataChange(String description) { + utils.writeWrapped(" o " + description); + } + + /** + * @see HumanReadableStatementConsumer#versionStart(String) + */ + @Override + public void versionStart(String versionNumber) { + outputStream.println(versionNumber); + outputStream.println(StringUtils.repeat("=", versionNumber.length())); + } + + /** + * @see HumanReadableStatementConsumer#versionEnd(String) + */ + @Override + public void versionEnd(String versionNumber) { + //nothing to write + } +} diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java new file mode 100644 index 000000000..b03a85553 --- /dev/null +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java @@ -0,0 +1,295 @@ +package org.alfasoftware.morf.upgrade; + +import java.util.List; +import java.util.Map; + +import org.alfasoftware.morf.metadata.Column; +import org.alfasoftware.morf.metadata.Index; +import org.alfasoftware.morf.metadata.Sequence; +import org.alfasoftware.morf.metadata.Table; +import org.alfasoftware.morf.sql.SelectStatement; +import org.alfasoftware.morf.sql.Statement; +import org.alfasoftware.morf.sql.element.FieldLiteral; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +public class EntityKnowledgeMapBuilder implements HumanReadableStatementConsumer, SchemaEditor, DataEditor { + private final String preferredSQLDialect; + private EntityKnowledgeMapUpgradeStep currentUpgradeStep; + + // tree map so entities are stored in alphabetical order + private final Map>> knowledgeMap = Maps.newTreeMap(String::compareTo); + + + public EntityKnowledgeMapBuilder(String preferredSQLDialect) { + this.preferredSQLDialect = preferredSQLDialect; + } + + public Map>> getKnowledgeMultimap() { + return knowledgeMap; + } + + private void putInMap(String tableName, String schemaChangeDescription) { + // linked hashmap so we maintain insert order of upgrade steps + knowledgeMap.computeIfAbsent(tableName, k -> Maps.newLinkedHashMap()) + .computeIfAbsent(currentUpgradeStep, k -> Lists.newArrayList()) + .add(schemaChangeDescription); + } + + //---------------------------------------------------------------- + //HumanReadableStatementConsumer Overrides + //---------------------------------------------------------------- + /** + * @see HumanReadableStatementConsumer#versionStart(String) + */ + @Override + public void versionStart(String versionNumber) { + //nothing to write + } + + /** + * @see HumanReadableStatementConsumer#upgradeStepStart(String, String, String) + */ + @Override + public void upgradeStepStart(String name, String description, String jiraId) { + currentUpgradeStep = new EntityKnowledgeMapUpgradeStep(name, description, jiraId); + } + + /** + * @see HumanReadableStatementConsumer#schemaChange(String) + */ + @Override + public void schemaChange(String description) { + //nothing to write + } + + /** + * @see HumanReadableStatementConsumer#upgradeStepEnd(String) + */ + @Override + public void upgradeStepEnd(String name) { + //nothing to write + } + + /** + * @see HumanReadableStatementConsumer#versionEnd(String) + */ + @Override + public void versionEnd(String versionNumber) { + //nothing to write + } + + /** + * @see HumanReadableStatementConsumer#dataChange(String) + */ + @Override + public void dataChange(String description) { + //nothing to write + } + + //---------------------------------------------------------------- + //SchemaEditor Overrides + //---------------------------------------------------------------- + /** + * @see SchemaEditor#addColumn(String, Column) + **/ + @Override + public void addColumn(String tableName, Column definition, FieldLiteral columnDefault) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateAddColumnString(tableName, definition, columnDefault)); + } + } + + + + /** + * @see SchemaEditor#addColumn(String, Column) + */ + @Override + public void addColumn(String tableName, Column definition) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateAddColumnString(tableName, definition)); + } + + } + + /** + * @see SchemaEditor#addIndex(String, Index) + **/ + @Override + public void addIndex(String tableName, Index index) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateAddIndexString(tableName, index)); + } + + } + + /** + * @see SchemaEditor#addTable(Table) + **/ + @Override + public void addTable(Table definition) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(definition.getName(), HumanReadableStatementHelper.generateAddTableString(definition)); + } + + } + + /** + * @see SchemaEditor#changeColumn(String, Column, Column) + **/ + @Override + public void changeColumn(String tableName, Column fromDefinition, Column toDefinition) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateChangeColumnString(tableName, fromDefinition, toDefinition)); + } + + } + + /** + * @see SchemaEditor#changeIndex(String, Index, Index) + **/ + @Override + public void changeIndex(String tableName, Index fromIndex, Index toIndex) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateChangeIndexString(tableName, fromIndex, toIndex)); + } + + } + + /** + * @see SchemaEditor#removeColumn(String, Column) + **/ + @Override + public void removeColumn(String tableName, Column definition) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateRemoveColumnString(tableName, definition)); + } + + } + + /** + * @see SchemaEditor#removeColumns(String, Column[]) + */ + @Override + public void removeColumns(String tableName, Column... definitions) { + for (Column definition : definitions) { + removeColumn(tableName, definition); + } + } + + /** + * @see SchemaEditor#removeIndex(String, Index) + **/ + @Override + public void removeIndex(String tableName, Index index) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateRemoveIndexString(tableName, index)); + } + + } + + + /** + * @see SchemaEditor#renameIndex(String, String, String) + */ + @Override + public void renameIndex(String tableName, String fromIndexName, String toIndexName) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateRenameIndexString(tableName, fromIndexName, toIndexName)); + } + + } + + /** + * @see SchemaEditor#removeTable(Table) + **/ + @Override + public void removeTable(Table table) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(table.getName(), HumanReadableStatementHelper.generateRemoveTableString(table)); + } + + } + + @Override + public void renameTable(String fromTableName, String toTableName) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(fromTableName, HumanReadableStatementHelper.generateRenameTableString(fromTableName, toTableName)); + } + + } + + @Override + public void changePrimaryKeyColumns(String tableName, List oldPrimaryKeyColumns, List newPrimaryKeyColumns) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateChangePrimaryKeyColumnsString(tableName, oldPrimaryKeyColumns, newPrimaryKeyColumns)); + } + + } + + + @Override + public void correctPrimaryKeyColumns(String tableName, List newPrimaryKeyColumns) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateChangePrimaryKeyColumnsString(tableName, newPrimaryKeyColumns)); + } + + } + + @Override + public void addTableFrom(Table table, SelectStatement select) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(table.getName(), HumanReadableStatementHelper.generateAddTableFromString(table, select)); + } + } + + /** + * @see SchemaEditor#analyseTable(String) + **/ + @Override + public void analyseTable(String tableName) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(tableName, HumanReadableStatementHelper.generateAnalyseTableFromString(tableName)); + } + } + + /** + * @see SchemaEditor#addSequence(Sequence) + **/ + @Override + public void addSequence(Sequence sequence) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(sequence.getName(), HumanReadableStatementHelper.generateAddSequenceString(sequence)); + } + } + + /** + * @see SchemaEditor#removeSequence(Sequence) + **/ + @Override + public void removeSequence(Sequence sequence) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(sequence.getName(), HumanReadableStatementHelper.generateRemoveSequenceString(sequence)); + } + } + + //---------------------------------------------------------------- + //DataEditor Overrides + //---------------------------------------------------------------- + + /** + * Causes execute statement schema change to be added to the change sequence. + * + * @param statement the {@link Statement} to execute + */ + @Override + public void executeStatement(Statement statement) { + if(!currentUpgradeStep.getJiraID().isEmpty()) { + putInMap(HumanReadableStatementHelper.dataUpgradeTableName(statement), + HumanReadableStatementHelper.generateDataUpgradeString(statement, preferredSQLDialect)); + } + } + +} diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapUpgradeStep.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapUpgradeStep.java new file mode 100644 index 000000000..dc3268ff0 --- /dev/null +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapUpgradeStep.java @@ -0,0 +1,21 @@ +package org.alfasoftware.morf.upgrade; + +public class EntityKnowledgeMapUpgradeStep { + private final String name; + private final String description; + private final String jiraID; + public EntityKnowledgeMapUpgradeStep(String currentUpgradeName, String description, String jiraID) { + this.name = currentUpgradeName; + this.description = description; + this.jiraID = jiraID; + } + public String getName() { + return name; + } + public String getDescription() { + return description; + } + public String getJiraID() { + return jiraID; + } +} diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementDataEditor.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementDataEditor.java new file mode 100644 index 000000000..312c8ecc6 --- /dev/null +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementDataEditor.java @@ -0,0 +1,23 @@ +package org.alfasoftware.morf.upgrade; + +import org.alfasoftware.morf.sql.Statement; + +public class HumanReadableStatementDataEditor implements DataEditor { + private final HumanReadableStatementConsumer consumer; + private final boolean reportDataChanges; + private final String preferredSQLDialect; + + HumanReadableStatementDataEditor(HumanReadableStatementConsumer consumer, boolean reportDataChanges, String preferredSQLDialect) { + this.consumer = consumer; + this.reportDataChanges = reportDataChanges; + this.preferredSQLDialect = preferredSQLDialect; + } + + + @Override + public void executeStatement(Statement statement) { + if (reportDataChanges) { + consumer.dataChange(HumanReadableStatementHelper.generateDataUpgradeString(statement, preferredSQLDialect)); + } + } +} diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementHelper.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementHelper.java index eec81bd7b..e3eecc46b 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementHelper.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementHelper.java @@ -510,6 +510,32 @@ public static String generateDataUpgradeString(final Statement statement, final } } + /** + * Returns name of table given a Statement object. + * @param statement the data upgrade statement to describe. + * @param preferredSQLDialect the dialect to use, by preference, when a human readable description is not available. If + * SQL is not available in this dialect, or none was specified, then an arbitrary choice is made from the bundle + * of available raw SQL fragments. + * @return name of table given a Statement object. + */ + public static String dataUpgradeTableName(final Statement statement) { + if (statement instanceof DeleteStatement) { + return ((DeleteStatement)statement).getTable().getName(); + } else if (statement instanceof InsertStatement) { + return ((InsertStatement)statement).getTable().getName(); + } else if (statement instanceof MergeStatement) { + return ((MergeStatement)statement).getTable().getName(); + } else if (statement instanceof PortableSqlStatement) { + return ""; //Table name extraction not possible. + } else if (statement instanceof TruncateStatement) { + return ((TruncateStatement)statement).getTable().getName(); + } else if (statement instanceof UpdateStatement) { + return ((UpdateStatement)statement).getTable().getName(); + } else { + throw new UnsupportedOperationException("Unable to generate data upgrade string for: [" + statement.getClass().getName() + "]"); + } + } + /** * Generates a human-readable description of a data delete operation. diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java index a854d4359..5baae252a 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java @@ -15,19 +15,16 @@ package org.alfasoftware.morf.upgrade; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; import java.lang.reflect.Constructor; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Comparator; import java.util.List; import java.util.TreeMap; -import org.alfasoftware.morf.metadata.Column; -import org.alfasoftware.morf.metadata.Index; -import org.alfasoftware.morf.metadata.Sequence; -import org.alfasoftware.morf.metadata.Table; -import org.alfasoftware.morf.sql.SelectStatement; -import org.alfasoftware.morf.sql.Statement; -import org.alfasoftware.morf.sql.element.FieldLiteral; +import org.alfasoftware.morf.changelog.EntityHumanReadableStatementConsumer; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Supplier; @@ -95,13 +92,23 @@ public HumanReadableStatementProducer(final Collection> upgradeSteps = upgradeGraph.orderedSteps(); @@ -123,7 +130,8 @@ public List get() { } }); - // Iterate over the upgrade steps initialising them, and reordering by version and then sequence + + // Iterate over the upgrade steps initializing them, and reordering by version and then sequence for (Class currentStepClass : upgradeSteps) { try { // Create an instance of the upgrade step @@ -138,136 +146,12 @@ public List get() { } // Create a proxy schema editor to pass through the consumer events - SchemaEditor schemaEditor = new SchemaEditor() { - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#addColumn(java.lang.String, org.alfasoftware.morf.metadata.Column) **/ - @Override - public void addColumn(String tableName, Column definition, FieldLiteral columnDefault) { - consumer.schemaChange(HumanReadableStatementHelper.generateAddColumnString(tableName, definition, columnDefault)); - } - - /** - * @see org.alfasoftware.morf.upgrade.SchemaEditor#addColumn(java.lang.String, org.alfasoftware.morf.metadata.Column) - */ - @Override - public void addColumn(String tableName, Column definition) { - consumer.schemaChange(HumanReadableStatementHelper.generateAddColumnString(tableName, definition)); - } - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#addIndex(java.lang.String, org.alfasoftware.morf.metadata.Index) **/ - @Override - public void addIndex(String tableName, Index index) { - consumer.schemaChange(HumanReadableStatementHelper.generateAddIndexString(tableName, index)); - } - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#addTable(org.alfasoftware.morf.metadata.Table) **/ - @Override - public void addTable(Table definition) { - consumer.schemaChange(HumanReadableStatementHelper.generateAddTableString(definition)); - } - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#changeColumn(java.lang.String, org.alfasoftware.morf.metadata.Column, org.alfasoftware.morf.metadata.Column) **/ - @Override - public void changeColumn(String tableName, Column fromDefinition, Column toDefinition) { - consumer.schemaChange(HumanReadableStatementHelper.generateChangeColumnString(tableName, fromDefinition, toDefinition)); - } - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#changeIndex(java.lang.String, org.alfasoftware.morf.metadata.Index, org.alfasoftware.morf.metadata.Index) **/ - @Override - public void changeIndex(String tableName, Index fromIndex, Index toIndex) { - consumer.schemaChange(HumanReadableStatementHelper.generateChangeIndexString(tableName, fromIndex, toIndex)); - } - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#removeColumn(java.lang.String, org.alfasoftware.morf.metadata.Column) **/ - @Override - public void removeColumn(String tableName, Column definition) { - consumer.schemaChange(HumanReadableStatementHelper.generateRemoveColumnString(tableName, definition)); - } - - /** - * @see org.alfasoftware.morf.upgrade.SchemaEditor#removeColumns(java.lang.String, org.alfasoftware.morf.metadata.Column[]) - */ - @Override - public void removeColumns(String tableName, Column... definitions) { - for (Column definition : definitions) { - removeColumn(tableName, definition); - } - } - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#removeIndex(java.lang.String, org.alfasoftware.morf.metadata.Index) **/ - @Override - public void removeIndex(String tableName, Index index) { - consumer.schemaChange(HumanReadableStatementHelper.generateRemoveIndexString(tableName, index)); - } - - - /** - * @see org.alfasoftware.morf.upgrade.SchemaEditor#renameIndex(java.lang.String, java.lang.String, java.lang.String) - */ - @Override - public void renameIndex(String tableName, String fromIndexName, String toIndexName) { - consumer.schemaChange(HumanReadableStatementHelper.generateRenameIndexString(tableName, fromIndexName, toIndexName)); - - } - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#removeTable(org.alfasoftware.morf.metadata.Table) **/ - @Override - public void removeTable(Table table) { - consumer.schemaChange(HumanReadableStatementHelper.generateRemoveTableString(table)); - } - - @Override - public void renameTable(String fromTableName, String toTableName) { - consumer.schemaChange(HumanReadableStatementHelper.generateRenameTableString(fromTableName, toTableName)); - } - - @Override - public void changePrimaryKeyColumns(String tableName, List oldPrimaryKeyColumns, List newPrimaryKeyColumns) { - consumer.schemaChange(HumanReadableStatementHelper.generateChangePrimaryKeyColumnsString(tableName, oldPrimaryKeyColumns, newPrimaryKeyColumns)); - } - - - @Override - public void correctPrimaryKeyColumns(String tableName, List newPrimaryKeyColumns) { - consumer.schemaChange(HumanReadableStatementHelper.generateChangePrimaryKeyColumnsString(tableName, newPrimaryKeyColumns)); - } - - @Override - public void addTableFrom(Table table, SelectStatement select) { - consumer.schemaChange(HumanReadableStatementHelper.generateAddTableFromString(table, select)); - } - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#analyseTable(String) **/ - @Override - public void analyseTable(String tableName) { - consumer.schemaChange(HumanReadableStatementHelper.generateAnalyseTableFromString(tableName)); - } - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#addSequence(Sequence) **/ - @Override - public void addSequence(Sequence sequence) { - consumer.schemaChange(HumanReadableStatementHelper.generateAddSequenceString(sequence)); - } - - /** @see org.alfasoftware.morf.upgrade.SchemaEditor#removeSequence(Sequence) **/ - @Override - public void removeSequence(Sequence sequence) { - consumer.schemaChange(HumanReadableStatementHelper.generateRemoveSequenceString(sequence)); - } - }; - + HumanReadableStatementSchemaEditor schemaEditor = new HumanReadableStatementSchemaEditor(consumer); //Similarly, we need a proxy DataEditor - DataEditor dataEditor = new DataEditor () { - @Override - public void executeStatement(Statement statement) { - if (reportDataChanges) { - consumer.dataChange(HumanReadableStatementHelper.generateDataUpgradeString(statement, preferredSQLDialect)); - } - } - }; - - - //Iterate over versions, then over the ordered upgrade steps + HumanReadableStatementDataEditor dataEditor = new HumanReadableStatementDataEditor(consumer, reportDataChanges, preferredSQLDialect); + // Create entityKnowledgeBuilder for populating entity based changelogs + EntityKnowledgeMapBuilder entityKnowledgeMapBuilder =new EntityKnowledgeMapBuilder(preferredSQLDialect); + // Iterate over versions, then over the ordered upgrade steps for (String version : orderedUpgradeSteps.keySet()) { consumer.versionStart("ALFA " + version); for (UpgradeStep currentStep : orderedUpgradeSteps.get(version)) { @@ -276,15 +160,33 @@ public void executeStatement(Statement statement) { // Fire all the actual schema change events currentStep.execute(schemaEditor, dataEditor); - // Indicate to the consumer that the upgrade step has ended consumer.upgradeStepEnd(currentStep.getClass().getSimpleName()); + + if(versionCompare(entityConsumer.getVersionStart(), version) >= 0){ + // Populate entityKnowledgeMapBuilder + entityKnowledgeMapBuilder.upgradeStepStart(currentStep.getClass().getSimpleName(), currentStep.getDescription(), currentStep.getJiraId()); + currentStep.execute(entityKnowledgeMapBuilder, entityKnowledgeMapBuilder); + } } consumer.versionEnd("ALFA " + version); } - } + + //now handle our knowledgeMap and place into consumer... + //Iterate over knowledge, then each entity within, then descriptions split by new line + entityKnowledgeMapBuilder.getKnowledgeMultimap().forEach((entity, upgradeStep) -> { + entityConsumer.entityStart(entity); + upgradeStep.forEach((upgradeStepID, schemaChanges) -> { + entityConsumer.upgradeStepStart(upgradeStepID.getName(), upgradeStepID.getDescription(), upgradeStepID.getJiraID()); + schemaChanges.forEach(entityConsumer::schemaChange); + entityConsumer.upgradeStepEnd(""); + }); + entityConsumer.entityEnd(""); + }); + } + /** * Gets the version the upgrade {@code step} belongs in. * First attempts to pull the version from the {@code @Version} @@ -338,4 +240,6 @@ protected static Integer versionCompare(String str1, String str2) { return Integer.signum(vals1.length - vals2.length); } } + } + diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementSchemaEditor.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementSchemaEditor.java new file mode 100644 index 000000000..06902babe --- /dev/null +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementSchemaEditor.java @@ -0,0 +1,155 @@ +package org.alfasoftware.morf.upgrade; + +import java.util.List; + +import org.alfasoftware.morf.metadata.Column; +import org.alfasoftware.morf.metadata.Index; +import org.alfasoftware.morf.metadata.Sequence; +import org.alfasoftware.morf.metadata.Table; +import org.alfasoftware.morf.sql.SelectStatement; +import org.alfasoftware.morf.sql.element.FieldLiteral; + +public class HumanReadableStatementSchemaEditor implements SchemaEditor { + private final HumanReadableStatementConsumer consumer; + + HumanReadableStatementSchemaEditor(HumanReadableStatementConsumer consumer) { + this.consumer = consumer; + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#addColumn(java.lang.String, org.alfasoftware.morf.metadata.Column) + **/ + @Override + public void addColumn(String tableName, Column definition, FieldLiteral columnDefault) { + consumer.schemaChange(HumanReadableStatementHelper.generateAddColumnString(tableName, definition, columnDefault)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#addColumn(java.lang.String, org.alfasoftware.morf.metadata.Column) + */ + @Override + public void addColumn(String tableName, Column definition) { + consumer.schemaChange(HumanReadableStatementHelper.generateAddColumnString(tableName, definition)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#addIndex(java.lang.String, org.alfasoftware.morf.metadata.Index) + **/ + @Override + public void addIndex(String tableName, Index index) { + consumer.schemaChange(HumanReadableStatementHelper.generateAddIndexString(tableName, index)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#addTable(org.alfasoftware.morf.metadata.Table) + **/ + @Override + public void addTable(Table definition) { + consumer.schemaChange(HumanReadableStatementHelper.generateAddTableString(definition)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#changeColumn(java.lang.String, org.alfasoftware.morf.metadata.Column, org.alfasoftware.morf.metadata.Column) + **/ + @Override + public void changeColumn(String tableName, Column fromDefinition, Column toDefinition) { + consumer.schemaChange(HumanReadableStatementHelper.generateChangeColumnString(tableName, fromDefinition, toDefinition)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#changeIndex(java.lang.String, org.alfasoftware.morf.metadata.Index, org.alfasoftware.morf.metadata.Index) + **/ + @Override + public void changeIndex(String tableName, Index fromIndex, Index toIndex) { + consumer.schemaChange(HumanReadableStatementHelper.generateChangeIndexString(tableName, fromIndex, toIndex)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#removeColumn(java.lang.String, org.alfasoftware.morf.metadata.Column) + **/ + @Override + public void removeColumn(String tableName, Column definition) { + consumer.schemaChange(HumanReadableStatementHelper.generateRemoveColumnString(tableName, definition)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#removeColumns(java.lang.String, org.alfasoftware.morf.metadata.Column[]) + */ + @Override + public void removeColumns(String tableName, Column... definitions) { + for (Column definition : definitions) { + removeColumn(tableName, definition); + } + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#removeIndex(java.lang.String, org.alfasoftware.morf.metadata.Index) + **/ + @Override + public void removeIndex(String tableName, Index index) { + consumer.schemaChange(HumanReadableStatementHelper.generateRemoveIndexString(tableName, index)); + } + + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#renameIndex(java.lang.String, java.lang.String, java.lang.String) + */ + @Override + public void renameIndex(String tableName, String fromIndexName, String toIndexName) { + consumer.schemaChange(HumanReadableStatementHelper.generateRenameIndexString(tableName, fromIndexName, toIndexName)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#removeTable(org.alfasoftware.morf.metadata.Table) + **/ + @Override + public void removeTable(Table table) { + consumer.schemaChange(HumanReadableStatementHelper.generateRemoveTableString(table)); + } + + @Override + public void renameTable(String fromTableName, String toTableName) { + consumer.schemaChange(HumanReadableStatementHelper.generateRenameTableString(fromTableName, toTableName)); + } + + @Override + public void changePrimaryKeyColumns(String tableName, List oldPrimaryKeyColumns, List newPrimaryKeyColumns) { + consumer.schemaChange(HumanReadableStatementHelper.generateChangePrimaryKeyColumnsString(tableName, oldPrimaryKeyColumns, newPrimaryKeyColumns)); + } + + + @Override + public void correctPrimaryKeyColumns(String tableName, List newPrimaryKeyColumns) { + consumer.schemaChange(HumanReadableStatementHelper.generateChangePrimaryKeyColumnsString(tableName, newPrimaryKeyColumns)); + } + + @Override + public void addTableFrom(Table table, SelectStatement select) { + consumer.schemaChange(HumanReadableStatementHelper.generateAddTableFromString(table, select)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#analyseTable(String) + **/ + @Override + public void analyseTable(String tableName) { + consumer.schemaChange(HumanReadableStatementHelper.generateAnalyseTableFromString(tableName)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#addSequence(org.alfasoftware.morf.metadata.Sequence) + **/ + @Override + public void addSequence(org.alfasoftware.morf.metadata.Sequence sequence) { + consumer.schemaChange(HumanReadableStatementHelper.generateAddSequenceString(sequence)); + } + + /** + * @see org.alfasoftware.morf.upgrade.SchemaEditor#removeSequence(org.alfasoftware.morf.metadata.Sequence) + **/ + @Override + public void removeSequence(Sequence sequence) { + consumer.schemaChange(HumanReadableStatementHelper.generateRemoveSequenceString(sequence)); + } +} + diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/ListBackedEntityHumanReadableStatementConsumer.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/ListBackedEntityHumanReadableStatementConsumer.java new file mode 100644 index 000000000..0afdac843 --- /dev/null +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/ListBackedEntityHumanReadableStatementConsumer.java @@ -0,0 +1,82 @@ +package org.alfasoftware.morf.upgrade; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import org.alfasoftware.morf.changelog.EntityHumanReadableStatementConsumer; + +class ListBackedEntityHumanReadableStatementConsumer extends EntityHumanReadableStatementConsumer { + + /** + * List of strings written to the consumer. + */ + private final List list = new ArrayList<>(); + + public ListBackedEntityHumanReadableStatementConsumer(String versionStart, PrintWriter outputStream) { + super(versionStart, outputStream); + } + + /** + * @see EntityHumanReadableStatementConsumer#entityStart(String) + */ + @Override + public void entityStart(String entityName) { + list.add("ENTITYSTART:[" + entityName + "]"); + } + + /** + * @see EntityHumanReadableStatementConsumer#entityEnd(String) + */ + @Override + public void entityEnd(String entityName) { + list.add("ENTITYEND:[]"); + } + + + /** + * @see HumanReadableStatementConsumer#upgradeStepStart(String, String, String) + */ + @Override + public void upgradeStepStart(String name, String description, String jiraId) { + list.add("STEPSTART:[" + jiraId + "]-[" + name + "]-[" + description + "]"); + } + + + /** + * @see HumanReadableStatementConsumer#schemaChange(String) + */ + @Override + public void schemaChange(String description) { + list.add("CHANGE:[" + description + "]"); + } + + + /** + * @see HumanReadableStatementConsumer#upgradeStepEnd(String) + */ + @Override + public void upgradeStepEnd(String name) { + list.add("STEPEND:[]"); + } + + + /** + * @see HumanReadableStatementConsumer#dataChange(String) + */ + @Override + public void dataChange(String description) { + list.add("CHANGE:[" + description + "]"); + } + + + /** + * Gets the list of items sent to the consumer. + * + * @return the list + */ + public List getList() { + return list; + } + +} diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/ListBackedHumanReadableStatementConsumer.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/ListBackedHumanReadableStatementConsumer.java new file mode 100644 index 000000000..93a61ac0c --- /dev/null +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/ListBackedHumanReadableStatementConsumer.java @@ -0,0 +1,82 @@ +package org.alfasoftware.morf.upgrade; + +import java.util.ArrayList; +import java.util.List; + +/** + * A statement consumer which adds any consumed items to an internal list. + * + * @author Copyright (c) Alfa Financial Software 2010 + */ +class ListBackedHumanReadableStatementConsumer implements HumanReadableStatementConsumer { + + /** + * List of strings written to the consumer. + */ + private final List list = new ArrayList<>(); + + + /** + * @see HumanReadableStatementConsumer#versionStart(String) + */ + @Override + public void versionStart(String versionNumber) { + list.add("VERSIONSTART:[" + versionNumber + "]"); + } + + + /** + * @see HumanReadableStatementConsumer#upgradeStepStart(String, String, String) + */ + @Override + public void upgradeStepStart(String name, String description, String jiraId) { + list.add("STEPSTART:[" + jiraId + "]-[" + name + "]-[" + description + "]"); + } + + + /** + * @see HumanReadableStatementConsumer#schemaChange(String) + */ + @Override + public void schemaChange(String description) { + list.add("CHANGE:[" + description + "]"); + } + + + /** + * @see HumanReadableStatementConsumer#upgradeStepEnd(String) + */ + @Override + public void upgradeStepEnd(String name) { + list.add("STEPEND:[" + name + "]"); + } + + + /** + * @see HumanReadableStatementConsumer#versionEnd(String) + */ + @Override + public void versionEnd(String versionNumber) { + list.add("VERSIONEND:[" + versionNumber + "]"); + } + + + /** + * @see HumanReadableStatementConsumer#dataChange(String) + */ + @Override + public void dataChange(String description) { + list.add("DATACHANGE:[" + description + "]"); + } + + + /** + * Gets the list of items sent to the consumer. + * + * @return the list + */ + public List getList() { + return list; + } + +} diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestEntityHumanReadableStatements.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestEntityHumanReadableStatements.java new file mode 100644 index 000000000..e69b6df5a --- /dev/null +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestEntityHumanReadableStatements.java @@ -0,0 +1,159 @@ +/* Copyright 2017 Alfa Financial Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.alfasoftware.morf.upgrade; + +import static org.junit.Assert.assertEquals; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; + +import org.alfasoftware.morf.upgrade.testhumanreadablestatements.upgrade.v1_0_0.AddColumnToTableUpgradeStep; +import org.alfasoftware.morf.upgrade.testhumanreadablestatements.upgrade.v1_0_0.AddDslDataChangeStep; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + +/** + * Tests that the human readable output of the upgrade path + * finder is correct. + * + * @author Copyright (c) Alfa Financial Software 2026 + */ +public class TestEntityHumanReadableStatements { + private StringWriter stringWriter; + + + /** + * {@inheritDoc} + * @see junit.framework.TestCase#setUp() + */ + @Before + public void setUp() throws Exception { + stringWriter = new StringWriter(); + } + + @Ignore + private List produceLogs(List> items, String startVersion) { + ListBackedHumanReadableStatementConsumer consumer = new ListBackedHumanReadableStatementConsumer(); + PrintWriter outputStream = new PrintWriter(stringWriter); + ListBackedEntityHumanReadableStatementConsumer consumer2 = new ListBackedEntityHumanReadableStatementConsumer(startVersion, outputStream); + HumanReadableStatementProducer producer = new HumanReadableStatementProducer(items, true,"FOO"); + producer. produceFor(consumer, consumer2); + + return consumer2.getList(); + } + + @Ignore + private List produceLogs(List> items) { + return produceLogs(items, "v.1.0.0"); + } + + @Test + public void testSimpleEntity(){ + List> items = new ArrayList<>(); + items.add(AddColumnToTableUpgradeStep.class); + + List results = produceLogs(items); + + assertEquals("Should have the right number of items: " + results, 20, results.size()); + int i=0; + assertEquals("Item should be correct", "ENTITYSTART:[table_four]", results.get(i++)); + assertEquals("Item should be correct", "STEPSTART:[SAMPLE-1]-[AddColumnToTableUpgradeStep]-[Adds new columns to tables]", results.get(i++)); + assertEquals("Item should be correct", "CHANGE:[Add a non-null column to table_four called column_four [DECIMAL(9,5)], set to 10.0]", results.get(i++)); + assertEquals("Item should be correct", "STEPEND:[]", results.get(i++)); + assertEquals("Item should be correct", "ENTITYEND:[]", results.get(i++)); + assertEquals("Item should be correct", "ENTITYSTART:[table_one]", results.get(i++)); + assertEquals("Item should be correct", "STEPSTART:[SAMPLE-1]-[AddColumnToTableUpgradeStep]-[Adds new columns to tables]", results.get(i++)); + assertEquals("Item should be correct", "CHANGE:[Add a nullable column to table_one called column_one [STRING(10)], set to 'A']", results.get(i++)); + assertEquals("Item should be correct", "STEPEND:[]", results.get(i++)); + assertEquals("Item should be correct", "ENTITYEND:[]", results.get(i++)); + assertEquals("Item should be correct", "ENTITYSTART:[table_three]", results.get(i++)); + assertEquals("Item should be correct", "STEPSTART:[SAMPLE-1]-[AddColumnToTableUpgradeStep]-[Adds new columns to tables]", results.get(i++)); + assertEquals("Item should be correct", "CHANGE:[Add a nullable column to table_three called column_three [DECIMAL(9,5)], set to 10.0]", results.get(i++)); + assertEquals("Item should be correct", "STEPEND:[]", results.get(i++)); + assertEquals("Item should be correct", "ENTITYEND:[]", results.get(i++)); + assertEquals("Item should be correct", "ENTITYSTART:[table_two]", results.get(i++)); + assertEquals("Item should be correct", "STEPSTART:[SAMPLE-1]-[AddColumnToTableUpgradeStep]-[Adds new columns to tables]", results.get(i++)); + assertEquals("Item should be correct", "CHANGE:[Add a non-null column to table_two called column_two [STRING(10)], set to 'A']", results.get(i++)); + assertEquals("Item should be correct", "STEPEND:[]", results.get(i++)); + assertEquals("Item should be correct", "ENTITYEND:[]", results.get(i++)); + + + } + + /** + * Tests that the data change steps are included when requested. Both the structural change + * step and the data change should be reported. + */ + @Test + public void testDataChangeEntity() { + List> items = ImmutableList.>of( + AddColumnToTableUpgradeStep.class, + AddDslDataChangeStep.class + ); + List actual = produceLogs(items); + + List expected = ImmutableList.of( + "ENTITYSTART:[myTable]", + "STEPSTART:[DAVEDEV-123]-[AddDslDataChangeStep]-[DSL data change]", + String.format("CHANGE:[Add record into myTable:%n - Set wibble to 'column1']"), + "STEPEND:[]", + "ENTITYEND:[]", + "ENTITYSTART:[table_four]", + "STEPSTART:[SAMPLE-1]-[AddColumnToTableUpgradeStep]-[Adds new columns to tables]", + "CHANGE:[Add a non-null column to table_four called column_four [DECIMAL(9,5)], set to 10.0]", + "STEPEND:[]", + "ENTITYEND:[]", + "ENTITYSTART:[table_one]", + "STEPSTART:[SAMPLE-1]-[AddColumnToTableUpgradeStep]-[Adds new columns to tables]", + "CHANGE:[Add a nullable column to table_one called column_one [STRING(10)], set to 'A']", + "STEPEND:[]", + "ENTITYEND:[]", + "ENTITYSTART:[table_three]", + "STEPSTART:[SAMPLE-1]-[AddColumnToTableUpgradeStep]-[Adds new columns to tables]", + "CHANGE:[Add a nullable column to table_three called column_three [DECIMAL(9,5)], set to 10.0]", + "STEPEND:[]", + "ENTITYEND:[]", + "ENTITYSTART:[table_two]", + "STEPSTART:[SAMPLE-1]-[AddColumnToTableUpgradeStep]-[Adds new columns to tables]", + "CHANGE:[Add a non-null column to table_two called column_two [STRING(10)], set to 'A']", + "STEPEND:[]", + "ENTITYEND:[]" + ); + + assertEquals(expected, actual); + } + + @Test + public void testEntityStartVersion_HigherThanStartVersion(){ + List> items = new ArrayList<>(); + items.add(AddColumnToTableUpgradeStep.class); + List results = produceLogs(items, "v1.1.0"); + assertEquals("Should have the right number of items: " + results, 20, results.size()); + } + + @Test + public void testEntityStartVersion_LowerThanStartVersion(){ + List> items = new ArrayList<>(); + items.add(AddColumnToTableUpgradeStep.class); + List results = produceLogs(items, "v0.1.0"); + assertEquals("Should have the right number of items: " + results, 0, results.size()); + } +} diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestHumanReadableStatements.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestHumanReadableStatements.java index a6b2e6bd5..4f7d82f7c 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestHumanReadableStatements.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestHumanReadableStatements.java @@ -319,81 +319,4 @@ public void testDataChangeInclusion() { } - /** - * A statement consumer which adds any consumed items to an internal list. - * - * @author Copyright (c) Alfa Financial Software 2010 - */ - private static class ListBackedHumanReadableStatementConsumer implements HumanReadableStatementConsumer { - - /** - * List of strings written to the consumer. - */ - private final List list = new ArrayList<>(); - - - /** - * @see org.alfasoftware.morf.upgrade.HumanReadableStatementConsumer#versionStart(java.lang.String) - */ - @Override - public void versionStart(String versionNumber) { - list.add("VERSIONSTART:[" + versionNumber + "]"); - } - - - /** - * @see org.alfasoftware.morf.upgrade.HumanReadableStatementConsumer#upgradeStepStart(java.lang.String, java.lang.String, String) - */ - @Override - public void upgradeStepStart(String name, String description, String jiraId) { - list.add("STEPSTART:[" + jiraId + "]-[" + name + "]-[" + description + "]"); - } - - - /** - * @see org.alfasoftware.morf.upgrade.HumanReadableStatementConsumer#schemaChange(java.lang.String) - */ - @Override - public void schemaChange(String description) { - list.add("CHANGE:[" + description + "]"); - } - - - /** - * @see org.alfasoftware.morf.upgrade.HumanReadableStatementConsumer#upgradeStepEnd(java.lang.String) - */ - @Override - public void upgradeStepEnd(String name) { - list.add("STEPEND:[" + name + "]"); - } - - - /** - * @see org.alfasoftware.morf.upgrade.HumanReadableStatementConsumer#versionEnd(java.lang.String) - */ - @Override - public void versionEnd(String versionNumber) { - list.add("VERSIONEND:[" + versionNumber + "]"); - } - - - /** - * @see org.alfasoftware.morf.upgrade.HumanReadableStatementConsumer#dataChange(java.lang.String) - */ - @Override - public void dataChange(String description) { - list.add("DATACHANGE:[" + description + "]"); - } - - - /** - * Gets the list of items sent to the consumer. - * - * @return the list - */ - public List getList() { - return list; - } - - } } From 30c90fbee201835590f48e08e2df572bb7713656 Mon Sep 17 00:00:00 2001 From: Caleb Bird Date: Tue, 10 Mar 2026 11:31:19 +0000 Subject: [PATCH 2/9] further development of the entity-based-changelogs --- .../morf/changelog/ChangelogBuilder.java | 37 ++++++++++++++++- .../upgrade/EntityKnowledgeMapBuilder.java | 36 ++++++++-------- .../EntityKnowledgeMapUpgradeStep.java | 6 +++ .../morf/changelog/TestChangelogBuilder.java | 41 +++++++++++++++++++ .../TestEntityHumanReadableStatements.java | 2 +- 5 files changed, 101 insertions(+), 21 deletions(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java b/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java index e1fcd553d..7ba35fa6f 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java @@ -40,6 +40,9 @@ public class ChangelogBuilder { private String preferredSQLDialect = "ORACLE"; private PrintWriter outputStream = new PrintWriter(new OutputStreamWriter(System.out, Charset.forName("UTF-8"))); + private PrintWriter entityOutputStream = new PrintWriter(new OutputStreamWriter(System.out, Charset.forName("UTF-8"))); + private String versionStart = "v0.0.0"; + private boolean includeEntityBasedChangelogs; private final Set> upgradeSteps = new HashSet<>(); public static ChangelogBuilder changelogBuilder(){ @@ -89,22 +92,52 @@ public ChangelogBuilder withUpgradeSteps(Collection /** * Set the {@link PrintWriter} target for this changelog. Default is the * console. - * + * @deprecated * @param outputStream The {@link PrintWriter} to output to. * @return This builder for chaining */ + @Deprecated public ChangelogBuilder withOutputTo(PrintWriter outputStream) { this.outputStream = outputStream; return this; } + /** + * Set the {@link PrintWriter} targets for this changelog. Default is the + * console. + * + * @param outputStream The {@link PrintWriter} to output to. + * @param entityOutputStream The {@link PrintWriter} to output entity based changelog to. + * @return This builder for chaining + */ + public ChangelogBuilder withOutputTo(PrintWriter outputStream, PrintWriter entityOutputStream) { + this.entityOutputStream = entityOutputStream; + this.outputStream = outputStream; + return this; + } + + /** + * Set the version from which the entity based logs start from + * + * @param versionStart of the entity based logs + * @return This builder for chaining + */ + public ChangelogBuilder withVersionStart(String versionStart) { + this.versionStart = versionStart; + includeEntityBasedChangelogs = true; + return this; + } /** * Produces the Changelog based on the given input settings. */ public void produceChangelog() { HumanReadableStatementProducer producer = new HumanReadableStatementProducer(upgradeSteps, includeDataChanges, preferredSQLDialect); - producer.produceFor(new ChangelogStatementConsumer(outputStream)); + if(includeEntityBasedChangelogs) { + producer.produceFor(new ChangelogStatementConsumer(outputStream), new EntityHumanReadableStatementConsumer(versionStart, entityOutputStream)); + } else { + producer.produceFor(new ChangelogStatementConsumer(outputStream)); + } } } \ No newline at end of file diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java index b03a85553..c823597d1 100644 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java @@ -96,7 +96,7 @@ public void dataChange(String description) { **/ @Override public void addColumn(String tableName, Column definition, FieldLiteral columnDefault) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateAddColumnString(tableName, definition, columnDefault)); } } @@ -108,7 +108,7 @@ public void addColumn(String tableName, Column definition, FieldLiteral columnDe */ @Override public void addColumn(String tableName, Column definition) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateAddColumnString(tableName, definition)); } @@ -119,7 +119,7 @@ public void addColumn(String tableName, Column definition) { **/ @Override public void addIndex(String tableName, Index index) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateAddIndexString(tableName, index)); } @@ -130,7 +130,7 @@ public void addIndex(String tableName, Index index) { **/ @Override public void addTable(Table definition) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(definition.getName(), HumanReadableStatementHelper.generateAddTableString(definition)); } @@ -141,7 +141,7 @@ public void addTable(Table definition) { **/ @Override public void changeColumn(String tableName, Column fromDefinition, Column toDefinition) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateChangeColumnString(tableName, fromDefinition, toDefinition)); } @@ -152,7 +152,7 @@ public void changeColumn(String tableName, Column fromDefinition, Column toDefin **/ @Override public void changeIndex(String tableName, Index fromIndex, Index toIndex) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateChangeIndexString(tableName, fromIndex, toIndex)); } @@ -163,7 +163,7 @@ public void changeIndex(String tableName, Index fromIndex, Index toIndex) { **/ @Override public void removeColumn(String tableName, Column definition) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateRemoveColumnString(tableName, definition)); } @@ -184,7 +184,7 @@ public void removeColumns(String tableName, Column... definitions) { **/ @Override public void removeIndex(String tableName, Index index) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateRemoveIndexString(tableName, index)); } @@ -196,7 +196,7 @@ public void removeIndex(String tableName, Index index) { */ @Override public void renameIndex(String tableName, String fromIndexName, String toIndexName) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateRenameIndexString(tableName, fromIndexName, toIndexName)); } @@ -207,7 +207,7 @@ public void renameIndex(String tableName, String fromIndexName, String toIndexNa **/ @Override public void removeTable(Table table) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(table.getName(), HumanReadableStatementHelper.generateRemoveTableString(table)); } @@ -215,7 +215,7 @@ public void removeTable(Table table) { @Override public void renameTable(String fromTableName, String toTableName) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(fromTableName, HumanReadableStatementHelper.generateRenameTableString(fromTableName, toTableName)); } @@ -223,7 +223,7 @@ public void renameTable(String fromTableName, String toTableName) { @Override public void changePrimaryKeyColumns(String tableName, List oldPrimaryKeyColumns, List newPrimaryKeyColumns) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateChangePrimaryKeyColumnsString(tableName, oldPrimaryKeyColumns, newPrimaryKeyColumns)); } @@ -232,7 +232,7 @@ public void changePrimaryKeyColumns(String tableName, List oldPrimaryKey @Override public void correctPrimaryKeyColumns(String tableName, List newPrimaryKeyColumns) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateChangePrimaryKeyColumnsString(tableName, newPrimaryKeyColumns)); } @@ -240,7 +240,7 @@ public void correctPrimaryKeyColumns(String tableName, List newPrimaryKe @Override public void addTableFrom(Table table, SelectStatement select) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(table.getName(), HumanReadableStatementHelper.generateAddTableFromString(table, select)); } } @@ -250,7 +250,7 @@ public void addTableFrom(Table table, SelectStatement select) { **/ @Override public void analyseTable(String tableName) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(tableName, HumanReadableStatementHelper.generateAnalyseTableFromString(tableName)); } } @@ -260,7 +260,7 @@ public void analyseTable(String tableName) { **/ @Override public void addSequence(Sequence sequence) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(sequence.getName(), HumanReadableStatementHelper.generateAddSequenceString(sequence)); } } @@ -270,7 +270,7 @@ public void addSequence(Sequence sequence) { **/ @Override public void removeSequence(Sequence sequence) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(sequence.getName(), HumanReadableStatementHelper.generateRemoveSequenceString(sequence)); } } @@ -286,7 +286,7 @@ public void removeSequence(Sequence sequence) { */ @Override public void executeStatement(Statement statement) { - if(!currentUpgradeStep.getJiraID().isEmpty()) { + if(currentUpgradeStep.isPopulated()) { putInMap(HumanReadableStatementHelper.dataUpgradeTableName(statement), HumanReadableStatementHelper.generateDataUpgradeString(statement, preferredSQLDialect)); } diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapUpgradeStep.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapUpgradeStep.java index dc3268ff0..f14cb6c1b 100644 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapUpgradeStep.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapUpgradeStep.java @@ -1,5 +1,8 @@ package org.alfasoftware.morf.upgrade; +import java.util.function.Predicate; +import java.util.stream.Stream; + public class EntityKnowledgeMapUpgradeStep { private final String name; private final String description; @@ -18,4 +21,7 @@ public String getDescription() { public String getJiraID() { return jiraID; } + public boolean isPopulated(){ + return Stream.of(name, description,jiraID).anyMatch(Predicate.not(String::isBlank)); + } } diff --git a/morf-core/src/test/java/org/alfasoftware/morf/changelog/TestChangelogBuilder.java b/morf-core/src/test/java/org/alfasoftware/morf/changelog/TestChangelogBuilder.java index d81389e3a..132574b5e 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/changelog/TestChangelogBuilder.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/changelog/TestChangelogBuilder.java @@ -16,6 +16,7 @@ package org.alfasoftware.morf.changelog; import static org.alfasoftware.morf.changelog.ChangelogBuilder.changelogBuilder; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.PrintWriter; @@ -89,4 +90,44 @@ public void testFullChangeLog() { assertTrue(changeLog.contains("Set address to 'Address'")); assertTrue(changeLog.contains("Set postCode to 'postCode'")); } + /** + * Test database entity based changelog generation. + * + * @throws Exception on error + */ + @Test + public void testEntityChangeLog() throws Exception { + StringWriter writer = new StringWriter(); + StringWriter entityWriter = new StringWriter(); + + changelogBuilder() + .withOutputTo(new PrintWriter(writer), new PrintWriter(entityWriter)) + .withUpgradeSteps(ImmutableList.of(ChangeCar.class, ChangeDriver.class)) + .withVersionStart("v1.0.0") + .withIncludeDataChanges(true) + .produceChangelog(); + + String actual = entityWriter.toString(); + + String expected = String.join("\r\n", + "Car", + "===", + "* xxx-123: ChangeCar ", + " o Remove column engineCapacity from Car", + " o Add a nullable column to Car called engineVolume [DECIMAL(20,0)], set to 0", + "", + "Driver", + "======", + "* : ChangeDriver", + " o Add a nullable column to Driver called postCode [STRING(8)], set to ''", + " o Add record into Driver:", + " - Set name to 'Dave'", + " - Set address to 'Address'", + " - Set postCode to 'postCode'", + "", + "" + ); + + assertEquals(expected, actual); + } } diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestEntityHumanReadableStatements.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestEntityHumanReadableStatements.java index e69b6df5a..a094f213a 100644 --- a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestEntityHumanReadableStatements.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestEntityHumanReadableStatements.java @@ -62,7 +62,7 @@ private List produceLogs(List> items, Strin @Ignore private List produceLogs(List> items) { - return produceLogs(items, "v.1.0.0"); + return produceLogs(items, "v1.0.0"); } @Test From b1004c055404c2ae88186c98cb60acb27572cc44 Mon Sep 17 00:00:00 2001 From: Caleb Bird Date: Tue, 10 Mar 2026 11:48:30 +0000 Subject: [PATCH 3/9] local test pass, remote build fail fix attempt --- .../org/alfasoftware/morf/changelog/TestChangelogBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/morf-core/src/test/java/org/alfasoftware/morf/changelog/TestChangelogBuilder.java b/morf-core/src/test/java/org/alfasoftware/morf/changelog/TestChangelogBuilder.java index 132574b5e..65da3326a 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/changelog/TestChangelogBuilder.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/changelog/TestChangelogBuilder.java @@ -109,7 +109,7 @@ public void testEntityChangeLog() throws Exception { String actual = entityWriter.toString(); - String expected = String.join("\r\n", + String expected = String.join(System.lineSeparator(), "Car", "===", "* xxx-123: ChangeCar ", From e524e32b6ec512e5964a58d5ed4711b575d9688a Mon Sep 17 00:00:00 2001 From: Caleb Bird Date: Tue, 10 Mar 2026 17:50:54 +0000 Subject: [PATCH 4/9] logic enhancement of the entity-based-changelogs --- .../org/alfasoftware/morf/changelog/ChangelogBuilder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java b/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java index 7ba35fa6f..f61352dbe 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java @@ -118,13 +118,15 @@ public ChangelogBuilder withOutputTo(PrintWriter outputStream, PrintWriter entit /** * Set the version from which the entity based logs start from + * and sets flag to include entity based changelogs + * depending on versionStart empty or not. * * @param versionStart of the entity based logs * @return This builder for chaining */ public ChangelogBuilder withVersionStart(String versionStart) { this.versionStart = versionStart; - includeEntityBasedChangelogs = true; + includeEntityBasedChangelogs = (versionStart != null &&!versionStart.isBlank()); return this; } From 3a2223a81238799c14f637f2c49b3550b439d110 Mon Sep 17 00:00:00 2001 From: Caleb Bird Date: Wed, 18 Mar 2026 17:33:00 +0000 Subject: [PATCH 5/9] additional null checks --- .../org/alfasoftware/morf/changelog/ChangelogBuilder.java | 2 +- .../morf/upgrade/HumanReadableStatementProducer.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java b/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java index f61352dbe..c93eeab6d 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/changelog/ChangelogBuilder.java @@ -126,7 +126,7 @@ public ChangelogBuilder withOutputTo(PrintWriter outputStream, PrintWriter entit */ public ChangelogBuilder withVersionStart(String versionStart) { this.versionStart = versionStart; - includeEntityBasedChangelogs = (versionStart != null &&!versionStart.isBlank()); + includeEntityBasedChangelogs = versionStart != null && !versionStart.isBlank(); return this; } diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java index 5baae252a..0005b89b8 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java @@ -112,7 +112,7 @@ public void produceFor(final HumanReadableStatementConsumer consumer, final Enti // Ensure the upgrade steps are in the correct order final Collection> upgradeSteps = upgradeGraph.orderedSteps(); - + final boolean populateEntityBasedChangelog = entityConsumer.getVersionStart() != null && !entityConsumer.getVersionStart().isBlank(); //Create a Multimap which has version ordered keys but insertion ordered values ListMultimap orderedUpgradeSteps = Multimaps.newListMultimap( Maps.>newTreeMap(new TreeMap>( @@ -163,7 +163,7 @@ public List get() { // Indicate to the consumer that the upgrade step has ended consumer.upgradeStepEnd(currentStep.getClass().getSimpleName()); - if(versionCompare(entityConsumer.getVersionStart(), version) >= 0){ + if(populateEntityBasedChangelog && versionCompare(entityConsumer.getVersionStart(), version) >= 0){ // Populate entityKnowledgeMapBuilder entityKnowledgeMapBuilder.upgradeStepStart(currentStep.getClass().getSimpleName(), currentStep.getDescription(), currentStep.getJiraId()); currentStep.execute(entityKnowledgeMapBuilder, entityKnowledgeMapBuilder); From 59c178ad6e58033c84ddaefcd85ed7d6061c2632 Mon Sep 17 00:00:00 2001 From: Caleb Bird Date: Mon, 23 Mar 2026 18:28:55 +0000 Subject: [PATCH 6/9] adding additional logging plus version name santisation functionality --- .../HumanReadableStatementProducer.java | 19 +++++++++++++++++- .../entitybasedchangelog/TestSanitise.java | 20 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 morf-core/src/test/java/org/alfasoftware/morf/entitybasedchangelog/TestSanitise.java diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java index 0005b89b8..d42f8aaec 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java @@ -25,6 +25,8 @@ import java.util.TreeMap; import org.alfasoftware.morf.changelog.EntityHumanReadableStatementConsumer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Supplier; @@ -41,6 +43,8 @@ */ public class HumanReadableStatementProducer { + private static final Log log = LogFactory.getLog(HumanReadableStatementProducer.class); + /** * The graph of upgrade steps. */ @@ -152,6 +156,8 @@ public List get() { // Create entityKnowledgeBuilder for populating entity based changelogs EntityKnowledgeMapBuilder entityKnowledgeMapBuilder =new EntityKnowledgeMapBuilder(preferredSQLDialect); // Iterate over versions, then over the ordered upgrade steps + log.debug("Populate EntityBasedChangelog: [ " + populateEntityBasedChangelog + " ], " + + "Entity Start version sanitised : [ " + sanitise(entityConsumer.getVersionStart())); for (String version : orderedUpgradeSteps.keySet()) { consumer.versionStart("ALFA " + version); for (UpgradeStep currentStep : orderedUpgradeSteps.get(version)) { @@ -163,7 +169,12 @@ public List get() { // Indicate to the consumer that the upgrade step has ended consumer.upgradeStepEnd(currentStep.getClass().getSimpleName()); - if(populateEntityBasedChangelog && versionCompare(entityConsumer.getVersionStart(), version) >= 0){ + + log.debug(" ], Upgrade step version sanitised [ " + sanitise(version) + + " ], comparison: [ " + + versionCompare(sanitise(entityConsumer.getVersionStart()), sanitise(version)) + " ]"); + if (populateEntityBasedChangelog && versionCompare(sanitise(entityConsumer.getVersionStart()), sanitise(version)) >= 0){ + log.debug("Upgrade Step [" + currentStep.getClass().getSimpleName() + "] was added to entity based knowledge map"); // Populate entityKnowledgeMapBuilder entityKnowledgeMapBuilder.upgradeStepStart(currentStep.getClass().getSimpleName(), currentStep.getDescription(), currentStep.getJiraId()); currentStep.execute(entityKnowledgeMapBuilder, entityKnowledgeMapBuilder); @@ -175,8 +186,10 @@ public List get() { //now handle our knowledgeMap and place into consumer... //Iterate over knowledge, then each entity within, then descriptions split by new line entityKnowledgeMapBuilder.getKnowledgeMultimap().forEach((entity, upgradeStep) -> { + log.debug("Printing information for entity [ " + entity + " ]"); entityConsumer.entityStart(entity); upgradeStep.forEach((upgradeStepID, schemaChanges) -> { + log.debug("Printing information for upgrade step [ " + upgradeStepID.getName() + " ]"); entityConsumer.upgradeStepStart(upgradeStepID.getName(), upgradeStepID.getDescription(), upgradeStepID.getJiraID()); schemaChanges.forEach(entityConsumer::schemaChange); entityConsumer.upgradeStepEnd(""); @@ -187,6 +200,10 @@ public List get() { } + public static String sanitise(String version) { + return version.replaceAll("^v", "").replaceAll("\\.r$", ""); + } + /** * Gets the version the upgrade {@code step} belongs in. * First attempts to pull the version from the {@code @Version} diff --git a/morf-core/src/test/java/org/alfasoftware/morf/entitybasedchangelog/TestSanitise.java b/morf-core/src/test/java/org/alfasoftware/morf/entitybasedchangelog/TestSanitise.java new file mode 100644 index 000000000..2e59875ed --- /dev/null +++ b/morf-core/src/test/java/org/alfasoftware/morf/entitybasedchangelog/TestSanitise.java @@ -0,0 +1,20 @@ +package org.alfasoftware.morf.entitybasedchangelog; + +import org.alfasoftware.morf.upgrade.HumanReadableStatementProducer; +import org.junit.Assert; +import org.junit.Test; + +public class TestSanitise { + + @Test + public void testSanitise() { + // Given + String version = "v5.7.24.r"; + + // When + String result = HumanReadableStatementProducer.sanitise(version); + + // Then + Assert.assertEquals("5.7.24", result); + } +} From 7f260fd95247a8393a952b826bae2a433ff298ac Mon Sep 17 00:00:00 2001 From: Caleb Bird Date: Tue, 24 Mar 2026 17:46:22 +0000 Subject: [PATCH 7/9] refactoring HumanReadableStatementProducer --- .../HumanReadableStatementProducer.java | 74 +++---------------- .../HumanReadableStatementProducerUtils.java | 64 ++++++++++++++++ .../entitybasedchangelog/TestSanitise.java | 5 +- .../upgrade/TestHumanReadableStatements.java | 24 +++--- 4 files changed, 89 insertions(+), 78 deletions(-) create mode 100644 morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducerUtils.java diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java index d42f8aaec..ebf87955f 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java @@ -64,6 +64,11 @@ public class HumanReadableStatementProducer { */ private final String preferredSQLDialect; + /** + * Contains utility functions used by producer. + */ + private final HumanReadableStatementProducerUtils utils = new HumanReadableStatementProducerUtils(); + /** * Constructs a new {@link HumanReadableStatementProducer}. @@ -123,7 +128,7 @@ public void produceFor(final HumanReadableStatementConsumer consumer, final Enti new Comparator() { @Override public int compare(String o1, String o2) { - return versionCompare(o1, o2); + return utils.versionCompare(o1, o2); } }) ), @@ -142,7 +147,7 @@ public List get() { Constructor constructor = currentStepClass.getDeclaredConstructor(); constructor.setAccessible(true); UpgradeStep step = constructor.newInstance(); - orderedUpgradeSteps.put(getUpgradeStepVersion(step), step); + orderedUpgradeSteps.put(utils.getUpgradeStepVersion(step), step); } catch (Exception e) { throw new IllegalStateException("Cannot instantiate upgrade step [" + currentStepClass.getName() + "]", e); @@ -157,7 +162,7 @@ public List get() { EntityKnowledgeMapBuilder entityKnowledgeMapBuilder =new EntityKnowledgeMapBuilder(preferredSQLDialect); // Iterate over versions, then over the ordered upgrade steps log.debug("Populate EntityBasedChangelog: [ " + populateEntityBasedChangelog + " ], " - + "Entity Start version sanitised : [ " + sanitise(entityConsumer.getVersionStart())); + + "Entity Start version sanitised : [ " + utils.sanitise(entityConsumer.getVersionStart())); for (String version : orderedUpgradeSteps.keySet()) { consumer.versionStart("ALFA " + version); for (UpgradeStep currentStep : orderedUpgradeSteps.get(version)) { @@ -170,10 +175,10 @@ public List get() { consumer.upgradeStepEnd(currentStep.getClass().getSimpleName()); - log.debug(" ], Upgrade step version sanitised [ " + sanitise(version) + log.debug(" ], Upgrade step version sanitised [ " + utils.sanitise(version) + " ], comparison: [ " - + versionCompare(sanitise(entityConsumer.getVersionStart()), sanitise(version)) + " ]"); - if (populateEntityBasedChangelog && versionCompare(sanitise(entityConsumer.getVersionStart()), sanitise(version)) >= 0){ + + utils.versionCompare(utils.sanitise(entityConsumer.getVersionStart()), utils.sanitise(version)) + " ]"); + if (populateEntityBasedChangelog && utils.versionCompare(utils.sanitise(entityConsumer.getVersionStart()), utils.sanitise(version)) >= 0){ log.debug("Upgrade Step [" + currentStep.getClass().getSimpleName() + "] was added to entity based knowledge map"); // Populate entityKnowledgeMapBuilder entityKnowledgeMapBuilder.upgradeStepStart(currentStep.getClass().getSimpleName(), currentStep.getDescription(), currentStep.getJiraId()); @@ -200,63 +205,6 @@ public List get() { } - public static String sanitise(String version) { - return version.replaceAll("^v", "").replaceAll("\\.r$", ""); - } - - /** - * Gets the version the upgrade {@code step} belongs in. - * First attempts to pull the version from the {@code @Version} - * annotation, otherwise from the package name. - * - * @param step the upgrade step. - * @return the version the upgrade step belongs in. - */ - private String getUpgradeStepVersion(UpgradeStep step) { - Version versionAnnotation = step.getClass().getAnnotation(Version.class); - if (versionAnnotation!=null) { - return "v".concat(versionAnnotation.value()); - } - - String version = step.getClass().getPackage().getName(); - version = version.substring(version.lastIndexOf('.') + 1); - return version.replace('_', '.'); - } - - - /** - * Compare two version strings. This differs from natural ordering - * as a version of 5.3.27 is higher than 5.3.3. - * @param str1 One version string to compare - * @param str2 The other version string to compare - * @return a negative integer, zero, or a positive integer as the - * first argument is less than, equal to, or greater than the - * second. */ - @VisibleForTesting - protected static Integer versionCompare(String str1, String str2) { - String[] vals1 = str1.split("\\."); - String[] vals2 = str2.split("\\."); - - // set index to first non-equal ordinal or length of shortest version string - int i = 0; - while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) { - i++; - } - // compare first non-equal ordinal number - if (i < vals1.length && i < vals2.length) { - try { - int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i])); - return Integer.signum(diff); - } catch (NumberFormatException e) { - return Integer.signum(vals1[i].compareTo(vals2[i])); - } - } - // the strings are equal or one string is a substring of the other - // e.g. "1.2.3" = "1.2.3" or "1.2.3" < "1.2.3.4" - else { - return Integer.signum(vals1.length - vals2.length); - } - } } diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducerUtils.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducerUtils.java new file mode 100644 index 000000000..26a07c269 --- /dev/null +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducerUtils.java @@ -0,0 +1,64 @@ +package org.alfasoftware.morf.upgrade; + +import com.google.common.annotations.VisibleForTesting; + +public class HumanReadableStatementProducerUtils { + + public String sanitise(String version) { + return version.replaceAll("^v", "").replaceAll("\\.r$", ""); + } + + /** + * Gets the version the upgrade {@code step} belongs in. + * First attempts to pull the version from the {@code @Version} + * annotation, otherwise from the package name. + * + * @param step the upgrade step. + * @return the version the upgrade step belongs in. + */ + public String getUpgradeStepVersion(UpgradeStep step) { + Version versionAnnotation = step.getClass().getAnnotation(Version.class); + if (versionAnnotation!=null) { + return "v".concat(versionAnnotation.value()); + } + + String version = step.getClass().getPackage().getName(); + version = version.substring(version.lastIndexOf('.') + 1); + return version.replace('_', '.'); + } + + + /** + * Compare two version strings. This differs from natural ordering + * as a version of 5.3.27 is higher than 5.3.3. + * @param str1 One version string to compare + * @param str2 The other version string to compare + * @return a negative integer, zero, or a positive integer as the + * first argument is less than, equal to, or greater than the + * second. */ + @VisibleForTesting + public Integer versionCompare(String str1, String str2) { + String[] vals1 = str1.split("\\."); + String[] vals2 = str2.split("\\."); + + // set index to first non-equal ordinal or length of shortest version string + int i = 0; + while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) { + i++; + } + // compare first non-equal ordinal number + if (i < vals1.length && i < vals2.length) { + try { + int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i])); + return Integer.signum(diff); + } catch (NumberFormatException e) { + return Integer.signum(vals1[i].compareTo(vals2[i])); + } + } + // the strings are equal or one string is a substring of the other + // e.g. "1.2.3" = "1.2.3" or "1.2.3" < "1.2.3.4" + else { + return Integer.signum(vals1.length - vals2.length); + } + } +} diff --git a/morf-core/src/test/java/org/alfasoftware/morf/entitybasedchangelog/TestSanitise.java b/morf-core/src/test/java/org/alfasoftware/morf/entitybasedchangelog/TestSanitise.java index 2e59875ed..9d97c2353 100644 --- a/morf-core/src/test/java/org/alfasoftware/morf/entitybasedchangelog/TestSanitise.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/entitybasedchangelog/TestSanitise.java @@ -1,6 +1,6 @@ package org.alfasoftware.morf.entitybasedchangelog; -import org.alfasoftware.morf.upgrade.HumanReadableStatementProducer; +import org.alfasoftware.morf.upgrade.HumanReadableStatementProducerUtils; import org.junit.Assert; import org.junit.Test; @@ -10,9 +10,8 @@ public class TestSanitise { public void testSanitise() { // Given String version = "v5.7.24.r"; - // When - String result = HumanReadableStatementProducer.sanitise(version); + String result = new HumanReadableStatementProducerUtils().sanitise(version); // Then Assert.assertEquals("5.7.24", result); diff --git a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestHumanReadableStatements.java b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestHumanReadableStatements.java index 4f7d82f7c..033071215 100755 --- a/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestHumanReadableStatements.java +++ b/morf-core/src/test/java/org/alfasoftware/morf/upgrade/TestHumanReadableStatements.java @@ -204,18 +204,18 @@ public void testFourStepSortedByVersionThenSequence() { */ @Test public void testDirectionVersionComparison() { - assertEquals("5.3.1 less than 5.3.2",Integer.valueOf(-1), HumanReadableStatementProducer.versionCompare("5.3.1", "5.3.2")); - assertEquals("5.3.2 greater than 5.3.1",Integer.valueOf(1), HumanReadableStatementProducer.versionCompare("5.3.2", "5.3.1")); - assertEquals("5.3.3 equals 5.3.3",Integer.valueOf(0), HumanReadableStatementProducer.versionCompare("5.3.3", "5.3.3")); - - assertEquals("5.3.1.2.3.4 less than 5.3.1.2.3.5",Integer.valueOf(-1), HumanReadableStatementProducer.versionCompare("5.3.1.2.3.4", "5.3.1.2.3.5")); - assertEquals("5.3.1 less than 5.3.1.2",Integer.valueOf(-1), HumanReadableStatementProducer.versionCompare("5.3.1", "5.3.1.2")); - - assertEquals("5.3.1a less than 5.3.2a",Integer.valueOf(-1), HumanReadableStatementProducer.versionCompare("5.3.1a", "5.3.2a")); - assertEquals("5.3.2a greater than 5.3.1a",Integer.valueOf(1), HumanReadableStatementProducer.versionCompare("5.3.2a", "5.3.1a")); - assertEquals("5.3.3a less than 5.3.3b",Integer.valueOf(-1), HumanReadableStatementProducer.versionCompare("5.3.3a", "5.3.3b")); - assertEquals("5.3.3a equals 5.3.3a",Integer.valueOf(0), HumanReadableStatementProducer.versionCompare("5.3.3a", "5.3.3a")); - assertEquals("5.3.3a.a less than 5.3.3a.b",Integer.valueOf(-1), HumanReadableStatementProducer.versionCompare("5.3.3a.a", "5.3.3a.b")); + assertEquals("5.3.1 less than 5.3.2",Integer.valueOf(-1), new HumanReadableStatementProducerUtils().versionCompare("5.3.1", "5.3.2")); + assertEquals("5.3.2 greater than 5.3.1",Integer.valueOf(1), new HumanReadableStatementProducerUtils().versionCompare("5.3.2", "5.3.1")); + assertEquals("5.3.3 equals 5.3.3",Integer.valueOf(0), new HumanReadableStatementProducerUtils().versionCompare("5.3.3", "5.3.3")); + + assertEquals("5.3.1.2.3.4 less than 5.3.1.2.3.5",Integer.valueOf(-1), new HumanReadableStatementProducerUtils().versionCompare("5.3.1.2.3.4", "5.3.1.2.3.5")); + assertEquals("5.3.1 less than 5.3.1.2",Integer.valueOf(-1), new HumanReadableStatementProducerUtils().versionCompare("5.3.1", "5.3.1.2")); + + assertEquals("5.3.1a less than 5.3.2a",Integer.valueOf(-1), new HumanReadableStatementProducerUtils().versionCompare("5.3.1a", "5.3.2a")); + assertEquals("5.3.2a greater than 5.3.1a",Integer.valueOf(1), new HumanReadableStatementProducerUtils().versionCompare("5.3.2a", "5.3.1a")); + assertEquals("5.3.3a less than 5.3.3b",Integer.valueOf(-1), new HumanReadableStatementProducerUtils().versionCompare("5.3.3a", "5.3.3b")); + assertEquals("5.3.3a equals 5.3.3a",Integer.valueOf(0), new HumanReadableStatementProducerUtils().versionCompare("5.3.3a", "5.3.3a")); + assertEquals("5.3.3a.a less than 5.3.3a.b",Integer.valueOf(-1), new HumanReadableStatementProducerUtils().versionCompare("5.3.3a.a", "5.3.3a.b")); } /** From ed7ece5efe8fb2b4d29badf4f608936d51c06f4d Mon Sep 17 00:00:00 2001 From: Caleb Bird Date: Tue, 31 Mar 2026 12:28:35 +0100 Subject: [PATCH 8/9] cleanup of logging on HumanReadableStatementProducer, clean up of imports --- .../upgrade/HumanReadableStatementProducer.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java index ebf87955f..0affa5484 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java @@ -28,7 +28,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Supplier; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; @@ -108,7 +107,7 @@ public HumanReadableStatementProducer(final Collection get() { // Create entityKnowledgeBuilder for populating entity based changelogs EntityKnowledgeMapBuilder entityKnowledgeMapBuilder =new EntityKnowledgeMapBuilder(preferredSQLDialect); // Iterate over versions, then over the ordered upgrade steps - log.debug("Populate EntityBasedChangelog: [ " + populateEntityBasedChangelog + " ], " - + "Entity Start version sanitised : [ " + utils.sanitise(entityConsumer.getVersionStart())); + log.debug("Populate EntityBasedChangelog: [ " + + populateEntityBasedChangelog + " ], " + + "Entity Start version sanitised : [ " + + utils.sanitise(entityConsumer.getVersionStart()) + " ], "); + for (String version : orderedUpgradeSteps.keySet()) { consumer.versionStart("ALFA " + version); for (UpgradeStep currentStep : orderedUpgradeSteps.get(version)) { @@ -175,8 +177,7 @@ public List get() { consumer.upgradeStepEnd(currentStep.getClass().getSimpleName()); - log.debug(" ], Upgrade step version sanitised [ " + utils.sanitise(version) - + " ], comparison: [ " + log.debug("Upgrade step version sanitised [ " + utils.sanitise(version) + " ], comparison: [ " + utils.versionCompare(utils.sanitise(entityConsumer.getVersionStart()), utils.sanitise(version)) + " ]"); if (populateEntityBasedChangelog && utils.versionCompare(utils.sanitise(entityConsumer.getVersionStart()), utils.sanitise(version)) >= 0){ log.debug("Upgrade Step [" + currentStep.getClass().getSimpleName() + "] was added to entity based knowledge map"); From 19dd94e4028c3b400a2d474620eb60420270292e Mon Sep 17 00:00:00 2001 From: Caleb Bird Date: Tue, 31 Mar 2026 16:57:19 +0100 Subject: [PATCH 9/9] EntityKnowledgeMapBuilder handles additional boolean,reportDataChanges. MORF-123 --- .../upgrade/EntityKnowledgeMapBuilder.java | 23 ++++++++++--------- .../HumanReadableStatementProducer.java | 10 ++++---- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java index c823597d1..b02a0344d 100644 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/EntityKnowledgeMapBuilder.java @@ -15,6 +15,7 @@ import com.google.common.collect.Maps; public class EntityKnowledgeMapBuilder implements HumanReadableStatementConsumer, SchemaEditor, DataEditor { + private final boolean reportDataChanges; private final String preferredSQLDialect; private EntityKnowledgeMapUpgradeStep currentUpgradeStep; @@ -22,7 +23,8 @@ public class EntityKnowledgeMapBuilder implements HumanReadableStatementConsumer private final Map>> knowledgeMap = Maps.newTreeMap(String::compareTo); - public EntityKnowledgeMapBuilder(String preferredSQLDialect) { + public EntityKnowledgeMapBuilder(boolean reportDataChanges, String preferredSQLDialect) { + this.reportDataChanges = reportDataChanges; this.preferredSQLDialect = preferredSQLDialect; } @@ -38,14 +40,14 @@ private void putInMap(String tableName, String schemaChangeDescription) { } //---------------------------------------------------------------- - //HumanReadableStatementConsumer Overrides + // HumanReadableStatementConsumer Overrides //---------------------------------------------------------------- /** * @see HumanReadableStatementConsumer#versionStart(String) */ @Override public void versionStart(String versionNumber) { - //nothing to write + // nothing to write } /** @@ -61,7 +63,7 @@ public void upgradeStepStart(String name, String description, String jiraId) { */ @Override public void schemaChange(String description) { - //nothing to write + // nothing to write } /** @@ -69,7 +71,7 @@ public void schemaChange(String description) { */ @Override public void upgradeStepEnd(String name) { - //nothing to write + // nothing to write } /** @@ -77,7 +79,7 @@ public void upgradeStepEnd(String name) { */ @Override public void versionEnd(String versionNumber) { - //nothing to write + // nothing to write } /** @@ -85,11 +87,11 @@ public void versionEnd(String versionNumber) { */ @Override public void dataChange(String description) { - //nothing to write + // nothing to write } //---------------------------------------------------------------- - //SchemaEditor Overrides + // SchemaEditor Overrides //---------------------------------------------------------------- /** * @see SchemaEditor#addColumn(String, Column) @@ -276,7 +278,7 @@ public void removeSequence(Sequence sequence) { } //---------------------------------------------------------------- - //DataEditor Overrides + // DataEditor Overrides //---------------------------------------------------------------- /** @@ -286,10 +288,9 @@ public void removeSequence(Sequence sequence) { */ @Override public void executeStatement(Statement statement) { - if(currentUpgradeStep.isPopulated()) { + if (currentUpgradeStep.isPopulated() && reportDataChanges) { putInMap(HumanReadableStatementHelper.dataUpgradeTableName(statement), HumanReadableStatementHelper.generateDataUpgradeString(statement, preferredSQLDialect)); } } - } diff --git a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java index 0affa5484..fab227bcb 100755 --- a/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java +++ b/morf-core/src/main/java/org/alfasoftware/morf/upgrade/HumanReadableStatementProducer.java @@ -121,7 +121,7 @@ public void produceFor(final HumanReadableStatementConsumer consumer, final Enti // Ensure the upgrade steps are in the correct order final Collection> upgradeSteps = upgradeGraph.orderedSteps(); final boolean populateEntityBasedChangelog = entityConsumer.getVersionStart() != null && !entityConsumer.getVersionStart().isBlank(); - //Create a Multimap which has version ordered keys but insertion ordered values + // Create a Multimap which has version ordered keys but insertion ordered values ListMultimap orderedUpgradeSteps = Multimaps.newListMultimap( Maps.>newTreeMap(new TreeMap>( new Comparator() { @@ -155,10 +155,10 @@ public List get() { // Create a proxy schema editor to pass through the consumer events HumanReadableStatementSchemaEditor schemaEditor = new HumanReadableStatementSchemaEditor(consumer); - //Similarly, we need a proxy DataEditor + // Similarly, we need a proxy DataEditor HumanReadableStatementDataEditor dataEditor = new HumanReadableStatementDataEditor(consumer, reportDataChanges, preferredSQLDialect); // Create entityKnowledgeBuilder for populating entity based changelogs - EntityKnowledgeMapBuilder entityKnowledgeMapBuilder =new EntityKnowledgeMapBuilder(preferredSQLDialect); + EntityKnowledgeMapBuilder entityKnowledgeMapBuilder = new EntityKnowledgeMapBuilder(reportDataChanges, preferredSQLDialect); // Iterate over versions, then over the ordered upgrade steps log.debug("Populate EntityBasedChangelog: [ " + populateEntityBasedChangelog + " ], " @@ -189,8 +189,8 @@ public List get() { consumer.versionEnd("ALFA " + version); } - //now handle our knowledgeMap and place into consumer... - //Iterate over knowledge, then each entity within, then descriptions split by new line + // Now handle our knowledgeMap and place into consumer... + // Iterate over knowledge, then each entity within, then descriptions split by new line entityKnowledgeMapBuilder.getKnowledgeMultimap().forEach((entity, upgradeStep) -> { log.debug("Printing information for entity [ " + entity + " ]"); entityConsumer.entityStart(entity);