From 6edf7c16dc398b125dc1cb474bd6944f91486749 Mon Sep 17 00:00:00 2001 From: Simon Urli Date: Thu, 21 Nov 2024 12:20:55 +0100 Subject: [PATCH] XWIKI-22571: Backlinks update changes an absolute reference to the moved page into one relative to the current wiki * Provide implementations for relative ResourceReferenceEntityReference resolvers and tests --- ...tiveStringEntityReferenceResolverTest.java | 15 + .../model/reference/WikiReferenceTest.java | 8 + ...ourceReferenceEntityReferenceResolver.java | 77 +++- ...ourceReferenceEntityReferenceResolver.java | 50 ++- ...ourceReferenceEntityReferenceResolver.java | 41 +- ...ourceReferenceEntityReferenceResolver.java | 5 +- ...ourceReferenceEntityReferenceResolver.java | 5 +- ...ourceReferenceEntityReferenceResolver.java | 5 +- ...eReferenceEntityReferenceResolverTest.java | 206 +++++---- ...eReferenceEntityReferenceResolverTest.java | 408 ++++++++++++++++++ 10 files changed, 700 insertions(+), 120 deletions(-) create mode 100644 xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/test/java/org/xwiki/rendering/internal/resolver/RelativeResourceReferenceEntityReferenceResolverTest.java diff --git a/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/RelativeStringEntityReferenceResolverTest.java b/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/RelativeStringEntityReferenceResolverTest.java index 92c918597397..f6a24f1e67cf 100644 --- a/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/RelativeStringEntityReferenceResolverTest.java +++ b/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/RelativeStringEntityReferenceResolverTest.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test; import org.xwiki.model.EntityType; import org.xwiki.model.reference.EntityReference; +import org.xwiki.model.reference.WikiReference; import org.xwiki.test.annotation.ComponentList; import org.xwiki.test.junit5.mockito.ComponentTest; import org.xwiki.test.junit5.mockito.InjectMockComponents; @@ -70,5 +71,19 @@ public void resolveDocumentReferenceWithBaseReference() assertNull(reference.extractReference(EntityType.WIKI)); assertEquals("space", reference.extractReference(EntityType.SPACE).getName()); assertNull(reference.extractReference(EntityType.DOCUMENT)); + + reference = + this.resolver.resolve("", EntityType.DOCUMENT, new EntityReference("wikiFoo", EntityType.WIKI)); + + assertEquals("wikiFoo", reference.extractReference(EntityType.WIKI).getName()); + assertNull(reference.extractReference(EntityType.SPACE)); + assertNull(reference.extractReference(EntityType.DOCUMENT)); + + reference = + this.resolver.resolve("", EntityType.DOCUMENT, new WikiReference("wikiFoo")); + + assertEquals("wikiFoo", reference.extractReference(EntityType.WIKI).getName()); + assertNull(reference.extractReference(EntityType.SPACE)); + assertNull(reference.extractReference(EntityType.DOCUMENT)); } } diff --git a/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/reference/WikiReferenceTest.java b/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/reference/WikiReferenceTest.java index 343679e21f66..6f0ee7e0aff7 100644 --- a/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/reference/WikiReferenceTest.java +++ b/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/reference/WikiReferenceTest.java @@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Unit tests for {@link WikiReference}. @@ -49,4 +50,11 @@ public void testInvalidParent() () -> new WikiReference(new EntityReference("wiki", EntityType.WIKI, badParent))); assertEquals("Unexpected parent [" + badParent + "] in a wiki reference", expected.getMessage()); } + + @Test + void instanceOf() + { + assertTrue(new WikiReference("foo") instanceof WikiReference); + assertTrue(new WikiReference("foo") instanceof EntityReference); + } } diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/AbstractRelativeResourceReferenceEntityReferenceResolver.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/AbstractRelativeResourceReferenceEntityReferenceResolver.java index 7d94b7b9fd86..f85386fa8cce 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/AbstractRelativeResourceReferenceEntityReferenceResolver.java +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/AbstractRelativeResourceReferenceEntityReferenceResolver.java @@ -19,6 +19,8 @@ */ package org.xwiki.rendering.internal.resolver; +import java.util.List; + import javax.inject.Inject; import javax.inject.Named; @@ -29,7 +31,7 @@ import org.xwiki.rendering.listener.reference.ResourceType; /** - * Convert document resource reference into entity reference. + * Abstract class for all relative resource reference resolvers. * * @version $Id$ * @since 17.0.0RC1 @@ -39,21 +41,84 @@ public abstract class AbstractRelativeResourceReferenceEntityReferenceResolver { @Inject @Named("relative") - private EntityReferenceResolver relativeReferenceResolver; + protected EntityReferenceResolver relativeReferenceResolver; /** - * Default constructor. + * @param type the resource type that this resolver will support */ - public AbstractRelativeResourceReferenceEntityReferenceResolver(ResourceType type) + protected AbstractRelativeResourceReferenceEntityReferenceResolver(ResourceType type) { super(type); } + @Override + public EntityReference resolve(ResourceReference resourceReference, EntityType entityType, Object... parameters) + { + if (resourceReference == null) { + return null; + } + + if (this.resourceType != null && !resourceReference.getType().equals(this.resourceType)) { + throw new IllegalArgumentException( + String.format("You must pass a resource reference of type [%s]. [%s] was passed", this.resourceType, + resourceReference)); + } + + EntityReference entityReference; + EntityReference baseReference = getBaseReference(resourceReference, parameters); + + if (resourceReference.isTyped()) { + entityReference = resolveTyped(resourceReference, baseReference); + } else { + entityReference = resolveUntyped(resourceReference, baseReference); + } + + return entityReference; + } + + @Override + protected EntityReference getBaseReference(ResourceReference resourceReference, Object... parameters) + { + EntityReference baseReference = + (parameters.length > 0 && parameters[0] instanceof EntityReference entityReference) + ? entityReference : null; + + if (!resourceReference.getBaseReferences().isEmpty()) { + // If the passed reference has a base reference, resolve it first with a relative resolver (it should + // normally be absolute but who knows what the API caller has specified...) + baseReference = resolveBaseReference(resourceReference.getBaseReferences(), baseReference); + } + + return baseReference; + } + + @Override + protected EntityReference resolveBaseReference(List baseReferences, EntityReference defaultBaseReference) + { + EntityReference resolvedBaseReference = defaultBaseReference; + for (String baseReference : baseReferences) { + resolvedBaseReference = + this.relativeReferenceResolver.resolve(baseReference, EntityType.DOCUMENT, resolvedBaseReference); + } + + return resolvedBaseReference; + } + + @Override + protected EntityReference resolveUntyped(ResourceReference resourceReference, EntityReference baseReference) + { + return resolveTyped(resourceReference, baseReference); + } + @Override protected EntityReference resolveTyped(ResourceReference resourceReference, EntityReference baseReference) { - return this.relativeReferenceResolver.resolve(resourceReference.getReference(), getEntityType()); + return this.relativeReferenceResolver.resolve(resourceReference.getReference(), getEntityType(), baseReference); } - public abstract EntityType getEntityType(); + /** + * + * @return the entity type of the {@link EntityReference} this resolver produces. + */ + protected abstract EntityType getEntityType(); } diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeAttachmentResourceReferenceEntityReferenceResolver.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeAttachmentResourceReferenceEntityReferenceResolver.java index e0ec7b137943..5727dfec920a 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeAttachmentResourceReferenceEntityReferenceResolver.java +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeAttachmentResourceReferenceEntityReferenceResolver.java @@ -19,11 +19,18 @@ */ package org.xwiki.rendering.internal.resolver; +import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.apache.commons.lang3.StringUtils; import org.xwiki.component.annotation.Component; import org.xwiki.model.EntityType; +import org.xwiki.model.reference.AttachmentReference; +import org.xwiki.model.reference.AttachmentReferenceResolver; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.EntityReference; +import org.xwiki.rendering.listener.reference.ResourceReference; import org.xwiki.rendering.listener.reference.ResourceType; /** @@ -38,14 +45,55 @@ public class RelativeAttachmentResourceReferenceEntityReferenceResolver extends AbstractRelativeResourceReferenceEntityReferenceResolver { + @Inject + private AttachmentReferenceResolver defaultReferenceAttachmentReferenceResolver; + + /** + * Default constructor. + */ public RelativeAttachmentResourceReferenceEntityReferenceResolver() { super(ResourceType.ATTACHMENT); } @Override - public EntityType getEntityType() + protected EntityType getEntityType() { return EntityType.ATTACHMENT; } + + @Override + protected EntityReference resolveTyped(ResourceReference resourceReference, EntityReference baseReference) + { + if (StringUtils.isEmpty(resourceReference.getReference())) { + return null; + } + + // Get relative reference + EntityReference relativeReference = + this.relativeReferenceResolver + .resolve(resourceReference.getReference(), EntityType.ATTACHMENT, baseReference); + + EntityReference result = relativeReference; + if (relativeReference.extractReference(EntityType.WIKI) != null) { + // Resolve full reference + AttachmentReference attachmentReference = + this.defaultReferenceAttachmentReferenceResolver.resolve(relativeReference, baseReference); + + // See if the resolved (terminal or WebHome) document exists and, if so, use it. + DocumentReference documentReference = attachmentReference.getDocumentReference(); + + // Take care of fallback if needed + DocumentReference finalDocumentReference = + resolveDocumentReference(relativeReference.getParent(), documentReference, baseReference); + // Also use that resolution if the relative reference doesn't contain any document, even if it doesn't + // exists, to not produce incorrect references. + if (finalDocumentReference != documentReference + || relativeReference.extractReference(EntityType.DOCUMENT) == null) { + result = new AttachmentReference(attachmentReference.getName(), finalDocumentReference); + } + } + + return result; + } } diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeDocumentResourceReferenceEntityReferenceResolver.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeDocumentResourceReferenceEntityReferenceResolver.java index 59f055ede35c..8021b6237e72 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeDocumentResourceReferenceEntityReferenceResolver.java +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeDocumentResourceReferenceEntityReferenceResolver.java @@ -19,11 +19,17 @@ */ package org.xwiki.rendering.internal.resolver; +import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.apache.commons.lang3.StringUtils; import org.xwiki.component.annotation.Component; import org.xwiki.model.EntityType; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.DocumentReferenceResolver; +import org.xwiki.model.reference.EntityReference; +import org.xwiki.rendering.listener.reference.ResourceReference; import org.xwiki.rendering.listener.reference.ResourceType; /** @@ -38,14 +44,47 @@ public class RelativeDocumentResourceReferenceEntityReferenceResolver extends AbstractRelativeResourceReferenceEntityReferenceResolver { + @Inject + private DocumentReferenceResolver defaultStringDocumentReferenceResolver; + + /** + * Default constructor. + */ public RelativeDocumentResourceReferenceEntityReferenceResolver() { super(ResourceType.DOCUMENT); } @Override - public EntityType getEntityType() + protected EntityType getEntityType() { return EntityType.DOCUMENT; } + + @Override + protected EntityReference resolveUntyped(ResourceReference resourceReference, EntityReference baseReference) + { + // If the reference is empty fallback on typed logic + if (StringUtils.isEmpty(resourceReference.getReference())) { + return resolveTyped(resourceReference, baseReference); + } + + // Get relative reference + EntityReference relativeReference = + this.relativeReferenceResolver.resolve(resourceReference.getReference(), EntityType.DOCUMENT, + baseReference); + + EntityReference result = relativeReference; + if (relativeReference.extractReference(EntityType.WIKI) != null) { + // Resolve the full document reference + // We don't start from the previously parsed relative reference to not loose "." prefixed reference meaning + DocumentReference reference = + this.defaultStringDocumentReferenceResolver.resolve(resourceReference.getReference(), baseReference); + + // Take care of fallback if needed + result = resolveDocumentReference(relativeReference, reference, baseReference); + } + + return result; + } } diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageAttachmentResourceReferenceEntityReferenceResolver.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageAttachmentResourceReferenceEntityReferenceResolver.java index e53bc17cc309..7c2ac8d8253f 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageAttachmentResourceReferenceEntityReferenceResolver.java +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageAttachmentResourceReferenceEntityReferenceResolver.java @@ -39,13 +39,16 @@ public class RelativePageAttachmentResourceReferenceEntityReferenceResolver extends AbstractRelativeResourceReferenceEntityReferenceResolver { + /** + * Default constructor. + */ public RelativePageAttachmentResourceReferenceEntityReferenceResolver() { super(ResourceType.PAGE_ATTACHMENT); } @Override - public EntityType getEntityType() + protected EntityType getEntityType() { return EntityType.PAGE_ATTACHMENT; } diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageResourceReferenceEntityReferenceResolver.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageResourceReferenceEntityReferenceResolver.java index 53502f775b5b..81099bc8efc1 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageResourceReferenceEntityReferenceResolver.java +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageResourceReferenceEntityReferenceResolver.java @@ -38,13 +38,16 @@ public class RelativePageResourceReferenceEntityReferenceResolver extends AbstractRelativeResourceReferenceEntityReferenceResolver { + /** + * Default constructor. + */ public RelativePageResourceReferenceEntityReferenceResolver() { super(ResourceType.PAGE); } @Override - public EntityType getEntityType() + protected EntityType getEntityType() { return EntityType.PAGE; } diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeSpaceResourceReferenceEntityReferenceResolver.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeSpaceResourceReferenceEntityReferenceResolver.java index 640299f6cb4b..437d86e1af81 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeSpaceResourceReferenceEntityReferenceResolver.java +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeSpaceResourceReferenceEntityReferenceResolver.java @@ -38,13 +38,16 @@ public class RelativeSpaceResourceReferenceEntityReferenceResolver extends AbstractRelativeResourceReferenceEntityReferenceResolver { + /** + * Default constructor. + */ public RelativeSpaceResourceReferenceEntityReferenceResolver() { super(ResourceType.SPACE); } @Override - public EntityType getEntityType() + protected EntityType getEntityType() { return EntityType.SPACE; } diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/test/java/org/xwiki/rendering/internal/resolver/DefaultResourceReferenceEntityReferenceResolverTest.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/test/java/org/xwiki/rendering/internal/resolver/DefaultResourceReferenceEntityReferenceResolverTest.java index 9c18dae0c465..40c5c00a1955 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/test/java/org/xwiki/rendering/internal/resolver/DefaultResourceReferenceEntityReferenceResolverTest.java +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/test/java/org/xwiki/rendering/internal/resolver/DefaultResourceReferenceEntityReferenceResolverTest.java @@ -19,21 +19,18 @@ */ package org.xwiki.rendering.internal.resolver; -import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; +import javax.inject.Named; import javax.inject.Provider; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.stubbing.Answer; import org.xwiki.bridge.DocumentAccessBridge; import org.xwiki.component.internal.ContextComponentManagerProvider; -import org.xwiki.component.manager.ComponentLookupException; -import org.xwiki.component.util.DefaultParameterizedType; import org.xwiki.model.EntityType; import org.xwiki.model.internal.reference.DefaultReferenceAttachmentReferenceResolver; import org.xwiki.model.internal.reference.DefaultReferenceDocumentReferenceResolver; @@ -56,12 +53,14 @@ import org.xwiki.rendering.listener.reference.ResourceType; import org.xwiki.rendering.listener.reference.SpaceResourceReference; import org.xwiki.test.annotation.ComponentList; -import org.xwiki.test.mockito.MockitoComponentMockingRule; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -88,8 +87,9 @@ ContextComponentManagerProvider.class, DefaultSymbolScheme.class }) +@ComponentTest // @formatter:on -public class DefaultResourceReferenceEntityReferenceResolverTest +class DefaultResourceReferenceEntityReferenceResolverTest { private static final String DEFAULT_PAGE = "defaultpage"; @@ -108,47 +108,35 @@ public class DefaultResourceReferenceEntityReferenceResolverTest private static final String PAGE = "Page"; private static final String ATTACHMENT = "file.ext"; + + @InjectMockComponents + private DefaultResourceReferenceEntityReferenceResolver resolver; - private static final DocumentReference CURRENT_DOCUMENT_REFERENCE = - new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE); - - @Rule - public MockitoComponentMockingRule> mocker = - new MockitoComponentMockingRule>( - DefaultResourceReferenceEntityReferenceResolver.class); - + @MockComponent + @Named("current") private EntityReferenceResolver currentEntityReferenceResolver; + @MockComponent + @Named("current") private Provider currentDocumentProvider; + @MockComponent private DocumentAccessBridge bridge; + @MockComponent private EntityReferenceProvider defaultEntityProvider; private final Set existingDocuments = new HashSet<>(); - @Before - public void before() throws Exception + @BeforeEach + void before() throws Exception { - this.currentEntityReferenceResolver = - this.mocker.registerMockComponent(EntityReferenceResolver.TYPE_STRING, "current"); - - this.currentDocumentProvider = this.mocker.registerMockComponent( - new DefaultParameterizedType(null, Provider.class, DocumentReference.class), "current"); when(this.currentDocumentProvider.get()) .thenReturn(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE)); - this.bridge = this.mocker.registerMockComponent(DocumentAccessBridge.class); - when(this.bridge.exists(any(DocumentReference.class))).then(new Answer() - { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable - { - return existingDocuments.contains(invocation.getArguments()[0]); - } - }); - - this.defaultEntityProvider = this.mocker.registerMockComponent(EntityReferenceProvider.class); + when(this.bridge.exists(any(DocumentReference.class))).then( + (Answer) invocation -> existingDocuments.contains(invocation.getArguments()[0])); + when(this.defaultEntityProvider.getDefaultReference(EntityType.DOCUMENT)) .thenReturn(new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT)); } @@ -182,26 +170,26 @@ private AttachmentResourceReference attachmentResource(String referenceString, b // Tests @Test - public void resolve() throws ComponentLookupException + void resolve() { - assertNull(this.mocker.getComponentUnderTest().resolve(null, null)); - assertNull(this.mocker.getComponentUnderTest().resolve(new ResourceReference("path", ResourceType.PATH), null)); + assertNull(this.resolver.resolve(null, null)); + assertNull(this.resolver.resolve(new ResourceReference("path", ResourceType.PATH), null)); } @Test - public void resolveTypeDocument() throws ComponentLookupException + void resolveTypeDocument() { assertEquals(new DocumentReference(WIKI, SPACE, PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(WIKI + ':' + SPACE + '.' + PAGE, true), null)); + this.resolver.resolve(documentResource(WIKI + ':' + SPACE + '.' + PAGE, true), null)); assertEquals(new DocumentReference(CURRENT_WIKI, SPACE, PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(SPACE + '.' + PAGE, true), null)); + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, true), null)); assertEquals(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(PAGE, true), null)); + this.resolver.resolve(documentResource(PAGE, true), null)); assertEquals(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource("", true), null)); + this.resolver.resolve(documentResource("", true), null)); when(this.currentEntityReferenceResolver.resolve(eq(WIKI + ':' + SPACE + '.' + PAGE), eq(EntityType.DOCUMENT), any())).thenReturn(new DocumentReference(WIKI, SPACE, PAGE)); @@ -209,95 +197,95 @@ public void resolveTypeDocument() throws ComponentLookupException ResourceReference withBaseReference = documentResource("", true); withBaseReference.addBaseReference(WIKI + ':' + SPACE + '.' + PAGE); assertEquals(new DocumentReference(WIKI, SPACE, PAGE), - this.mocker.getComponentUnderTest().resolve(withBaseReference, null)); + this.resolver.resolve(withBaseReference, null)); - assertEquals(new DocumentReference(WIKI, SPACE, PAGE), this.mocker.getComponentUnderTest() + assertEquals(new DocumentReference(WIKI, SPACE, PAGE), this.resolver .resolve(documentResource("", true), null, new DocumentReference(WIKI, SPACE, PAGE))); } @Test - public void resolveUntypeDocument() throws ComponentLookupException + void resolveUntypeDocument() { // When the page does not exist - assertEquals(new DocumentReference(WIKI, Arrays.asList(SPACE, PAGE), DEFAULT_PAGE), this.mocker - .getComponentUnderTest().resolve(documentResource(WIKI + ':' + SPACE + '.' + PAGE, false), null)); - assertEquals(new DocumentReference(CURRENT_WIKI, Arrays.asList(SPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(SPACE + '.' + PAGE, false), null)); - assertEquals(new DocumentReference(CURRENT_WIKI, Arrays.asList(CURRENT_SPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(PAGE, false), null)); + assertEquals(new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(WIKI + ':' + SPACE + '.' + PAGE, false), null)); + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(PAGE, false), null)); // Already ends with default page name - assertEquals(new DocumentReference(WIKI, SPACE, DEFAULT_PAGE), this.mocker.getComponentUnderTest() + assertEquals(new DocumentReference(WIKI, SPACE, DEFAULT_PAGE), this.resolver .resolve(documentResource(WIKI + ':' + SPACE + '.' + DEFAULT_PAGE, false), null)); assertEquals(new DocumentReference(CURRENT_WIKI, SPACE, DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(SPACE + '.' + DEFAULT_PAGE, false), null)); + this.resolver.resolve(documentResource(SPACE + '.' + DEFAULT_PAGE, false), null)); assertEquals(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(DEFAULT_PAGE, false), null)); + this.resolver.resolve(documentResource(DEFAULT_PAGE, false), null)); // When the page exist this.existingDocuments.add(new DocumentReference(WIKI, SPACE, PAGE)); - assertEquals(new DocumentReference(WIKI, SPACE, PAGE), this.mocker.getComponentUnderTest() + assertEquals(new DocumentReference(WIKI, SPACE, PAGE), this.resolver .resolve(documentResource(WIKI + ':' + SPACE + '.' + PAGE, false), null)); this.existingDocuments.add(new DocumentReference(CURRENT_WIKI, SPACE, PAGE)); assertEquals(new DocumentReference(CURRENT_WIKI, SPACE, PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(SPACE + '.' + PAGE, false), null)); + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); this.existingDocuments.add(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, PAGE)); assertEquals(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(PAGE, false), null)); + this.resolver.resolve(documentResource(PAGE, false), null)); // When the page is current page assertEquals(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(CURRENT_PAGE, false), null)); + this.resolver.resolve(documentResource(CURRENT_PAGE, false), null)); assertEquals(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource("", false), null)); + this.resolver.resolve(documentResource("", false), null)); } @Test - public void resolveUntypeDocumentWhenCurrentPageIsSpace() throws ComponentLookupException + void resolveUntypeDocumentWhenCurrentPageIsSpace() { // Current is top level space when(this.currentDocumentProvider.get()) .thenReturn(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, DEFAULT_PAGE)); - assertEquals(new DocumentReference(CURRENT_WIKI, Arrays.asList(CURRENT_SPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(PAGE, false), null)); + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(PAGE, false), null)); - assertEquals(new DocumentReference(CURRENT_WIKI, Arrays.asList(SPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(SPACE + '.' + PAGE, false), null)); + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); - assertEquals(new DocumentReference(CURRENT_WIKI, Arrays.asList(CURRENT_SPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource('.' + PAGE, false), null)); + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource('.' + PAGE, false), null)); - assertEquals(new DocumentReference(CURRENT_WIKI, Arrays.asList(CURRENT_SPACE, PAGE), DEFAULT_PAGE), this.mocker - .getComponentUnderTest().resolve(documentResource('.' + PAGE + '.' + DEFAULT_PAGE, false), null)); + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource('.' + PAGE + '.' + DEFAULT_PAGE, false), null)); // Current is subspace // When sibling page does not exist when(this.currentDocumentProvider.get()).thenReturn( - new DocumentReference(CURRENT_WIKI, Arrays.asList(CURRENT_SPACE, CURRENT_SUBSPACE), DEFAULT_PAGE)); + new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, CURRENT_SUBSPACE), DEFAULT_PAGE)); - assertEquals(new DocumentReference(CURRENT_WIKI, Arrays.asList(CURRENT_SPACE, CURRENT_SUBSPACE, PAGE), + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, CURRENT_SUBSPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(PAGE, false), null)); + this.resolver.resolve(documentResource(PAGE, false), null)); - assertEquals(new DocumentReference(CURRENT_WIKI, Arrays.asList(SPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(SPACE + '.' + PAGE, false), null)); + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); - assertEquals(new DocumentReference(CURRENT_WIKI, Arrays.asList(CURRENT_SPACE, CURRENT_SUBSPACE, PAGE), + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, CURRENT_SUBSPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource('.' + PAGE, false), null)); + this.resolver.resolve(documentResource('.' + PAGE, false), null)); assertEquals( - new DocumentReference(CURRENT_WIKI, Arrays.asList(CURRENT_SPACE, CURRENT_SUBSPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource('.' + PAGE + '.' + DEFAULT_PAGE, false), + new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, CURRENT_SUBSPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource('.' + PAGE + '.' + DEFAULT_PAGE, false), null)); // When sibling page exist @@ -305,32 +293,32 @@ public void resolveUntypeDocumentWhenCurrentPageIsSpace() throws ComponentLookup this.existingDocuments.add(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, PAGE)); assertEquals(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(PAGE, false), null)); + this.resolver.resolve(documentResource(PAGE, false), null)); - assertEquals(new DocumentReference(CURRENT_WIKI, Arrays.asList(SPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(SPACE + '.' + PAGE, false), null)); + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); // FIXME: This should always be resolved to a child (terminal or non-terminal) page and never to a sibling. assertEquals(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource('.' + PAGE, false), null)); + this.resolver.resolve(documentResource('.' + PAGE, false), null)); assertEquals( - new DocumentReference(CURRENT_WIKI, Arrays.asList(CURRENT_SPACE, CURRENT_SUBSPACE, PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource('.' + PAGE + '.' + DEFAULT_PAGE, false), + new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, CURRENT_SUBSPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource('.' + PAGE + '.' + DEFAULT_PAGE, false), null)); } @Test - public void resolveTypeSpace() throws ComponentLookupException + void resolveTypeSpace() { assertEquals(new SpaceReference(WIKI, SPACE), - this.mocker.getComponentUnderTest().resolve(spaceResource(WIKI + ':' + SPACE, true), null)); + this.resolver.resolve(spaceResource(WIKI + ':' + SPACE, true), null)); assertEquals(new SpaceReference(CURRENT_WIKI, SPACE), - this.mocker.getComponentUnderTest().resolve(spaceResource(SPACE, true), null)); + this.resolver.resolve(spaceResource(SPACE, true), null)); assertEquals(new SpaceReference(CURRENT_WIKI, CURRENT_SPACE), - this.mocker.getComponentUnderTest().resolve(spaceResource("", true), null)); + this.resolver.resolve(spaceResource("", true), null)); when(this.currentEntityReferenceResolver.resolve(eq(WIKI + ':' + SPACE + '.' + PAGE), eq(EntityType.DOCUMENT), any())).thenReturn(new DocumentReference(WIKI, SPACE, PAGE)); @@ -338,58 +326,58 @@ public void resolveTypeSpace() throws ComponentLookupException ResourceReference withBaseReference = spaceResource("", true); withBaseReference.addBaseReference(WIKI + ':' + SPACE + '.' + PAGE); assertEquals(new SpaceReference(WIKI, SPACE), - this.mocker.getComponentUnderTest().resolve(withBaseReference, null)); + this.resolver.resolve(withBaseReference, null)); - assertEquals(new SpaceReference(WIKI, SPACE), this.mocker.getComponentUnderTest() + assertEquals(new SpaceReference(WIKI, SPACE), this.resolver .resolve(spaceResource("", true), null, new DocumentReference(WIKI, SPACE, PAGE))); } @Test - public void resolveTypeAttachment() throws ComponentLookupException + void resolveTypeAttachment() { // When the page does not exist assertEquals( - new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, Arrays.asList(SPACE, PAGE), DEFAULT_PAGE)), - this.mocker.getComponentUnderTest() + new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE)), + this.resolver .resolve(attachmentResource(WIKI + ':' + SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null)); assertEquals( new AttachmentReference(ATTACHMENT, - new DocumentReference(CURRENT_WIKI, Arrays.asList(SPACE, PAGE), DEFAULT_PAGE)), - this.mocker.getComponentUnderTest().resolve(attachmentResource(SPACE + '.' + PAGE + '@' + ATTACHMENT, true), + new DocumentReference(CURRENT_WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE)), + this.resolver.resolve(attachmentResource(SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null)); assertEquals( new AttachmentReference(ATTACHMENT, - new DocumentReference(CURRENT_WIKI, Arrays.asList(CURRENT_SPACE, PAGE), DEFAULT_PAGE)), - this.mocker.getComponentUnderTest().resolve(attachmentResource(PAGE + '@' + ATTACHMENT, true), null)); + new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, PAGE), DEFAULT_PAGE)), + this.resolver.resolve(attachmentResource(PAGE + '@' + ATTACHMENT, true), null)); // When the page exist this.existingDocuments.add(new DocumentReference(WIKI, SPACE, PAGE)); assertEquals(new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, SPACE, PAGE)), - this.mocker.getComponentUnderTest() + this.resolver .resolve(attachmentResource(WIKI + ':' + SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null)); this.existingDocuments.add(new DocumentReference(CURRENT_WIKI, SPACE, PAGE)); - assertEquals(new AttachmentReference(ATTACHMENT, new DocumentReference(CURRENT_WIKI, SPACE, PAGE)), this.mocker - .getComponentUnderTest().resolve(attachmentResource(SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null)); + assertEquals(new AttachmentReference(ATTACHMENT, new DocumentReference(CURRENT_WIKI, SPACE, PAGE)), + this.resolver.resolve(attachmentResource(SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null)); this.existingDocuments.add(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, PAGE)); assertEquals(new AttachmentReference(ATTACHMENT, new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, PAGE)), - this.mocker.getComponentUnderTest().resolve(attachmentResource(PAGE + '@' + ATTACHMENT, true), null)); + this.resolver.resolve(attachmentResource(PAGE + '@' + ATTACHMENT, true), null)); // When page is current page assertEquals( new AttachmentReference(ATTACHMENT, new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE)), - this.mocker.getComponentUnderTest().resolve(attachmentResource(ATTACHMENT, true), null)); + this.resolver.resolve(attachmentResource(ATTACHMENT, true), null)); this.existingDocuments.add(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE)); assertEquals( new AttachmentReference(ATTACHMENT, new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE)), - this.mocker.getComponentUnderTest().resolve(attachmentResource(ATTACHMENT, true), null)); + this.resolver.resolve(attachmentResource(ATTACHMENT, true), null)); } class VoidResourceReferenceEntityReferenceResolve extends AbstractResourceReferenceEntityReferenceResolver @@ -407,7 +395,7 @@ protected EntityReference resolveTyped(ResourceReference resourceReference, Enti } @Test - public void trySpaceSiblingFallback() + void trySpaceSiblingFallback() { VoidResourceReferenceEntityReferenceResolve resolver = new VoidResourceReferenceEntityReferenceResolve(); diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/test/java/org/xwiki/rendering/internal/resolver/RelativeResourceReferenceEntityReferenceResolverTest.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/test/java/org/xwiki/rendering/internal/resolver/RelativeResourceReferenceEntityReferenceResolverTest.java new file mode 100644 index 000000000000..02286f4b3d44 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/test/java/org/xwiki/rendering/internal/resolver/RelativeResourceReferenceEntityReferenceResolverTest.java @@ -0,0 +1,408 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.xwiki.rendering.internal.resolver; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.inject.Named; +import javax.inject.Provider; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.stubbing.Answer; +import org.xwiki.bridge.DocumentAccessBridge; +import org.xwiki.component.internal.ContextComponentManagerProvider; +import org.xwiki.model.EntityType; +import org.xwiki.model.internal.reference.DefaultReferenceAttachmentReferenceResolver; +import org.xwiki.model.internal.reference.DefaultReferenceDocumentReferenceResolver; +import org.xwiki.model.internal.reference.DefaultReferenceEntityReferenceResolver; +import org.xwiki.model.internal.reference.DefaultStringAttachmentReferenceResolver; +import org.xwiki.model.internal.reference.DefaultStringDocumentReferenceResolver; +import org.xwiki.model.internal.reference.DefaultStringEntityReferenceResolver; +import org.xwiki.model.internal.reference.DefaultStringSpaceReferenceResolver; +import org.xwiki.model.internal.reference.DefaultSymbolScheme; +import org.xwiki.model.internal.reference.RelativeStringEntityReferenceResolver; +import org.xwiki.model.reference.AttachmentReference; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.EntityReference; +import org.xwiki.model.reference.EntityReferenceProvider; +import org.xwiki.model.reference.EntityReferenceResolver; +import org.xwiki.model.reference.SpaceReference; +import org.xwiki.model.reference.WikiReference; +import org.xwiki.rendering.listener.reference.AttachmentResourceReference; +import org.xwiki.rendering.listener.reference.DocumentResourceReference; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; +import org.xwiki.rendering.listener.reference.SpaceResourceReference; +import org.xwiki.test.annotation.ComponentList; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +/** + * Validate {@link RelativeResourceReferenceEntityReferenceResolver}. + * + * @version $Id$ + * @since 17.0.0RC1 + */ +// @formatter:off +@ComponentList({ + RelativeResourceReferenceEntityReferenceResolver.class, + RelativeAttachmentResourceReferenceEntityReferenceResolver.class, + RelativeDocumentResourceReferenceEntityReferenceResolver.class, + DefaultStringAttachmentReferenceResolver.class, + DefaultStringDocumentReferenceResolver.class, + RelativeSpaceResourceReferenceEntityReferenceResolver.class, + DefaultReferenceEntityReferenceResolver.class, + DefaultStringEntityReferenceResolver.class, + RelativeStringEntityReferenceResolver.class, + DefaultReferenceAttachmentReferenceResolver.class, + DefaultReferenceDocumentReferenceResolver.class, + DefaultStringSpaceReferenceResolver.class, + ContextComponentManagerProvider.class, + DefaultSymbolScheme.class +}) +@ComponentTest +// @formatter:on +class RelativeResourceReferenceEntityReferenceResolverTest +{ + private static final String DEFAULT_PAGE = "defaultpage"; + + private static final String CURRENT_PAGE = "currentpage"; + + private static final String CURRENT_SPACE = "currentspace"; + + private static final String CURRENT_SUBSPACE = "currentsubspace"; + + private static final String CURRENT_WIKI = "currentwiki"; + + private static final String WIKI = "Wiki"; + + private static final String SPACE = "Space"; + + private static final String PAGE = "Page"; + + private static final String ATTACHMENT = "file.ext"; + + private static final SpaceReference BASE_REFERENCE = new SpaceReference(WIKI, SPACE); + private static final EntityReference SPACE_ENTITY_REFERENCE = new EntityReference(SPACE, EntityType.SPACE); + private static final EntityReference PAGE_ENTITY_REFERENCE = + new EntityReference(PAGE, EntityType.DOCUMENT, SPACE_ENTITY_REFERENCE); + private static final EntityReference PAGE_ALONE_ENTITY_REFERENCE = new EntityReference(PAGE, EntityType.DOCUMENT); + private static final EntityReference DEFAULT_PAGE_ENTITY_REFERENCE = + new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT, SPACE_ENTITY_REFERENCE); + + + @InjectMockComponents + private RelativeResourceReferenceEntityReferenceResolver resolver; + + @MockComponent + @Named("current") + private EntityReferenceResolver currentEntityReferenceResolver; + + @MockComponent + @Named("current") + private Provider currentDocumentProvider; + + @MockComponent + private DocumentAccessBridge bridge; + + @MockComponent + private EntityReferenceProvider defaultEntityProvider; + + private final Set existingDocuments = new HashSet<>(); + + @BeforeEach + void before() throws Exception + { + when(this.currentDocumentProvider.get()) + .thenReturn(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE)); + + when(this.bridge.exists(any(DocumentReference.class))).then( + (Answer) invocation -> existingDocuments.contains(invocation.getArguments()[0])); + + when(this.defaultEntityProvider.getDefaultReference(EntityType.DOCUMENT)) + .thenReturn(new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT)); + } + + private DocumentResourceReference documentResource(String referenceString, boolean typed) + { + DocumentResourceReference reference = new DocumentResourceReference(referenceString); + + reference.setTyped(typed); + + return reference; + } + + private SpaceResourceReference spaceResource(String referenceString, boolean typed) + { + SpaceResourceReference reference = new SpaceResourceReference(referenceString); + + reference.setTyped(typed); + + return reference; + } + + private AttachmentResourceReference attachmentResource(String referenceString, boolean typed) + { + AttachmentResourceReference reference = new AttachmentResourceReference(referenceString); + + reference.setTyped(typed); + + return reference; + } + // Tests + + @Test + void resolve() + { + assertNull(this.resolver.resolve(null, null)); + assertNull(this.resolver.resolve(new ResourceReference("path", ResourceType.PATH), null)); + } + + @Test + void resolveTypeDocument() + { + assertEquals(new DocumentReference(WIKI, SPACE, PAGE), + this.resolver.resolve(documentResource(WIKI + ':' + SPACE + '.' + PAGE, true), null)); + assertEquals(PAGE_ENTITY_REFERENCE, this.resolver.resolve(documentResource(SPACE + '.' + PAGE, true), null)); + + assertEquals(new EntityReference(PAGE, EntityType.DOCUMENT), + this.resolver.resolve(documentResource(PAGE, true), null)); + + assertNull(this.resolver.resolve(documentResource("", true), null)); + + ResourceReference withBaseReference = documentResource("", true); + withBaseReference.addBaseReference(WIKI + ':' + SPACE + '.' + PAGE); + assertEquals(new DocumentReference(WIKI, SPACE, PAGE), + this.resolver.resolve(withBaseReference, null)); + + assertEquals(new DocumentReference(WIKI, SPACE, PAGE), this.resolver + .resolve(documentResource("", true), null, new DocumentReference(WIKI, SPACE, PAGE))); + } + + @Test + void resolveUntypeDocument() + { + // When the page does not exist + + assertEquals(new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(WIKI + ':' + SPACE + '.' + PAGE, false), null)); + + // TODO: check that this assert is ok, we don't get the default page since we don't have any info to properly + // resolve the absolute ref (no wiki, no base reference) + assertEquals(PAGE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); + assertEquals(PAGE_ALONE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(PAGE, false), null)); + + assertEquals(new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(WIKI + ':' + SPACE + '.' + PAGE, false), null, BASE_REFERENCE)); + assertEquals(new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null, BASE_REFERENCE)); + assertEquals(new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource(PAGE, false), null, BASE_REFERENCE)); + + // Already ends with default page name + assertEquals(new DocumentReference(WIKI, SPACE, DEFAULT_PAGE), this.resolver + .resolve(documentResource(WIKI + ':' + SPACE + '.' + DEFAULT_PAGE, false), null)); + + assertEquals(DEFAULT_PAGE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(SPACE + '.' + DEFAULT_PAGE, false), null)); + assertEquals(new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT), + this.resolver.resolve(documentResource(DEFAULT_PAGE, false), null)); + + assertEquals(new DocumentReference(WIKI, SPACE, DEFAULT_PAGE), this.resolver + .resolve(documentResource(WIKI + ':' + SPACE + '.' + DEFAULT_PAGE, false), null, BASE_REFERENCE)); + assertEquals(new DocumentReference(WIKI, SPACE, DEFAULT_PAGE), + this.resolver.resolve(documentResource(SPACE + '.' + DEFAULT_PAGE, false), null, BASE_REFERENCE)); + assertEquals(new DocumentReference(WIKI, SPACE, DEFAULT_PAGE), + this.resolver.resolve(documentResource(DEFAULT_PAGE, false), null, BASE_REFERENCE)); + + + // When the page exist + + this.existingDocuments.add(new DocumentReference(WIKI, SPACE, PAGE)); + assertEquals(new DocumentReference(WIKI, SPACE, PAGE), this.resolver + .resolve(documentResource(WIKI + ':' + SPACE + '.' + PAGE, false), null)); + + assertEquals(PAGE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); + assertEquals(PAGE_ALONE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(PAGE, false), null)); + + assertEquals(new DocumentReference(WIKI, SPACE, PAGE), + this.resolver.resolve(documentResource(WIKI + ':' + SPACE + '.' + PAGE, false), null, BASE_REFERENCE)); + assertEquals(new DocumentReference(WIKI, SPACE, PAGE), + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null, BASE_REFERENCE)); + assertEquals(new DocumentReference(WIKI, SPACE, PAGE), + this.resolver.resolve(documentResource(PAGE, false), null, BASE_REFERENCE)); + + assertNull(this.resolver.resolve(documentResource("", false), null)); + } + + @Test + void resolveUntypeDocumentWhenCurrentPageIsSpace() + { + // Current is top level space + assertEquals(PAGE_ALONE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(PAGE, false), null)); + + assertEquals(PAGE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); + + assertEquals(PAGE_ALONE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource('.' + PAGE, false), null)); + + EntityReference pageSpaceReference = new EntityReference(PAGE, EntityType.SPACE); + EntityReference defaultPageSpaceReference = + new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT, pageSpaceReference); + assertEquals(defaultPageSpaceReference, + this.resolver.resolve(documentResource('.' + PAGE + '.' + DEFAULT_PAGE, false), null)); + + // Current is subspace + + // When sibling page does not exist + assertEquals(PAGE_ALONE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(PAGE, false), null)); + + assertEquals(PAGE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); + + assertEquals(PAGE_ALONE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource('.' + PAGE, false), null)); + + assertEquals( + defaultPageSpaceReference, + this.resolver.resolve(documentResource('.' + PAGE + '.' + DEFAULT_PAGE, false), + null)); + + // When sibling page exist + + this.existingDocuments.add(new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, PAGE)); + + assertEquals(PAGE_ALONE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(PAGE, false), null)); + + assertEquals(PAGE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); + + assertEquals(PAGE_ALONE_ENTITY_REFERENCE, + this.resolver.resolve(documentResource('.' + PAGE, false), null)); + + assertEquals(defaultPageSpaceReference, + this.resolver.resolve(documentResource('.' + PAGE + '.' + DEFAULT_PAGE, false), + null)); + } + + @Test + void resolveTypeSpace() + { + assertEquals(new SpaceReference(WIKI, SPACE), + this.resolver.resolve(spaceResource(WIKI + ':' + SPACE, true), null)); + + assertEquals(SPACE_ENTITY_REFERENCE, + this.resolver.resolve(spaceResource(SPACE, true), null)); + + assertEquals(new SpaceReference(WIKI, SPACE), + this.resolver.resolve(spaceResource(SPACE, true), null, new WikiReference(WIKI))); + + assertNull(this.resolver.resolve(spaceResource("", true), null)); + assertEquals(new SpaceReference(WIKI, SPACE), this.resolver + .resolve(spaceResource("", true), null, new DocumentReference(WIKI, SPACE, PAGE))); + + ResourceReference withBaseReference = spaceResource("", true); + withBaseReference.addBaseReference(WIKI + ':' + SPACE + '.' + PAGE); + assertEquals(new SpaceReference(WIKI, SPACE), + this.resolver.resolve(withBaseReference, null)); + } + + @Test + void resolveTypeAttachment() + { + // When the page does not exist + EntityReference attachmentInSpacePage = + new EntityReference(ATTACHMENT, EntityType.ATTACHMENT, PAGE_ENTITY_REFERENCE); + EntityReference attachmentInPage = + new EntityReference(ATTACHMENT, EntityType.ATTACHMENT, PAGE_ALONE_ENTITY_REFERENCE); + + SpaceReference baseReference = new SpaceReference(WIKI, SPACE); + + assertEquals( + new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE)), + this.resolver + .resolve(attachmentResource(WIKI + ':' + SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null)); + assertEquals(attachmentInSpacePage, + this.resolver.resolve(attachmentResource(SPACE + '.' + PAGE + '@' + ATTACHMENT, true), + null)); + assertEquals(attachmentInPage, + this.resolver.resolve(attachmentResource(PAGE + '@' + ATTACHMENT, true), null)); + + assertEquals( + new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE)), + this.resolver + .resolve(attachmentResource(WIKI + ':' + SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null, + baseReference)); + assertEquals( + new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE)), + this.resolver.resolve(attachmentResource(SPACE + '.' + PAGE + '@' + ATTACHMENT, true), + null, baseReference)); + assertEquals( + new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE)), + this.resolver.resolve(attachmentResource(PAGE + '@' + ATTACHMENT, true), null, baseReference)); + + // When the page exist + + this.existingDocuments.add(new DocumentReference(WIKI, SPACE, PAGE)); + assertEquals(new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, SPACE, PAGE)), + this.resolver + .resolve(attachmentResource(WIKI + ':' + SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null)); + assertEquals(attachmentInSpacePage, + this.resolver.resolve(attachmentResource(SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null)); + assertEquals(attachmentInPage, + this.resolver.resolve(attachmentResource(PAGE + '@' + ATTACHMENT, true), null)); + + assertEquals(new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, SPACE, PAGE)), + this.resolver + .resolve(attachmentResource(WIKI + ':' + SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null, + baseReference)); + + assertEquals(new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, SPACE, PAGE)), + this.resolver.resolve(attachmentResource(SPACE + '.' + PAGE + '@' + ATTACHMENT, true), null, + baseReference)); + + assertEquals(new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, SPACE, PAGE)), + this.resolver.resolve(attachmentResource(PAGE + '@' + ATTACHMENT, true), null, baseReference)); + + assertEquals( + new EntityReference(ATTACHMENT, EntityType.ATTACHMENT), + this.resolver.resolve(attachmentResource(ATTACHMENT, true), null)); + assertEquals( + new AttachmentReference(ATTACHMENT, new DocumentReference(WIKI, SPACE, DEFAULT_PAGE)), + this.resolver.resolve(attachmentResource(ATTACHMENT, true), null, baseReference)); + } +}