diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/DeletePageIT.java b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/DeletePageIT.java index ffd26b99768e..e736e4dbb25f 100644 --- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/DeletePageIT.java +++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/DeletePageIT.java @@ -773,7 +773,7 @@ void deleteWithUpdateLinksAndAutoRedirect(TestUtils testUtils, TestReference ref // Verify that a redirect was added and the link was updated. viewPage = testUtils.gotoPage(reference); assertEquals("New target", this.viewPage.getDocumentTitle()); - assertEquals("[[Link>>doc:NewTarget.WebHome]]", + assertEquals("[[Link>>doc:xwiki:NewTarget.WebHome]]", testUtils.rest().get(backlinkDocumentReference).getContent()); } @@ -826,7 +826,7 @@ void deleteWithAffectChildrenAndNewTarget(TestUtils testUtils, TestReference par TestConfiguration testConfiguration) throws Exception { DocumentReference childReference = new DocumentReference("Child", parentReference.getLastSpaceReference()); - String childFullName = testUtils.serializeReference(childReference).split(":")[1]; + String childFullName = testUtils.serializeLocalReference(childReference); DocumentReference backlinkDocReference = new DocumentReference("xwiki", "Backlink", "WebHome"); DocumentReference newTargetReference = new DocumentReference("xwiki", "NewTarget", "WebHome"); @@ -836,7 +836,7 @@ void deleteWithAffectChildrenAndNewTarget(TestUtils testUtils, TestReference par // Create backlinks to the parent and the child page. String format = "[[Parent>>doc:%s]] [[Child>>doc:%s]]"; testUtils.createPage(backlinkDocReference, - String.format(format, testUtils.serializeReference(parentReference), childFullName), "Backlink document"); + String.format(format, testUtils.serializeLocalReference(parentReference), childFullName), "Backlink document"); // Wait for Solr indexing to complete as backlink information from Solr is needed new SolrTestUtils(testUtils, testConfiguration.getServletEngine()).waitEmptyQueue(); @@ -855,7 +855,7 @@ void deleteWithAffectChildrenAndNewTarget(TestUtils testUtils, TestReference par // Verify that there is no redirect on the child page and backlink was not altered. assertEquals(DELETE_SUCCESSFUL, deletingPage.getInfoMessage()); String newContent = - String.format(format, testUtils.serializeReference(newTargetReference).split(":")[1], childFullName); + String.format(format, testUtils.serializeLocalReference(newTargetReference), childFullName); assertEquals(newContent, testUtils.rest().get(backlinkDocReference).getContent()); parentPage = testUtils.gotoPage(parentReference); assertEquals("New target", parentPage.getDocumentTitle()); diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/RenamePageIT.java b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/RenamePageIT.java index ae59c7810ea4..3d6a669b6478 100644 --- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/RenamePageIT.java +++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/RenamePageIT.java @@ -723,4 +723,24 @@ void renameWithRelativeLinks(TestUtils testUtils, TestReference testReference, T //wikiEditPage = WikiEditPage.gotoPage(new DocumentReference("WebHome", newBobSpace)); //assertEquals(String.format("[[%s]]", serializedAlice2Reference), wikiEditPage.getContent()); } + + @Order(10) + @Test + void renameLinkContainingWiki(TestUtils testUtils, TestReference testReference, TestConfiguration testConfiguration) + throws Exception + { + DocumentReference documentReference = new DocumentReference("xwiki", "TestLinkWithWiki", "WebHome"); + testUtils.rest().delete(documentReference); + testUtils.rest().savePage(documentReference, "Some content", "TestLinkWithWiki"); + testUtils.rest().savePage(testReference, "[[MyPage>>xwiki:TestLinkWithWiki.WebHome]]", + "renameLinkContainingWiki"); + new SolrTestUtils(testUtils, testConfiguration.getServletEngine()).waitEmptyQueue(); + RenamePage renamePage = testUtils.gotoPage(documentReference).rename(); + renamePage.getDocumentPicker().setName("TestLinkWithWikiNew"); + CopyOrRenameOrDeleteStatusPage statusPage = + renamePage.clickRenameButton().waitUntilFinished(); + assertEquals("Done.", statusPage.getInfoMessage()); + WikiEditPage wikiEditPage = WikiEditPage.gotoPage(testReference); + assertEquals("[[MyPage>>xwiki:TestLinkWithWikiNew.WebHome]]", wikiEditPage.getContent()); + } } 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-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/ResourceReferenceRenamer.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/ResourceReferenceRenamer.java index a0729086e16a..8d672d573ef5 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/ResourceReferenceRenamer.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/ResourceReferenceRenamer.java @@ -59,10 +59,17 @@ public class ResourceReferenceRenamer @Inject private EntityReferenceResolver entityReferenceResolver; + @Inject + @Named("relative") + private EntityReferenceResolver relativeEntityReferenceResolver; + @Inject @Named("compact") private EntityReferenceSerializer compactEntityReferenceSerializer; + @Inject + private EntityReferenceSerializer defaultEntityReferenceSerializer; + @Inject private DocumentReferenceResolver defaultReferenceDocumentReferenceResolver; @@ -152,8 +159,6 @@ private boolean updateAbsoluteResourceReference(ResourceReference resourceRefere DocumentReference absoluteResolvedDocumentReference = this.defaultReferenceDocumentReferenceResolver.resolve(absoluteResolvedEntityReference); - boolean isRelativePageReferenceOutsideOfParent = false; - // If the link targets the old (renamed) document reference and it's an absolute reference // (i.e. its resolution without any given parameter gives same result than its resolution with the // currentDocument) then we must update it @@ -193,9 +198,8 @@ private boolean updateAbsoluteResourceReference(ResourceReference resourceRefere newTargetReference = new AttachmentReference(linkEntityReference.getName(), newReference); } - String newReferenceString = - this.compactEntityReferenceSerializer.serialize(newTargetReference, currentDocumentReference); - + String newReferenceString = getNewTargetReference(resourceReference, newTargetReference, + currentDocumentReference); resourceReference.setReference(newReferenceString); resourceReference.setType(newResourceType); result = true; @@ -203,6 +207,19 @@ private boolean updateAbsoluteResourceReference(ResourceReference resourceRefere return result; } + private String getNewTargetReference(ResourceReference resourceReference, EntityReference newTargetReference, + EntityReference currentReference) + { + EntityReference entityReference = + this.relativeEntityReferenceResolver.resolve(resourceReference, null, (Object) null); + // If the reference contains the wiki name, then we should keep the absolute serialization. + if (entityReference.extractReference(EntityType.WIKI) != null) { + return this.defaultEntityReferenceSerializer.serialize(newTargetReference, currentReference); + } else { + return this.compactEntityReferenceSerializer.serialize(newTargetReference, currentReference); + } + } + private boolean isPageReferenceOutOfParent(ResourceReference resourceReference, DocumentReference linkTargetDocumentReference, Map updatedEntities) { @@ -266,8 +283,7 @@ private boolean updateRelativeResourceReference(Reso if (shouldBeUpdated) { // Serialize the old (original) link relative to the new document's location, in compact form. - String serializedLinkReference = - this.compactEntityReferenceSerializer.serialize(oldLinkReference, newReference); + String serializedLinkReference = getNewTargetReference(resourceReference, oldLinkReference, newReference); resourceReference.setReference(serializedLinkReference); result = true; } diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultReferenceUpdaterTest.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultReferenceUpdaterTest.java index 3c5fe356493f..996e7f242bf7 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultReferenceUpdaterTest.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultReferenceUpdaterTest.java @@ -19,8 +19,6 @@ */ package org.xwiki.refactoring.internal; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -116,6 +114,9 @@ class DefaultReferenceUpdaterTest @Named("compact") private EntityReferenceSerializer compactEntityReferenceSerializer; + @MockComponent + private EntityReferenceSerializer defaultEntityReferenceSerializer; + @MockComponent private DocumentReferenceResolver defaultReferenceDocumentReferenceResolver; @@ -220,7 +221,7 @@ private void setTextarea(XWikiDocument document, XDOM xdom) .thenReturn(new ObjectPropertyReference("area", new ObjectReference("areaobject", documentReference))); when(document.getXObjects()) - .thenReturn(Collections.singletonMap(documentReference, Collections.singletonList(baseObject))); + .thenReturn(Map.of(documentReference, List.of(baseObject))); when(this.contentParser.parse("areacontent", Syntax.XWIKI_2_1, documentReference)).thenReturn(xdom); } @@ -242,32 +243,40 @@ void updateRelativeLinks() throws Exception // Setup document content ResourceReference docLinkReference = new ResourceReference("C", ResourceType.DOCUMENT); - LinkBlock docLinkBlock = new LinkBlock(Collections.emptyList(), docLinkReference, false); + LinkBlock docLinkBlock = new LinkBlock(List.of(), docLinkReference, false); ResourceReference spaceLinkReference = new ResourceReference("Z", ResourceType.SPACE); - LinkBlock spaceLinkBlock = new LinkBlock(Collections.emptyList(), spaceLinkReference, false); + LinkBlock spaceLinkBlock = new LinkBlock(List.of(), spaceLinkReference, false); ResourceReference imageReference = new AttachmentResourceReference("attachment.txt"); ImageBlock imageBlock = new ImageBlock(imageReference, false); + ResourceReference absoluteDocLinkResourceReference = new ResourceReference("xwiki:C.WebHome", + ResourceType.DOCUMENT); + LinkBlock absoluteDocLinkBlock = + new LinkBlock(List.of(), absoluteDocLinkResourceReference, false); when(newDocument.getXDOM()) - .thenReturn(new XDOM(Arrays.asList(docLinkBlock, spaceLinkBlock, imageBlock))); + .thenReturn(new XDOM(List.of(docLinkBlock, spaceLinkBlock, imageBlock, absoluteDocLinkBlock))); // Setup object content ResourceReference xobjectDocLinkReference = new ResourceReference("C", ResourceType.DOCUMENT); - LinkBlock xobjectDocLinkBlock = new LinkBlock(Collections.emptyList(), xobjectDocLinkReference, false); + LinkBlock xobjectDocLinkBlock = new LinkBlock(List.of(), xobjectDocLinkReference, false); ResourceReference xobjectSpaceLinkReference = new ResourceReference("Z", ResourceType.SPACE); LinkBlock xobjectSpaceLinkBlock = - new LinkBlock(Collections.emptyList(), xobjectSpaceLinkReference, false); + new LinkBlock(List.of(), xobjectSpaceLinkReference, false); ResourceReference xobjectImageReference = new AttachmentResourceReference("attachment.txt"); ImageBlock xobjectImageBlock = new ImageBlock(xobjectImageReference, false); setTextarea(newDocument, - new XDOM(Arrays.asList(xobjectDocLinkBlock, xobjectSpaceLinkBlock, xobjectImageBlock))); + new XDOM(List.of(xobjectDocLinkBlock, xobjectSpaceLinkBlock, xobjectImageBlock))); DocumentReference originalDocLinkReference = new DocumentReference("WebHome", new SpaceReference("C", oldReference.getLastSpaceReference())); DocumentReference absoluteDocLinkReference = new DocumentReference("WebHome", new SpaceReference("wiki", "C")); when(this.resourceReferenceResolver.resolve(docLinkReference, null)) .thenReturn(absoluteDocLinkReference); + when(this.resourceReferenceResolver.resolve(absoluteDocLinkResourceReference, null)) + .thenReturn(absoluteDocLinkReference); when(this.resourceReferenceResolver.resolve(docLinkReference, null, oldReference)) .thenReturn(originalDocLinkReference); + when(this.resourceReferenceResolver.resolve(absoluteDocLinkResourceReference, null, oldReference)) + .thenReturn(absoluteDocLinkReference); when(this.resourceReferenceResolver.resolve(xobjectDocLinkReference, null)) .thenReturn(absoluteDocLinkReference); when(this.resourceReferenceResolver.resolve(xobjectDocLinkReference, null, oldReference)) @@ -284,6 +293,8 @@ void updateRelativeLinks() throws Exception .thenReturn(newDocLinkReference); when(this.resourceReferenceResolver.resolve(imageReference, null, newReference)) .thenReturn(newImageTargetAttachment); + when(this.resourceReferenceResolver.resolve(absoluteDocLinkResourceReference, null, newReference)) + .thenReturn(new DocumentReference("WebHome", new SpaceReference("wiki", "E"))); SpaceReference originalSpaceReference = new SpaceReference("wiki", "Z"); when(this.resourceReferenceResolver.resolve(spaceLinkReference, null)) @@ -300,12 +311,16 @@ void updateRelativeLinks() throws Exception .thenReturn(originalSpaceReference); when(this.compactEntityReferenceSerializer.serialize(originalDocLinkReference, newReference)).thenReturn("A.C"); + when(this.defaultEntityReferenceSerializer.serialize(absoluteDocLinkReference, newReference)) + .thenReturn("wiki:C.WebHome"); updater.update(newReference, oldReference, newReference); // Document link block is updated. assertEquals("A.C", docLinkBlock.getReference().getReference()); assertEquals(ResourceType.DOCUMENT, docLinkBlock.getReference().getType()); + assertEquals("wiki:C.WebHome", absoluteDocLinkBlock.getReference().getReference()); + assertEquals(ResourceType.DOCUMENT, absoluteDocLinkBlock.getReference().getType()); // Space link block stays the same, since they were on the same wiki. assertEquals("Z", spaceLinkBlock.getReference().getReference()); assertEquals(ResourceType.SPACE, spaceLinkBlock.getReference().getType()); @@ -339,13 +354,13 @@ void updateRelativeLinksAcrossWikis() throws Exception when(newDocument.getXDOM()).thenReturn(xdom); ResourceReference docLinkReference = new ResourceReference("C", ResourceType.DOCUMENT); - LinkBlock docLinkBlock = new LinkBlock(Collections.emptyList(), docLinkReference, false); + LinkBlock docLinkBlock = new LinkBlock(List.of(), docLinkReference, false); ResourceReference spaceLinkReference = new ResourceReference("Z", ResourceType.SPACE); - LinkBlock spaceLinkBlock = new LinkBlock(Collections.emptyList(), spaceLinkReference, false); + LinkBlock spaceLinkBlock = new LinkBlock(List.of(), spaceLinkReference, false); when(xdom.getBlocks(any(), eq(Block.Axes.DESCENDANT))) - .thenReturn(Arrays.asList(docLinkBlock, spaceLinkBlock)); + .thenReturn(List.of(docLinkBlock, spaceLinkBlock)); DocumentReference originalDocLinkReference = new DocumentReference("C", oldReference.getLastSpaceReference()); DocumentReference absoluteDocLinkReference = new DocumentReference("C", new SpaceReference("xwiki", "Main")); @@ -396,18 +411,23 @@ void update() throws Exception // Setup document content ResourceReference linkReference = new ResourceReference("A.B", ResourceType.DOCUMENT); - LinkBlock linkBlock = new LinkBlock(Collections.emptyList(), linkReference, false); - XDOM xdom = new XDOM(Collections.singletonList(linkBlock)); + LinkBlock linkBlock = new LinkBlock(List.of(), linkReference, false); + ResourceReference absoluteLinkReference = new ResourceReference("xwiki:A.B.WebHome", ResourceType.DOCUMENT); + LinkBlock absoluteLinkBlock = new LinkBlock(List.of(), absoluteLinkReference, false); + XDOM xdom = new XDOM(List.of(linkBlock, absoluteLinkBlock)); when(document.getXDOM()).thenReturn(xdom); // Setup object content ResourceReference xobjectLinkReference = new ResourceReference("A.B", ResourceType.DOCUMENT); - LinkBlock xobjectLinkBlock = new LinkBlock(Collections.emptyList(), xobjectLinkReference, false); - XDOM xobjectXDOM = new XDOM(Collections.singletonList(xobjectLinkBlock)); + LinkBlock xobjectLinkBlock = new LinkBlock(List.of(), xobjectLinkReference, false); + XDOM xobjectXDOM = new XDOM(List.of(xobjectLinkBlock)); setTextarea(document, xobjectXDOM); when(this.resourceReferenceResolver.resolve(linkReference, null)).thenReturn(oldLinkTarget); when(this.resourceReferenceResolver.resolve(linkReference, null, documentReference)).thenReturn(oldLinkTarget); + when(this.resourceReferenceResolver.resolve(absoluteLinkReference, null)).thenReturn(oldLinkTarget); + when(this.resourceReferenceResolver.resolve(absoluteLinkReference, null, documentReference)) + .thenReturn(oldLinkTarget); when(this.resourceReferenceResolver.resolve(xobjectLinkReference, null)) .thenReturn(oldLinkTarget); when(this.resourceReferenceResolver.resolve(xobjectLinkReference, null, documentReference)) @@ -415,10 +435,13 @@ void update() throws Exception when(this.defaultReferenceDocumentReferenceResolver.resolve(oldLinkTarget)).thenReturn(oldLinkTarget); when(this.compactEntityReferenceSerializer.serialize(newLinkTarget, documentReference)).thenReturn("X.Y"); + when(this.defaultEntityReferenceSerializer.serialize(newLinkTarget, documentReference)) + .thenReturn("xwiki:X.Y.WebHome"); updater.update(documentReference, oldLinkTarget, newLinkTarget); assertEquals("X.Y", linkBlock.getReference().getReference()); + assertEquals("xwiki:X.Y.WebHome", absoluteLinkBlock.getReference().getReference()); assertEquals("X.Y", xobjectLinkBlock.getReference().getReference()); assertEquals(ResourceType.DOCUMENT, linkBlock.getReference().getType()); verifyDocumentSave(document, "Renamed back-links.", false, false); @@ -444,7 +467,7 @@ void renameImage() throws Exception ResourceReference imageReference = new AttachmentResourceReference("A.B@attachment.txt"); ImageBlock imageBlock = new ImageBlock(imageReference, false); - when(xdom.getBlocks(any(), eq(Block.Axes.DESCENDANT))).thenReturn(Arrays.asList(imageBlock)); + when(xdom.getBlocks(any(), eq(Block.Axes.DESCENDANT))).thenReturn(List.of(imageBlock)); when(this.resourceReferenceResolver.resolve(imageReference, null)).thenReturn(oldImageTargetAttachment); when(this.resourceReferenceResolver.resolve(imageReference, null, documentReference)) @@ -481,8 +504,8 @@ public void renameAttachment() throws Exception when(document.getXDOM()).thenReturn(xdom); ResourceReference linkReference = new AttachmentResourceReference("A.B@attachment.txt"); - LinkBlock linkBlock = new LinkBlock(Collections.emptyList(), linkReference, false); - when(xdom.getBlocks(any(), eq(Block.Axes.DESCENDANT))).thenReturn(Arrays.asList(linkBlock)); + LinkBlock linkBlock = new LinkBlock(List.of(), linkReference, false); + when(xdom.getBlocks(any(), eq(Block.Axes.DESCENDANT))).thenReturn(List.of(linkBlock)); when(this.resourceReferenceResolver.resolve(linkReference, null)) .thenReturn(oldLinkTargetAttachment); @@ -517,13 +540,13 @@ void renameNonTerminalDocumentLinks() throws Exception when(document.getXDOM()).thenReturn(xdom); ResourceReference docLinkReference = new ResourceReference("A.WebHome", ResourceType.DOCUMENT); - LinkBlock documentLinkBlock = new LinkBlock(Collections.emptyList(), docLinkReference, false); + LinkBlock documentLinkBlock = new LinkBlock(List.of(), docLinkReference, false); ResourceReference spaceLinkReference = new ResourceReference("A", ResourceType.SPACE); - LinkBlock spaceLinkBlock = new LinkBlock(Collections.emptyList(), spaceLinkReference, false); + LinkBlock spaceLinkBlock = new LinkBlock(List.of(), spaceLinkReference, false); when(xdom.getBlocks(any(), eq(Block.Axes.DESCENDANT))) - .thenReturn(Arrays.asList(documentLinkBlock, spaceLinkBlock)); + .thenReturn(List.of(documentLinkBlock, spaceLinkBlock)); // Doc link when(this.resourceReferenceResolver.resolve(docLinkReference, null)) @@ -569,13 +592,13 @@ void renameNonTerminalToTerminalDocumentLinks() throws Exception when(document.getXDOM()).thenReturn(xdom); ResourceReference docLinkReference = new ResourceReference("A.WebHome", ResourceType.DOCUMENT); - LinkBlock documentLinkBlock = new LinkBlock(Collections.emptyList(), docLinkReference, false); + LinkBlock documentLinkBlock = new LinkBlock(List.of(), docLinkReference, false); ResourceReference spaceLinkReference = new ResourceReference("A", ResourceType.SPACE); - LinkBlock spaceLinkBlock = new LinkBlock(Collections.emptyList(), spaceLinkReference, false); + LinkBlock spaceLinkBlock = new LinkBlock(List.of(), spaceLinkReference, false); when(xdom.getBlocks(any(), eq(Block.Axes.DESCENDANT))) - .thenReturn(Arrays.asList(documentLinkBlock, spaceLinkBlock)); + .thenReturn(List.of(documentLinkBlock, spaceLinkBlock)); // Doc link when(this.resourceReferenceResolver.resolve(docLinkReference, null)) @@ -638,7 +661,7 @@ void updateFromMacros(MockitoComponentManager componentManager) throws Exception displayMacroBlock.setParent(xdom); when(xdom.getBlocks(any(), eq(Block.Axes.DESCENDANT))) - .thenReturn(Arrays.asList(includeMacroBlock1, includeMacroBlock2, displayMacroBlock)); + .thenReturn(List.of(includeMacroBlock1, includeMacroBlock2, displayMacroBlock)); ResourceReference macroResourceReference = new ResourceReference("A.B", ResourceType.DOCUMENT); @@ -680,7 +703,7 @@ void updateAttachments() throws Exception DocumentReference targetDocument = new DocumentReference("wiki", "Space", "Target"); AttachmentReference newLinkTarget = new AttachmentReference("newname.txt", targetDocument); ResourceReference resourceReference = new ResourceReference("oldname.txt", ResourceType.ATTACHMENT); - LinkBlock documentLinkBlock = new LinkBlock(Collections.emptyList(), resourceReference, false); + LinkBlock documentLinkBlock = new LinkBlock(List.of(), resourceReference, false); XWikiDocument document = mock(XWikiDocument.class); XDOM xdom = mock(XDOM.class); @@ -734,10 +757,10 @@ void updateFromLinksAndMacros(MockitoComponentManager componentManager) throws E MacroBlock includeMacroBlock = new MacroBlock("include", includeParameters, false); ResourceReference resourceReference = new ResourceReference("A.B", ResourceType.DOCUMENT); - LinkBlock documentLinkBlock = new LinkBlock(Collections.emptyList(), resourceReference, false); + LinkBlock documentLinkBlock = new LinkBlock(List.of(), resourceReference, false); when(xdom.getBlocks(any(), eq(Block.Axes.DESCENDANT))) - .thenReturn(Arrays.asList(includeMacroBlock, documentLinkBlock)); + .thenReturn(List.of(includeMacroBlock, documentLinkBlock)); when(this.resourceReferenceResolver.resolve(resourceReference, null)) .thenReturn(oldLinkTarget); @@ -784,7 +807,7 @@ void updateAndTranslations() throws Exception when(this.xcontext.getWiki().getDocument(baseDocumentReference, this.xcontext)).thenReturn(baseDocument); when(baseDocument.getDocumentReference()).thenReturn(baseDocumentReference); - when(baseDocument.getTranslationLocales(xcontext)).thenReturn(Arrays.asList(Locale.FRENCH, Locale.ENGLISH)); + when(baseDocument.getTranslationLocales(xcontext)).thenReturn(List.of(Locale.FRENCH, Locale.ENGLISH)); DocumentReference frenchDocumentReference = new DocumentReference("wiki", "Space", "Page", Locale.FRENCH); XWikiDocument frenchDocument = mock(XWikiDocument.class); when(baseDocument.getTranslatedDocument(Locale.FRENCH, xcontext)).thenReturn(frenchDocument); @@ -799,7 +822,7 @@ void updateAndTranslations() throws Exception DocumentReference oldLinkTarget = new DocumentReference("wiki", "A", "B"); DocumentReference newLinkTarget = new DocumentReference("wiki", "X", "Y"); - List documentsToUpdate = Arrays.asList(baseDocument, frenchDocument, englishDocument); + List documentsToUpdate = List.of(baseDocument, frenchDocument, englishDocument); for (XWikiDocument xWikiDocument : documentsToUpdate) { DocumentReference documentReference = xWikiDocument.getDocumentReference(); @@ -808,7 +831,7 @@ void updateAndTranslations() throws Exception when(xWikiDocument.getXDOM()).thenReturn(xdom); ResourceReference linkReference = new ResourceReference("A.B", ResourceType.DOCUMENT); - LinkBlock linkBlock = new LinkBlock(Collections.emptyList(), linkReference, false); + LinkBlock linkBlock = new LinkBlock(List.of(), linkReference, false); when(xdom.getBlocks(any(), eq(Block.Axes.DESCENDANT))).thenReturn(List.of(linkBlock)); when(this.resourceReferenceResolver.resolve(linkReference, null)) diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/ResourceReferenceRenamerTest.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/ResourceReferenceRenamerTest.java index 63cd5422cc40..a933cfbe2ffe 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/ResourceReferenceRenamerTest.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/ResourceReferenceRenamerTest.java @@ -71,6 +71,9 @@ class ResourceReferenceRenamerTest @Named("compact") private EntityReferenceSerializer compactEntityReferenceSerializer; + @MockComponent + private EntityReferenceSerializer defaultEntityReferenceSerializer; + @MockComponent private DocumentReferenceResolver defaultReferenceDocumentReferenceResolver; @@ -94,7 +97,7 @@ void setup() throws XWikiException @Test void updateResourceReferenceRelative() { - DocumentResourceReference resourceReference = new DocumentResourceReference("xwiki:Main.WebHome"); + DocumentResourceReference resourceReference = new DocumentResourceReference("Main.WebHome"); AttachmentReference oldReference = new AttachmentReference("file.txt", new DocumentReference("wiki", "space", "page")); AttachmentReference newReference = 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 new file mode 100644 index 000000000000..f85386fa8cce --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/AbstractRelativeResourceReferenceEntityReferenceResolver.java @@ -0,0 +1,124 @@ +/* + * 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.List; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.xwiki.model.EntityType; +import org.xwiki.model.reference.EntityReference; +import org.xwiki.model.reference.EntityReferenceResolver; +import org.xwiki.rendering.listener.reference.ResourceReference; +import org.xwiki.rendering.listener.reference.ResourceType; + +/** + * Abstract class for all relative resource reference resolvers. + * + * @version $Id$ + * @since 17.0.0RC1 + */ +public abstract class AbstractRelativeResourceReferenceEntityReferenceResolver + extends AbstractResourceReferenceEntityReferenceResolver +{ + @Inject + @Named("relative") + protected EntityReferenceResolver relativeReferenceResolver; + + /** + * @param type the resource type that this resolver will support + */ + 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(), baseReference); + } + + /** + * + * @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 new file mode 100644 index 000000000000..5727dfec920a --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeAttachmentResourceReferenceEntityReferenceResolver.java @@ -0,0 +1,99 @@ +/* + * 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 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; + +/** + * Convert attachment resource reference into entity reference. + * + * @version $Id$ + * @since 17.0.0RC1 + */ +@Component +@Named("relative/attach") +@Singleton +public class RelativeAttachmentResourceReferenceEntityReferenceResolver + extends AbstractRelativeResourceReferenceEntityReferenceResolver +{ + @Inject + private AttachmentReferenceResolver defaultReferenceAttachmentReferenceResolver; + + /** + * Default constructor. + */ + public RelativeAttachmentResourceReferenceEntityReferenceResolver() + { + super(ResourceType.ATTACHMENT); + } + + @Override + 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 new file mode 100644 index 000000000000..8021b6237e72 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeDocumentResourceReferenceEntityReferenceResolver.java @@ -0,0 +1,90 @@ +/* + * 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 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; + +/** + * Convert document resource reference into entity reference. + * + * @version $Id$ + * @since 17.0.0RC1 + */ +@Component +@Named("relative/doc") +@Singleton +public class RelativeDocumentResourceReferenceEntityReferenceResolver + extends AbstractRelativeResourceReferenceEntityReferenceResolver +{ + @Inject + private DocumentReferenceResolver defaultStringDocumentReferenceResolver; + + /** + * Default constructor. + */ + public RelativeDocumentResourceReferenceEntityReferenceResolver() + { + super(ResourceType.DOCUMENT); + } + + @Override + 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 new file mode 100644 index 000000000000..7c2ac8d8253f --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageAttachmentResourceReferenceEntityReferenceResolver.java @@ -0,0 +1,55 @@ +/* + * 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 javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.model.EntityType; +import org.xwiki.rendering.listener.reference.ResourceType; + +/** + * Convert attachment resource reference into entity reference. + * + * @version $Id$ + * @since 13.10.5 + * @since 17.0.0RC1 + */ +@Component +@Named("relative/pageAttach") +@Singleton +public class RelativePageAttachmentResourceReferenceEntityReferenceResolver + extends AbstractRelativeResourceReferenceEntityReferenceResolver +{ + /** + * Default constructor. + */ + public RelativePageAttachmentResourceReferenceEntityReferenceResolver() + { + super(ResourceType.PAGE_ATTACHMENT); + } + + @Override + 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 new file mode 100644 index 000000000000..81099bc8efc1 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageResourceReferenceEntityReferenceResolver.java @@ -0,0 +1,54 @@ +/* + * 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 javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.model.EntityType; +import org.xwiki.rendering.listener.reference.ResourceType; + +/** + * Convert page resource reference into entity reference. + * + * @version $Id$ + * @since 17.0.0RC1 + */ +@Component +@Named("relative/page") +@Singleton +public class RelativePageResourceReferenceEntityReferenceResolver + extends AbstractRelativeResourceReferenceEntityReferenceResolver +{ + /** + * Default constructor. + */ + public RelativePageResourceReferenceEntityReferenceResolver() + { + super(ResourceType.PAGE); + } + + @Override + 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/RelativeResourceReferenceEntityReferenceResolver.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeResourceReferenceEntityReferenceResolver.java new file mode 100644 index 000000000000..3e34f7d355d3 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeResourceReferenceEntityReferenceResolver.java @@ -0,0 +1,91 @@ +/* + * 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.lang.reflect.ParameterizedType; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; +import org.xwiki.component.util.DefaultParameterizedType; +import org.xwiki.model.EntityType; +import org.xwiki.model.reference.EntityReference; +import org.xwiki.model.reference.EntityReferenceResolver; +import org.xwiki.rendering.listener.reference.ResourceReference; + +/** + * Default entry point to convert a resource reference into an entity reference. + * + * @version $Id$ + * @since 17.0.0RC1 + */ +@Component +@Named("relative") +@Singleton +public class RelativeResourceReferenceEntityReferenceResolver implements EntityReferenceResolver +{ + /** + * Type instance for EntityReferenceResolver. + */ + public static final ParameterizedType TYPE_RESOURCEREFERENCE = + new DefaultParameterizedType(null, EntityReferenceResolver.class, ResourceReference.class); + + private static final String RELATIVE_HINT = "relative/%s"; + + @Inject + @Named("context") + private Provider componentManagerProvider; + + @Override + public EntityReference resolve(ResourceReference resourceReference, EntityType type, Object... parameters) + { + if (resourceReference == null) { + return null; + } + + if (this.componentManagerProvider.get().hasComponent(TYPE_RESOURCEREFERENCE, + getRelativeHint(resourceReference))) { + EntityReferenceResolver resolver; + try { + resolver = this.componentManagerProvider.get().getInstance(TYPE_RESOURCEREFERENCE, + getRelativeHint(resourceReference)); + } catch (ComponentLookupException e) { + throw new RuntimeException( + String.format("Unknown error when trying to load resolver for reference [%s]", resourceReference), + e); + } + + return resolver.resolve(resourceReference, type, parameters); + } + + // Unsupported resource reference type + return null; + } + + private String getRelativeHint(ResourceReference resourceReference) + { + return String.format(RELATIVE_HINT, resourceReference.getType().getScheme()); + } +} 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 new file mode 100644 index 000000000000..437d86e1af81 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeSpaceResourceReferenceEntityReferenceResolver.java @@ -0,0 +1,54 @@ +/* + * 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 javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.model.EntityType; +import org.xwiki.rendering.listener.reference.ResourceType; + +/** + * Convert space resource reference into entity reference. + * + * @version $Id$ + * @since 17.0.0RC1 + */ +@Component +@Named("relative/space") +@Singleton +public class RelativeSpaceResourceReferenceEntityReferenceResolver + extends AbstractRelativeResourceReferenceEntityReferenceResolver +{ + /** + * Default constructor. + */ + public RelativeSpaceResourceReferenceEntityReferenceResolver() + { + super(ResourceType.SPACE); + } + + @Override + protected EntityType getEntityType() + { + return EntityType.SPACE; + } +} diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/resources/META-INF/components.txt b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/resources/META-INF/components.txt index a1627d0569eb..b73c2c8b79c5 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/resources/META-INF/components.txt +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/resources/META-INF/components.txt @@ -12,6 +12,12 @@ org.xwiki.rendering.internal.resolver.DefaultResourceReferenceEntityReferenceRes org.xwiki.rendering.internal.resolver.DocumentResourceReferenceEntityReferenceResolver org.xwiki.rendering.internal.resolver.PageAttachmentResourceReferenceEntityReferenceResolver org.xwiki.rendering.internal.resolver.PageResourceReferenceEntityReferenceResolver +org.xwiki.rendering.internal.resolver.RelativeAttachmentResourceReferenceEntityReferenceResolver +org.xwiki.rendering.internal.resolver.RelativeDocumentResourceReferenceEntityReferenceResolver +org.xwiki.rendering.internal.resolver.RelativePageAttachmentResourceReferenceEntityReferenceResolver +org.xwiki.rendering.internal.resolver.RelativePageResourceReferenceEntityReferenceResolver +org.xwiki.rendering.internal.resolver.RelativeSpaceResourceReferenceEntityReferenceResolver +org.xwiki.rendering.internal.resolver.RelativeResourceReferenceEntityReferenceResolver org.xwiki.rendering.internal.resolver.SpaceResourceReferenceEntityReferenceResolver org.xwiki.rendering.script.RenderingScriptService org.xwiki.rendering.internal.parser.LinkParser 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)); + } +}