From bb9b32cbd985788672db68e41b415eb1728546d9 Mon Sep 17 00:00:00 2001 From: Simon Urli Date: Fri, 22 Nov 2024 11:24:53 +0100 Subject: [PATCH] XWIKI-22681: Provide a relative ResourceReferenceEntityReferenceResolver --- ...tiveStringEntityReferenceResolverTest.java | 15 + .../model/reference/WikiReferenceTest.java | 8 + ...ourceReferenceEntityReferenceResolver.java | 124 ++++++ ...ourceReferenceEntityReferenceResolver.java | 99 +++++ ...ourceReferenceEntityReferenceResolver.java | 90 ++++ ...ourceReferenceEntityReferenceResolver.java | 55 +++ ...ourceReferenceEntityReferenceResolver.java | 54 +++ ...ourceReferenceEntityReferenceResolver.java | 91 ++++ ...ourceReferenceEntityReferenceResolver.java | 54 +++ .../main/resources/META-INF/components.txt | 6 + ...eReferenceEntityReferenceResolverTest.java | 206 +++++---- ...eReferenceEntityReferenceResolverTest.java | 408 ++++++++++++++++++ 12 files changed, 1101 insertions(+), 109 deletions(-) create mode 100644 xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/AbstractRelativeResourceReferenceEntityReferenceResolver.java create mode 100644 xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeAttachmentResourceReferenceEntityReferenceResolver.java create mode 100644 xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeDocumentResourceReferenceEntityReferenceResolver.java create mode 100644 xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageAttachmentResourceReferenceEntityReferenceResolver.java create mode 100644 xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageResourceReferenceEntityReferenceResolver.java create mode 100644 xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeResourceReferenceEntityReferenceResolver.java create mode 100644 xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeSpaceResourceReferenceEntityReferenceResolver.java create mode 100644 xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/test/java/org/xwiki/rendering/internal/resolver/RelativeResourceReferenceEntityReferenceResolverTest.java diff --git a/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/RelativeStringEntityReferenceResolverTest.java b/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/RelativeStringEntityReferenceResolverTest.java index 92c918597397..f6a24f1e67cf 100644 --- a/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/RelativeStringEntityReferenceResolverTest.java +++ b/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/RelativeStringEntityReferenceResolverTest.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test; import org.xwiki.model.EntityType; import org.xwiki.model.reference.EntityReference; +import org.xwiki.model.reference.WikiReference; import org.xwiki.test.annotation.ComponentList; import org.xwiki.test.junit5.mockito.ComponentTest; import org.xwiki.test.junit5.mockito.InjectMockComponents; @@ -70,5 +71,19 @@ public void resolveDocumentReferenceWithBaseReference() assertNull(reference.extractReference(EntityType.WIKI)); assertEquals("space", reference.extractReference(EntityType.SPACE).getName()); assertNull(reference.extractReference(EntityType.DOCUMENT)); + + reference = + this.resolver.resolve("", EntityType.DOCUMENT, new EntityReference("wikiFoo", EntityType.WIKI)); + + assertEquals("wikiFoo", reference.extractReference(EntityType.WIKI).getName()); + assertNull(reference.extractReference(EntityType.SPACE)); + assertNull(reference.extractReference(EntityType.DOCUMENT)); + + reference = + this.resolver.resolve("", EntityType.DOCUMENT, new WikiReference("wikiFoo")); + + assertEquals("wikiFoo", reference.extractReference(EntityType.WIKI).getName()); + assertNull(reference.extractReference(EntityType.SPACE)); + assertNull(reference.extractReference(EntityType.DOCUMENT)); } } diff --git a/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/reference/WikiReferenceTest.java b/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/reference/WikiReferenceTest.java index 343679e21f66..6f0ee7e0aff7 100644 --- a/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/reference/WikiReferenceTest.java +++ b/xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/reference/WikiReferenceTest.java @@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Unit tests for {@link WikiReference}. @@ -49,4 +50,11 @@ public void testInvalidParent() () -> new WikiReference(new EntityReference("wiki", EntityType.WIKI, badParent))); assertEquals("Unexpected parent [" + badParent + "] in a wiki reference", expected.getMessage()); } + + @Test + void instanceOf() + { + assertTrue(new WikiReference("foo") instanceof WikiReference); + assertTrue(new WikiReference("foo") instanceof EntityReference); + } } diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/AbstractRelativeResourceReferenceEntityReferenceResolver.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/AbstractRelativeResourceReferenceEntityReferenceResolver.java 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 29c5e578334f..ef7272e50ada 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,44 +197,44 @@ 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 @@ -258,53 +246,53 @@ public void resolveUntypeDocument() throws ComponentLookupException // 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 @@ -312,32 +300,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 +333,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 +402,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)); + } +}