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 374ec4acc6d6c072176ae03e1236e2c8f069730b
Author: Andrus Adamchik <[email protected]>
AuthorDate: Fri May 8 16:59:27 2026 -0400

    CAY-2937 Decomission "graph" support
    
    * wiring up v12 upgrade mechanism
---
 .../java/org/apache/cayenne/project/Project.java   |   2 +-
 .../org/apache/cayenne/project/ProjectModule.java  |   4 +-
 .../upgrade/handlers/UpgradeHandler_V12.java       |  99 ++++++++++++++++
 .../project/upgrade/DefaultUpgradeServiceTest.java |  12 +-
 .../upgrade/handlers/UpgradeHandler_V12Test.java   | 128 +++++++++++++++++++++
 .../upgrade/handlers/cayenne-project-v11.xml       |   2 +-
 ...nne-project-v11.xml => cayenne-project-v13.xml} |   2 +-
 .../project/upgrade/v12/cayenne-project1.xml       |  19 +++
 .../cayenne/project/upgrade/v12/map1.map.xml       |  42 +++++++
 .../cayenne/project/upgrade/v12/project1.graph.xml |   7 ++
 10 files changed, 309 insertions(+), 8 deletions(-)

diff --git 
a/cayenne-project/src/main/java/org/apache/cayenne/project/Project.java 
b/cayenne-project/src/main/java/org/apache/cayenne/project/Project.java
index 4cd6c3242..20e840d88 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/Project.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/Project.java
@@ -42,7 +42,7 @@ public class Project {
         *
         * @since 4.1
         */
-       static public final int VERSION = 11;
+       static public final int VERSION = 12;
 
        protected boolean modified;
 
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 a594bd1ca..0b9ede4dc 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
@@ -29,6 +29,7 @@ import org.apache.cayenne.project.upgrade.UpgradeService;
 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;
+import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V12;
 import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V7;
 import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V8;
 import org.apache.cayenne.project.upgrade.handlers.UpgradeHandler_V9;
@@ -85,6 +86,7 @@ public class ProjectModule implements Module {
                 .addUpgradeHandler(UpgradeHandler_V8.class)
                 .addUpgradeHandler(UpgradeHandler_V9.class)
                 .addUpgradeHandler(UpgradeHandler_V10.class)
-                .addUpgradeHandler(UpgradeHandler_V11.class);
+                .addUpgradeHandler(UpgradeHandler_V11.class)
+                .addUpgradeHandler(UpgradeHandler_V12.class);
     }
 }
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
new file mode 100644
index 000000000..78a46d88f
--- /dev/null
+++ 
b/cayenne-project/src/main/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V12.java
@@ -0,0 +1,99 @@
+/*****************************************************************
+ *   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.handlers;
+
+import org.apache.cayenne.project.upgrade.UpgradeUnit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+import java.io.File;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Upgrade handler for the project version "12" introduced by 5.0.M2 release.
+ * Changes: graph extension removal from Cayenne projects.
+ *
+ * @since 5.0
+ */
+public class UpgradeHandler_V12 implements UpgradeHandler {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(UpgradeHandler_V12.class);
+
+    static final String GRAPH_SUFFIX = ".graph.xml";
+
+    @Override
+    public String getVersion() {
+        return "12";
+    }
+
+    @Override
+    public void processProjectDom(UpgradeUnit upgradeUnit) {
+        updateDomainSchemaAndVersion(upgradeUnit);
+        removeGraphIncludes(upgradeUnit);
+    }
+
+    @Override
+    public void processDataMapDom(UpgradeUnit upgradeUnit) {
+        updateDataMapSchemaAndVersion(upgradeUnit);
+    }
+
+    private void removeGraphIncludes(UpgradeUnit upgradeUnit) {
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        NodeList nodes;
+        try {
+            nodes = (NodeList) 
xpath.evaluate("/domain/*[local-name()='include']",
+                    upgradeUnit.getDocument(), XPathConstants.NODESET);
+        } catch (Exception e) {
+            return;
+        }
+
+        List<Element> toRemove = new ArrayList<>();
+        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)) {
+                deleteGraphFile(upgradeUnit, href);
+                toRemove.add(element);
+            }
+        }
+        for (Element element : toRemove) {
+            element.getParentNode().removeChild(element);
+        }
+    }
+
+    private void deleteGraphFile(UpgradeUnit upgradeUnit, String href) {
+        try {
+            File projectFile = new 
File(upgradeUnit.getResource().getURL().toURI());
+            File graphFile = new File(projectFile.getParentFile(), href);
+            if (!Files.deleteIfExists(graphFile.toPath())) {
+                logger.warn("Graph file not found, skipping deletion: {}", 
graphFile);
+            }
+        } catch (Exception e) {
+            logger.warn("Failed to delete graph file '{}': {}", href, 
e.getMessage());
+        }
+    }
+}
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/DefaultUpgradeServiceTest.java
index a2ba5ca12..11eddc377 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/DefaultUpgradeServiceTest.java
@@ -68,9 +68,12 @@ public class DefaultUpgradeServiceTest {
         assertEquals(UpgradeType.UPGRADE_NEEDED, metaData.getUpgradeType());
 
         metaData = upgradeService.getUpgradeType(getResourceForVersion("11"));
-        assertEquals(UpgradeType.UPGRADE_NOT_NEEDED, 
metaData.getUpgradeType());
+        assertEquals(UpgradeType.UPGRADE_NEEDED, metaData.getUpgradeType());
 
         metaData = upgradeService.getUpgradeType(getResourceForVersion("12"));
+        assertEquals(UpgradeType.UPGRADE_NOT_NEEDED, 
metaData.getUpgradeType());
+
+        metaData = upgradeService.getUpgradeType(getResourceForVersion("13"));
         assertEquals(UpgradeType.DOWNGRADE_NEEDED, metaData.getUpgradeType());
     }
 
