Skip to content

Commit 6edf7c1

Browse files
committed
XWIKI-22571: Backlinks update changes an absolute reference to the moved page into one relative to the current wiki
* Provide implementations for relative ResourceReferenceEntityReference resolvers and tests
1 parent f3c97a6 commit 6edf7c1

File tree

10 files changed

+700
-120
lines changed

10 files changed

+700
-120
lines changed

xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/internal/reference/RelativeStringEntityReferenceResolverTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.junit.jupiter.api.Test;
2323
import org.xwiki.model.EntityType;
2424
import org.xwiki.model.reference.EntityReference;
25+
import org.xwiki.model.reference.WikiReference;
2526
import org.xwiki.test.annotation.ComponentList;
2627
import org.xwiki.test.junit5.mockito.ComponentTest;
2728
import org.xwiki.test.junit5.mockito.InjectMockComponents;
@@ -70,5 +71,19 @@ public void resolveDocumentReferenceWithBaseReference()
7071
assertNull(reference.extractReference(EntityType.WIKI));
7172
assertEquals("space", reference.extractReference(EntityType.SPACE).getName());
7273
assertNull(reference.extractReference(EntityType.DOCUMENT));
74+
75+
reference =
76+
this.resolver.resolve("", EntityType.DOCUMENT, new EntityReference("wikiFoo", EntityType.WIKI));
77+
78+
assertEquals("wikiFoo", reference.extractReference(EntityType.WIKI).getName());
79+
assertNull(reference.extractReference(EntityType.SPACE));
80+
assertNull(reference.extractReference(EntityType.DOCUMENT));
81+
82+
reference =
83+
this.resolver.resolve("", EntityType.DOCUMENT, new WikiReference("wikiFoo"));
84+
85+
assertEquals("wikiFoo", reference.extractReference(EntityType.WIKI).getName());
86+
assertNull(reference.extractReference(EntityType.SPACE));
87+
assertNull(reference.extractReference(EntityType.DOCUMENT));
7388
}
7489
}

xwiki-platform-core/xwiki-platform-model/xwiki-platform-model-api/src/test/java/org/xwiki/model/reference/WikiReferenceTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import static org.junit.jupiter.api.Assertions.assertEquals;
2626
import static org.junit.jupiter.api.Assertions.assertThrows;
27+
import static org.junit.jupiter.api.Assertions.assertTrue;
2728

2829
/**
2930
* Unit tests for {@link WikiReference}.
@@ -49,4 +50,11 @@ public void testInvalidParent()
4950
() -> new WikiReference(new EntityReference("wiki", EntityType.WIKI, badParent)));
5051
assertEquals("Unexpected parent [" + badParent + "] in a wiki reference", expected.getMessage());
5152
}
53+
54+
@Test
55+
void instanceOf()
56+
{
57+
assertTrue(new WikiReference("foo") instanceof WikiReference);
58+
assertTrue(new WikiReference("foo") instanceof EntityReference);
59+
}
5260
}

xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/AbstractRelativeResourceReferenceEntityReferenceResolver.java

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
*/
2020
package org.xwiki.rendering.internal.resolver;
2121

22+
import java.util.List;
23+
2224
import javax.inject.Inject;
2325
import javax.inject.Named;
2426

@@ -29,7 +31,7 @@
2931
import org.xwiki.rendering.listener.reference.ResourceType;
3032

3133
/**
32-
* Convert document resource reference into entity reference.
34+
* Abstract class for all relative resource reference resolvers.
3335
*
3436
* @version $Id$
3537
* @since 17.0.0RC1
@@ -39,21 +41,84 @@ public abstract class AbstractRelativeResourceReferenceEntityReferenceResolver
3941
{
4042
@Inject
4143
@Named("relative")
42-
private EntityReferenceResolver<String> relativeReferenceResolver;
44+
protected EntityReferenceResolver<String> relativeReferenceResolver;
4345

4446
/**
45-
* Default constructor.
47+
* @param type the resource type that this resolver will support
4648
*/
47-
public AbstractRelativeResourceReferenceEntityReferenceResolver(ResourceType type)
49+
protected AbstractRelativeResourceReferenceEntityReferenceResolver(ResourceType type)
4850
{
4951
super(type);
5052
}
5153

