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 41ce36f57713fb104c9e265878ddfda9074b86e0 Author: Andrus Adamchik <[email protected]> AuthorDate: Sun May 24 08:51:04 2026 -0400 CAY-2949 CayenneModeler MCP: dbimport_run tool preliminary refactoring - node ID calculator needs to be shared --- .../cayenne/modeler/pref/PreferenceNodeIds.java | 8 +- .../modeler/pref/PreferenceNodeIdsTest.java | 123 +++++++++++++++++++++ 2 files changed, 126 insertions(+), 5 deletions(-) diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferenceNodeIds.java b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/PreferenceNodeIds.java similarity index 92% rename from modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferenceNodeIds.java rename to modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/PreferenceNodeIds.java index fef18c281..e8be4c3c5 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/pref/PreferenceNodeIds.java +++ b/modeler/cayenne-modeler-prefs/src/main/java/org/apache/cayenne/modeler/pref/PreferenceNodeIds.java @@ -25,12 +25,10 @@ import java.security.NoSuchAlgorithmException; import java.util.prefs.Preferences; /** - * Encodes a file path into a single-segment {@link Preferences} node name. The id has - * the form {@code <16-hex-sha256>-<sanitized-basename>} and stays under {@link #MAX_LEN} - * characters, well below {@link Preferences#MAX_NAME_LENGTH}. The original absolute - * path is meant to be stored alongside the node as a {@code path} value. + * Does repeatable encoding of a file path into a single-segment {@link Preferences} node name. The id has + * the form {@code <16-hex-sha256>-<sanitized-basename>} and stays under {@link Preferences#MAX_NAME_LENGTH}. */ -class PreferenceNodeIds { +public class PreferenceNodeIds { static final int MAX_LEN = 60; static final int HASH_LEN = 16; diff --git a/modeler/cayenne-modeler-prefs/src/test/java/org/apache/cayenne/modeler/pref/PreferenceNodeIdsTest.java b/modeler/cayenne-modeler-prefs/src/test/java/org/apache/cayenne/modeler/pref/PreferenceNodeIdsTest.java new file mode 100644 index 000000000..5b9c51ade --- /dev/null +++ b/modeler/cayenne-modeler-prefs/src/test/java/org/apache/cayenne/modeler/pref/PreferenceNodeIdsTest.java @@ -0,0 +1,123 @@ +/***************************************************************** + * 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.modeler.pref; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class PreferenceNodeIdsTest { + + @Test + public void idForPathIsStable() { + String id1 = PreferenceNodeIds.idForPath("/home/user/project/myapp.xml"); + String id2 = PreferenceNodeIds.idForPath("/home/user/project/myapp.xml"); + assertEquals(id1, id2); + } + + @Test + public void idForPathStaysUnderMaxLen() { + String longPath = "/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/very-long-name.xml"; + String id = PreferenceNodeIds.idForPath(longPath); + assertTrue(id.length() <= PreferenceNodeIds.MAX_LEN, + "id length " + id.length() + " exceeds MAX_LEN " + PreferenceNodeIds.MAX_LEN); + } + + @Test + public void idForPathStartsWithHash() { + String id = PreferenceNodeIds.idForPath("/foo/bar.xml"); + assertEquals(PreferenceNodeIds.HASH_LEN, id.indexOf('-'), + "id should start with exactly HASH_LEN hex chars before the dash"); + } + + @Test + public void idForPathDifferentPathsProduceDifferentIds() { + String id1 = PreferenceNodeIds.idForPath("/project/a.xml"); + String id2 = PreferenceNodeIds.idForPath("/project/b.xml"); + assertTrue(!id1.equals(id2), "different paths must produce different ids"); + } + + @Test + public void idForPathXmlSuffixStripped() { + String withXml = PreferenceNodeIds.idForPath("/foo/bar.xml"); + String withoutXml = PreferenceNodeIds.idForPath("/foo/bar"); + assertEquals(withXml, withoutXml, ".xml suffix must be stripped before hashing"); + } + + @Test + public void idForPathNullReturnsHashOnly() { + String id = PreferenceNodeIds.idForPath(null); + assertEquals(PreferenceNodeIds.HASH_LEN, id.length()); + } + + @Test + public void canonicalizeNullReturnsEmpty() { + assertEquals("", PreferenceNodeIds.canonicalize(null)); + } + + @Test + public void canonicalizeStripsXmlSuffix() { + String result = PreferenceNodeIds.canonicalize("/foo/bar.xml"); + assertTrue(result.endsWith("/foo/bar"), "expected .xml stripped, got: " + result); + } + + @Test + public void canonicalizeConvertsBackslashes() { + String result = PreferenceNodeIds.canonicalize("C:\\Users\\test\\project.xml"); + assertTrue(!result.contains("\\"), "backslashes must be converted to forward slashes"); + } + + @Test + public void basenameExtractsLastSegment() { + assertEquals("myproject", PreferenceNodeIds.basename("/home/user/myproject")); + } + + @Test + public void basenameNoSlashReturnsInput() { + assertEquals("standalone", PreferenceNodeIds.basename("standalone")); + } + + @Test + public void sanitizeAllowsAlphanumAndSafePunctuation() { + assertEquals("Abc-123_.", PreferenceNodeIds.sanitize("Abc-123_.")); + } + + @Test + public void sanitizeReplacesSpacesAndSpecialChars() { + String result = PreferenceNodeIds.sanitize("my project (v2)"); + assertEquals("my_project__v2_", result); + } + + @Test + public void sanitizeEmptyInputReturnsEmpty() { + assertEquals("", PreferenceNodeIds.sanitize("")); + } + + @Test + public void sha256HexReturnsSixtyFourChars() { + assertEquals(64, PreferenceNodeIds.sha256Hex("hello").length()); + } + + @Test + public void sha256HexIsStable() { + assertEquals(PreferenceNodeIds.sha256Hex("test"), PreferenceNodeIds.sha256Hex("test")); + } +}