@@ -78,12 +81,13 @@ public class DefaultUpgradeServiceTest {
     public void getHandlersForVersion() throws Exception {
 
         List<UpgradeHandler> handlers = 
upgradeService.getHandlersForVersion("6");
-        assertEquals(5, handlers.size());
+        assertEquals(6, handlers.size());
 
         handlers = upgradeService.getHandlersForVersion("9");
-        assertEquals(2, handlers.size());
+        assertEquals(3, handlers.size());
         assertEquals("10", handlers.get(0).getVersion());
         assertEquals("11", handlers.get(1).getVersion());
+        assertEquals("12", handlers.get(2).getVersion());
     }
 
     @Test
@@ -148,7 +152,7 @@ public class DefaultUpgradeServiceTest {
 
     private void createHandlers() {
         handlers = new ArrayList<>();
-        String[] versions = {"7", "8", "9", "10", "11"};
+        String[] versions = {"7", "8", "9", "10", "11", "12"};
         for(String version : versions) {
             handlers.add(createHandler(version));
         }
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
new file mode 100644
index 000000000..af7ba9b99
--- /dev/null
+++ 
b/cayenne-project/src/test/java/org/apache/cayenne/project/upgrade/handlers/UpgradeHandler_V12Test.java
@@ -0,0 +1,128 @@
+/*****************************************************************
+ *   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.handlers;
+
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.project.upgrade.UpgradeUnit;
+import org.apache.cayenne.resource.URLResource;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyNoInteractions;
+
+/**
+ * @since 5.0
+ */
+public class UpgradeHandler_V12Test extends BaseUpgradeHandlerTest {
+
+    @Rule
+    public TemporaryFolder tempFolder = new TemporaryFolder();
+
+    @Override
+    UpgradeHandler newHandler() {
+        return new UpgradeHandler_V12();
+    }
+
+    @Test
+    public void testProjectDomUpgrade() throws Exception {
+        File projectFile = copyResourceToTemp("../v12/cayenne-project1.xml", 
"cayenne-project.xml");
+        File graphFile = copyResourceToTemp("../v12/project1.graph.xml", 
"project1.graph.xml");
+        assertTrue("precondition: graph file exists", graphFile.exists());
+
+        Document document = processProjectDomFromFile(projectFile);
+
+        Element root = document.getDocumentElement();
+        assertEquals("12", root.getAttribute("project-version"));
+        assertEquals("http://cayenne.apache.org/schema/12/domain";, 
root.getAttribute("xmlns"));
+
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        NodeList includes = (NodeList) 
xpath.evaluate("/domain/*[local-name()='include']",
+                document, XPathConstants.NODESET);
+        assertEquals("xi:include must be removed", 0, includes.getLength());
+
+        assertFalse("graph file must be deleted", graphFile.exists());
+    }
+
+    @Test
+    public void testProjectDomUpgradeNoGraphFile() throws Exception {
+        File projectFile = copyResourceToTemp("../v12/cayenne-project1.xml", 
"cayenne-project.xml");
+
+        // graph file intentionally absent — upgrade must complete without 
exception
+        Document document = processProjectDomFromFile(projectFile);
+
+        Element root = document.getDocumentElement();
+        assertEquals("12", root.getAttribute("project-version"));
+
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        NodeList includes = (NodeList) 
xpath.evaluate("/domain/*[local-name()='include']",
+                document, XPathConstants.NODESET);
+        assertEquals("xi:include must be removed", 0, includes.getLength());
+    }
+
+    @Test
+    public void testDataMapDomUpgrade() throws Exception {
+        Document document = processDataMapDom("../v12/map1.map.xml");
+
+        Element root = document.getDocumentElement();
+        assertEquals("12", root.getAttribute("project-version"));
+        assertEquals("http://cayenne.apache.org/schema/12/modelMap";, 
root.getAttribute("xmlns"));
+    }
+
+    @Test
+    public void testModelUpgrade() {
+        DataChannelDescriptor descriptor = mock(DataChannelDescriptor.class);
+        handler.processModel(descriptor);
+        verifyNoInteractions(descriptor);
+    }
+
+    private File copyResourceToTemp(String resourcePath, String targetName) 
throws Exception {
+        File target = new File(tempFolder.getRoot(), targetName);
+        try (InputStream in = getClass().getResourceAsStream(resourcePath)) {
+            Files.copy(in, target.toPath());
+        }
+        return target;
+    }
+
+    private Document 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);
+        handler.processProjectDom(unit);
+        return doc;
+    }
+}
diff --git 
a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml
 
b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml
index 51f7c4cd1..28d421695 100644
--- 
a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml
+++ 
b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml
@@ -1,3 +1,3 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- Fake version to test DefaultUpgradeService -->
-<domain project-version="11"/>
\ No newline at end of file
+<domain project-version="11"/>
diff --git 
a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml
 
b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v13.xml
similarity index 74%
copy from 
cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml
copy to 
cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v13.xml
index 51f7c4cd1..35dd50c5e 100644
--- 
a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v11.xml
+++ 
b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/handlers/cayenne-project-v13.xml
@@ -1,3 +1,3 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- Fake version to test DefaultUpgradeService -->
-<domain project-version="11"/>
\ No newline at end of file
+<domain project-version="13"/>
diff --git 
a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/v12/cayenne-project1.xml
 
b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/v12/cayenne-project1.xml
new file mode 100644
index 000000000..b305de836
--- /dev/null
+++ 
b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/v12/cayenne-project1.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain xmlns="http://cayenne.apache.org/schema/11/domain";
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+        xsi:schemaLocation="http://cayenne.apache.org/schema/11/domain 
https://cayenne.apache.org/schema/11/domain.xsd";
+        project-version="11">
+       <map name="map1"/>
+       <node name="node1"
+                adapter="org.example.test.Adapter"
+                
factory="org.apache.cayenne.configuration.runtime.XMLPoolingDataSourceFactory">
+               <map-ref name="map1"/>
+               <data-source>
+                       <driver/>
+                       <url/>
+                       <connectionPool min="1" max="1"/>
+                       <login/>
+               </data-source>
+       </node>
+       <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; 
href="project1.graph.xml"/>
+</domain>
diff --git 
a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/v12/map1.map.xml
 
b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/v12/map1.map.xml
new file mode 100644
index 000000000..c34c87c39
--- /dev/null
+++ 
b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/v12/map1.map.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/11/modelMap";
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+        xsi:schemaLocation="http://cayenne.apache.org/schema/11/modelMap 
https://cayenne.apache.org/schema/11/modelMap.xsd";
+        project-version="11">
+       <property name="defaultPackage" value="org.apache.cayenne.x"/>
+       <db-entity name="db_entity">
+               <db-attribute name="untitledAttr" type="INTEGER" 
isPrimaryKey="true" isMandatory="true"/>
+       </db-entity>
+       <db-entity name="db_entity1">
+               <db-attribute name="untitledAttr" type="INTEGER" 
isPrimaryKey="true" isMandatory="true"/>
+       </db-entity>
+       <dbImport xmlns="http://cayenne.apache.org/schema/11/dbimport";>
+               <tableTypes>
+                       <tableType>TABLE</tableType>
+                       <tableType>VIEW</tableType>
+               </tableTypes>
+               <forceDataMapCatalog>false</forceDataMapCatalog>
+               <forceDataMapSchema>false</forceDataMapSchema>
+               
<namingStrategy>org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator</namingStrategy>
+               <skipPrimaryKeyLoading>false</skipPrimaryKeyLoading>
+               <skipRelationshipsLoading>false</skipRelationshipsLoading>
+               <useJava7Types>false</useJava7Types>
+       </dbImport>
+       <cgen xmlns="http://cayenne.apache.org/schema/11/cgen";>
+               <name>Default</name>
+               <destDir>../../../../../../../java</destDir>
+               <mode>entity</mode>
+               <template>templates/v4_1/subclass.vm</template>
+               <superTemplate>templates/v4_1/superclass.vm</superTemplate>
+               
<embeddableTemplate>templates/v4_1/embeddable-subclass.vm</embeddableTemplate>
+               
<embeddableSuperTemplate>templates/v4_1/embeddable-superclass.vm</embeddableSuperTemplate>
+               
<dataMapTemplate>templates/v4_1/datamap-subclass.vm</dataMapTemplate>
+               
<dataMapSuperTemplate>templates/v4_1/datamap-superclass.vm</dataMapSuperTemplate>
+               <outputPattern>*.java</outputPattern>
+               <makePairs>true</makePairs>
+               <usePkgPath>true</usePkgPath>
+               <overwrite>false</overwrite>
+               <createPropertyNames>false</createPropertyNames>
+               <createPKProperties>true</createPKProperties>
+       </cgen>
+</data-map>
diff --git 
a/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/v12/project1.graph.xml
 
b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/v12/project1.graph.xml
new file mode 100644
index 000000000..447447a36
--- /dev/null
+++ 
b/cayenne-project/src/test/resources/org/apache/cayenne/project/upgrade/v12/project1.graph.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<graphs xmlns="http://cayenne.apache.org/schema/11/graph";>
+       <graph type="ER" scale="1.0">
+               <entity name="db_entity" x="36.0" y="178.5" width="75.0" 
height="50.0"/>
+               <entity name="db_entity1" x="183.0" y="176.5" width="75.0" 
height="50.0"/>
+       </graph>
+</graphs>

Reply via email to