From b67c19779c5b8b09df1f30b7c013e5663c5585e5 Mon Sep 17 00:00:00 2001 From: Simon Urli Date: Wed, 6 Nov 2024 14:54:18 +0100 Subject: [PATCH] XWIKI-12987: Relative links are made absolute or even broken after moving a page * Change APIs to use a Map corresponding to the source and target of refactorings in renamers * Change some logic of AbstractCopyOrMoveJob to compute the actual couple source/destination before performing any operation and store the info in EntitySelection * Add a log in RenameJob if it's not executed because of the number of entities (not needed for this issue, but felt better to understand what's happening) --- .../src/main/java/com/xpn/xwiki/XWiki.java | 3 +- .../internal/render/DefaultOldRendering.java | 4 +- .../test/java/com/xpn/xwiki/XWikiTest.java | 10 +- .../xwiki/refactoring/ReferenceRenamer.java | 17 +- .../internal/ReferenceUpdater.java | 7 +- .../internal/job/AbstractCopyOrMoveJob.java | 164 +++++++++++++----- .../job/AbstractEntityJobWithChecks.java | 24 +-- .../job/InternalCopyOrMoveJobException.java | 38 ++++ .../refactoring/internal/job/RenameJob.java | 2 + .../listener/BackLinkUpdaterListener.java | 14 +- .../job/question/EntitySelection.java | 63 ++++++- .../refactoring/internal/job/MoveJobTest.java | 23 ++- .../internal/job/RenameJobTest.java | 7 + .../listener/BackLinkUpdaterListenerTest.java | 21 +-- .../internal/DefaultMacroRefactoring.java | 14 +- .../internal/DefaultReferenceRenamer.java | 18 +- .../internal/DefaultReferenceUpdater.java | 19 +- .../internal/ResourceReferenceRenamer.java | 42 +++-- .../internal/DefaultMacroRefactoringTest.java | 13 +- .../internal/DefaultReferenceUpdaterTest.java | 9 +- .../ResourceReferenceRenamerTest.java | 6 +- .../include/IncludeMacroRefactoring.java | 16 +- .../include/IncludeMacroRefactoringTest.java | 23 +-- .../rendering/macro/MacroRefactoring.java | 14 +- 24 files changed, 383 insertions(+), 188 deletions(-) create mode 100644 xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/InternalCopyOrMoveJobException.java diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java index f2099f7dbe47..0023a55697f1 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java @@ -4974,7 +4974,8 @@ private void updateLinksForRename(XWikiDocument sourceDoc, DocumentReference new JobContext jobContext = Utils.getComponent(JobContext.class); Job currentJob = jobContext.getCurrentJob(); - Set updatedReferences = Set.of(); + Map updatedReferences = + Map.of(sourceDoc.getDocumentReference(), newDocumentReference); if (currentJob instanceof AbstractCopyOrMoveJob) { updatedReferences = ((AbstractCopyOrMoveJob) currentJob).getSelectedEntities(); } diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/render/DefaultOldRendering.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/render/DefaultOldRendering.java index bc0d1f0d81ac..eaf71afdfade 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/render/DefaultOldRendering.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/render/DefaultOldRendering.java @@ -20,6 +20,7 @@ package com.xpn.xwiki.internal.render; import java.io.StringWriter; +import java.util.Map; import java.util.Set; import javax.inject.Inject; @@ -117,7 +118,8 @@ private void refactorDocumentLinks(XWikiDocument document, DocumentReference old DocumentReference newDocumentReference, XWikiContext context) throws XWikiException { this.referenceRenamer.renameReferences(document.getXDOM(), document.getDocumentReference(), - oldDocumentReference, newDocumentReference, false, Set.of()); + oldDocumentReference, newDocumentReference, false, + Map.of(oldDocumentReference, newDocumentReference)); } @Override diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/XWikiTest.java b/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/XWikiTest.java index 4001bb8fb359..e4200bbe2d43 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/XWikiTest.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/test/java/com/xpn/xwiki/XWikiTest.java @@ -29,7 +29,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Set; import javax.inject.Provider; import javax.servlet.http.Cookie; @@ -1094,13 +1093,14 @@ void atomicRename() throws Exception new DocumentReference(targetReference, Locale.GERMAN), xWikiContext); // Test links - verify(this.referenceUpdater).update(targetReference, sourceReference, targetReference, Set.of()); + verify(this.referenceUpdater).update(targetReference, sourceReference, targetReference, + Map.of(sourceReference, targetReference)); verify(this.referenceRenamer).renameReferences(doc1.getXDOM(), reference1, sourceReference, - targetReference, false, Set.of()); + targetReference, false, Map.of(sourceReference, targetReference)); verify(this.referenceRenamer).renameReferences(doc2.getXDOM(), reference2, sourceReference, - targetReference, false, Set.of()); + targetReference, false, Map.of(sourceReference, targetReference)); verify(this.referenceRenamer).renameReferences(doc3.getXDOM(), reference3, sourceReference, - targetReference, false, Set.of()); + targetReference, false, Map.of(sourceReference, targetReference)); assertTrue(this.xwiki .getDocument(new DocumentReference(DOCWIKI, DOCSPACE, DOCNAME), this.oldcore.getXWikiContext()).isNew()); diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/ReferenceRenamer.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/ReferenceRenamer.java index 48fd1ac93b09..e50bb3117de4 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/ReferenceRenamer.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/ReferenceRenamer.java @@ -19,11 +19,12 @@ */ package org.xwiki.refactoring; -import java.util.Set; +import java.util.Map; import org.xwiki.component.annotation.Role; import org.xwiki.model.reference.AttachmentReference; import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.EntityReference; import org.xwiki.rendering.block.Block; import org.xwiki.stability.Unstable; @@ -57,15 +58,15 @@ boolean renameReferences(Block block, DocumentReference currentDocumentReference * @param oldTarget the previous reference of the renamed entity (attachment or document) * @param newTarget the new reference of the renamed entity (attachment or document) * @param relative {@code true} if the link should be serialized relatively to the current document - * @param updatedDocuments the list of documents that have been renamed in the same job: this list contains the - * old references before the rename + * @param updatedEntities the map of entities that are or are going to be updated: the map contains the source + * and target destination. * @return {@code true} if the given {@link Block} was modified * @since 16.10.0RC1 */ @Unstable default boolean renameReferences(Block block, DocumentReference currentDocumentReference, - DocumentReference oldTarget, - DocumentReference newTarget, boolean relative, Set updatedDocuments) + DocumentReference oldTarget, DocumentReference newTarget, boolean relative, + Map updatedEntities) { return renameReferences(block, currentDocumentReference, oldTarget, newTarget, relative); } @@ -95,15 +96,15 @@ default boolean renameReferences(Block block, DocumentReference currentDocumentR * @param oldTarget the previous reference of the renamed entity (attachment or document) * @param newTarget the new reference of the renamed entity (attachment or document) * @param relative {@code true} if the link should be serialized relatively to the current document - * @param updatedDocuments the list of documents that have been renamed in the same job: this list contains the - * old references before the rename + * @param updatedEntities the map of entities that are or are going to be updated: the map contains the source + * and target destination. * @return {@code true} if the given {@link Block} was modified * @since 16.10.0RC1 */ @Unstable default boolean renameReferences(Block block, DocumentReference currentDocumentReference, AttachmentReference oldTarget, AttachmentReference newTarget, boolean relative, - Set updatedDocuments) + Map updatedEntities) { return renameReferences(block, currentDocumentReference, oldTarget, newTarget, relative); } diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/ReferenceUpdater.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/ReferenceUpdater.java index f0a467ac926a..38a87cb95da4 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/ReferenceUpdater.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/ReferenceUpdater.java @@ -19,7 +19,7 @@ */ package org.xwiki.refactoring.internal; -import java.util.Set; +import java.util.Map; import org.xwiki.component.annotation.Role; import org.xwiki.model.reference.DocumentReference; @@ -38,11 +38,12 @@ public interface ReferenceUpdater * @param documentReference the reference of the document in which to update the references * @param oldTargetReference the previous reference of the renamed entity * @param newTargetReference the new reference of the renamed entity - * @param updatedEntities the set of entities that might have been updated. + * @param updatedEntities the map of entities that are or are going to be updated: the map contains the source + * and target destination. * @since 16.10.0RC1 */ default void update(DocumentReference documentReference, EntityReference oldTargetReference, - EntityReference newTargetReference, Set updatedEntities) + EntityReference newTargetReference, Map updatedEntities) { update(documentReference, oldTargetReference, newTargetReference); } diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/AbstractCopyOrMoveJob.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/AbstractCopyOrMoveJob.java index 02d7168e7648..37b71d86cccc 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/AbstractCopyOrMoveJob.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/AbstractCopyOrMoveJob.java @@ -21,6 +21,9 @@ import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; import org.xwiki.model.EntityType; import org.xwiki.model.reference.DocumentReference; @@ -100,26 +103,14 @@ protected void process(EntityReference source) EntityReference destination = this.request.getDestination(); - if (processOnlySameSourceDestinationTypes()) { - if (source.getType() != destination.getType()) { - this.logger.error("You cannot change the entity type (from [{}] to [{}]).", source.getType(), - destination.getType()); - return; - } - } - - if (isDescendantOrSelf(destination, source)) { - this.logger.error("Cannot make [{}] a descendant of itself.", source); - return; - } - - if (source.getParent() != null && source.getParent().equals(destination)) { - this.logger.error("Cannot move [{}] into [{}], it's already there.", source, destination); + try { + checkSourceDestination(source, destination); + } catch (InternalCopyOrMoveJobException e) { + this.logger.error(e.getMessage()); return; } // Dispatch the move operation based on the source entity type. - switch (source.getType()) { case DOCUMENT: try { @@ -129,13 +120,34 @@ protected void process(EntityReference source) } break; case SPACE: - process(new SpaceReference(source), destination); + visitSpace(new SpaceReference(source), destination, this::maybePerformRefactoring); break; default: this.logger.error("Unsupported source entity type [{}].", source.getType()); } } + private void checkSourceDestination(EntityReference source, EntityReference destination) + throws InternalCopyOrMoveJobException + { + if (processOnlySameSourceDestinationTypes() && source.getType() != destination.getType()) { + throw new InternalCopyOrMoveJobException( + String.format("You cannot change the entity type (from [%s] to [%s]).", + source.getType(), + destination.getType())); + } + + if (isDescendantOrSelf(destination, source)) { + throw new InternalCopyOrMoveJobException( + String.format("Cannot make [%s] a descendant of itself.", source)); + } + + if (source.getParent() != null && source.getParent().equals(destination)) { + throw new InternalCopyOrMoveJobException( + String.format("Cannot move [%s] into [%s], it's already there.", source, destination)); + } + } + private boolean isDescendantOrSelf(EntityReference alice, EntityReference bob) { EntityReference parent = alice; @@ -145,6 +157,71 @@ private boolean isDescendantOrSelf(EntityReference alice, EntityReference bob) return parent != null; } + @Override + protected void getEntities(DocumentReference documentReference) + { + this.putInConcernedEntities(documentReference); + } + + @Override + protected void putInConcernedEntities(DocumentReference documentReference) + { + DocumentReference source = cleanLocale(documentReference); + try { + EntityReference destination = this.request.getDestination(); + checkSourceDestination(source, destination); + DocumentReference destinationDocumentReference; + if (processOnlySameSourceDestinationTypes()) { + putInConcernedEntitiesOnlySameSource(source, destination); + } else { + if (this.request.isDeep() && isSpaceHomeReference(source)) { + visitSpace(source.getLastSpaceReference(), destination, this::putInConcernedEntities); + } else if (destination.getType() == EntityType.SPACE) { + destinationDocumentReference = + new DocumentReference(source.getName(), new SpaceReference(destination)); + this.putInConcernedEntities(source, destinationDocumentReference); + } else if (destination.getType() == EntityType.DOCUMENT + && isSpaceHomeReference(new DocumentReference(destination))) { + destinationDocumentReference = + new DocumentReference(source.getName(), new SpaceReference(destination.getParent())); + this.putInConcernedEntities(source, destinationDocumentReference); + } else if (destination.getType() == EntityType.WIKI) { + visitSpace(source.getLastSpaceReference(), destination, this::putInConcernedEntities); + } + } + } catch (InternalCopyOrMoveJobException e) { + this.logger.debug(e.getMessage()); + } + } + + private void putInConcernedEntitiesOnlySameSource(DocumentReference source, EntityReference destination) + { + DocumentReference destinationDocumentReference = new DocumentReference(destination); + if (this.request.isDeep() && isSpaceHomeReference(source)) { + if (isSpaceHomeReference(destinationDocumentReference)) { + visitSpace(source.getLastSpaceReference(), destinationDocumentReference.getLastSpaceReference(), + this::putInConcernedEntities); + } + } else { + this.putInConcernedEntities(source, destinationDocumentReference); + } + } + + private void putInConcernedEntities(DocumentReference sourceDocument, DocumentReference destination) + { + try { + if (!this.modelBridge.exists(sourceDocument)) { + this.logger.warn("Skipping [{}] because it doesn't exist.", sourceDocument); + } else if (this.checkAllRights(sourceDocument, destination)) { + this.concernedEntities.put(sourceDocument, new EntitySelection(sourceDocument, destination)); + } + } catch (Exception e) { + logger.error("Failed to perform the refactoring from document with reference [{}] to [{}]", + sourceDocument, destination, e); + } + } + + // FIXME: this should be factorized with the code from getTargetReference protected void process(DocumentReference source, EntityReference destination) throws Exception { if (processOnlySameSourceDestinationTypes()) { @@ -153,7 +230,7 @@ protected void process(DocumentReference source, EntityReference destination) th this.process(source, destinationDocumentReference); } else { if (this.request.isDeep() && isSpaceHomeReference(source)) { - process(source.getLastSpaceReference(), destination); + visitSpace(source.getLastSpaceReference(), destination, this::maybePerformRefactoring); } else if (destination.getType() == EntityType.SPACE) { maybePerformRefactoring(source, new DocumentReference(source.getName(), new SpaceReference(destination))); @@ -182,39 +259,35 @@ protected void process(DocumentReference source, DocumentReference destination) } } - protected void process(SpaceReference source, EntityReference destination) + private void visitSpace(final SpaceReference source, final EntityReference destination, + BiConsumer callback) { + SpaceReference spaceDestination; if (processOnlySameSourceDestinationTypes()) { // We know the destination is a space (see above). - process(source, new SpaceReference(destination)); + spaceDestination = new SpaceReference(destination); } else { if (destination.getType() == EntityType.SPACE || destination.getType() == EntityType.WIKI) { - process(source, new SpaceReference(source.getName(), destination)); + spaceDestination = new SpaceReference(source.getName(), destination); } else if (destination.getType() == EntityType.DOCUMENT && isSpaceHomeReference(new DocumentReference(destination))) { - process(source, new SpaceReference(source.getName(), destination.getParent())); + spaceDestination = new SpaceReference(source.getName(), destination.getParent()); } else { + spaceDestination = null; this.logger.error("Unsupported destination entity type [{}] for a space.", destination.getType()); } } + if (spaceDestination != null) { + visitDocuments(source, oldChildReference -> { + DocumentReference newChildReference = oldChildReference.replaceParent(source, spaceDestination); + callback.accept(oldChildReference, newChildReference); + }); + } } protected void process(final SpaceReference source, final SpaceReference destination) { - visitDocuments(source, new Visitor() - { - @Override - public void visit(DocumentReference oldChildReference) - { - DocumentReference newChildReference = oldChildReference.replaceParent(source, destination); - try { - maybePerformRefactoring(oldChildReference, newChildReference); - } catch (Exception e) { - logger.error("Failed to perform the refactoring from document with reference [{}] to [{}]", - oldChildReference, newChildReference, e); - } - } - }); + visitSpace(source, destination, this::maybePerformRefactoring); } protected boolean checkAllRights(DocumentReference oldReference, DocumentReference newReference) throws Exception @@ -232,18 +305,14 @@ protected boolean checkAllRights(DocumentReference oldReference, DocumentReferen } protected void maybePerformRefactoring(DocumentReference oldReference, DocumentReference newReference) - throws Exception { // Perform checks that are specific to the document source/destination type. - EntitySelection entitySelection = this.getConcernedEntitiesEntitySelection(oldReference); if (entitySelection == null) { this.logger.info("Skipping [{}] because it does not match any entity selection.", oldReference); } else if (!entitySelection.isSelected()) { this.logger.info("Skipping [{}] because it has been unselected.", oldReference); - } else if (!this.modelBridge.exists(oldReference)) { - this.logger.warn("Skipping [{}] because it doesn't exist.", oldReference); - } else if (this.checkAllRights(oldReference, newReference)) { + } else { performRefactoring(oldReference, newReference); } } @@ -330,6 +399,19 @@ protected EntityReference getCommonParent() return getCommonParent(entityReferences); } + /** + * @return the list of references that have been selected to be refactored. + * @since 16.10.0RC1 + */ + public Map getSelectedEntities() + { + return this.concernedEntities.values().stream() + .filter(EntitySelection::isSelected) + .filter(entity -> entity.getTargetEntityReference().isPresent()) + .collect(Collectors.toMap(EntitySelection::getEntityReference, + entity -> entity.getTargetEntityReference().get())); + } + /** * Atomic operation to perform: should be a rename for Rename/Move and copy for Copy. * @param source the source reference diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/AbstractEntityJobWithChecks.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/AbstractEntityJobWithChecks.java index ecc442b5fd22..5bbf26f9daf3 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/AbstractEntityJobWithChecks.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/AbstractEntityJobWithChecks.java @@ -23,8 +23,6 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; import org.xwiki.bridge.event.DocumentsDeletingEvent; import org.xwiki.model.reference.DocumentReference; @@ -49,7 +47,7 @@ public abstract class AbstractEntityJobWithChecks concernedEntities = new HashMap<>(); + protected final Map concernedEntities = new HashMap<>(); @Override protected void runInternal() throws Exception @@ -106,7 +104,7 @@ protected void getEntities(EntityReference entityReference) } } - private DocumentReference cleanLocale(DocumentReference documentReference) + protected DocumentReference cleanLocale(DocumentReference documentReference) { // We don't want to have locale information for root locale in the reference to not have problems with // the questions. @@ -123,13 +121,13 @@ private DocumentReference cleanLocale(DocumentReference documentReference) } } - private void putInConcernedEntities(DocumentReference documentReference) + protected void putInConcernedEntities(DocumentReference documentReference) { DocumentReference cleanDocumentReference = cleanLocale(documentReference); this.concernedEntities.put(cleanDocumentReference, new EntitySelection(cleanDocumentReference)); } - private void getEntities(DocumentReference documentReference) + protected void getEntities(DocumentReference documentReference) { if (this.request.isDeep() && isSpaceHomeReference(documentReference)) { getEntities(documentReference.getLastSpaceReference()); @@ -138,7 +136,7 @@ private void getEntities(DocumentReference documentReference) } } - private void getEntities(SpaceReference spaceReference) + protected void getEntities(SpaceReference spaceReference) { visitDocuments(spaceReference, this::putInConcernedEntities); } @@ -167,16 +165,4 @@ protected EntitySelection getConcernedEntitiesEntitySelection(EntityReference re } return entitySelection; } - - /** - * @return the list of references that have been selected to be refactored. - * @since 16.10.0RC1 - */ - public Set getSelectedEntities() - { - return this.concernedEntities.values().stream() - .filter(EntitySelection::isSelected) - .map(EntitySelection::getEntityReference) - .collect(Collectors.toSet()); - } } diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/InternalCopyOrMoveJobException.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/InternalCopyOrMoveJobException.java new file mode 100644 index 000000000000..2653e69b2b90 --- /dev/null +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/InternalCopyOrMoveJobException.java @@ -0,0 +1,38 @@ +/* + * 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.refactoring.internal.job; + +/** + * Internal exception to be used in {@link AbstractCopyOrMoveJob}. + * + * @version $Id$ + * @since 16.10.0RC1 + */ +public class InternalCopyOrMoveJobException extends Exception +{ + /** + * Default constructor. + * @param message the message of the exception. + */ + public InternalCopyOrMoveJobException(String message) + { + super(message); + } +} diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/RenameJob.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/RenameJob.java index dfac6f9d42e1..eb4123c4a35d 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/RenameJob.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/job/RenameJob.java @@ -48,6 +48,8 @@ protected void process(Collection entityReferences) { if (entityReferences.size() == 1) { process(entityReferences.iterator().next()); + } else { + this.logger.warn("Cannot rename multiple entities."); } } diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/listener/BackLinkUpdaterListener.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/listener/BackLinkUpdaterListener.java index f15091a5b1ce..0cf8138c3f65 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/listener/BackLinkUpdaterListener.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/internal/listener/BackLinkUpdaterListener.java @@ -19,6 +19,7 @@ */ package org.xwiki.refactoring.internal.listener; +import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; @@ -41,7 +42,6 @@ import org.xwiki.refactoring.event.DocumentRenamedEvent; import org.xwiki.refactoring.internal.ModelBridge; import org.xwiki.refactoring.internal.ReferenceUpdater; -import org.xwiki.refactoring.internal.job.AbstractEntityJobWithChecks; import org.xwiki.refactoring.internal.job.DeleteJob; import org.xwiki.refactoring.internal.job.MoveJob; import org.xwiki.refactoring.job.DeleteRequest; @@ -118,7 +118,7 @@ private void maybeUpdateLinksAfterDelete(Event event) throws RefactoringExceptio DocumentReference newTarget = request.getNewBacklinkTargets().get(deletedEvent.getDocumentReference()); if (request.isUpdateLinks() && newTarget != null) { - updateBackLinks(deletedEvent.getDocumentReference(), newTarget, canEdit, Set.of()); + updateBackLinks(deletedEvent.getDocumentReference(), newTarget, canEdit, Map.of()); } } @@ -128,24 +128,24 @@ private void maybeUpdateLinksAfterRename(Event event, Object source, Object data Predicate canEdit = entityReference -> this.authorization.hasAccess(Right.EDIT, entityReference); - Set movedDocuments = Set.of(); + Map updatedEntities = Map.of(); if (source instanceof MoveJob) { MoveRequest request = (MoveRequest) data; updateLinks = request.isUpdateLinks(); // Check access rights taking into account the move request. canEdit = entityReference -> ((MoveJob) source).hasAccess(Right.EDIT, entityReference); - movedDocuments = ((AbstractEntityJobWithChecks) source).getSelectedEntities(); + updatedEntities = ((MoveJob) source).getSelectedEntities(); } if (updateLinks) { DocumentRenamedEvent renameEvent = (DocumentRenamedEvent) event; updateBackLinks(renameEvent.getSourceReference(), renameEvent.getTargetReference(), canEdit, - movedDocuments); + updatedEntities); } } private void updateBackLinks(DocumentReference source, DocumentReference target, - Predicate canEdit, Set movedDocuments) + Predicate canEdit, Map updatedEntities) throws RefactoringException { this.logger.info("Updating the back-links for document [{}].", source); @@ -162,7 +162,7 @@ private void updateBackLinks(DocumentReference source, DocumentReference target, for (DocumentReference backlinkDocumentReference : backlinkDocumentReferences) { this.progressManager.startStep(this); if (canEdit.test(backlinkDocumentReference)) { - this.updater.update(backlinkDocumentReference, source, target, movedDocuments); + this.updater.update(backlinkDocumentReference, source, target, updatedEntities); } this.progressManager.endStep(this); } diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/job/question/EntitySelection.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/job/question/EntitySelection.java index 24ee96ac0751..68ee2ab4e8de 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/job/question/EntitySelection.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/main/java/org/xwiki/refactoring/job/question/EntitySelection.java @@ -19,9 +19,13 @@ */ package org.xwiki.refactoring.job.question; +import java.util.Optional; + import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; import org.xwiki.model.reference.EntityReference; +import org.xwiki.stability.Unstable; /** * Represent an entity with an information about either or not the entity is selected to perform some refactoring. @@ -55,7 +59,8 @@ public enum State /** * Reference to the entity to select for the refactoring. */ - private EntityReference entityReference; + private final EntityReference sourceEntityReference; + private final EntityReference targetEntityReference; /** * Indicate if the entity is selected or not by the user. @@ -68,7 +73,20 @@ public enum State */ public EntitySelection(EntityReference entityReference) { - this.entityReference = entityReference; + this(entityReference, null); + } + + /** + * Constructor of an EntitySelection when there is a target destination. + * @param sourceEntityReference the original reference + * @param targetEntityReference the target reference of the refactoring + * @since 16.10.0RC1 + */ + @Unstable + public EntitySelection(EntityReference sourceEntityReference, EntityReference targetEntityReference) + { + this.sourceEntityReference = sourceEntityReference; + this.targetEntityReference = targetEntityReference; } /** @@ -76,7 +94,17 @@ public EntitySelection(EntityReference entityReference) */ public EntityReference getEntityReference() { - return entityReference; + return sourceEntityReference; + } + + /** + * @return the target reference of the refactoring if any. + * @since 16.10.0RC1 + */ + @Unstable + public Optional getTargetEntityReference() + { + return (targetEntityReference != null) ? Optional.of(targetEntityReference) : Optional.empty(); } /** @@ -111,7 +139,11 @@ public void setSelected(boolean selected) @Override public int hashCode() { - return new HashCodeBuilder(3, 13).append(getEntityReference()).append(isSelected).toHashCode(); + return new HashCodeBuilder(3, 13) + .append(getEntityReference()) + .append(getTargetEntityReference()) + .append(isSelected) + .toHashCode(); } @Override @@ -127,8 +159,21 @@ public boolean equals(Object object) return false; } EntitySelection entitySelection = (EntitySelection) object; - return new EqualsBuilder().append(getEntityReference(), entitySelection.getEntityReference()) - .append(isSelected(), entitySelection.isSelected()).isEquals(); + return new EqualsBuilder() + .append(getEntityReference(), entitySelection.getEntityReference()) + .append(getTargetEntityReference(), entitySelection.getTargetEntityReference()) + .append(isSelected(), entitySelection.isSelected()) + .isEquals(); + } + + @Override + public String toString() + { + return new ToStringBuilder(this) + .append("sourceEntityReference", sourceEntityReference) + .append("targetEntityReference", targetEntityReference) + .append("isSelected", isSelected) + .toString(); } @Override @@ -142,15 +187,15 @@ public int compareTo(EntitySelection entitySelection) return 0; } - if (entityReference == null) { + if (sourceEntityReference == null) { return -1; } - if (entitySelection.entityReference == null) { + if (entitySelection.sourceEntityReference == null) { return 1; } - int result = entityReference.compareTo(entitySelection.entityReference); + int result = sourceEntityReference.compareTo(entitySelection.sourceEntityReference); if (result == 0) { return isSelected.compareTo(entitySelection.isSelected); diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/job/MoveJobTest.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/job/MoveJobTest.java index f7e6a2cb2db1..6f611010bbaa 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/job/MoveJobTest.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/job/MoveJobTest.java @@ -451,14 +451,22 @@ void moveDocumentToSpaceHome() throws Throwable verify(this.modelBridge).rename(source, new DocumentReference("wiki", "C", "B")); } + /* + * This test scenario checks performing a move of the space chess:A.B.C that contains docs X et Y to wiki tennis. + * The resulting references are tennis:C.X and tennis:C.Y. Note that it's a space move because the request is using + * deep flag set to true. + */ @Test void moveSpaceHomeDeep() throws Throwable { DocumentReference spaceHome = new DocumentReference("chess", List.of("A", "B", "C"), "WebHome"); DocumentReference docFromSpace = new DocumentReference("X", spaceHome.getLastSpaceReference()); + DocumentReference otherDocFromSpace = new DocumentReference("Y", spaceHome.getLastSpaceReference()); when(this.modelBridge.getDocumentReferences(spaceHome.getLastSpaceReference())) - .thenReturn(List.of(docFromSpace)); + .thenReturn(List.of(spaceHome, docFromSpace, otherDocFromSpace)); + when(this.modelBridge.exists(spaceHome)).thenReturn(false); when(this.modelBridge.exists(docFromSpace)).thenReturn(true); + when(this.modelBridge.exists(otherDocFromSpace)).thenReturn(true); WikiReference newWiki = new WikiReference("tennis"); @@ -468,10 +476,19 @@ void moveSpaceHomeDeep() throws Throwable request.setDeep(true); run(request); - verify(this.modelBridge).rename(docFromSpace, new DocumentReference("tennis", "C", "X")); + DocumentReference targetDoc1 = new DocumentReference("tennis", "C", "X"); + verify(this.modelBridge).rename(docFromSpace, targetDoc1); + + DocumentReference targetDoc2 = new DocumentReference("tennis", "C", "Y"); + verify(this.modelBridge).rename(otherDocFromSpace, targetDoc2); verify(this.observationManager).notify(any(DocumentsDeletingEvent.class), any(MoveJob.class), - eq(Map.of(docFromSpace, new EntitySelection(docFromSpace)))); + eq(Map.of( + docFromSpace, new EntitySelection(docFromSpace, targetDoc1), + otherDocFromSpace, new EntitySelection(otherDocFromSpace, targetDoc2) + ))); + assertEquals(1, getLogCapture().size()); + assertEquals("Skipping [chess:A.B.C.WebHome] because it doesn't exist.", getLogCapture().getMessage(0)); } @Test diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/job/RenameJobTest.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/job/RenameJobTest.java index fbefa091638f..895c9cf7c770 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/job/RenameJobTest.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/job/RenameJobTest.java @@ -61,12 +61,19 @@ void renameMultipleEntities() throws Throwable DocumentReference whiteReference = new DocumentReference("wiki", "Color", "White"); DocumentReference orangeReference = new DocumentReference("wiki", "Color", "Orange"); + when(this.modelBridge.exists(blackReference)).thenReturn(true); + when(this.modelBridge.exists(whiteReference)).thenReturn(true); + MoveRequest request = new MoveRequest(); request.setEntityReferences(List.of(blackReference, whiteReference)); request.setDestination(orangeReference); + request.setCheckAuthorRights(false); + request.setCheckRights(false); run(request); verifyNoMove(); + assertEquals(1, getLogCapture().size()); + assertEquals("Cannot rename multiple entities.", getLogCapture().getMessage(0)); } @Test diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/listener/BackLinkUpdaterListenerTest.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/listener/BackLinkUpdaterListenerTest.java index 0198ed1ca28a..6d1ed10d6216 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/listener/BackLinkUpdaterListenerTest.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-api/src/test/java/org/xwiki/refactoring/internal/listener/BackLinkUpdaterListenerTest.java @@ -20,6 +20,7 @@ package org.xwiki.refactoring.internal.listener; import java.util.Collections; +import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -129,8 +130,8 @@ void onDocumentRenamedWithUpdateLinksOnFarm() this.listener.onEvent(documentRenamedEvent, renameJob, renameRequest); - verify(this.updater).update(carolReference, aliceReference, bobReference, Set.of()); - verify(this.updater).update(denisReference, aliceReference, bobReference, Set.of()); + verify(this.updater).update(carolReference, aliceReference, bobReference, Map.of()); + verify(this.updater).update(denisReference, aliceReference, bobReference, Map.of()); assertEquals("Updating the back-links for document [foo:Users.Alice].", logCapture.getMessage(0)); } @@ -147,7 +148,7 @@ void onDocumentRenamedWithUpdateLinksOnFarmAndNoEditRight() this.listener.onEvent(documentRenamedEvent, renameJob, renameRequest); - verify(this.updater).update(carolReference, aliceReference, bobReference, Set.of()); + verify(this.updater).update(carolReference, aliceReference, bobReference, Map.of()); verify(this.updater, never()).update(eq(denisReference), any(DocumentReference.class), any()); assertEquals("Updating the back-links for document [foo:Users.Alice].", logCapture.getMessage(0)); @@ -163,7 +164,7 @@ void onDocumentRenamedWithUpdateLinksOnWiki() this.listener.onEvent(documentRenamedEvent, renameJob, renameRequest); - verify(this.updater).update(carolReference, aliceReference, bobReference, Set.of()); + verify(this.updater).update(carolReference, aliceReference, bobReference, Map.of()); verify(this.updater, never()).update(eq(denisReference), any(DocumentReference.class), any()); assertEquals("Updating the back-links for document [foo:Users.Alice].", logCapture.getMessage(0)); @@ -189,8 +190,8 @@ void onDocumentRenamedWithoutRenameJob() this.listener.onEvent(documentRenamedEvent, null, null); - verify(this.updater).update(carolReference, aliceReference, bobReference, Set.of()); - verify(this.updater).update(denisReference, aliceReference, bobReference, Set.of()); + verify(this.updater).update(carolReference, aliceReference, bobReference, Map.of()); + verify(this.updater).update(denisReference, aliceReference, bobReference, Map.of()); assertEquals("Updating the back-links for document [foo:Users.Alice].", logCapture.getMessage(0)); } @@ -205,7 +206,7 @@ void onDocumentRenamedWithoutRenameJobAndNoEditRight() this.listener.onEvent(documentRenamedEvent, null, null); verify(this.updater, never()).update(eq(carolReference), any(DocumentReference.class), any()); - verify(this.updater).update(denisReference, aliceReference, bobReference, Set.of()); + verify(this.updater).update(denisReference, aliceReference, bobReference, Map.of()); assertEquals("Updating the back-links for document [foo:Users.Alice].", logCapture.getMessage(0)); } @@ -220,8 +221,8 @@ void onDocumentDeletedWithUpdateLinksOnFarm() this.listener.onEvent(documentDeletedEvent, null, null); - verify(this.updater).update(carolReference, aliceReference, bobReference, Set.of()); - verify(this.updater).update(denisReference, aliceReference, bobReference, Set.of()); + verify(this.updater).update(carolReference, aliceReference, bobReference, Map.of()); + verify(this.updater).update(denisReference, aliceReference, bobReference, Map.of()); assertEquals("Updating the back-links for document [foo:Users.Alice].", logCapture.getMessage(0)); } @@ -252,7 +253,7 @@ void onDocumentDeleteWithUpdateLinksOnFarmAndNoEditRight() this.listener.onEvent(documentDeletedEvent, null, null); - verify(this.updater).update(carolReference, aliceReference, bobReference, Set.of()); + verify(this.updater).update(carolReference, aliceReference, bobReference, Map.of()); verify(this.updater, never()).update(eq(denisReference), any(DocumentReference.class), any()); assertEquals("Updating the back-links for document [foo:Users.Alice].", this.logCapture.getMessage(0)); diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultMacroRefactoring.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultMacroRefactoring.java index 68944f16e610..36b755d8e113 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultMacroRefactoring.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultMacroRefactoring.java @@ -20,6 +20,7 @@ package org.xwiki.refactoring.internal; import java.util.Collections; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Predicate; @@ -36,6 +37,7 @@ import org.xwiki.component.manager.ComponentManager; import org.xwiki.model.reference.AttachmentReference; import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.EntityReference; import org.xwiki.refactoring.ReferenceRenamer; import org.xwiki.rendering.block.Block; import org.xwiki.rendering.block.MacroBlock; @@ -150,23 +152,23 @@ private XDOM parseMacro(MacroBlock macroBlock) throws MacroRefactoringException @Override public Optional replaceReference(MacroBlock macroBlock, DocumentReference currentDocumentReference, DocumentReference sourceReference, DocumentReference targetReference, boolean relative, - Set updatedDocuments) + Map updatedEntities) throws MacroRefactoringException { return innerReplaceReference(macroBlock, xdom -> this.referenceRenamerProvider.get().renameReferences(xdom, currentDocumentReference, - sourceReference, targetReference, relative, updatedDocuments)); + sourceReference, targetReference, relative, updatedEntities)); } @Override public Optional replaceReference(MacroBlock macroBlock, DocumentReference currentDocumentReference, AttachmentReference sourceReference, AttachmentReference targetReference, boolean relative, - Set updatedDocuments) + Map updatedEntities) throws MacroRefactoringException { return innerReplaceReference(macroBlock, xdom -> this.referenceRenamerProvider.get().renameReferences(xdom, currentDocumentReference, - sourceReference, targetReference, relative, updatedDocuments)); + sourceReference, targetReference, relative, updatedEntities)); } @Override @@ -175,7 +177,7 @@ public Optional replaceReference(MacroBlock macroBlock, DocumentRefe throws MacroRefactoringException { return replaceReference(macroBlock, currentDocumentReference, sourceReference, targetReference, relative, - Set.of(sourceReference)); + Map.of(sourceReference, targetReference)); } @Override @@ -184,7 +186,7 @@ public Optional replaceReference(MacroBlock macroBlock, DocumentRefe throws MacroRefactoringException { return replaceReference(macroBlock, currentDocumentReference, sourceReference, targetReference, relative, - Set.of()); + Map.of(sourceReference.getDocumentReference(), targetReference.getDocumentReference())); } private Optional innerReplaceReference(MacroBlock macroBlock, Predicate lambda) diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultReferenceRenamer.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultReferenceRenamer.java index 34cdec113928..c252b3741dd0 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultReferenceRenamer.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultReferenceRenamer.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; @@ -115,41 +116,42 @@ private interface RenameResourceLambda @Override public boolean renameReferences(Block block, DocumentReference currentDocumentReference, DocumentReference oldTarget, DocumentReference newTarget, boolean relative, - Set updatedDocuments) + Map updatedEntities) { return innerRenameReferences(block, currentDocumentReference, oldTarget, newTarget, SUPPORTED_RESOURCE_TYPES_FOR_DOCUMENTS, (MacroRefactoring macroRefactoring, MacroBlock macroBlock) -> macroRefactoring.replaceReference(macroBlock, - currentDocumentReference, oldTarget, newTarget, relative, updatedDocuments), + currentDocumentReference, oldTarget, newTarget, relative, updatedEntities), reference -> this.resourceReferenceRenamer.updateResourceReference(reference, oldTarget, - newTarget, currentDocumentReference, relative, updatedDocuments)); + newTarget, currentDocumentReference, relative, updatedEntities)); } @Override public boolean renameReferences(Block block, DocumentReference currentDocumentReference, DocumentReference oldTarget, DocumentReference newTarget, boolean relative) { - return renameReferences(block, currentDocumentReference, oldTarget, newTarget, relative, Set.of(oldTarget)); + return renameReferences(block, currentDocumentReference, oldTarget, newTarget, relative, + Map.of(oldTarget, newTarget)); } @Override public boolean renameReferences(Block block, DocumentReference currentDocumentReference, AttachmentReference oldTarget, AttachmentReference newTarget, boolean relative, - Set updatedDocuments) + Map updatedEntities) { return innerRenameReferences(block, currentDocumentReference, oldTarget, newTarget, SUPPORTED_RESOURCE_TYPES_FOR_ATTACHMENTS, (MacroRefactoring macroRefactoring, MacroBlock macroBlock) -> macroRefactoring.replaceReference(macroBlock, - currentDocumentReference, oldTarget, newTarget, relative, updatedDocuments), + currentDocumentReference, oldTarget, newTarget, relative, updatedEntities), reference -> this.resourceReferenceRenamer.updateResourceReference(reference, - oldTarget, newTarget, currentDocumentReference, relative, updatedDocuments)); + oldTarget, newTarget, currentDocumentReference, relative, updatedEntities)); } @Override public boolean renameReferences(Block block, DocumentReference currentDocumentReference, AttachmentReference oldTarget, AttachmentReference newTarget, boolean relative) { - return renameReferences(block, currentDocumentReference, oldTarget, newTarget, relative, Set.of()); + return renameReferences(block, currentDocumentReference, oldTarget, newTarget, relative, Map.of()); } private boolean innerRenameReferences(Block block, DocumentReference currentDocumentReference, diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultReferenceUpdater.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultReferenceUpdater.java index a62c14038fe2..e3bfabbe28a3 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultReferenceUpdater.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/DefaultReferenceUpdater.java @@ -21,7 +21,7 @@ import java.util.List; import java.util.Locale; -import java.util.Set; +import java.util.Map; import javax.inject.Inject; import javax.inject.Named; @@ -266,20 +266,20 @@ private void renameLinks(XWikiDocument document, EntityReference oldTarget, Enti } private void renameLinks(DocumentReference documentReference, DocumentReference oldLinkTarget, - DocumentReference newLinkTarget, boolean relative, Set updatedDocuments) + DocumentReference newLinkTarget, boolean relative, Map updatedEntities) { internalRenameLinks(documentReference, oldLinkTarget, newLinkTarget, relative, (xdom, currentDocumentReference, r) -> this.renamer.renameReferences(xdom, currentDocumentReference, oldLinkTarget, newLinkTarget, r, - updatedDocuments)); + updatedEntities)); } private void renameLinks(DocumentReference documentReference, AttachmentReference oldLinkTarget, - AttachmentReference newLinkTarget, boolean relative, Set updatedDocuments) + AttachmentReference newLinkTarget, boolean relative, Map updatedEntities) { internalRenameLinks(documentReference, oldLinkTarget, newLinkTarget, relative, (xdom, currentDocumentReference, r) -> this.renamer.renameReferences(xdom, currentDocumentReference, oldLinkTarget, newLinkTarget, r, - updatedDocuments)); + updatedEntities)); } private void internalRenameLinks(DocumentReference documentReference, EntityReference oldLinkTarget, @@ -335,7 +335,7 @@ private AttachmentReference toAttachmentReference(EntityReference entityReferenc @Override public void update(DocumentReference documentReference, EntityReference oldTargetReference, - EntityReference newTargetReference, Set updatedDocuments) + EntityReference newTargetReference, Map updatedEntities) { // If the current document is the moved entity the links should be serialized relative to it boolean relative = newTargetReference.equals(documentReference); @@ -348,10 +348,10 @@ public void update(DocumentReference documentReference, EntityReference oldTarge // Only support documents and attachments targets if (oldTargetReference.getType() == EntityType.ATTACHMENT) { renameLinks(documentReference, toAttachmentReference(oldTargetReference), - toAttachmentReference(newTargetReference), relative, updatedDocuments); + toAttachmentReference(newTargetReference), relative, updatedEntities); } else if (oldTargetReference.getType() == EntityType.DOCUMENT) { renameLinks(documentReference, toDocumentReference(oldTargetReference), - toDocumentReference(newTargetReference), relative, updatedDocuments); + toDocumentReference(newTargetReference), relative, updatedEntities); } } @@ -359,6 +359,7 @@ public void update(DocumentReference documentReference, EntityReference oldTarge public void update(DocumentReference documentReference, EntityReference oldTargetReference, EntityReference newTargetReference) { - update(documentReference, oldTargetReference, newTargetReference, Set.of()); + update(documentReference, oldTargetReference, newTargetReference, + Map.of(oldTargetReference, newTargetReference)); } } diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/ResourceReferenceRenamer.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/ResourceReferenceRenamer.java index 79186bef8889..74108ff78741 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/ResourceReferenceRenamer.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/main/java/org/xwiki/refactoring/internal/ResourceReferenceRenamer.java @@ -19,7 +19,7 @@ */ package org.xwiki.refactoring.internal; -import java.util.Set; +import java.util.Map; import javax.inject.Inject; import javax.inject.Named; @@ -82,18 +82,18 @@ public class ResourceReferenceRenamer * @param newReference the new document reference target * @param currentDocumentReference the current document where the resource reference is located * @param relative {@code true} if the reference should be kept relative to the current document - * @param movedReferences the list of references that have been moved in the same job: this list contains the old - * references before the move. + * @param updatedEntities the map of entities that are or are going to be updated: the map contains the source + * and target destination. * @return {@code true} if the resource reference has been updated */ public boolean updateResourceReference(ResourceReference resourceReference, DocumentReference oldReference, DocumentReference newReference, DocumentReference currentDocumentReference, - boolean relative, Set movedReferences) + boolean relative, Map updatedEntities) { return (relative) - ? this.updateRelativeResourceReference(resourceReference, oldReference, newReference, movedReferences) + ? this.updateRelativeResourceReference(resourceReference, oldReference, newReference, updatedEntities) : this.updateAbsoluteResourceReference(resourceReference, oldReference, newReference, - currentDocumentReference, movedReferences); + currentDocumentReference, updatedEntities); } private boolean checkIfDocExists(DocumentReference documentReference) @@ -118,23 +118,23 @@ private boolean checkIfDocExists(DocumentReference documentReference) * @param newReference the new attachment reference target * @param currentDocumentReference the current document where the resource reference is located * @param relative {@code true} if the reference should be kept relative to the current document - * @param movedReferences the list of references that have been moved in the same job: this list contains the old - * references before the move. + * @param updatedEntities the map of entities that are or are going to be updated: the map contains the source + * and target destination. * @return {@code true} if the attachment reference has been updated */ public boolean updateResourceReference(ResourceReference resourceReference, AttachmentReference oldReference, AttachmentReference newReference, DocumentReference currentDocumentReference, - boolean relative, Set movedReferences) + boolean relative, Map updatedEntities) { return (relative) - ? this.updateRelativeResourceReference(resourceReference, oldReference, newReference, movedReferences) + ? this.updateRelativeResourceReference(resourceReference, oldReference, newReference, updatedEntities) : this.updateAbsoluteResourceReference(resourceReference, oldReference, newReference, - currentDocumentReference, movedReferences); + currentDocumentReference, updatedEntities); } private boolean updateAbsoluteResourceReference(ResourceReference resourceReference, DocumentReference oldReference, DocumentReference newReference, DocumentReference currentDocumentReference, - Set movedReferences) + Map updatedEntities) { boolean result = false; @@ -155,7 +155,7 @@ private boolean updateAbsoluteResourceReference(ResourceReference resourceRefere // as in this case there won't be any other call to perform the link refactoring. boolean shouldBeUpdated = linkTargetDocumentReference.equals(oldReference) && (absoluteResolvedReference.equals(linkEntityReference) - || !movedReferences.contains(currentDocumentReference)); + || !updatedEntities.containsKey(currentDocumentReference)); if (shouldBeUpdated) { // If the link was resolved to a space... @@ -195,7 +195,7 @@ private boolean updateAbsoluteResourceReference(ResourceReference resourceRefere } private boolean updateRelativeResourceReference(ResourceReference resourceReference, - T oldReference, T newReference, Set movedReferences) + T oldReference, T newReference, Map updatedEntities) { boolean result = false; @@ -208,9 +208,13 @@ private boolean updateRelativeResourceReference(Reso boolean docExists = false; EntityType entityType = linkEntityReference.getType(); + DocumentReference documentReference = null; + DocumentReference documentReferenceTarget = null; if (entityType == EntityType.DOCUMENT || entityType.getAllowedParents().contains(EntityType.DOCUMENT)) { - DocumentReference documentReference = + documentReference = (DocumentReference) oldLinkReference.extractReference(EntityType.DOCUMENT); + documentReferenceTarget = + (DocumentReference) linkEntityReference.extractReference(EntityType.DOCUMENT); docExists = checkIfDocExists(documentReference); } else { docExists = true; @@ -218,9 +222,8 @@ private boolean updateRelativeResourceReference(Reso boolean anyMatchInMovedReferences = (oldLinkReference.hasParent(oldReference) - || movedReferences.contains(oldLinkReference) - // TODO: check if that oracle is good in case of holes in the hierarchy - || movedReferences.stream().anyMatch(oldLinkReference::hasParent)); + || (documentReferenceTarget != null + && documentReferenceTarget.equals(updatedEntities.get(documentReference)))); // We should update the reference if: // - it's relative: the resolution of the reference without any parameter, and the resolution of the reference @@ -243,9 +246,10 @@ private boolean updateRelativeResourceReference(Reso return result; } + // FIXME: Check if we shouldn't use the updatedEntities here. private boolean updateAbsoluteResourceReference(ResourceReference resourceReference, AttachmentReference oldReference, AttachmentReference newReference, DocumentReference currentDocumentReference, - Set movedReferences) + Map updatedEntities) { boolean result = false; diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultMacroRefactoringTest.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultMacroRefactoringTest.java index a9ed5dc66fa9..980e310f265f 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultMacroRefactoringTest.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultMacroRefactoringTest.java @@ -22,7 +22,6 @@ import java.util.Collections; import java.util.Map; import java.util.Optional; -import java.util.Set; import javax.inject.Provider; @@ -153,10 +152,10 @@ void replaceReferenceUnparseableMacro() throws MacroRefactoringException }); assertEquals(Optional.empty(), this.macroRefactoring.replaceReference(this.macroBlock, this.currentDocumentReference, - this.sourceReference, this.targetReference, true, Set.of())); + this.sourceReference, this.targetReference, true, Map.of())); assertEquals(Optional.empty(), this.macroRefactoring.replaceReference(this.macroBlock, this.currentDocumentReference, - this.sourceReference, this.targetReference, false, Set.of())); + this.sourceReference, this.targetReference, false, Map.of())); verify(this.referenceRenamer, never()).renameReferences(any(), any(), any(DocumentReference.class), any(), anyBoolean(), any()); } @@ -188,10 +187,10 @@ void replaceReferenceNotUpdated() throws Exception return xdom; }); when(this.referenceRenamer.renameReferences(xdom, this.currentDocumentReference, this.sourceReference, - this.targetReference, true, Set.of())).thenReturn(false); + this.targetReference, true, Map.of())).thenReturn(false); assertEquals(Optional.empty(), this.macroRefactoring.replaceReference(this.macroBlock, this.currentDocumentReference, this.sourceReference, - this.targetReference, true, Set.of())); + this.targetReference, true, Map.of())); verify(this.blockRenderer, never()).render(any(Block.class), any()); } @@ -213,7 +212,7 @@ void replaceReferenceUpdated() throws Exception return xdom; }); when(this.referenceRenamer.renameReferences(xdom, this.currentDocumentReference, this.sourceReference, - this.targetReference, true, Set.of())).thenReturn(true); + this.targetReference, true, Map.of())).thenReturn(true); String expectedContent = "the expected content"; doAnswer(invocationOnMock -> { WikiPrinter printer = invocationOnMock.getArgument(1); @@ -234,7 +233,7 @@ void replaceReferenceUpdated() throws Exception MacroBlock expectedBlock = new MacroBlock(this.macroId, parameters, expectedContent, false); assertEquals(Optional.of(expectedBlock), this.macroRefactoring.replaceReference(this.macroBlock, this.currentDocumentReference, this.sourceReference, - this.targetReference, true, Set.of())); + this.targetReference, true, Map.of())); } @Test diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultReferenceUpdaterTest.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultReferenceUpdaterTest.java index 3ec23251e625..3c5fe356493f 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultReferenceUpdaterTest.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/DefaultReferenceUpdaterTest.java @@ -26,7 +26,6 @@ import java.util.Locale; import java.util.Map; import java.util.Optional; -import java.util.Set; import javax.inject.Named; import javax.inject.Provider; @@ -661,11 +660,11 @@ void updateFromMacros(MockitoComponentManager componentManager) throws Exception updater.update(documentReference, oldLinkTarget, newLinkTarget); verify(includeMacroRefactoring).replaceReference(includeMacroBlock1, documentReference, oldLinkTarget, - newLinkTarget, false, Set.of()); + newLinkTarget, false, Map.of(oldLinkTarget, newLinkTarget)); verify(includeMacroRefactoring).replaceReference(includeMacroBlock2, documentReference, oldLinkTarget, - newLinkTarget, false, Set.of()); + newLinkTarget, false, Map.of(oldLinkTarget, newLinkTarget)); verify(displayMacroRefactoring).replaceReference(displayMacroBlock, documentReference, oldLinkTarget, - newLinkTarget, false, Set.of()); + newLinkTarget, false, Map.of(oldLinkTarget, newLinkTarget)); verify(this.mutableRenderingContext, times(3)).push(any(), any(), eq(Syntax.XWIKI_2_1), any(), anyBoolean(), any()); verify(this.mutableRenderingContext, times(3)).pop(); @@ -753,7 +752,7 @@ void updateFromLinksAndMacros(MockitoComponentManager componentManager) throws E updater.update(documentReference, oldLinkTarget, newLinkTarget); verify(includeMacroRefactoring).replaceReference(includeMacroBlock, documentReference, oldLinkTarget, - newLinkTarget, false, Set.of()); + newLinkTarget, false, Map.of(oldLinkTarget, newLinkTarget)); assertEquals("X.Y", documentLinkBlock.getReference().getReference()); assertEquals(ResourceType.DOCUMENT, documentLinkBlock.getReference().getType()); verifyDocumentSave(document, "Renamed back-links.", false, false); diff --git a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/ResourceReferenceRenamerTest.java b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/ResourceReferenceRenamerTest.java index 231b0cf2cdbd..63cd5422cc40 100644 --- a/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/ResourceReferenceRenamerTest.java +++ b/xwiki-platform-core/xwiki-platform-refactoring/xwiki-platform-refactoring-default/src/test/java/org/xwiki/refactoring/internal/ResourceReferenceRenamerTest.java @@ -19,7 +19,7 @@ */ package org.xwiki.refactoring.internal; -import java.util.Set; +import java.util.Map; import javax.inject.Named; import javax.inject.Provider; @@ -107,7 +107,7 @@ void updateResourceReferenceRelative() assertTrue(this.renamer.updateResourceReference(resourceReference, oldReference, newReference, - new DocumentReference("xwiki", "Space", "Page"), true, Set.of())); + new DocumentReference("xwiki", "Space", "Page"), true, Map.of())); verify(this.compactEntityReferenceSerializer).serialize(oldReference, newReference); } @@ -133,7 +133,7 @@ void updateResourceReferenceNotRelative() assertTrue(this.renamer.updateResourceReference(resourceReference, oldReference, newReference, currentDocumentReference, - false, Set.of())); + false, Map.of())); assertEquals(new AttachmentResourceReference("xwiki:Space.Page.file2.txt"), resourceReference); } } diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-include/src/main/java/org/xwiki/rendering/internal/macro/include/IncludeMacroRefactoring.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-include/src/main/java/org/xwiki/rendering/internal/macro/include/IncludeMacroRefactoring.java index bc208d9eaf22..52ec5c307ee4 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-include/src/main/java/org/xwiki/rendering/internal/macro/include/IncludeMacroRefactoring.java +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-include/src/main/java/org/xwiki/rendering/internal/macro/include/IncludeMacroRefactoring.java @@ -20,6 +20,7 @@ package org.xwiki.rendering.internal.macro.include; import java.util.Collections; +import java.util.Map; import java.util.Optional; import java.util.Set; @@ -86,21 +87,21 @@ public class IncludeMacroRefactoring implements MacroRefactoring @Override public Optional replaceReference(MacroBlock macroBlock, DocumentReference currentDocumentReference, DocumentReference sourceReference, DocumentReference targetReference, boolean relative, - Set updatedDocuments) + Map updatedEntities) throws MacroRefactoringException { return getMacroBlock(macroBlock, currentDocumentReference, sourceReference, targetReference, relative, - updatedDocuments); + updatedEntities); } @Override public Optional replaceReference(MacroBlock macroBlock, DocumentReference currentDocumentReference, AttachmentReference sourceReference, AttachmentReference targetReference, boolean relative, - Set updatedDocuments) + Map updatedEntities) throws MacroRefactoringException { return getMacroBlock(macroBlock, currentDocumentReference, sourceReference, targetReference, relative, - updatedDocuments); + updatedEntities); } @Override @@ -109,7 +110,7 @@ public Optional replaceReference(MacroBlock macroBlock, DocumentRefe throws MacroRefactoringException { return getMacroBlock(macroBlock, currentDocumentReference, sourceReference, targetReference, relative, - Set.of()); + Map.of(sourceReference, targetReference)); } @Override @@ -118,12 +119,13 @@ public Optional replaceReference(MacroBlock macroBlock, DocumentRefe throws MacroRefactoringException { return getMacroBlock(macroBlock, currentDocumentReference, sourceReference, targetReference, relative, - Set.of()); + Map.of(sourceReference.getDocumentReference(), targetReference.getDocumentReference())); } + // FIXME: double check we don't need to use updated documents parameters here. private Optional getMacroBlock(MacroBlock macroBlock, DocumentReference currentDocumentReference, T sourceReference, T targetReference, boolean relative, - Set updatedDocuments) + Map updatedEntities) throws MacroRefactoringException { Optional result; diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-include/src/test/java/org/xwiki/rendering/internal/macro/include/IncludeMacroRefactoringTest.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-include/src/test/java/org/xwiki/rendering/internal/macro/include/IncludeMacroRefactoringTest.java index 9de3b607d9dc..93c0192c8c26 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-include/src/test/java/org/xwiki/rendering/internal/macro/include/IncludeMacroRefactoringTest.java +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-macros/xwiki-platform-rendering-macro-include/src/test/java/org/xwiki/rendering/internal/macro/include/IncludeMacroRefactoringTest.java @@ -20,6 +20,7 @@ package org.xwiki.rendering.internal.macro.include; import java.util.Collections; +import java.util.Map; import java.util.Optional; import java.util.Set; @@ -110,7 +111,7 @@ void replaceDocumentReferenceWhenNoReferenceParameterSet() throws Exception { MacroBlock block = new MacroBlock("include", Collections.emptyMap(), false); assertEquals(Optional.empty(), this.includeMacroRefactoring.replaceReference(block, null, null, - (DocumentReference) null, false, Set.of())); + (DocumentReference) null, false, Map.of())); } @Test @@ -119,7 +120,7 @@ void replaceDocumentReferenceWhenEmptyReferenceParameterSet() throws Exception MacroBlock block = new MacroBlock("include", Collections.emptyMap(), false); block.setParameter("reference", ""); assertEquals(Optional.empty(), this.includeMacroRefactoring.replaceReference(block, null, null, - (DocumentReference) null, false, Set.of())); + (DocumentReference) null, false, Map.of())); } @Test @@ -128,7 +129,7 @@ void replaceDocumentReferenceWhenEmptyPageParameterSet() throws Exception MacroBlock block = new MacroBlock("include", Collections.emptyMap(), false); block.setParameter("page", ""); assertEquals(Optional.empty(), this.includeMacroRefactoring.replaceReference(block, null, null, - (DocumentReference) null, false, Set.of())); + (DocumentReference) null, false, Map.of())); } @Test @@ -153,7 +154,7 @@ void replaceDocumentReferenceWhenIncludedReferenceIsRenamedUsingReferenceParamet new EntityReference("sourcewiki", EntityType.WIKI))).thenReturn("sourcespace.foo"); Optional result = this.includeMacroRefactoring.replaceReference(block, currentReference, - sourceReference, targetReference, false, Set.of()); + sourceReference, targetReference, false, Map.of()); assertFalse(result.isEmpty()); assertEquals("targetwiki:targetspace.targetfoo", result.get().getParameter("reference")); } @@ -189,7 +190,7 @@ void replaceDocumentReferenceWhenIncludingDocumentRenamedUsingReferenceParameter new EntityReference("sourcewiki", EntityType.WIKI))).thenReturn("sourcespace.foo"); Optional result = this.includeMacroRefactoring.replaceReference(block, null, - sourceReference, targetReference, false, Set.of()); + sourceReference, targetReference, false, Map.of()); assertFalse(result.isEmpty()); assertEquals("sourcewiki:sourcespace.foo", result.get().getParameter("reference")); } @@ -225,7 +226,7 @@ void replaceDocumentReferenceWhenIncludingDocumentRenamedUsingPageParameterAndNo new EntityReference("sourcewiki", EntityType.WIKI))).thenReturn("sourcespace/foo"); Optional result = this.includeMacroRefactoring.replaceReference(block, null, - sourceReference, targetReference, false, Set.of()); + sourceReference, targetReference, false, Map.of()); assertFalse(result.isEmpty()); assertEquals("sourcewiki:sourcespace.foo", result.get().getParameter("page")); } @@ -254,7 +255,7 @@ void replaceDocumentReferenceWhenIncludedReferenceIsRenamedUsingPageParameterAnd new EntityReference("sourcewiki", EntityType.WIKI))).thenReturn("sourcespace/foo"); Optional result = this.includeMacroRefactoring.replaceReference(block, currentReference, - sourceReference, targetReference, false, Set.of()); + sourceReference, targetReference, false, Map.of()); assertFalse(result.isEmpty()); assertEquals("targetwiki:targetspace.targetfoo", result.get().getParameter("page")); } @@ -282,7 +283,7 @@ void replaceDocumentReferenceWhenIncludingDocumentIsRenamedToSameReference() thr new EntityReference("sourcewiki", EntityType.WIKI))).thenReturn("sourcespace.foo"); Optional result = this.includeMacroRefactoring.replaceReference(block, null, sourceReference, - targetReference, false, Set.of()); + targetReference, false, Map.of()); assertTrue(result.isEmpty()); } @@ -312,7 +313,7 @@ void replaceAttachmentReferenceWhenIncludedAttachmentReferenceIsRenamedUsingRefe new EntityReference("sourcewiki", EntityType.WIKI))).thenReturn("sourcespace.foo"); Optional result = this.includeMacroRefactoring.replaceReference(block, currentReference, - sourceReference, targetAttachmentReference, false, Set.of()); + sourceReference, targetAttachmentReference, false, Map.of()); assertFalse(result.isEmpty()); assertEquals("targetwiki:targetspace.targetfoo@targetfile", result.get().getParameter("reference")); } @@ -355,7 +356,7 @@ void replaceDocumentReferenceWhenIncludingDocumentIsRenamedUsingAttachmentRefere new EntityReference("sourcewiki", EntityType.WIKI))).thenReturn("sourcespace.foopage@foofile"); Optional result = this.includeMacroRefactoring.replaceReference(block, null, - sourceReference, targetReference, false, Set.of()); + sourceReference, targetReference, false, Map.of()); assertFalse(result.isEmpty()); assertEquals("sourcewiki:sourcespace.foopage@foofile", result.get().getParameter("reference")); } @@ -370,7 +371,7 @@ void replaceDocumentReferenceWhenParametersPopulateError() throws Exception Throwable exception = assertThrows(MacroRefactoringException.class, () -> this.includeMacroRefactoring.replaceReference(block, null, null, (DocumentReference) null, false, - Set.of())); + Map.of())); assertEquals("There's one or several invalid parameters for an [include] macro with parameters " + "[{type=invalid}]", exception.getMessage()); } diff --git a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/macro/MacroRefactoring.java b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/macro/MacroRefactoring.java index 8603a14e3eda..e752a0981ec7 100644 --- a/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/macro/MacroRefactoring.java +++ b/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-xwiki/src/main/java/org/xwiki/rendering/macro/MacroRefactoring.java @@ -20,12 +20,14 @@ package org.xwiki.rendering.macro; import java.util.Collections; +import java.util.Map; import java.util.Optional; import java.util.Set; import org.xwiki.component.annotation.Role; import org.xwiki.model.reference.AttachmentReference; import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.EntityReference; import org.xwiki.rendering.block.MacroBlock; import org.xwiki.rendering.listener.reference.ResourceReference; import org.xwiki.stability.Unstable; @@ -70,8 +72,8 @@ Optional replaceReference(MacroBlock macroBlock, DocumentReference c * @param targetReference the reference to use as replacement. * @param relative if {@code true} indicate that the reference should be resolved relatively to the current * document - * @param updatedDocuments the list of documents that have been renamed in the same job: this list contains the - * old references before the rename + * @param updatedEntities the map of entities that are or are going to be updated: the map contains the source + * and target destination. * @return an optional containing the new macro block with proper information if it needs to be updated, else an * empty optional. * @throws MacroRefactoringException in case of problem to parse or render the macro content. @@ -80,7 +82,7 @@ Optional replaceReference(MacroBlock macroBlock, DocumentReference c @Unstable default Optional replaceReference(MacroBlock macroBlock, DocumentReference currentDocumentReference, DocumentReference sourceReference, DocumentReference targetReference, boolean relative, - Set updatedDocuments) + Map updatedEntities) throws MacroRefactoringException { return replaceReference(macroBlock, currentDocumentReference, sourceReference, targetReference, relative); @@ -118,8 +120,8 @@ Optional replaceReference(MacroBlock macroBlock, DocumentReference c * @param targetReference the reference to use as replacement * @param relative if {@code true} indicate that the reference should be resolved relatively to the current * document - * @param updatedDocuments the list of documents that have been renamed in the same job: this list contains the - * old references before the rename + * @param updatedEntities the map of entities that are or are going to be updated: the map contains the source + * and target destination. * @return an optional containing the new macro block with proper information if it needs to be updated, else an * empty optional. * @throws MacroRefactoringException in case of problem to parse or render the macro content. @@ -128,7 +130,7 @@ Optional replaceReference(MacroBlock macroBlock, DocumentReference c @Unstable default Optional replaceReference(MacroBlock macroBlock, DocumentReference currentDocumentReference, AttachmentReference sourceReference, AttachmentReference targetReference, boolean relative, - Set updatedDocuments) + Map updatedEntities) throws MacroRefactoringException { return replaceReference(macroBlock, currentDocumentReference, sourceReference, targetReference, relative);