You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by kw...@apache.org on 2025/01/16 15:14:28 UTC

(jackrabbit-oak) branch feature/generate-expanded-names created (now 57e042ff87)

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a change to branch feature/generate-expanded-names
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git


      at 57e042ff87 OAK-11397 Map Oak to expanded JCR name in NameMapper

This branch includes the following new commits:

     new 57e042ff87 OAK-11397 Map Oak to expanded JCR name in NameMapper

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(jackrabbit-oak) 01/01: OAK-11397 Map Oak to expanded JCR name in NameMapper

Posted by kw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/generate-expanded-names
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit 57e042ff8717f38cb77ee6eb47fbcfe345b42d7d
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Thu Jan 16 16:14:21 2025 +0100

    OAK-11397 Map Oak to expanded JCR name in NameMapper
---
 .../apache/jackrabbit/oak/namepath/NameMapper.java | 23 +++++++++++--
 .../jackrabbit/oak/namepath/NamePathMapper.java    |  7 ++++
 .../jackrabbit/oak/namepath/package-info.java      |  2 +-
 .../oak/namepath/impl/GlobalNameMapper.java        | 38 ++++++++++++++++++++--
 .../oak/namepath/impl/NamePathMapperImpl.java      |  6 ++++
 .../oak/namepath/impl/GlobalNameMapperTest.java    | 31 ++++++++++++++----
 6 files changed, 94 insertions(+), 13 deletions(-)

diff --git a/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/NameMapper.java b/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/NameMapper.java
index ec62432521..20f9deb9a5 100644
--- a/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/NameMapper.java
+++ b/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/NameMapper.java
@@ -63,16 +63,35 @@ public interface NameMapper {
     Map<String, String> getSessionLocalMappings();
 
     /**
-     * Returns the JCR name for the given Oak name. The given name is
+     * Returns the JCR name in qualified form for the given Oak name. The given name is
      * expected to have come from a valid Oak repository that contains
      * only valid names with proper namespace mappings. If that's not
      * the case, either a programming error or a repository corruption
      * has occurred and an appropriate unchecked exception gets thrown.
      *
      * @param oakName Oak name
-     * @return JCR name
+     * @return JCR name in qualified form
+     * 
+     * @see <a href="https://s.apache.org/jcr-2.0-spec/3_Repository_Model.html#3.2.5.2%20Qualified%20Form">JCR 2.0, 3.2.5.2 Qualifed Form</a>
      */
     @NotNull
     String getJcrName(@NotNull String oakName);
+    
+    /**
+     * Returns the JCR name in expanded form for the given Oak name. The given name is
+     * expected to have come from a valid Oak repository that contains
+     * only valid names with proper namespace mappings. If that's not
+     * the case, either a programming error or a repository corruption
+     * has occurred and an appropriate unchecked exception gets thrown.
+     *
+     * @param oakName Oak name
+     * @return JCR name in expanded form
+     * @since Oak 1.76.0
+     * @throws IllegalStateException in case the namespace URI for the given Oak name cannot be resolved
+     * 
+     * @see <a href="https://s.apache.org/jcr-2.0-spec/3_Repository_Model.html#3.2.5.1%20Expanded%20Form">JCR 2.0, 3.2.5.1 Expanded Form</a>
+     */
+    @NotNull
+    String getExpandedJcrName(@NotNull String oakName);
 
 }
diff --git a/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapper.java b/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapper.java
index 5ab341a0c2..d002b374ea 100644
--- a/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapper.java
+++ b/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/NamePathMapper.java
@@ -62,6 +62,12 @@ public interface NamePathMapper extends NameMapper, PathMapper {
             return oakName;
         }
 
+        @NotNull
+        @Override
+        public String getExpandedJcrName(@NotNull String oakName) {
+            throw new UnsupportedOperationException("Cannot create expanded JCR name as no namespace mappings are available");
+        }
+
         @Override
         public String getOakPath(String jcrPath) {
             return jcrPath;
@@ -72,5 +78,6 @@ public interface NamePathMapper extends NameMapper, PathMapper {
         public String getJcrPath(String oakPath) {
             return oakPath;
         }
+
     }
 }
diff --git a/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/package-info.java b/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/package-info.java
index b372e71426..746dffb91b 100644
--- a/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/package-info.java
+++ b/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/package-info.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.0.1")
+@Version("1.1.0")
 package org.apache.jackrabbit.oak.namepath;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/impl/GlobalNameMapper.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/impl/GlobalNameMapper.java
