diff --git a/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/DefaultReferenceEntityReferenceResolverTest.java b/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/DefaultReferenceEntityReferenceResolverTest.java index 9181fdf985be..004cec175b66 100644 --- a/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/DefaultReferenceEntityReferenceResolverTest.java +++ b/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/DefaultReferenceEntityReferenceResolverTest.java @@ -50,7 +50,7 @@ */ @ComponentTest @ComponentList({ DefaultSymbolScheme.class }) -public class DefaultReferenceEntityReferenceResolverTest implements TestConstants +class DefaultReferenceEntityReferenceResolverTest implements TestConstants { @MockComponent private EntityReferenceProvider referenceProvider; @@ -59,7 +59,7 @@ public class DefaultReferenceEntityReferenceResolverTest implements TestConstant private DefaultReferenceEntityReferenceResolver resolver; @BeforeComponent - public void beforeComponent() + void beforeComponent() { when(this.referenceProvider.getDefaultReference(EntityType.WIKI)).thenReturn(DEFAULT_WIKI_REFERENCE); when(this.referenceProvider.getDefaultReference(EntityType.SPACE)).thenReturn(DEFAULT_SPACE_REFERENCE); @@ -78,7 +78,7 @@ public void beforeComponent() } @Test - public void resolveDocumentReferenceWhenMissingParents() + void resolveDocumentReferenceWhenMissingParents() { EntityReference partialReference = new EntityReference("document", EntityType.DOCUMENT); @@ -89,10 +89,29 @@ public void resolveDocumentReferenceWhenMissingParents() assertEquals(EntityType.SPACE, reference.getParent().getType()); assertEquals(DEFAULT_WIKI, reference.getParent().getParent().getName()); assertEquals(EntityType.WIKI, reference.getParent().getParent().getType()); + + partialReference = new EntityReference("WebHome", EntityType.DOCUMENT); + reference = this.resolver.resolve(partialReference, EntityType.DOCUMENT); + + assertNotSame(partialReference, reference); + assertEquals(DEFAULT_SPACE, reference.getParent().getName()); + assertEquals(EntityType.SPACE, reference.getParent().getType()); + assertEquals(DEFAULT_WIKI, reference.getParent().getParent().getName()); + assertEquals(EntityType.WIKI, reference.getParent().getParent().getType()); + + EntityReference spaceReference = new EntityReference("Space", EntityType.SPACE); + partialReference = new EntityReference("WebHome", EntityType.DOCUMENT, spaceReference); + reference = this.resolver.resolve(partialReference, EntityType.DOCUMENT); + + assertNotSame(partialReference, reference); + assertEquals("Space", reference.getParent().getName()); + assertEquals(EntityType.SPACE, reference.getParent().getType()); + assertEquals(DEFAULT_WIKI, reference.getParent().getParent().getName()); + assertEquals(EntityType.WIKI, reference.getParent().getParent().getType()); } @Test - public void resolveAttachmentReferenceWhenMissingParents() + void resolveAttachmentReferenceWhenMissingParents() { EntityReference reference = this.resolver.resolve(new EntityReference("filename", EntityType.ATTACHMENT), EntityType.ATTACHMENT); @@ -106,7 +125,7 @@ public void resolveAttachmentReferenceWhenMissingParents() } @Test - public void resolveDocumentReferenceWhenMissingParentBetweenReferences() + void resolveDocumentReferenceWhenMissingParentBetweenReferences() { EntityReference partialReference = new EntityReference("document", EntityType.DOCUMENT, new EntityReference("wiki", EntityType.WIKI)); @@ -122,7 +141,7 @@ public void resolveDocumentReferenceWhenMissingParentBetweenReferences() } @Test - public void resolveAttachmentReferenceWhenMissingParentBetweenReferences() + void resolveAttachmentReferenceWhenMissingParentBetweenReferences() { EntityReference reference = this.resolver.resolve( new EntityReference("filename", EntityType.ATTACHMENT, new EntityReference("wiki", EntityType.WIKI)), @@ -137,7 +156,7 @@ public void resolveAttachmentReferenceWhenMissingParentBetweenReferences() } @Test - public void resolveDocumentReferenceWhenInvalidReference() + void resolveDocumentReferenceWhenInvalidReference() { try { this.resolver.resolve(new EntityReference("document", EntityType.DOCUMENT, @@ -150,7 +169,7 @@ public void resolveDocumentReferenceWhenInvalidReference() } @Test - public void resolveDocumentReferenceWhenTypeIsSpace() + void resolveDocumentReferenceWhenTypeIsSpace() { EntityReference reference = this.resolver.resolve(new EntityReference("space", EntityType.SPACE), EntityType.DOCUMENT); @@ -164,7 +183,7 @@ public void resolveDocumentReferenceWhenTypeIsSpace() } @Test - public void resolveSpaceReferenceWhenTypeIsDocument() + void resolveSpaceReferenceWhenTypeIsDocument() { EntityReference reference = this.resolver.resolve(new EntityReference("document", EntityType.DOCUMENT), EntityType.SPACE); @@ -179,7 +198,7 @@ public void resolveSpaceReferenceWhenTypeIsDocument() * Tests that a relative object reference is resolved correctly and completed with the default document parent. */ @Test - public void resolveObjectReferenceWhenMissingParents() + void resolveObjectReferenceWhenMissingParents() { EntityReference reference = resolver.resolve(new EntityReference("object", EntityType.OBJECT), EntityType.OBJECT); @@ -197,7 +216,7 @@ public void resolveObjectReferenceWhenMissingParents() * Tests that a relative object property is resolved correctly and completed with the default object parent. */ @Test - public void resolveObjectPropertyReferenceWhenMissingParents() + void resolveObjectPropertyReferenceWhenMissingParents() { EntityReference reference = resolver.resolve(new EntityReference("property", EntityType.OBJECT_PROPERTY), EntityType.OBJECT_PROPERTY); @@ -218,7 +237,7 @@ public void resolveObjectPropertyReferenceWhenMissingParents() * values for object name. */ @Test - public void resolveObjectReferenceWhenTypeIsDocument() + void resolveObjectReferenceWhenTypeIsDocument() { EntityReference reference = resolver.resolve( new EntityReference("document", EntityType.DOCUMENT, @@ -239,7 +258,7 @@ public void resolveObjectReferenceWhenTypeIsDocument() * values for object and property name. */ @Test - public void resolveObjectPropertyReferenceWhenTypeIsDocument() + void resolveObjectPropertyReferenceWhenTypeIsDocument() { EntityReference reference = resolver.resolve( new EntityReference("document", EntityType.DOCUMENT, @@ -258,7 +277,7 @@ public void resolveObjectPropertyReferenceWhenTypeIsDocument() } @Test - public void resolveDocumentReferenceWhenNullReference() + void resolveDocumentReferenceWhenNullReference() { EntityReference reference = this.resolver.resolve(null, EntityType.DOCUMENT); @@ -271,7 +290,7 @@ public void resolveDocumentReferenceWhenNullReference() } @Test - public void resolvePageReferenceWhenTypeIsDocument() + void resolvePageReferenceWhenTypeIsDocument() { EntityReference reference = this.resolver.resolve(new EntityReference("document", EntityType.DOCUMENT), EntityType.PAGE); @@ -284,7 +303,7 @@ public void resolvePageReferenceWhenTypeIsDocument() } @Test - public void resolvePageReferenceWhenTypeIsSpace() + void resolvePageReferenceWhenTypeIsSpace() { EntityReference reference = this.resolver.resolve(new EntityReference("space", EntityType.SPACE), EntityType.PAGE); @@ -293,7 +312,7 @@ public void resolvePageReferenceWhenTypeIsSpace() } @Test - public void resolveDocumentReferenceWhenTypeIsPage() + void resolveDocumentReferenceWhenTypeIsPage() { EntityReference reference = this.resolver.resolve(new EntityReference("page", EntityType.PAGE), EntityType.DOCUMENT); @@ -303,12 +322,14 @@ public void resolveDocumentReferenceWhenTypeIsPage() reference = this.resolver.resolve( new EntityReference("page1", EntityType.PAGE, new EntityReference("page2", EntityType.PAGE)), EntityType.DOCUMENT); - + + // FIXME: there should be a check if the page exists or not. + // See https://jira.xwiki.org/browse/XWIKI-22699 assertEquals(new DocumentReference(DEFAULT_WIKI, List.of("page2", "page1"), DEFAULT_DOCUMENT), reference); } @Test - public void resolveSpaceReferenceWhenTypeIsPage() + void resolveSpaceReferenceWhenTypeIsPage() { EntityReference reference = this.resolver.resolve(new EntityReference("page", EntityType.PAGE), EntityType.SPACE); 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 98b326229b9c..56fc503fd21d 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 @@ 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-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..21b9995a89db --- /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,94 @@ +/* + * 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 + * @since 16.10.2 + */ +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 + 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 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..af20ffd9a64f --- /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,100 @@ +/* + * 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 + * @since 16.10.2 + */ +@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..ab8ad263357e --- /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,119 @@ +/* + * 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.Map; + +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 + * @since 16.10.2 + */ +@Component +@Named("relative/doc") +@Singleton +public class RelativeDocumentResourceReferenceEntityReferenceResolver + extends AbstractRelativeResourceReferenceEntityReferenceResolver +{ + @Inject + private DocumentReferenceResolver defaultStringDocumentReferenceResolver; + + @Inject + private DocumentReferenceResolver documentReferenceResolver; + + /** + * 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); + + DocumentReference reference; + if (relativeReference != null && (relativeReference.extractReference(EntityType.SPACE) == null + || relativeReference.extractReference(EntityType.WIKI) == null)) { + return setDefaultDocument(relativeReference); + } else { + // Resolve the full document reference + // We don't start from the previously parsed relative reference to not loose "." prefixed reference meaning + reference = + this.defaultStringDocumentReferenceResolver.resolve(resourceReference.getReference(), baseReference); + // Take care of fallback if needed + return resolveDocumentReference(relativeReference, reference, baseReference); + } + } + + private EntityReference setDefaultDocument(EntityReference relativeReference) + { + String defaultDocumentName = + this.defaultReferenceProvider.getDefaultReference(EntityType.DOCUMENT).getName(); + + EntityReference result; + if (!defaultDocumentName.equals(relativeReference.getName())) { + EntityReference parentSpace = new EntityReference(relativeReference.getName(), EntityType.SPACE, + relativeReference.getParent()); + result = new EntityReference(defaultDocumentName, EntityType.DOCUMENT, parentSpace); + } else { + result = relativeReference; + } + + EntityReference oldSpaceReference = result.extractFirstReference(EntityType.SPACE); + if (oldSpaceReference != null) { + EntityReference newSpaceReference = new EntityReference(oldSpaceReference, + Map.of(EntityReference.PARENT_TYPE_PARAMETER, EntityType.SPACE)); + result = result.replaceParent(oldSpaceReference, newSpaceReference); + } + 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..c1f63681628e --- /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 17.0.0RC1 + * @since 16.10.2 + */ +@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..7756ff310e3a --- /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,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 page resource reference into entity reference. + * + * @version $Id$ + * @since 17.0.0RC1 + * @since 16.10.2 + */ +@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..56abd87909bb --- /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,92 @@ +/* + * 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 + * @since 16.10.2 + */ +@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..f74659630214 --- /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,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 space resource reference into entity reference. + * + * @version $Id$ + * @since 17.0.0RC1 + * @since 16.10.2 + */ +@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 29c5e578334f..f1c8eb030472 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; @@ -41,6 +38,7 @@ 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.DefaultStringPageReferenceResolver; import org.xwiki.model.internal.reference.DefaultStringSpaceReferenceResolver; import org.xwiki.model.internal.reference.DefaultSymbolScheme; import org.xwiki.model.internal.reference.RelativeStringEntityReferenceResolver; @@ -49,19 +47,23 @@ import org.xwiki.model.reference.EntityReference; import org.xwiki.model.reference.EntityReferenceProvider; import org.xwiki.model.reference.EntityReferenceResolver; +import org.xwiki.model.reference.PageReference; import org.xwiki.model.reference.SpaceReference; import org.xwiki.rendering.listener.reference.AttachmentResourceReference; import org.xwiki.rendering.listener.reference.DocumentResourceReference; +import org.xwiki.rendering.listener.reference.PageResourceReference; 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.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; @@ -86,10 +88,13 @@ DefaultReferenceDocumentReferenceResolver.class, DefaultStringSpaceReferenceResolver.class, ContextComponentManagerProvider.class, - DefaultSymbolScheme.class + DefaultSymbolScheme.class, + PageResourceReferenceEntityReferenceResolver.class, + DefaultStringPageReferenceResolver.class }) +@ComponentTest // @formatter:on -public class DefaultResourceReferenceEntityReferenceResolverTest +class DefaultResourceReferenceEntityReferenceResolverTest { private static final String DEFAULT_PAGE = "defaultpage"; @@ -109,46 +114,34 @@ public class DefaultResourceReferenceEntityReferenceResolverTest private static final String ATTACHMENT = "file.ext"; - private static final DocumentReference CURRENT_DOCUMENT_REFERENCE = - new DocumentReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE); - - @Rule - public MockitoComponentMockingRule> mocker = - new MockitoComponentMockingRule>( - DefaultResourceReferenceEntityReferenceResolver.class); + @InjectMockComponents + private DefaultResourceReferenceEntityReferenceResolver 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<>(); - @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)); } @@ -156,52 +149,53 @@ public Boolean answer(InvocationOnMock invocation) throws Throwable 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; } + + private PageResourceReference pageResource(String referenceString, boolean typed) + { + PageResourceReference pageReference = new PageResourceReference(referenceString); + pageReference.setTyped(typed); + return pageReference; + } // 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,102 +203,102 @@ 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 reference cannot be parsed by the relative resolver assertEquals( new DocumentReference(CURRENT_WIKI, - Arrays.asList(CURRENT_SPACE, CURRENT_SPACE, CURRENT_SPACE, CURRENT_PAGE), DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource("...", false), null)); + List.of(CURRENT_SPACE, CURRENT_SPACE, CURRENT_SPACE, CURRENT_PAGE), DEFAULT_PAGE), + this.resolver.resolve(documentResource("...", 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), - DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource(PAGE, false), null)); + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, CURRENT_SUBSPACE, 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, CURRENT_SUBSPACE, PAGE), - DEFAULT_PAGE), - this.mocker.getComponentUnderTest().resolve(documentResource('.' + PAGE, false), null)); + assertEquals(new DocumentReference(CURRENT_WIKI, List.of(CURRENT_SPACE, CURRENT_SUBSPACE, PAGE), + DEFAULT_PAGE), + 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 @@ -312,32 +306,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)); @@ -345,58 +339,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 @@ -414,7 +408,7 @@ protected EntityReference resolveTyped(ResourceReference resourceReference, Enti } @Test - public void trySpaceSiblingFallback() + void trySpaceSiblingFallback() { VoidResourceReferenceEntityReferenceResolve resolver = new VoidResourceReferenceEntityReferenceResolve(); @@ -437,4 +431,31 @@ public void trySpaceSiblingFallback() assertFalse(resolver.trySpaceSiblingFallback(sourceReference, finalReference, baseReference, defaultDocumentName)); } + + @Test + void resolveTypedPage() + { + assertEquals(new PageReference(WIKI, SPACE, PAGE), + this.resolver.resolve(pageResource(WIKI + ':' + SPACE + '/' + PAGE, true), null)); + + assertEquals(new PageReference(WIKI, SPACE), + this.resolver.resolve(pageResource(WIKI + ':' + SPACE, true), null)); + + assertEquals(new PageReference(CURRENT_WIKI, SPACE), + this.resolver.resolve(pageResource(SPACE, true), null)); + + assertEquals(new PageReference(CURRENT_WIKI, CURRENT_SPACE, CURRENT_PAGE), + this.resolver.resolve(pageResource("", true), null)); + + assertEquals(new PageReference(WIKI, SPACE, PAGE), + this.resolver.resolve(pageResource("", true), null, new DocumentReference(WIKI, SPACE, PAGE))); + + assertEquals(new DocumentReference(WIKI, List.of(SPACE, PAGE), DEFAULT_PAGE), + this.resolver.resolve(pageResource(WIKI + ':' + SPACE + '/' + PAGE, true), EntityType.DOCUMENT)); + + // FIXME: See https://jira.xwiki.org/browse/XWIKI-22699 + //this.existingDocuments.add(new DocumentReference(WIKI, SPACE, PAGE)); + //assertEquals(new DocumentReference(WIKI, SPACE, PAGE), + // this.resolver.resolve(pageResource(WIKI + ':' + SPACE + '/' + PAGE, true), EntityType.DOCUMENT)); + } } 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..2f9b7f5bdcb6 --- /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,423 @@ +/* + * 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.io.Serializable; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +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.DefaultModelConfiguration; +import org.xwiki.model.internal.reference.DefaultEntityReferenceProvider; +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.EntityReferenceResolver; +import org.xwiki.model.reference.PageAttachmentReference; +import org.xwiki.model.reference.PageReference; +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.PageAttachmentResourceReference; +import org.xwiki.rendering.listener.reference.PageResourceReference; +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, + RelativePageResourceReferenceEntityReferenceResolver.class, + RelativePageAttachmentResourceReferenceEntityReferenceResolver.class, + DefaultReferenceEntityReferenceResolver.class, + DefaultStringEntityReferenceResolver.class, + RelativeStringEntityReferenceResolver.class, + DefaultReferenceAttachmentReferenceResolver.class, + DefaultReferenceDocumentReferenceResolver.class, + DefaultStringSpaceReferenceResolver.class, + ContextComponentManagerProvider.class, + DefaultSymbolScheme.class, + DefaultEntityReferenceProvider.class, + DefaultModelConfiguration.class +}) +@ComponentTest +// @formatter:on +class RelativeResourceReferenceEntityReferenceResolverTest +{ + private static final String DEFAULT_PAGE = "WebHome"; + + 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 Map PARENT_TYPE_PARAMETER_MAP = + Map.of(EntityReference.PARENT_TYPE_PARAMETER, EntityType.SPACE); + private static final SpaceReference BASE_REFERENCE = new SpaceReference(WIKI, SPACE); + private static final EntityReference SPACE_ENTITY_REFERENCE_SPACE_PARENT_TYPE = + new EntityReference(SPACE, EntityType.SPACE, PARENT_TYPE_PARAMETER_MAP); + 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_SPACE_ENTITY_REFERENCE = + new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT, SPACE_ENTITY_REFERENCE_SPACE_PARENT_TYPE); + + + @InjectMockComponents + private RelativeResourceReferenceEntityReferenceResolver resolver; + + @MockComponent + @Named("current") + private EntityReferenceResolver currentEntityReferenceResolver; + + @MockComponent + @Named("current") + private Provider currentDocumentProvider; + + @MockComponent + private DocumentAccessBridge bridge; + + private final Set existingDocuments = new HashSet<>(); + + @BeforeEach + void before() throws Exception + { + when(this.bridge.exists(any(DocumentReference.class))).then( + (Answer) invocation -> existingDocuments.contains(invocation.getArguments()[0])); + } + + 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; + } + + private PageResourceReference pageResource(String referenceString, boolean typed) + { + PageResourceReference reference = new PageResourceReference(referenceString); + reference.setTyped(typed); + return reference; + } + + private PageAttachmentResourceReference pageAttachmentResource(String referenceString, boolean typed) + { + PageAttachmentResourceReference reference = new PageAttachmentResourceReference(referenceString); + reference.setTyped(typed); + return reference; + } + + @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)); + + assertEquals(new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT, + new EntityReference(PAGE, EntityType.SPACE, SPACE_ENTITY_REFERENCE_SPACE_PARENT_TYPE)), + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); + assertEquals(new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT, + new EntityReference(PAGE, EntityType.SPACE, PARENT_TYPE_PARAMETER_MAP)), + 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_SPACE_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(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)); + assertEquals(new DocumentReference("xwiki", List.of("Main", "Main", "Main"), DEFAULT_PAGE), + this.resolver.resolve(documentResource("...", false), null)); + } + + @Test + void resolveUntypeDocumentWhenCurrentPageIsSpace() + { + assertEquals(new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT, + new EntityReference(PAGE, EntityType.SPACE, SPACE_ENTITY_REFERENCE_SPACE_PARENT_TYPE)), + this.resolver.resolve(documentResource(SPACE + '.' + PAGE, false), null)); + assertEquals(new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT, + new EntityReference(PAGE, EntityType.SPACE, PARENT_TYPE_PARAMETER_MAP)), + this.resolver.resolve(documentResource(PAGE, false), null)); + + assertEquals(new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT, + new EntityReference(PAGE, EntityType.SPACE, PARENT_TYPE_PARAMETER_MAP)), + this.resolver.resolve(documentResource('.' + PAGE, false), null)); + + assertEquals(new EntityReference(DEFAULT_PAGE, EntityType.DOCUMENT, + new EntityReference(PAGE, EntityType.SPACE, PARENT_TYPE_PARAMETER_MAP)), + 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)); + } + + @Test + void resolveTypePage() + { + assertEquals(new EntityReference("page2", EntityType.PAGE, new EntityReference(SPACE, EntityType.PAGE)), + this.resolver.resolve(pageResource("Space/page2", false), null)); + + assertEquals(new PageReference(WIKI, SPACE, "page2"), + this.resolver.resolve(pageResource("Space/page2", false), null, new WikiReference(WIKI))); + + assertEquals(new EntityReference("page2", EntityType.PAGE, new EntityReference(SPACE, EntityType.PAGE)), + this.resolver.resolve(pageResource("Space/page2", true), null)); + + assertEquals(new PageReference(WIKI, SPACE, "page2"), + this.resolver.resolve(pageResource("Space/page2", true), null, new WikiReference(WIKI))); + + PageResourceReference pageResourceReference = pageResource("Space/page2", false); + pageResourceReference.addBaseReference("Wiki:space1.doc1"); + + assertEquals(new PageReference(WIKI, SPACE, "page2"), + this.resolver.resolve(pageResourceReference, null)); + } + + @Test + void resolveTypePageAttachment() + { + EntityReference relativeEntityReference = + new EntityReference("page2", EntityType.PAGE, new EntityReference(SPACE, EntityType.PAGE)); + assertEquals(new EntityReference("file.ext", EntityType.PAGE_ATTACHMENT, relativeEntityReference), + this.resolver.resolve(pageAttachmentResource("Space/page2/file.ext", false), null)); + + PageReference pageReference = new PageReference(WIKI, SPACE, "page2"); + assertEquals(new PageAttachmentReference("file.ext", pageReference), + this.resolver.resolve(pageAttachmentResource("Space/page2/file.ext", false), null, + new WikiReference(WIKI))); + + assertEquals(new EntityReference("file.ext", EntityType.PAGE_ATTACHMENT, relativeEntityReference), + this.resolver.resolve(pageAttachmentResource("Space/page2/file.ext", true), null)); + + assertEquals(new PageAttachmentReference("file.ext", pageReference), + this.resolver.resolve(pageAttachmentResource("Space/page2/file.ext", true), null, new WikiReference(WIKI))); + + PageAttachmentResourceReference pageAttachmentResourceReference = + pageAttachmentResource("Space/page2/file.ext", false); + pageAttachmentResourceReference.addBaseReference("Wiki:space1.doc1"); + + assertEquals(new PageAttachmentReference("file.ext", pageReference), + this.resolver.resolve(pageAttachmentResourceReference, null)); + } +}