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

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


The following commit(s) were added to refs/heads/trunk by this push:
     new 81c09d1825  OAK-11397: add new API for expanded names/paths  (#2079)
81c09d1825 is described below

commit 81c09d18251380c604a31c5a399d834b001c7035
Author: Julian Reschke <[email protected]>
AuthorDate: Sun Feb 23 16:31:47 2025 +0100

     OAK-11397: add new API for expanded names/paths  (#2079)
    
    Co-authored-by: Konrad Windszus <[email protected]>
---
 .../apache/jackrabbit/oak/namepath/NameMapper.java | 23 ++++++++-
 .../jackrabbit/oak/namepath/NamePathMapper.java    | 12 +++++
 .../apache/jackrabbit/oak/namepath/PathMapper.java | 16 ++++++
 .../jackrabbit/oak/namepath/package-info.java      |  2 +-
 .../oak/namepath/impl/GlobalNameMapper.java        | 31 ++++++++++++
 .../oak/namepath/impl/NamePathMapperImpl.java      | 23 +++++++--
 .../oak/namepath/impl/GlobalNameMapperTest.java    | 31 +++++++++---
 .../oak/namepath/impl/NamePathMapperImplTest.java  | 21 ++++++++
 .../apache/jackrabbit/api/JackrabbitSession.java   | 20 ++++++++
 .../org/apache/jackrabbit/api/package-info.java    |  2 +-
 .../jackrabbit/oak/jcr/session/ItemImpl.java       | 57 ++++++++++++++--------
 .../jackrabbit/oak/jcr/session/SessionContext.java | 12 +++++
 .../jackrabbit/oak/jcr/session/SessionImpl.java    | 22 +++++++++
 .../oak/jcr/session/JackrabbitSessionTest.java     | 25 ++++++++--
 14 files changed, 259 insertions(+), 38 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..94c8d9bf84 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.78.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..5e756e0dbe 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,11 @@ public interface NamePathMapper extends NameMapper, 
PathMapper {
         public String getJcrPath(String oakPath) {
             return oakPath;
         }
+
+        @NotNull
+        @Override
+        public String getExpandedJcrPath(@NotNull String oakPath) {
+            throw new UnsupportedOperationException("Cannot create expanded 
JCR path as no namespace mappings are available");
+        }
     }
 }
diff --git 
a/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/PathMapper.java 
b/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/PathMapper.java
index d99cdb41b2..a333fc8675 100644
--- 
a/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/PathMapper.java
+++ 
b/oak-core-spi/src/main/java/org/apache/jackrabbit/oak/namepath/PathMapper.java
@@ -56,4 +56,20 @@ public interface PathMapper {
     @NotNull
     String getJcrPath(String oakPath);
 
+    /**
+     * Returns the JCR path in expanded form for the given Oak path. The given 
path 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 oakPath Oak path
+     * @return JCR path in expanded form
+     * @since Oak 1.78.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 getExpandedJcrPath(@NotNull String 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 507f1ab2cb..45ca3ffc52 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
@@ -130,6 +130,37 @@ public class GlobalNameMapper implements NameMapper {
         return oakName;
     }
 
+    @Override
+    @NotNull
+    public String getExpandedJcrName(@NotNull String oakName) {
+        // Sanity checks, can be turned to assertions if needed for performance
+        requireNonNull(oakName);
+        checkArgument(!isHiddenName(oakName), oakName);
+        checkArgument(!isExpandedName(oakName), oakName);
+
+        String uri;
+        final String localName;
+        int colon = oakName.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 = oakName.substring(colon + 1);
+        } else {
+            uri = "";
+            localName = oakName;
+        }
+        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..c38c2cbeb5 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
@@ -19,6 +19,8 @@ package org.apache.jackrabbit.oak.namepath.impl;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.function.BooleanSupplier;
+import java.util.function.UnaryOperator;
 
 import javax.jcr.RepositoryException;
 
@@ -73,6 +75,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();
@@ -160,14 +168,23 @@ public class NamePathMapperImpl implements NamePathMapper 
{
     @Override
     @NotNull
     public String getJcrPath(final String oakPath) {
+        return getJcrPath(oakPath, nameMapper::getJcrName, () -> 
nameMapper.getSessionLocalMappings().isEmpty());
+    }
+
+    @Override
+    @NotNull
+    public String getExpandedJcrPath(@NotNull String oakPath) {
+        return getJcrPath(oakPath, nameMapper::getExpandedJcrName, () -> 
false);
+    }
+
+    public String getJcrPath(final String oakPath, final UnaryOperator<String> 
mapFunction, final BooleanSupplier shouldSkipMappingFunction) {
         if ("/".equals(oakPath)) {
             // avoid the need to special case the root path later on
             return "/";
         } else if (oakPath.isEmpty()) {
             // empty path: map to "."
             return ".";
-        } else if (nameMapper.getSessionLocalMappings().isEmpty()) {
-            // no local namespace mappings
+        } else if (shouldSkipMappingFunction.getAsBoolean()) {
             return oakPath;
         }
 
@@ -185,7 +202,7 @@ public class NamePathMapperImpl implements NamePathMapper {
 
             @Override
             public boolean name(String name, int index) {
-                String p = nameMapper.getJcrName(name);
+                String p = mapFunction.apply(name);
                 if (index == 0) {
                     elements.add(p);
                 } else {
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 268116cd37..7a33ffd2f3 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
@@ -48,6 +48,7 @@ public class GlobalNameMapperTest {
         assertEquals("", mapper.getJcrName(""));
         assertEquals("", mapper.getOakNameOrNull(""));
         assertEquals("", mapper.getOakName(""));
+        assertEquals("{}", mapper.getExpandedJcrName(""));
     }
 
 
@@ -84,6 +85,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";));
@@ -97,17 +103,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
         }
     }
 
diff --git 
a/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/impl/NamePathMapperImplTest.java
 
b/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/impl/NamePathMapperImplTest.java
index 190bd2e4bf..238911f02f 100644
--- 
a/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/impl/NamePathMapperImplTest.java
+++ 
b/oak-core/src/test/java/org/apache/jackrabbit/oak/namepath/impl/NamePathMapperImplTest.java
@@ -135,6 +135,27 @@ public class NamePathMapperImplTest {
         }
     }
 
+    @Test
+    public void testOakToExpandedJcr() {
+        assertEquals("/{http://www.example.com/foo}bar";, 
npMapper.getExpandedJcrPath("/oak-foo:bar"));
+        
assertEquals("/{http://www.example.com/foo}bar/{http://www.example.com/quu}qux";,
 npMapper.getExpandedJcrPath("/oak-foo:bar/oak-quu:qux"));
+        assertEquals("{http://www.example.com/foo}bar";, 
npMapper.getExpandedJcrPath("oak-foo:bar"));
+        // this is the self-segment from 
https://s.apache.org/jcr-2.0-spec/3_Repository_Model.html#3.4.2%20Path%20Resolution
+        assertEquals(".", npMapper.getExpandedJcrPath(""));
+
+        try {
+            
npMapper.getExpandedJcrPath("{http://www.jcp.org/jcr/nt/1.0}unstructured";);
+            fail("expanded name should not be accepted");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            
npMapper.getExpandedJcrPath("foobar/{http://www.jcp.org/jcr/1.0}content";);
+            fail("expanded name should not be accepted");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
     @Test
     public void testInvalidJcrPaths() {
         String[] paths = {
diff --git 
a/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitSession.java
 
b/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitSession.java
index 5ad47e6b3d..db1bf7cb0d 100644
--- 
a/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitSession.java
+++ 
b/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitSession.java
@@ -277,4 +277,24 @@ public interface JackrabbitSession extends Session {
             return null;
         }
     }
+
+    /**
+     * Returns the expanded name of the given {@code Item}.
+     * @param item the item for which to retrieve the name
+     * @return the name of the item in expanded form.
+     * @throws RepositoryException if another error occurs.
+     * @since 1.78.0
+     * @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 getExpandedName(@NotNull Item item) throws 
RepositoryException;
+
+    /**
+     * Returns the expanded path of the given {@code Item}.
+     * @param item the item for which to retrieve the name
+     * @return the path of the item in expanded form.
+     * @throws RepositoryException if another error occurs.
+     * @since 1.78.0
+     * @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 getExpandedPath(@NotNull Item item) throws 
RepositoryException;
 }
diff --git 
a/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java 
b/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java
index 9d79c4bf19..fdbb2c7688 100644
--- 
a/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java
+++ 
b/oak-jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java
@@ -18,6 +18,6 @@
 /**
  * Jackrabbit extensions for JCR core interfaces
  */
[email protected]("2.9.0")
[email protected]("2.10.0")
 package org.apache.jackrabbit.api;
 
diff --git 
a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/ItemImpl.java 
b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/ItemImpl.java
index cd782aa814..a98920064b 100644
--- a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/ItemImpl.java
+++ b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/ItemImpl.java
@@ -121,19 +121,9 @@ abstract class ItemImpl<T extends ItemDelegate> implements 
Item {
     @Override
     @NotNull
     public String getName() throws RepositoryException {
-        String oakName = perform(new ItemOperation<String>(dlg, "getName") {
-            @NotNull
-            @Override
-            public String perform() {
-                return item.getName();
-            }
-            @Override
-            public String toString() {
-                return format("getName [%s]", dlg.getPath());
-            }
-        });
+        String oakName = getOakName();
         // special case name of root node
-        return oakName.isEmpty() ? "" : toJcrPath(dlg.getName());
+        return oakName.isEmpty() ? "" : toJcrPath(oakName);
     }
 
     /**
@@ -142,13 +132,7 @@ abstract class ItemImpl<T extends ItemDelegate> implements 
Item {
     @Override
     @NotNull
     public String getPath() throws RepositoryException {
-        return toJcrPath(perform(new ItemOperation<String>(dlg, "getPath") {
-            @NotNull
-            @Override
-            public String perform() {
-                return item.getPath();
-            }
-        }));
+        return toJcrPath(getOakPath());
     }
 
     @Override @NotNull
@@ -319,8 +303,39 @@ abstract class ItemImpl<T extends ItemDelegate> implements 
Item {
 
     //-----------------------------------------------------------< internal 
>---
     @NotNull
-    String getOakName(String name) throws RepositoryException {
-        return sessionContext.getOakName(name);
+    String getOakName() throws RepositoryException {
+        return perform(new ItemOperation<String>(dlg, "getName") {
+            @NotNull
+            @Override
+            public String perform() {
+                return item.getName();
+            }
+            @Override
+            public String toString() {
+                return format("getName [%s]", dlg.getPath());
+            }
+        });
+    }
+    
+    @NotNull
+    String getOakPath() throws RepositoryException {
+        return perform(new ItemOperation<String>(dlg, "getPath") {
+            @NotNull
+            @Override
+            public String perform() {
+                return item.getPath();
+            }
+
+            @Override
+            public String toString() {
+                return format("getPath [%s]", dlg.getPath());
+            }
+        });
+    }
+
+    @NotNull
+    String getOakName(String jcrName) throws RepositoryException {
+        return sessionContext.getOakName(jcrName);
     }
 
     @NotNull
diff --git 
a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
 
b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
index fadd201209..ebc3781783 100644
--- 
a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
+++ 
b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java
@@ -353,6 +353,12 @@ public class SessionContext implements NamePathMapper {
         return namePathMapper.getJcrName(oakName);
     }
 
+    @NotNull
+    @Override
+    public String getExpandedJcrName(@NotNull String oakName) {
+        return namePathMapper.getExpandedJcrName(oakName);
+    }
+
     @Override
     @Nullable
     public String getOakPath(String jcrPath) {
@@ -365,6 +371,12 @@ public class SessionContext implements NamePathMapper {
         return namePathMapper.getJcrPath(oakPath);
     }
 
+    @Override
+    @NotNull
+    public String getExpandedJcrPath(@NotNull String oakPath) {
+        return namePathMapper.getExpandedJcrPath(oakPath);
+    }
+
     /**
      * Returns the Oak path for the given JCR path, or throws a
      * {@link javax.jcr.RepositoryException} if the path can not be mapped.
diff --git 
a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionImpl.java 
b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionImpl.java
index cce9688439..5eb76868cb 100644
--- 
a/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionImpl.java
+++ 
b/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionImpl.java
@@ -852,4 +852,26 @@ public class SessionImpl implements JackrabbitSession {
         }
         return "null";
     }
+
+    @Override
+    @NotNull
+    public String getExpandedName(@NotNull Item item) throws 
RepositoryException {
+        try {
+            ItemImpl<?> itemImpl = checkItemImpl(item);
+            return 
itemImpl.sessionContext.getExpandedJcrName(itemImpl.getOakName());
+        } catch (IllegalStateException e) {
+            throw new RepositoryException("Namespace exception " + 
e.getMessage());
+        }
+    }
+
+    @Override
+    @NotNull
+    public String getExpandedPath(@NotNull Item item) throws 
RepositoryException {
+        try {
+            ItemImpl<?> itemImpl = checkItemImpl(item);
+            return 
itemImpl.sessionContext.getExpandedJcrPath(itemImpl.getOakPath());
+        } catch (IllegalStateException e) {
+            throw new RepositoryException("Namespace exception " + 
e.getMessage());
+        }
+    }
 }
diff --git 
a/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/session/JackrabbitSessionTest.java
 
b/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/session/JackrabbitSessionTest.java
index 9e9eca4d60..f7c86562ad 100644
--- 
a/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/session/JackrabbitSessionTest.java
+++ 
b/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/session/JackrabbitSessionTest.java
@@ -37,7 +37,6 @@ public class JackrabbitSessionTest extends AbstractJCRTest {
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        
         if (superuser instanceof JackrabbitSession) {
             s = (JackrabbitSession) superuser;
         } else {
@@ -81,6 +80,26 @@ public class JackrabbitSessionTest extends AbstractJCRTest {
             // success
         }
     }
-    
-    
+
+    public void testGetExpandedName() throws RepositoryException {
+        // empty namespace uri
+        assertEquals("{}testroot", s.getExpandedName(testRootNode));
+        Node n = testRootNode.addNode("test:bar");
+        assertEquals("{http://www.apache.org/jackrabbit/test}bar";, 
s.getExpandedName(n));
+        // now remap namespace uri
+        s.setNamespacePrefix("test", "urn:foo");
+        assertEquals("{urn:foo}bar", s.getExpandedName(n));
+        // use special namespace uri
+        n = testRootNode.addNode("rep:bar");
+        assertEquals("{internal}bar", s.getExpandedName(n));
+    }
+
+    public void testGetExpandedPath() throws RepositoryException {
+        assertEquals("/{}testroot", s.getExpandedPath(testRootNode));
+        Node n = testRootNode.addNode("test:bar").addNode("rep:bar");
+        
assertEquals("/{}testroot/{http://www.apache.org/jackrabbit/test}bar/{internal}bar";,
 s.getExpandedPath(n));
+        // now remap namespace uri
+        s.setNamespacePrefix("test", "urn:foo");
+        assertEquals("/{}testroot/{urn:foo}bar/{internal}bar", 
s.getExpandedPath(n));
+    }
 }
\ No newline at end of file

Reply via email to