index d2c54d12c2..9f81bdd8a6 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/impl/GlobalNameMapper.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/impl/GlobalNameMapper.java
@@ -67,10 +67,15 @@ public class GlobalNameMapper implements NameMapper {
     protected static boolean isExpandedName(String name) {
         if (name.startsWith("{")) {
             int brace = name.indexOf('}', 1);
-            return brace != -1 && name.substring(1, brace).indexOf(':') != -1;
-        } else {
-            return false;
+            if (brace != -1) {
+                String namespace = name.substring(1, brace);
+                // the empty namespace is valid as well, otherwise it always contains a colon (as it is a URI)
+                if (namespace.isEmpty() || namespace.indexOf(':') != -1) {
+                    return true;
+                }
+            }
         }
+        return false;
     }
 
     private final Root root;
@@ -123,6 +128,33 @@ public class GlobalNameMapper implements NameMapper {
         return oakName;
     }
 
+    @Override
+    @NotNull
+    public String getExpandedJcrName(@NotNull String oakName) {
+        String qualifiedName = getJcrName(oakName); // sanity check
+        String uri;
+        final String localName;
+        int colon = qualifiedName.indexOf(':');
+        if (colon > 0) {
+            String oakPrefix = oakName.substring(0, colon);
+            // local mapping must take precedence...
+            uri = getSessionLocalMappings().get(oakPrefix);
+            if (uri == null) {
+                // ...over global mappings
+                uri = getNamespacesProperty(oakPrefix);
+            }
+            if (uri == null) {
+                throw new IllegalStateException(
+                        "No namespace mapping found for " + oakName);
+            }
+            localName = qualifiedName.substring(colon + 1);
+        } else {
+            uri = "";
+            localName = qualifiedName;
+        }
+        return "{" + uri + "}" + localName;
+    }
+
     @Override @Nullable
     public String getOakNameOrNull(@NotNull String jcrName) {
         if (jcrName.startsWith("{")) {
diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/impl/NamePathMapperImpl.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/impl/NamePathMapperImpl.java
index 3f9c3451c9..f4c1e2a06d 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/impl/NamePathMapperImpl.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/impl/NamePathMapperImpl.java
@@ -73,6 +73,12 @@ public class NamePathMapperImpl implements NamePathMapper {
         return nameMapper.getJcrName(oakName);
     }
 
+    @NotNull
+    @Override
+    public String getExpandedJcrName(@NotNull String oakName) {
+        return nameMapper.getExpandedJcrName(oakName);
+    }
+
     @Override @NotNull
     public Map<String, String> getSessionLocalMappings() {
         return nameMapper.getSessionLocalMappings();
diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/impl/GlobalNameMapperTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/impl/GlobalNameMapperTest.java
index d0eade307b..bd1884aac0 100644
--- a/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/impl/GlobalNameMapperTest.java
+++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/impl/GlobalNameMapperTest.java
@@ -46,6 +46,7 @@ public class GlobalNameMapperTest {
         assertEquals("", mapper.getJcrName(""));
         assertEquals("", mapper.getOakNameOrNull(""));
         assertEquals("", mapper.getOakName(""));
+        assertEquals("{}", mapper.getExpandedJcrName(""));
     }
 
 
@@ -82,6 +83,11 @@ public class GlobalNameMapperTest {
         for (String jcrName : jcrToOak.keySet()) {
             assertEquals(jcrToOak.get(jcrName), mapper.getOakNameOrNull(jcrName));
             assertEquals(jcrToOak.get(jcrName), mapper.getOakName(jcrName));
+            if (GlobalNameMapper.isExpandedName(jcrName)) {
+                assertEquals(jcrName, mapper.getExpandedJcrName(jcrToOak.get(jcrName)));
+            } else {
+                assertEquals("{}"+jcrName, mapper.getExpandedJcrName(jcrToOak.get(jcrName)));
+            }
         }
 
         assertNull(mapper.getOakNameOrNull("{http://www.example.com/bar}bar"));
@@ -95,17 +101,28 @@ public class GlobalNameMapperTest {
 
     @Test
     public void testPrefixedNames() throws RepositoryException {
-        List<String> prefixed = new ArrayList<String>();
-        prefixed.add("nt:base");
-        prefixed.add("foo: bar");
-        prefixed.add("quu:bar ");
-        // unknown prefixes are only captured by the NameValidator
-        prefixed.add("unknown:bar");
+        Map<String, String> prefixedToExpanded = new HashMap<>();
+        prefixedToExpanded.put("nt:base", "{http://www.jcp.org/jcr/nt/1.0}base");
+        prefixedToExpanded.put("foo: bar", "{http://www.example.com/foo} bar");
+        prefixedToExpanded.put("quu:bar ", "{http://www.example.com/quu}bar ");
 
-        for (String name : prefixed) {
+        for (String name : prefixedToExpanded.keySet()) {
             assertEquals(name, mapper.getOakNameOrNull(name));
             assertEquals(name, mapper.getOakName(name));
             assertEquals(name, mapper.getJcrName(name));
+            assertEquals(prefixedToExpanded.get(name), mapper.getExpandedJcrName(name));
+        }
+        
+        // unknown prefixes are only captured by the NameValidator
+        String unknownPrefix = "unknown:bar";
+        assertEquals(unknownPrefix, mapper.getOakNameOrNull(unknownPrefix));
+        assertEquals(unknownPrefix, mapper.getOakName(unknownPrefix));
+        assertEquals(unknownPrefix, mapper.getJcrName(unknownPrefix));
+        try {
+            mapper.getExpandedJcrName(unknownPrefix);
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+            // successs
         }
     }
 }