54+
@Override
55+
public EntityReference resolve(ResourceReference resourceReference, EntityType entityType, Object... parameters)
56+
{
57+
if (resourceReference == null) {
58+
return null;
59+
}
60+
61+
if (this.resourceType != null && !resourceReference.getType().equals(this.resourceType)) {
62+
throw new IllegalArgumentException(
63+
String.format("You must pass a resource reference of type [%s]. [%s] was passed", this.resourceType,
64+
resourceReference));
65+
}
66+
67+
EntityReference entityReference;
68+
EntityReference baseReference = getBaseReference(resourceReference, parameters);
69+
70+
if (resourceReference.isTyped()) {
71+
entityReference = resolveTyped(resourceReference, baseReference);
72+
} else {
73+
entityReference = resolveUntyped(resourceReference, baseReference);
74+
}
75+
76+
return entityReference;
77+
}
78+
79+
@Override
80+
protected EntityReference getBaseReference(ResourceReference resourceReference, Object... parameters)
81+
{
82+
EntityReference baseReference =
83+
(parameters.length > 0 && parameters[0] instanceof EntityReference entityReference)
84+
? entityReference : null;
85+
86+
if (!resourceReference.getBaseReferences().isEmpty()) {
87+
// If the passed reference has a base reference, resolve it first with a relative resolver (it should
88+
// normally be absolute but who knows what the API caller has specified...)
89+
baseReference = resolveBaseReference(resourceReference.getBaseReferences(), baseReference);
90+
}
91+
92+
return baseReference;
93+
}
94+
95+
@Override
96+
protected EntityReference resolveBaseReference(List<String> baseReferences, EntityReference defaultBaseReference)
97+
{
98+
EntityReference resolvedBaseReference = defaultBaseReference;
99+
for (String baseReference : baseReferences) {
100+
resolvedBaseReference =
101+
this.relativeReferenceResolver.resolve(baseReference, EntityType.DOCUMENT, resolvedBaseReference);
102+
}
103+
104+
return resolvedBaseReference;
105+
}
106+
107+
@Override
108+
protected EntityReference resolveUntyped(ResourceReference resourceReference, EntityReference baseReference)
109+
{
110+
return resolveTyped(resourceReference, baseReference);
111+
}
112+
52113
@Override
53114
protected EntityReference resolveTyped(ResourceReference resourceReference, EntityReference baseReference)
54115
{
55-
return this.relativeReferenceResolver.resolve(resourceReference.getReference(), getEntityType());
116+
return this.relativeReferenceResolver.resolve(resourceReference.getReference(), getEntityType(), baseReference);
56117
}
57118

58-
public abstract EntityType getEntityType();
119+
/**
120+
*
121+
* @return the entity type of the {@link EntityReference} this resolver produces.
122+
*/
123+
protected abstract EntityType getEntityType();
59124
}

xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeAttachmentResourceReferenceEntityReferenceResolver.java

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,18 @@
1919
*/
2020
package org.xwiki.rendering.internal.resolver;
2121

22+
import javax.inject.Inject;
2223
import javax.inject.Named;
2324
import javax.inject.Singleton;
2425

26+
import org.apache.commons.lang3.StringUtils;
2527
import org.xwiki.component.annotation.Component;
2628
import org.xwiki.model.EntityType;
29+
import org.xwiki.model.reference.AttachmentReference;
30+
import org.xwiki.model.reference.AttachmentReferenceResolver;
31+
import org.xwiki.model.reference.DocumentReference;
32+
import org.xwiki.model.reference.EntityReference;
33+
import org.xwiki.rendering.listener.reference.ResourceReference;
2734
import org.xwiki.rendering.listener.reference.ResourceType;
2835

2936
/**
@@ -38,14 +45,55 @@
3845
public class RelativeAttachmentResourceReferenceEntityReferenceResolver
3946
extends AbstractRelativeResourceReferenceEntityReferenceResolver
4047
{
48+
@Inject
49+
private AttachmentReferenceResolver<EntityReference> defaultReferenceAttachmentReferenceResolver;
50+
51+
/**
52+
* Default constructor.
53+
*/
4154
public RelativeAttachmentResourceReferenceEntityReferenceResolver()
4255
{
4356
super(ResourceType.ATTACHMENT);
4457
}
4558

4659
@Override
47-
public EntityType getEntityType()
60+
protected EntityType getEntityType()
4861
{
4962
return EntityType.ATTACHMENT;
5063
}
64+
65+
@Override
66+
protected EntityReference resolveTyped(ResourceReference resourceReference, EntityReference baseReference)
67+
{
68+
if (StringUtils.isEmpty(resourceReference.getReference())) {
69+
return null;
70+
}
71+
72+
// Get relative reference
73+
EntityReference relativeReference =
74+
this.relativeReferenceResolver
75+
.resolve(resourceReference.getReference(), EntityType.ATTACHMENT, baseReference);
76+
77+
EntityReference result = relativeReference;
78+
if (relativeReference.extractReference(EntityType.WIKI) != null) {
79+
// Resolve full reference
80+
AttachmentReference attachmentReference =
81+
this.defaultReferenceAttachmentReferenceResolver.resolve(relativeReference, baseReference);
82+
83+
// See if the resolved (terminal or WebHome) document exists and, if so, use it.
84+
DocumentReference documentReference = attachmentReference.getDocumentReference();
85+
86+
// Take care of fallback if needed
87+
DocumentReference finalDocumentReference =
88+
resolveDocumentReference(relativeReference.getParent(), documentReference, baseReference);
89+
// Also use that resolution if the relative reference doesn't contain any document, even if it doesn't
90+
// exists, to not produce incorrect references.
91+
if (finalDocumentReference != documentReference
92+
|| relativeReference.extractReference(EntityType.DOCUMENT) == null) {
93+
result = new AttachmentReference(attachmentReference.getName(), finalDocumentReference);
94+
}
95+
}
96+
97+
return result;
98+
}
5199
}

xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeDocumentResourceReferenceEntityReferenceResolver.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,17 @@
1919
*/
2020
package org.xwiki.rendering.internal.resolver;
2121

22+
import javax.inject.Inject;
2223
import javax.inject.Named;
2324
import javax.inject.Singleton;
2425

26+
import org.apache.commons.lang3.StringUtils;
2527
import org.xwiki.component.annotation.Component;
2628
import org.xwiki.model.EntityType;
29+
import org.xwiki.model.reference.DocumentReference;
30+
import org.xwiki.model.reference.DocumentReferenceResolver;
31+
import org.xwiki.model.reference.EntityReference;
32+
import org.xwiki.rendering.listener.reference.ResourceReference;
2733
import org.xwiki.rendering.listener.reference.ResourceType;
2834

2935
/**
@@ -38,14 +44,47 @@
3844
public class RelativeDocumentResourceReferenceEntityReferenceResolver
3945
extends AbstractRelativeResourceReferenceEntityReferenceResolver
4046
{
47+
@Inject
48+
private DocumentReferenceResolver<String> defaultStringDocumentReferenceResolver;
49+
50+
/**
51+
* Default constructor.
52+
*/
4153
public RelativeDocumentResourceReferenceEntityReferenceResolver()
4254
{
4355
super(ResourceType.DOCUMENT);
4456
}
4557

4658
@Override
47-
public EntityType getEntityType()
59+
protected EntityType getEntityType()
4860
{
4961
return EntityType.DOCUMENT;
5062
}
63+
64+
@Override
65+
protected EntityReference resolveUntyped(ResourceReference resourceReference, EntityReference baseReference)
66+
{
67+
// If the reference is empty fallback on typed logic
68+
if (StringUtils.isEmpty(resourceReference.getReference())) {
69+
return resolveTyped(resourceReference, baseReference);
70+
}
71+
72+
// Get relative reference
73+
EntityReference relativeReference =
74+
this.relativeReferenceResolver.resolve(resourceReference.getReference(), EntityType.DOCUMENT,
75+
baseReference);
76+
77+
EntityReference result = relativeReference;
78+
if (relativeReference.extractReference(EntityType.WIKI) != null) {
79+
// Resolve the full document reference
80+
// We don't start from the previously parsed relative reference to not loose "." prefixed reference meaning
81+
DocumentReference reference =
82+
this.defaultStringDocumentReferenceResolver.resolve(resourceReference.getReference(), baseReference);
83+
84+
// Take care of fallback if needed
85+
result = resolveDocumentReference(relativeReference, reference, baseReference);
86+
}
87+
88+
return result;
89+
}
5190
}

xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageAttachmentResourceReferenceEntityReferenceResolver.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,16 @@
3939
public class RelativePageAttachmentResourceReferenceEntityReferenceResolver
4040
extends AbstractRelativeResourceReferenceEntityReferenceResolver
4141
{
42+
/**
43+
* Default constructor.
44+
*/
4245
public RelativePageAttachmentResourceReferenceEntityReferenceResolver()
4346
{
4447
super(ResourceType.PAGE_ATTACHMENT);
4548
}
4649

4750
@Override
48-
public EntityType getEntityType()
51+
protected EntityType getEntityType()
4952
{
5053
return EntityType.PAGE_ATTACHMENT;
5154
}

xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativePageResourceReferenceEntityReferenceResolver.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,16 @@
3838
public class RelativePageResourceReferenceEntityReferenceResolver
3939
extends AbstractRelativeResourceReferenceEntityReferenceResolver
4040
{
41+
/**
42+
* Default constructor.
43+
*/
4144
public RelativePageResourceReferenceEntityReferenceResolver()
4245
{
4346
super(ResourceType.PAGE);
4447
}
4548

4649
@Override
47-
public EntityType getEntityType()
50+
protected EntityType getEntityType()
4851
{
4952
return EntityType.PAGE;
5053
}

xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/internal/resolver/RelativeSpaceResourceReferenceEntityReferenceResolver.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,16 @@
3838
public class RelativeSpaceResourceReferenceEntityReferenceResolver
3939
extends AbstractRelativeResourceReferenceEntityReferenceResolver
4040
{
41+
/**
42+
* Default constructor.
43+
*/
4144
public RelativeSpaceResourceReferenceEntityReferenceResolver()
4245
{
4346
super(ResourceType.SPACE);
4447
}
4548

4649
@Override
47-
public EntityType getEntityType()
50+
protected EntityType getEntityType()
4851
{
4952
return EntityType.SPACE;
5053
}

0 commit comments

Comments
 (0)