This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 1f90bd9711524559755f343314d4a3fd3362ea7c Author: Andrus Adamchik <[email protected]> AuthorDate: Tue Jul 21 11:42:13 2026 +0200 CAY-2982 Modeler: when upgrading projects allow upgraders to send outcome messages --- RELEASE-NOTES.txt | 1 + ...vice.java => CompatibilityProjectUpgrader.java} | 19 ++-- .../compatibility/ProjectCompatibilityModule.java | 4 +- .../CompatibilityDataChannelDescriptorLoader.java | 22 ++-- .../configuration/CompatibilityDataMapLoader.java | 10 +- .../compatibility/CompatibilityTestModule.java | 4 +- .../CompatibilityUpgradeServiceIT.java | 12 +-- .../org/apache/cayenne/project/ProjectModule.java | 6 +- ...adeService.java => DefaultProjectUpgrader.java} | 118 ++++++++++++--------- .../{UpgradeUnit.java => PostUpgradeState.java} | 36 ++----- .../{UpgradeService.java => PreUpgradeState.java} | 18 ++-- .../{UpgradeService.java => ProjectUpgrader.java} | 8 +- .../{UpgradeUnit.java => UpgradeContext.java} | 32 ++++-- .../cayenne/project/upgrade/UpgradeMetaData.java | 66 ------------ .../project/upgrade/handlers/UpgradeHandler.java | 16 +-- .../upgrade/handlers/UpgradeHandler_V10.java | 6 +- .../upgrade/handlers/UpgradeHandler_V11.java | 26 ++--- .../upgrade/handlers/UpgradeHandler_V12.java | 13 +-- .../upgrade/handlers/UpgradeHandler_V7.java | 18 ++-- .../upgrade/handlers/UpgradeHandler_V8.java | 6 +- .../upgrade/handlers/UpgradeHandler_V9.java | 6 +- ...ceTest.java => DefaultProjectUpgraderTest.java} | 26 ++--- .../upgrade/handlers/BaseUpgradeHandlerTest.java | 7 +- .../upgrade/handlers/UpgradeHandler_V12Test.java | 16 +-- .../org/apache/cayenne/modeler/Application.java | 6 +- .../modeler/ui/action/OpenProjectAction.java | 32 ++++-- 26 files changed, 250 insertions(+), 284 deletions(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index dfdb33ca7..0361549fa 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -28,6 +28,7 @@ CAY-2975 Mnemonic table aliases in generated SQL CAY-2978 AI skill: "cayenne-model-naming" CAY-2979 AI skill: "cayenne-full-db-sync" CAY-2980 Improve model name generation +CAY-2982 Modeler: when upgrading projects allow upgraders to send outcome messages Bug Fixes: diff --git a/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeService.java b/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/CompatibilityProjectUpgrader.java similarity index 77% rename from cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeService.java rename to cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/CompatibilityProjectUpgrader.java index d1ccb4ad7..0e5bc1781 100644 --- a/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeService.java +++ b/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/CompatibilityProjectUpgrader.java @@ -21,8 +21,9 @@ package org.apache.cayenne.project.compatibility; import org.apache.cayenne.configuration.DataChannelDescriptor; import org.apache.cayenne.di.Inject; -import org.apache.cayenne.project.upgrade.DefaultUpgradeService; -import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.apache.cayenne.project.upgrade.DefaultProjectUpgrader; +import org.apache.cayenne.project.upgrade.PostUpgradeState; +import org.apache.cayenne.project.upgrade.UpgradeContext; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler; import org.apache.cayenne.resource.Resource; import org.w3c.dom.Document; @@ -32,31 +33,31 @@ import java.util.List; /** * @since 4.1 */ -public class CompatibilityUpgradeService extends DefaultUpgradeService { +public class CompatibilityProjectUpgrader extends DefaultProjectUpgrader { @Inject DocumentProvider documentProvider; - public CompatibilityUpgradeService(@Inject List<UpgradeHandler> handlerList) { + public CompatibilityProjectUpgrader(@Inject List<UpgradeHandler> handlerList) { super(handlerList); } @Override - public Resource upgradeProject(Resource resource) { + public PostUpgradeState upgrade(Resource resource) { List<UpgradeHandler> handlerList = getHandlersForVersion(loadProjectVersion(resource)); - List<UpgradeUnit> upgradeUnits = upgradeDOM(resource, handlerList); + List<UpgradeContext> upgradeUnits = upgradeDOM(resource, handlerList); - for(UpgradeUnit unit : upgradeUnits) { + for(UpgradeContext unit : upgradeUnits) { documentProvider.putDocument(unit.getResource().getURL(), unit.getDocument()); } - return resource; + return new PostUpgradeState(resource, collectPostUpgradeMessages(upgradeUnits)); } public Resource upgradeDataMap(Resource resource) { List<UpgradeHandler> handlerList = getHandlersForVersion(loadProjectVersion(resource)); Document document = readDocument(resource.getURL()); - UpgradeUnit upgradeUnit = new UpgradeUnit(resource, document); + UpgradeContext upgradeUnit = new UpgradeContext(resource, document); for(UpgradeHandler handler : handlerList) { handler.processDataMapDom(upgradeUnit); } diff --git a/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/ProjectCompatibilityModule.java b/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/ProjectCompatibilityModule.java index 582b7abfa..637418d36 100644 --- a/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/ProjectCompatibilityModule.java +++ b/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/ProjectCompatibilityModule.java @@ -26,7 +26,7 @@ import org.apache.cayenne.project.compatibility.configuration.CompatibilityDataM import org.apache.cayenne.di.Binder; import org.apache.cayenne.di.Module; import org.apache.cayenne.project.ProjectModule; -import org.apache.cayenne.project.upgrade.UpgradeService; +import org.apache.cayenne.project.upgrade.ProjectUpgrader; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V10; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V11; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V12; @@ -44,7 +44,7 @@ public class ProjectCompatibilityModule implements Module { binder.bind(DataChannelDescriptorLoader.class).to(CompatibilityDataChannelDescriptorLoader.class); binder.bind(DataMapLoader.class).to(CompatibilityDataMapLoader.class); - binder.bind(UpgradeService.class).to(CompatibilityUpgradeService.class); + binder.bind(ProjectUpgrader.class).to(CompatibilityProjectUpgrader.class); binder.bind(DocumentProvider.class).to(DefaultDocumentProvider.class); ProjectModule.extend(binder) diff --git a/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/configuration/CompatibilityDataChannelDescriptorLoader.java b/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/configuration/CompatibilityDataChannelDescriptorLoader.java index 85b48a79b..5dd1feffe 100644 --- a/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/configuration/CompatibilityDataChannelDescriptorLoader.java +++ b/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/configuration/CompatibilityDataChannelDescriptorLoader.java @@ -35,10 +35,10 @@ import org.apache.cayenne.configuration.xml.LoaderContext; import org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader; import org.apache.cayenne.di.Inject; import org.apache.cayenne.di.Provider; -import org.apache.cayenne.project.compatibility.CompatibilityUpgradeService; +import org.apache.cayenne.project.compatibility.CompatibilityProjectUpgrader; import org.apache.cayenne.project.compatibility.DocumentProvider; -import org.apache.cayenne.project.upgrade.UpgradeMetaData; -import org.apache.cayenne.project.upgrade.UpgradeService; +import org.apache.cayenne.project.upgrade.PreUpgradeState; +import org.apache.cayenne.project.upgrade.ProjectUpgrader; import org.apache.cayenne.project.upgrade.UpgradeType; import org.apache.cayenne.resource.Resource; import org.apache.cayenne.util.Util; @@ -57,7 +57,7 @@ public class CompatibilityDataChannelDescriptorLoader extends XMLDataChannelDesc private static final Logger LOGGER = LoggerFactory.getLogger(XMLDataChannelDescriptorLoader.class); @Inject - Provider<UpgradeService> upgradeServiceProvider; + Provider<ProjectUpgrader> upgradeServiceProvider; @Inject DocumentProvider documentProvider; @@ -68,30 +68,30 @@ public class CompatibilityDataChannelDescriptorLoader extends XMLDataChannelDesc throw new NullPointerException("Null configurationResource"); } - if(!(upgradeServiceProvider.get() instanceof CompatibilityUpgradeService)) { + if(!(upgradeServiceProvider.get() instanceof CompatibilityProjectUpgrader)) { throw new ConfigurationException("CompatibilityUpgradeService expected"); } - CompatibilityUpgradeService upgradeService = (CompatibilityUpgradeService)upgradeServiceProvider.get(); + CompatibilityProjectUpgrader upgradeService = (CompatibilityProjectUpgrader)upgradeServiceProvider.get(); - UpgradeMetaData metaData = upgradeService.getUpgradeType(configurationResource); - if(metaData.getUpgradeType() == UpgradeType.UPGRADE_NOT_NEEDED) { + PreUpgradeState metaData = upgradeService.checkUpgradeNeeded(configurationResource); + if(metaData.requiredUpgrade() == UpgradeType.UPGRADE_NOT_NEEDED) { return super.load(configurationResource); } - if(metaData.getUpgradeType() == UpgradeType.DOWNGRADE_NEEDED) { + if(metaData.requiredUpgrade() == UpgradeType.DOWNGRADE_NEEDED) { throw new ConfigurationException("Unable to load configuration from %s: " + "It was created using a newer version of the Modeler", configurationResource.getURL()); } - if(metaData.getUpgradeType() == UpgradeType.INTERMEDIATE_UPGRADE_NEEDED) { + if(metaData.requiredUpgrade() == UpgradeType.INTERMEDIATE_UPGRADE_NEEDED) { throw new ConfigurationException("Unable to load configuration from %s: " + "Open the project in the older Modeler to do an intermediate upgrade.", configurationResource.getURL()); } URL configurationURL = configurationResource.getURL(); - upgradeService.upgradeProject(configurationResource); + upgradeService.upgrade(configurationResource); Document projectDocument = documentProvider.getDocument(configurationURL); if(projectDocument == null) { throw new ConfigurationException("Unable to upgrade " + configurationURL); diff --git a/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/configuration/CompatibilityDataMapLoader.java b/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/configuration/CompatibilityDataMapLoader.java index e7ccf5732..d2a736451 100644 --- a/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/configuration/CompatibilityDataMapLoader.java +++ b/cayenne-project-compatibility/src/main/java/org/apache/cayenne/project/compatibility/configuration/CompatibilityDataMapLoader.java @@ -34,9 +34,9 @@ import org.apache.cayenne.configuration.xml.XMLDataMapLoader; import org.apache.cayenne.di.Inject; import org.apache.cayenne.di.Provider; import org.apache.cayenne.map.DataMap; -import org.apache.cayenne.project.compatibility.CompatibilityUpgradeService; +import org.apache.cayenne.project.compatibility.CompatibilityProjectUpgrader; import org.apache.cayenne.project.compatibility.DocumentProvider; -import org.apache.cayenne.project.upgrade.UpgradeService; +import org.apache.cayenne.project.upgrade.ProjectUpgrader; import org.apache.cayenne.resource.Resource; import org.apache.cayenne.util.Util; import org.w3c.dom.Document; @@ -49,7 +49,7 @@ import org.xml.sax.XMLReader; public class CompatibilityDataMapLoader extends XMLDataMapLoader { @Inject - Provider<UpgradeService> upgradeServiceProvider; + Provider<ProjectUpgrader> upgradeServiceProvider; @Inject DocumentProvider documentProvider; @@ -59,11 +59,11 @@ public class CompatibilityDataMapLoader extends XMLDataMapLoader { Document document = documentProvider.getDocument(configurationResource.getURL()); // no document yet in provider, maybe DataMap is directly loaded if(document == null) { - if(!(upgradeServiceProvider.get() instanceof CompatibilityUpgradeService)) { + if(!(upgradeServiceProvider.get() instanceof CompatibilityProjectUpgrader)) { throw new ConfigurationException("CompatibilityUpgradeService expected"); } // try to upgrade datamap directly - CompatibilityUpgradeService upgradeService = (CompatibilityUpgradeService)upgradeServiceProvider.get(); + CompatibilityProjectUpgrader upgradeService = (CompatibilityProjectUpgrader)upgradeServiceProvider.get(); upgradeService.upgradeDataMap(configurationResource); document = documentProvider.getDocument(configurationResource.getURL()); diff --git a/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityTestModule.java b/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityTestModule.java index a2b8cbf78..0836d57bd 100644 --- a/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityTestModule.java +++ b/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityTestModule.java @@ -31,7 +31,7 @@ import org.apache.cayenne.di.Module; import org.apache.cayenne.di.spi.DefaultAdhocObjectFactory; import org.apache.cayenne.di.spi.DefaultClassLoaderManager; import org.apache.cayenne.project.ProjectSaver; -import org.apache.cayenne.project.upgrade.UpgradeService; +import org.apache.cayenne.project.upgrade.ProjectUpgrader; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V10; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V11; @@ -46,7 +46,7 @@ public class CompatibilityTestModule implements Module { @Override public void configure(Binder binder) { - binder.bind(UpgradeService.class).to(CompatibilityUpgradeService.class); + binder.bind(ProjectUpgrader.class).to(CompatibilityProjectUpgrader.class); binder.bind(DocumentProvider.class).to(DefaultDocumentProvider.class); binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class); diff --git a/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeServiceIT.java b/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeServiceIT.java index d62ed1634..553407870 100644 --- a/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeServiceIT.java +++ b/cayenne-project-compatibility/src/test/java/org/apache/cayenne/project/compatibility/CompatibilityUpgradeServiceIT.java @@ -23,7 +23,7 @@ import java.net.URL; import org.apache.cayenne.di.DIBootstrap; import org.apache.cayenne.di.Injector; -import org.apache.cayenne.project.upgrade.UpgradeService; +import org.apache.cayenne.project.upgrade.ProjectUpgrader; import org.apache.cayenne.resource.Resource; import org.apache.cayenne.resource.URLResource; import org.junit.jupiter.api.Test; @@ -37,14 +37,14 @@ public class CompatibilityUpgradeServiceIT { public void upgradeFullProjectDom() { Injector injector = getInjector(); - CompatibilityUpgradeService upgradeService = (CompatibilityUpgradeService)injector - .getInstance(UpgradeService.class); + CompatibilityProjectUpgrader upgradeService = (CompatibilityProjectUpgrader)injector + .getInstance(ProjectUpgrader.class); DocumentProvider documentProvider = injector.getInstance(DocumentProvider.class); URL resourceUrl = getClass().getResource("cayenne-project-v6.xml"); Resource resource = new URLResource(resourceUrl); - upgradeService.upgradeProject(resource); + upgradeService.upgrade(resource); Document domainDocument = documentProvider.getDocument(resourceUrl); @@ -64,8 +64,8 @@ public class CompatibilityUpgradeServiceIT { public void upgradeStandAloneDataMapDom() { Injector injector = getInjector(); - CompatibilityUpgradeService upgradeService = (CompatibilityUpgradeService)injector - .getInstance(UpgradeService.class); + CompatibilityProjectUpgrader upgradeService = (CompatibilityProjectUpgrader)injector + .getInstance(ProjectUpgrader.class); DocumentProvider documentProvider = injector.getInstance(DocumentProvider.class); diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java index 97a5afb8e..0eb00a0cf 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/ProjectModule.java @@ -24,8 +24,8 @@ import org.apache.cayenne.di.Binder; import org.apache.cayenne.di.ListBuilder; import org.apache.cayenne.di.Module; import org.apache.cayenne.project.extension.ProjectExtension; -import org.apache.cayenne.project.upgrade.DefaultUpgradeService; -import org.apache.cayenne.project.upgrade.UpgradeService; +import org.apache.cayenne.project.upgrade.DefaultProjectUpgrader; +import org.apache.cayenne.project.upgrade.ProjectUpgrader; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V10; import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V11; @@ -76,7 +76,7 @@ public class ProjectModule implements Module { binder.bind(ConfigurationNodeParentGetter.class).to(DefaultConfigurationNodeParentGetter.class); binder.bind(ConfigurationNameMapper.class).to(DefaultConfigurationNameMapper.class); - binder.bind(UpgradeService.class).to(DefaultUpgradeService.class); + binder.bind(ProjectUpgrader.class).to(DefaultProjectUpgrader.class); extend(binder) .initAllExtensions() diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultProjectUpgrader.java similarity index 76% rename from cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java rename to cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultProjectUpgrader.java index ecaa22571..5559f117c 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultUpgradeService.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/DefaultProjectUpgrader.java @@ -60,8 +60,10 @@ import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; import static org.apache.cayenne.util.Util.isBlank; @@ -70,27 +72,27 @@ import static org.apache.cayenne.util.Util.isBlank; * * Upgrade service sequence is following: * 1. This cycle should be done by Modeler and will result in a full project upgrade - * - * - find all project and datamap resources - * - define set of upgrade handlers to process those resources - * - process DOM (project + N data maps) - * - save & load cycle to flush all DOM changes - * - process project model - * - save once again to cleanup and sort final XML - * + * <p> + * - find all project and datamap resources + * - define set of upgrade handlers to process those resources + * - process DOM (project + N data maps) + * - save & load cycle to flush all DOM changes + * - process project model + * - save once again to cleanup and sort final XML + * <p> * 2. This cycle can be used by CayenneRuntime to optionally support old project versions - * - * - find all project and datamap resources - * - define set of upgrade handlers to process those resources - * - process DOM (project + N data maps) - * - directly load model from DOM w/o saving - * - process project model + * <p> + * - find all project and datamap resources + * - define set of upgrade handlers to process those resources + * - process DOM (project + N data maps) + * - directly load model from DOM w/o saving + * - process project model * * @since 4.1 */ -public class DefaultUpgradeService implements UpgradeService { +public class DefaultProjectUpgrader implements ProjectUpgrader { - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultUpgradeService.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultProjectUpgrader.class); public static final String UNKNOWN_VERSION = "0"; public static final String MIN_SUPPORTED_VERSION = "6"; @@ -103,48 +105,48 @@ public class DefaultUpgradeService implements UpgradeService { @Inject private DataChannelDescriptorLoader loader; - public DefaultUpgradeService(@Inject List<UpgradeHandler> handlerList) { - for(UpgradeHandler handler : handlerList) { + public DefaultProjectUpgrader(@Inject List<UpgradeHandler> handlerList) { + for (UpgradeHandler handler : handlerList) { handlers.put(handler.getVersion(), handler); } } @Override - public UpgradeMetaData getUpgradeType(Resource resource) { - UpgradeMetaData metaData = new UpgradeMetaData(); - + public PreUpgradeState checkUpgradeNeeded(Resource resource) { String version = loadProjectVersion(resource); - metaData.setProjectVersion(version); - metaData.setSupportedVersion(String.valueOf(Project.VERSION)); + String supportedVersion = String.valueOf(Project.VERSION); int c1 = VersionComparator.INSTANCE.compare(version, MIN_SUPPORTED_VERSION); if (c1 < 0) { - metaData.setIntermediateUpgradeVersion(MIN_SUPPORTED_VERSION); - metaData.setUpgradeType(UpgradeType.INTERMEDIATE_UPGRADE_NEEDED); - return metaData; + return new PreUpgradeState( + UpgradeType.INTERMEDIATE_UPGRADE_NEEDED, + version, + supportedVersion, + MIN_SUPPORTED_VERSION); } - int c2 = VersionComparator.INSTANCE.compare(String.valueOf(Project.VERSION), version); + int c2 = VersionComparator.INSTANCE.compare(supportedVersion, version); + UpgradeType upgradeType; if (c2 < 0) { - metaData.setUpgradeType(UpgradeType.DOWNGRADE_NEEDED); + upgradeType = UpgradeType.DOWNGRADE_NEEDED; } else if (c2 == 0) { - metaData.setUpgradeType(UpgradeType.UPGRADE_NOT_NEEDED); + upgradeType = UpgradeType.UPGRADE_NOT_NEEDED; } else { - metaData.setUpgradeType(UpgradeType.UPGRADE_NEEDED); + upgradeType = UpgradeType.UPGRADE_NEEDED; } - return metaData; + return new PreUpgradeState(upgradeType, version, supportedVersion, null); } protected List<UpgradeHandler> getHandlersForVersion(String version) { boolean found = MIN_SUPPORTED_VERSION.equals(version); List<UpgradeHandler> handlerList = new ArrayList<>(); - for(Map.Entry<String, UpgradeHandler> entry : handlers.entrySet()) { - if(entry.getKey().equals(version)) { + for (Map.Entry<String, UpgradeHandler> entry : handlers.entrySet()) { + if (entry.getKey().equals(version)) { found = true; continue; } - if(!found) { + if (!found) { continue; } @@ -155,39 +157,51 @@ public class DefaultUpgradeService implements UpgradeService { } @Override - public Resource upgradeProject(Resource resource) { + public PostUpgradeState upgrade(Resource resource) { List<UpgradeHandler> handlerList = getHandlersForVersion(loadProjectVersion(resource)); - List<UpgradeUnit> upgradeUnits = upgradeDOM(resource, handlerList); + List<UpgradeContext> upgradeUnits = upgradeDOM(resource, handlerList); saveDOM(upgradeUnits); - resource = upgradeUnits.get(0).getResource(); + resource = upgradeUnits.getFirst().getResource(); ConfigurationTree<DataChannelDescriptor> configurationTree = upgradeModel(resource, handlerList); saveModel(configurationTree); - return resource; + return new PostUpgradeState(resource, collectPostUpgradeMessages(upgradeUnits)); + } + + /** + * Collects user-facing messages recorded by upgrade handlers while processing the units, deduplicating repeats + * of the same message across units. + */ + protected static List<String> collectPostUpgradeMessages(Collection<UpgradeContext> upgradeUnits) { + Set<String> messages = new LinkedHashSet<>(); + for (UpgradeContext unit : upgradeUnits) { + messages.addAll(unit.getPostUpgradeMessages()); + } + return new ArrayList<>(messages); } - protected List<UpgradeUnit> upgradeDOM(Resource resource, List<UpgradeHandler> handlerList) { - List<UpgradeUnit> allUnits = new ArrayList<>(); + protected List<UpgradeContext> upgradeDOM(Resource resource, List<UpgradeHandler> handlerList) { + List<UpgradeContext> allUnits = new ArrayList<>(); // Load DOM for all resources Document projectDocument = readDocument(resource.getURL()); - UpgradeUnit projectUnit = new UpgradeUnit(resource, projectDocument); + UpgradeContext projectUnit = new UpgradeContext(resource, projectDocument); allUnits.add(projectUnit); List<Resource> dataMapResources = getAdditionalDatamapResources(projectUnit); - List<UpgradeUnit> dataMapUnits = new ArrayList<>(dataMapResources.size()); + List<UpgradeContext> dataMapUnits = new ArrayList<>(dataMapResources.size()); for (Resource dataMapResource : dataMapResources) { - dataMapUnits.add(new UpgradeUnit(dataMapResource, readDocument(dataMapResource.getURL()))); + dataMapUnits.add(new UpgradeContext(dataMapResource, readDocument(dataMapResource.getURL()))); } allUnits.addAll(dataMapUnits); // Update DOM - for(UpgradeHandler handler : handlerList) { + for (UpgradeHandler handler : handlerList) { handler.processProjectDom(projectUnit); - for(UpgradeUnit dataMapUnit : dataMapUnits) { + for (UpgradeContext dataMapUnit : dataMapUnits) { handler.processDataMapDom(dataMapUnit); } } @@ -195,8 +209,8 @@ public class DefaultUpgradeService implements UpgradeService { return allUnits; } - protected void saveDOM(Collection<UpgradeUnit> upgradeUnits) { - for(UpgradeUnit unit : upgradeUnits) { + protected void saveDOM(Collection<UpgradeContext> upgradeUnits) { + for (UpgradeContext unit : upgradeUnits) { saveDocument(unit); } } @@ -206,7 +220,7 @@ public class DefaultUpgradeService implements UpgradeService { ConfigurationTree<DataChannelDescriptor> configurationTree = loadProject(resource); // Update model level if needed - for(UpgradeHandler handler : handlerList) { + for (UpgradeHandler handler : handlerList) { handler.processModel(configurationTree.getRootNode()); } @@ -219,7 +233,7 @@ public class DefaultUpgradeService implements UpgradeService { // link all datamaps, or else we will lose cross-datamaps relationships EntityResolver resolver = new EntityResolver(); - for(DataMap dataMap : configurationTree.getRootNode().getDataMaps()) { + for (DataMap dataMap : configurationTree.getRootNode().getDataMaps()) { resolver.addDataMap(dataMap); dataMap.setNamespace(resolver); } @@ -232,7 +246,7 @@ public class DefaultUpgradeService implements UpgradeService { projectSaver.save(project); } - List<Resource> getAdditionalDatamapResources(UpgradeUnit upgradeUnit) { + List<Resource> getAdditionalDatamapResources(UpgradeContext upgradeUnit) { List<Resource> resources = new ArrayList<>(); try { XPath xpath = XPathFactory.newInstance().newXPath(); @@ -250,7 +264,7 @@ public class DefaultUpgradeService implements UpgradeService { return resources; } - protected void saveDocument(UpgradeUnit upgradeUnit) { + protected void saveDocument(UpgradeContext upgradeUnit) { try { Source input = new DOMSource(upgradeUnit.getDocument()); Result output = new StreamResult(Util.toFile(upgradeUnit.getResource().getURL())); @@ -348,7 +362,7 @@ public class DefaultUpgradeService implements UpgradeService { } } - class RootTagHandler extends DefaultHandler { + static class RootTagHandler extends DefaultHandler { private String projectVersion; diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeUnit.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/PostUpgradeState.java similarity index 64% copy from cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeUnit.java copy to cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/PostUpgradeState.java index 8803a2200..4aedeb027 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeUnit.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/PostUpgradeState.java @@ -16,39 +16,21 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ - package org.apache.cayenne.project.upgrade; import org.apache.cayenne.resource.Resource; -import org.w3c.dom.Document; + +import java.util.List; /** - * @since 4.1 + * A result of a project upgrade: the resource of the upgraded project plus optional messages from individual upgrade + * handlers, describing manual steps the user must perform to complete the upgrade. + * + * @since 5.0 */ -public class UpgradeUnit { - - private Resource resource; - - private Document document; - - public UpgradeUnit(Resource resource, Document document) { - this.resource = resource; - this.document = document; - } - - public Document getDocument() { - return document; - } - - public Resource getResource() { - return resource; - } - - public void setDocument(Document document) { - this.document = document; - } +public record PostUpgradeState(Resource resource, List<String> messages) { - public void setResource(Resource resource) { - this.resource = resource; + public PostUpgradeState { + messages = List.copyOf(messages); } } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeService.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/PreUpgradeState.java similarity index 76% copy from cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeService.java copy to cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/PreUpgradeState.java index edeb0df12..4ae52d50b 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeService.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/PreUpgradeState.java @@ -16,18 +16,16 @@ * specific language governing permissions and limitations * under the License. ****************************************************************/ - package org.apache.cayenne.project.upgrade; -import org.apache.cayenne.resource.Resource; - /** - * @since 4.1 + * An object providing upgrade information about a specific project in the context of enclosing Cayenne runtime. + * + * @since 3.1 */ -public interface UpgradeService { - - UpgradeMetaData getUpgradeType(Resource resource); - - Resource upgradeProject(Resource resource); - +public record PreUpgradeState( + UpgradeType requiredUpgrade, + String projectVersion, + String supportedVersion, + String intermediateUpgradeVersion) { } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeService.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/ProjectUpgrader.java similarity index 87% rename from cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeService.java rename to cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/ProjectUpgrader.java index edeb0df12..fd75206c9 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeService.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/ProjectUpgrader.java @@ -22,12 +22,12 @@ package org.apache.cayenne.project.upgrade; import org.apache.cayenne.resource.Resource; /** - * @since 4.1 + * @since 5.0 */ -public interface UpgradeService { +public interface ProjectUpgrader { - UpgradeMetaData getUpgradeType(Resource resource); + PreUpgradeState checkUpgradeNeeded(Resource resource); - Resource upgradeProject(Resource resource); + PostUpgradeState upgrade(Resource resource); } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeUnit.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeContext.java similarity index 59% rename from cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeUnit.java rename to cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeContext.java index 8803a2200..1d1acfbd5 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeUnit.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeContext.java @@ -22,18 +22,22 @@ package org.apache.cayenne.project.upgrade; import org.apache.cayenne.resource.Resource; import org.w3c.dom.Document; +import java.util.ArrayList; +import java.util.List; + /** * @since 4.1 */ -public class UpgradeUnit { - - private Resource resource; +public class UpgradeContext { - private Document document; + private final Resource resource; + private final Document document; + private final List<String> postUpgradeMessages; - public UpgradeUnit(Resource resource, Document document) { + public UpgradeContext(Resource resource, Document document) { this.resource = resource; this.document = document; + this.postUpgradeMessages = new ArrayList<>(); } public Document getDocument() { @@ -44,11 +48,21 @@ public class UpgradeUnit { return resource; } - public void setDocument(Document document) { - this.document = document; + /** + * Records a message shown to the user once the upgrade is done, describing manual steps required to complete + * the transition (e.g. regenerating classes or updating application code). Intended for upgrade handlers that + * detect a condition in this unit that they can't fix automatically. + * + * @since 5.0 + */ + public void addPostUpgradeMessage(String message) { + postUpgradeMessages.add(message); } - public void setResource(Resource resource) { - this.resource = resource; + /** + * @since 5.0 + */ + public List<String> getPostUpgradeMessages() { + return postUpgradeMessages; } } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeMetaData.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeMetaData.java deleted file mode 100644 index 1e5253855..000000000 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/UpgradeMetaData.java +++ /dev/null @@ -1,66 +0,0 @@ -/***************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 - * - * https://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.apache.cayenne.project.upgrade; - -/** - * An object providing upgrade information about a specific project in the context of - * enclosing Cayenne runtime. - * - * @since 3.1 - */ -public class UpgradeMetaData { - - protected UpgradeType upgradeType; - protected String projectVersion; - protected String supportedVersion; - protected String intermediateUpgradeVersion; - - public UpgradeType getUpgradeType() { - return upgradeType; - } - - public void setUpgradeType(UpgradeType upgradeType) { - this.upgradeType = upgradeType; - } - - public String getProjectVersion() { - return projectVersion; - } - - public void setProjectVersion(String projectVersion) { - this.projectVersion = projectVersion; - } - - public String getSupportedVersion() { - return supportedVersion; - } - - public void setSupportedVersion(String supportedVersion) { - this.supportedVersion = supportedVersion; - } - - public String getIntermediateUpgradeVersion() { - return intermediateUpgradeVersion; - } - - public void setIntermediateUpgradeVersion(String intermediateUpgradeVersion) { - this.intermediateUpgradeVersion = intermediateUpgradeVersion; - } - -} diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler.java index 680a6a4de..7baf63737 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler.java @@ -20,7 +20,7 @@ package org.apache.cayenne.project.upgrade.handlers; import org.apache.cayenne.configuration.DataChannelDescriptor; -import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.apache.cayenne.project.upgrade.UpgradeContext; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -73,12 +73,12 @@ public interface UpgradeHandler { /** * Process DOM for the project root file (e.g. cayenne-project.xml) */ - void processProjectDom(UpgradeUnit upgradeUnit); + void processProjectDom(UpgradeContext upgradeUnit); /** * Process DOM for the data map file (e.g. datamap.map.xml) */ - void processDataMapDom(UpgradeUnit upgradeUnit); + void processDataMapDom(UpgradeContext upgradeUnit); /** * This method should be avoided as much as possible, as @@ -93,7 +93,7 @@ public interface UpgradeHandler { * * @param upgradeUnit for the datamap */ - default void updateDomainSchemaAndVersion(UpgradeUnit upgradeUnit) { + default void updateDomainSchemaAndVersion(UpgradeContext upgradeUnit) { Element domain = upgradeUnit.getDocument().getDocumentElement(); // update schema domain.setAttribute("xmlns", "http://cayenne.apache.org/schema/" + getVersion() + "/domain"); @@ -109,7 +109,7 @@ public interface UpgradeHandler { * * @param upgradeUnit for the datamap */ - default void updateDataMapSchemaAndVersion(UpgradeUnit upgradeUnit) { + default void updateDataMapSchemaAndVersion(UpgradeContext upgradeUnit) { Element dataMap = upgradeUnit.getDocument().getDocumentElement(); // update schema dataMap.setAttribute("xmlns", "http://cayenne.apache.org/schema/" + getVersion() + "/modelMap"); @@ -125,7 +125,7 @@ public interface UpgradeHandler { * @param upgradeUnit a unit to work with * @param extension name of the extension (cgen, dbImport, etc.) */ - default void updateExtensionSchema(UpgradeUnit upgradeUnit, String extension) { + default void updateExtensionSchema(UpgradeContext upgradeUnit, String extension) { XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes; try { @@ -147,7 +147,7 @@ public interface UpgradeHandler { * @param extension name of the extension (e.g. validation) * @since 5.0-M2 */ - default void updateDomainExtensionSchema(UpgradeUnit upgradeUnit, String extension) { + default void updateDomainExtensionSchema(UpgradeContext upgradeUnit, String extension) { XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes; try { @@ -169,7 +169,7 @@ public interface UpgradeHandler { * @param upgradeUnit a unit to work with * @since 5.0 */ - default void updateInfoSchema(UpgradeUnit upgradeUnit) { + default void updateInfoSchema(UpgradeContext upgradeUnit) { XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes; try { diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10.java index ba01d8b2b..32aea9bef 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V10.java @@ -19,7 +19,7 @@ package org.apache.cayenne.project.upgrade.handlers; -import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.apache.cayenne.project.upgrade.UpgradeContext; /** * Upgrade handler for the project version "10" introduced by 4.1.M1 release. @@ -37,13 +37,13 @@ public class UpgradeHandler_V10 implements UpgradeHandler { } @Override - public void processProjectDom(UpgradeUnit upgradeUnit) { + public void processProjectDom(UpgradeContext upgradeUnit) { // introduce xml namespace and schema for domain updateDomainSchemaAndVersion(upgradeUnit); } @Override - public void processDataMapDom(UpgradeUnit upgradeUnit) { + public void processDataMapDom(UpgradeContext upgradeUnit) { updateDataMapSchemaAndVersion(upgradeUnit); } } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V11.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V11.java index 752fe2f63..a32736fa1 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V11.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V11.java @@ -19,7 +19,7 @@ package org.apache.cayenne.project.upgrade.handlers; -import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.apache.cayenne.project.upgrade.UpgradeContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; @@ -68,13 +68,13 @@ public class UpgradeHandler_V11 implements UpgradeHandler { } @Override - public void processProjectDom(UpgradeUnit upgradeUnit) { + public void processProjectDom(UpgradeContext upgradeUnit) { updateDomainSchemaAndVersion(upgradeUnit); updateDataNodeConnectionPool(upgradeUnit); } @Override - public void processDataMapDom(UpgradeUnit upgradeUnit) { + public void processDataMapDom(UpgradeContext upgradeUnit) { updateDataMapSchemaAndVersion(upgradeUnit); updateExtensionSchema(upgradeUnit, CGEN); updateExtensionSchema(upgradeUnit, DB_IMPORT); @@ -88,7 +88,7 @@ public class UpgradeHandler_V11 implements UpgradeHandler { updateDbImportConfig(upgradeUnit); } - private void dropROPProperties(UpgradeUnit upgradeUnit) { + private void dropROPProperties(UpgradeContext upgradeUnit) { Element dataMap = upgradeUnit.getDocument().getDocumentElement(); NodeList propertyNodes; try { @@ -112,7 +112,7 @@ public class UpgradeHandler_V11 implements UpgradeHandler { } } - private void dropObjEntityClientInfo(UpgradeUnit upgradeUnit) { + private void dropObjEntityClientInfo(UpgradeContext upgradeUnit) { NodeList objEntityNodes; try { XPath xpath = XPathFactory.newInstance().newXPath(); @@ -129,7 +129,7 @@ public class UpgradeHandler_V11 implements UpgradeHandler { } } - private void upgradeGenericObjEntity(UpgradeUnit upgradeUnit) { + private void upgradeGenericObjEntity(UpgradeContext upgradeUnit) { NodeList objEntityNodes; try { XPath xpath = XPathFactory.newInstance().newXPath(); @@ -147,7 +147,7 @@ public class UpgradeHandler_V11 implements UpgradeHandler { } } - private void updateDbImportConfig(UpgradeUnit upgradeUnit) { + private void updateDbImportConfig(UpgradeContext upgradeUnit) { XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes; try { @@ -162,13 +162,13 @@ public class UpgradeHandler_V11 implements UpgradeHandler { } } - private void updateCgenConfig(UpgradeUnit upgradeUnit) { + private void updateCgenConfig(UpgradeContext upgradeUnit) { renameQueryTemplates(upgradeUnit); dropCgenClientConfig(upgradeUnit); updateTemplates(upgradeUnit); } - private void updateDataNodeConnectionPool(UpgradeUnit upgradeUnit) { + private void updateDataNodeConnectionPool(UpgradeContext upgradeUnit) { XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes; try { @@ -187,7 +187,7 @@ public class UpgradeHandler_V11 implements UpgradeHandler { } } - private void renameQueryTemplates(UpgradeUnit upgradeUnit) { + private void renameQueryTemplates(UpgradeContext upgradeUnit) { XPath xpath = XPathFactory.newInstance().newXPath(); NodeList queryTemplates; NodeList querySuperTemplates; @@ -211,7 +211,7 @@ public class UpgradeHandler_V11 implements UpgradeHandler { } } - private void dropCgenClientConfig(UpgradeUnit upgradeUnit) { + private void dropCgenClientConfig(UpgradeContext upgradeUnit) { XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes; try { @@ -233,7 +233,7 @@ public class UpgradeHandler_V11 implements UpgradeHandler { * * @param upgradeUnit - unit to upgrade */ - private void updateTemplates(UpgradeUnit upgradeUnit) { + private void updateTemplates(UpgradeContext upgradeUnit) { updateTemplate(upgradeUnit, "template"); updateTemplate(upgradeUnit, "superTemplate"); updateTemplate(upgradeUnit, "embeddableTemplate"); @@ -242,7 +242,7 @@ public class UpgradeHandler_V11 implements UpgradeHandler { updateTemplate(upgradeUnit, "dataMapSuperTemplate"); } - private void updateTemplate(UpgradeUnit upgradeUnit, String nodeName) { + private void updateTemplate(UpgradeContext upgradeUnit, String nodeName) { XPath xpath = XPathFactory.newInstance().newXPath(); NodeList templates; try { diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V12.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V12.java index d5c56f183..cfd0e9075 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V12.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V12.java @@ -19,7 +19,7 @@ package org.apache.cayenne.project.upgrade.handlers; -import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.apache.cayenne.project.upgrade.UpgradeContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; @@ -51,21 +51,21 @@ public class UpgradeHandler_V12 implements UpgradeHandler { } @Override - public void processProjectDom(UpgradeUnit upgradeUnit) { + public void processProjectDom(UpgradeContext upgradeUnit) { updateDomainSchemaAndVersion(upgradeUnit); removeGraphIncludes(upgradeUnit); updateDomainExtensionSchema(upgradeUnit, VALIDATION); } @Override - public void processDataMapDom(UpgradeUnit upgradeUnit) { + public void processDataMapDom(UpgradeContext upgradeUnit) { updateDataMapSchemaAndVersion(upgradeUnit); updateExtensionSchema(upgradeUnit, CGEN); updateExtensionSchema(upgradeUnit, DB_IMPORT); updateInfoSchema(upgradeUnit); } - private void removeGraphIncludes(UpgradeUnit upgradeUnit) { + private void removeGraphIncludes(UpgradeContext upgradeUnit) { XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes; try { @@ -79,9 +79,10 @@ public class UpgradeHandler_V12 implements UpgradeHandler { for (int j = 0; j < nodes.getLength(); j++) { Element element = (Element) nodes.item(j); String href = element.getAttribute("href"); - if (href != null && href.endsWith(GRAPH_SUFFIX)) { + if (href.endsWith(GRAPH_SUFFIX)) { deleteGraphFile(upgradeUnit, href); toRemove.add(element); + upgradeUnit.addPostUpgradeMessage("The 'graph' diagram layout is no longer supported and was deleted from the project"); } } for (Element element : toRemove) { @@ -89,7 +90,7 @@ public class UpgradeHandler_V12 implements UpgradeHandler { } } - private void deleteGraphFile(UpgradeUnit upgradeUnit, String href) { + private void deleteGraphFile(UpgradeContext upgradeUnit, String href) { try { File projectFile = new File(upgradeUnit.getResource().getURL().toURI()); File graphFile = new File(projectFile.getParentFile(), href); diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7.java index 217645818..9a41e7e0b 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V7.java @@ -19,20 +19,20 @@ package org.apache.cayenne.project.upgrade.handlers; -import java.util.ArrayList; -import java.util.List; -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathFactory; - import org.apache.cayenne.configuration.DataChannelDescriptor; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.map.ObjEntity; -import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.apache.cayenne.project.upgrade.UpgradeContext; import org.w3c.dom.Element; import org.w3c.dom.Node; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; +import java.util.ArrayList; +import java.util.List; + /** * @since 4.1 */ @@ -44,7 +44,7 @@ public class UpgradeHandler_V7 implements UpgradeHandler { } @Override - public void processProjectDom(UpgradeUnit upgradeUnit) { + public void processProjectDom(UpgradeContext upgradeUnit) { Element domain = upgradeUnit.getDocument().getDocumentElement(); domain.setAttribute("project-version", getVersion()); @@ -63,7 +63,7 @@ public class UpgradeHandler_V7 implements UpgradeHandler { } @Override - public void processDataMapDom(UpgradeUnit upgradeUnit) { + public void processDataMapDom(UpgradeContext upgradeUnit) { updateDataMapSchemaAndVersion(upgradeUnit); } diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8.java index 5ce9328f9..74ea62bf7 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V8.java @@ -25,7 +25,7 @@ import javax.xml.xpath.XPathFactory; import org.apache.cayenne.ConfigurationException; import org.apache.cayenne.map.QueryDescriptor; -import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.apache.cayenne.project.upgrade.UpgradeContext; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -40,13 +40,13 @@ public class UpgradeHandler_V8 implements UpgradeHandler { } @Override - public void processProjectDom(UpgradeUnit upgradeUnit) { + public void processProjectDom(UpgradeContext upgradeUnit) { Element domain = upgradeUnit.getDocument().getDocumentElement(); domain.setAttribute("project-version", getVersion()); } @Override - public void processDataMapDom(UpgradeUnit upgradeUnit) { + public void processDataMapDom(UpgradeContext upgradeUnit) { updateDataMapSchemaAndVersion(upgradeUnit); XPath xpath = XPathFactory.newInstance().newXPath(); diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9.java b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9.java index b6836e6d5..499cc7fea 100644 --- a/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9.java +++ b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V9.java @@ -24,7 +24,7 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; -import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.apache.cayenne.project.upgrade.UpgradeContext; import org.apache.cayenne.util.Util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,13 +45,13 @@ public class UpgradeHandler_V9 implements UpgradeHandler { } @Override - public void processProjectDom(UpgradeUnit upgradeUnit) { + public void processProjectDom(UpgradeContext upgradeUnit) { Element domain = upgradeUnit.getDocument().getDocumentElement(); domain.setAttribute("project-version", getVersion()); } @Override - public void processDataMapDom(UpgradeUnit upgradeUnit) { + public void processDataMapDom(UpgradeContext upgradeUnit) { Document document = upgradeUnit.getDocument(); Element dataMap = document.getDocumentElement(); updateDataMapSchemaAndVersion(upgradeUnit); diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultProjectUpgraderTest.java similarity index 86% rename from cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java rename to cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultProjectUpgraderTest.java index 8a006c96c..62d9a02f4 100644 --- a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultUpgradeServiceTest.java +++ b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/DefaultProjectUpgraderTest.java @@ -43,16 +43,16 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; -public class DefaultUpgradeServiceTest { +public class DefaultProjectUpgraderTest { - DefaultUpgradeService upgradeService; + DefaultProjectUpgrader upgradeService; List<UpgradeHandler> handlers; @BeforeEach public void createService() { createHandlers(); - upgradeService = new DefaultUpgradeService(handlers); + upgradeService = new DefaultProjectUpgrader(handlers); } @ParameterizedTest @@ -64,9 +64,9 @@ public class DefaultUpgradeServiceTest { "12, UPGRADE_NOT_NEEDED", "13, DOWNGRADE_NEEDED" }) - public void getUpgradeType(String version, UpgradeType expectedType) { - UpgradeMetaData metaData = upgradeService.getUpgradeType(getResourceForVersion(version)); - assertEquals(expectedType, metaData.getUpgradeType()); + public void checkUpgradeNeeded(String version, UpgradeType expectedType) { + PreUpgradeState metaData = upgradeService.checkUpgradeNeeded(getResourceForVersion(version)); + assertEquals(expectedType, metaData.requiredUpgrade()); } @Test @@ -87,7 +87,7 @@ public class DefaultUpgradeServiceTest { URL url = Objects.requireNonNull(getClass().getResource("../cayenne-PROJECT1.xml")); Resource resource = new URLResource(url); Document document = readDocument(url); - UpgradeUnit unit = new UpgradeUnit(resource, document); + UpgradeContext unit = new UpgradeContext(resource, document); List<Resource> resources = upgradeService.getAdditionalDatamapResources(unit); assertEquals(2, resources.size()); @@ -107,7 +107,7 @@ public class DefaultUpgradeServiceTest { "10, 10.0" }) public void decodeVersion(String version, double expected) { - assertEquals(expected, DefaultUpgradeService.decodeVersion(version), 0.000001); + assertEquals(expected, DefaultProjectUpgrader.decodeVersion(version), 0.000001); } @Test @@ -115,10 +115,10 @@ public class DefaultUpgradeServiceTest { Resource resource = new URLResource(getClass().getResource("../cayenne-PROJECT1.xml")); // Mock service so it will use actual reading but skip actual saving part - upgradeService = mock(DefaultUpgradeService.class); + upgradeService = mock(DefaultProjectUpgrader.class); when(upgradeService.upgradeDOM(any(Resource.class), ArgumentMatchers.anyList())) .thenCallRealMethod(); - when(upgradeService.getAdditionalDatamapResources(any(UpgradeUnit.class))) + when(upgradeService.getAdditionalDatamapResources(any(UpgradeContext.class))) .thenCallRealMethod(); upgradeService.upgradeDOM(resource, handlers); @@ -127,16 +127,16 @@ public class DefaultUpgradeServiceTest { // verify(upgradeService, times(3)).saveDocument(any(UpgradeUnit.class)); for(UpgradeHandler handler : handlers) { verify(handler).getVersion(); - verify(handler).processProjectDom(any(UpgradeUnit.class)); + verify(handler).processProjectDom(any(UpgradeContext.class)); // two data maps - verify(handler, times(2)).processDataMapDom(any(UpgradeUnit.class)); + verify(handler, times(2)).processDataMapDom(any(UpgradeContext.class)); verifyNoMoreInteractions(handler); } } @Test public void readDocument() { - Document document = DefaultUpgradeService.readDocument(getClass().getResource("../cayenne-PROJECT1.xml")); + Document document = DefaultProjectUpgrader.readDocument(getClass().getResource("../cayenne-PROJECT1.xml")); assertEquals("12", document.getDocumentElement().getAttribute("project-version")); } diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/BaseUpgradeHandlerTest.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/BaseUpgradeHandlerTest.java index 7b548a3a7..f330496dc 100644 --- a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/BaseUpgradeHandlerTest.java +++ b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/BaseUpgradeHandlerTest.java @@ -20,11 +20,10 @@ package org.apache.cayenne.project.upgrade.handlers; import java.io.InputStreamReader; -import java.io.StringReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.apache.cayenne.project.upgrade.UpgradeContext; import org.apache.cayenne.resource.URLResource; import org.junit.jupiter.api.BeforeEach; import org.w3c.dom.Document; @@ -42,14 +41,14 @@ abstract class BaseUpgradeHandlerTest { abstract UpgradeHandler newHandler(); Document processProjectDom(String xmlResourceName) throws Exception { - UpgradeUnit unit = new UpgradeUnit(new URLResource(getClass().getResource(xmlResourceName)), + UpgradeContext unit = new UpgradeContext(new URLResource(getClass().getResource(xmlResourceName)), documentFromResource(xmlResourceName)); handler.processProjectDom(unit); return unit.getDocument(); } Document processDataMapDom(String xmlResourceName) throws Exception { - UpgradeUnit unit = new UpgradeUnit(new URLResource(getClass().getResource(xmlResourceName)), + UpgradeContext unit = new UpgradeContext(new URLResource(getClass().getResource(xmlResourceName)), documentFromResource(xmlResourceName)); handler.processDataMapDom(unit); return unit.getDocument(); diff --git a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V12Test.java b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V12Test.java index a2394069e..14c7ce002 100644 --- a/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V12Test.java +++ b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V12Test.java @@ -20,7 +20,7 @@ package org.apache.cayenne.project.upgrade.handlers; import org.apache.cayenne.configuration.DataChannelDescriptor; -import org.apache.cayenne.project.upgrade.UpgradeUnit; +import org.apache.cayenne.project.upgrade.UpgradeContext; import org.apache.cayenne.resource.URLResource; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -57,7 +57,8 @@ public class UpgradeHandler_V12Test extends BaseUpgradeHandlerTest { File graphFile = copyResourceToTemp("../v12/project1.graph.xml", "project1.graph.xml"); assertTrue(graphFile.exists(), "precondition: graph file exists"); - Document document = processProjectDomFromFile(projectFile); + UpgradeContext unit = processProjectDomFromFile(projectFile); + Document document = unit.getDocument(); Element root = document.getDocumentElement(); assertEquals("12", root.getAttribute("project-version")); @@ -75,6 +76,9 @@ public class UpgradeHandler_V12Test extends BaseUpgradeHandlerTest { ((Element) validation.item(0)).getAttribute("xmlns")); assertFalse(graphFile.exists(), "graph file must be deleted"); + + assertEquals(1, unit.getPostUpgradeMessages().size()); + assertEquals("The 'graph' diagram layout is no longer supported and was deleted from the project", unit.getPostUpgradeMessages().getFirst()); } @Test @@ -82,7 +86,7 @@ public class UpgradeHandler_V12Test extends BaseUpgradeHandlerTest { File projectFile = copyResourceToTemp("../v12/cayenne-project1.xml", "cayenne-project.xml"); // graph file intentionally absent — upgrade must complete without exception - Document document = processProjectDomFromFile(projectFile); + Document document = processProjectDomFromFile(projectFile).getDocument(); Element root = document.getDocumentElement(); assertEquals("12", root.getAttribute("project-version")); @@ -142,14 +146,14 @@ public class UpgradeHandler_V12Test extends BaseUpgradeHandlerTest { return target; } - private Document processProjectDomFromFile(File file) throws Exception { + private UpgradeContext processProjectDomFromFile(File file) throws Exception { DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document doc; try (InputStream in = Files.newInputStream(file.toPath())) { doc = db.parse(in); } - UpgradeUnit unit = new UpgradeUnit(new URLResource(file.toURI().toURL()), doc); + UpgradeContext unit = new UpgradeContext(new URLResource(file.toURI().toURL()), doc); handler.processProjectDom(unit); - return doc; + return unit; } } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java index 0498d786b..0fa9e2073 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java @@ -50,7 +50,7 @@ import org.apache.cayenne.project.ConfigurationNodeParentGetter; import org.apache.cayenne.project.ProjectLoader; import org.apache.cayenne.project.ProjectModule; import org.apache.cayenne.project.ProjectSaver; -import org.apache.cayenne.project.upgrade.UpgradeService; +import org.apache.cayenne.project.upgrade.ProjectUpgrader; import org.apache.cayenne.project.validation.ProjectValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -140,8 +140,8 @@ public class Application { return injector.getInstance(DataMapLoader.class); } - public UpgradeService getUpgradeService() { - return injector.getInstance(UpgradeService.class); + public ProjectUpgrader getUpgradeService() { + return injector.getInstance(ProjectUpgrader.class); } public CMFileChooser getFileChooser(Component parent, String title) { diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/OpenProjectAction.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/OpenProjectAction.java index 4df09b64f..e4ad6f95b 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/OpenProjectAction.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/action/OpenProjectAction.java @@ -26,8 +26,9 @@ import org.apache.cayenne.modeler.toolkit.filechooser.FileFilters; import org.apache.cayenne.modeler.ui.MainFrame; import org.apache.cayenne.modeler.ui.errors.ErrorDialog; import org.apache.cayenne.project.Project; -import org.apache.cayenne.project.upgrade.UpgradeMetaData; -import org.apache.cayenne.project.upgrade.UpgradeService; +import org.apache.cayenne.project.upgrade.PostUpgradeState; +import org.apache.cayenne.project.upgrade.PreUpgradeState; +import org.apache.cayenne.project.upgrade.ProjectUpgrader; import org.apache.cayenne.resource.Resource; import org.apache.cayenne.resource.URLResource; import org.slf4j.Logger; @@ -42,6 +43,7 @@ import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.io.File; import java.net.URL; +import java.util.List; import java.util.Map; public class OpenProjectAction extends AppAction { @@ -137,11 +139,13 @@ public class OpenProjectAction extends AppAction { URL url = file.toURI().toURL(); Resource rootSource = new URLResource(url); - UpgradeService upgradeService = app.getUpgradeService(); - UpgradeMetaData metaData = upgradeService.getUpgradeType(rootSource); - switch (metaData.getUpgradeType()) { + List<String> upgradeMessages = List.of(); + + ProjectUpgrader projectUpgrader = app.getUpgradeService(); + PreUpgradeState metaData = projectUpgrader.checkUpgradeNeeded(rootSource); + switch (metaData.requiredUpgrade()) { case INTERMEDIATE_UPGRADE_NEEDED: - String modelerVersion = PROJECT_TO_MODELER_VERSION.get(metaData.getProjectVersion()); + String modelerVersion = PROJECT_TO_MODELER_VERSION.get(metaData.projectVersion()); if (modelerVersion == null) { modelerVersion = ""; } @@ -161,7 +165,9 @@ public class OpenProjectAction extends AppAction { case UPGRADE_NEEDED: if (processUpgrades()) { - rootSource = upgradeService.upgradeProject(rootSource); + PostUpgradeState postUpgrade = projectUpgrader.upgrade(rootSource); + rootSource = postUpgrade.resource(); + upgradeMessages = postUpgrade.messages(); } else { CloseProjectAction.closeProject(app, false); return; @@ -171,6 +177,10 @@ public class OpenProjectAction extends AppAction { openProjectResource(rootSource, controller, mcpHandshakeNonce); + if (!upgradeMessages.isEmpty()) { + showPostUpgradeMessages(upgradeMessages); + } + } catch (Exception ex) { LOGGER.warn("Error loading project file.", ex); @@ -184,6 +194,14 @@ public class OpenProjectAction extends AppAction { return project; } + private void showPostUpgradeMessages(List<String> messages) { + JOptionPane.showMessageDialog( + app.getFrame(), + "The project was upgraded, but some manual steps are required:\n\n" + String.join("\n\n", messages), + "Manual Steps Required", + JOptionPane.INFORMATION_MESSAGE); + } + private boolean processUpgrades() { // need an upgrade int returnCode = JOptionPane.showConfirmDialog(
