/* * 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; import javax.inject.Named; import org.xwiki.component.annotation.Component; import org.xwiki.model.EntityType; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.EntityReference; import org.xwiki.model.reference.SpaceReference; import org.xwiki.refactoring.job.CreateRequest; import org.xwiki.refactoring.job.EntityJobStatus; import org.xwiki.refactoring.job.RefactoringJobs; import org.xwiki.security.authorization.Right; /** * A job that can create entities (optionally, from a template). * * @version $Id: f580c228f45ef66320c3aed5125bf7616c90a49e $ * @since 7.4M2 */ @Component @Named(RefactoringJobs.CREATE) public class CreateJob extends AbstractEntityJob<CreateRequest, EntityJobStatus<CreateRequest>> { @Override public String getType() { return RefactoringJobs.CREATE; } @Override protected void process(EntityReference entityReference) { // Dispatch the create operation based on the entity type. switch (entityReference.getType()) { case DOCUMENT: process(new DocumentReference(entityReference)); break; case SPACE: process(new SpaceReference(entityReference)); break; default: this.logger.error("Unsupported entity type [{}].", entityReference.getType()); } } private void process(DocumentReference documentReference) { // The template, if specified, must be a document. DocumentReference templateDocumentReference = null; if (this.request.getTemplateReference() != null && this.request.getTemplateReference().extractReference(EntityType.DOCUMENT) != null) { templateDocumentReference = new DocumentReference(this.request.getTemplateReference().extractReference(EntityType.DOCUMENT)); } progressManager.pushLevelProgress(3, this); try { progressManager.startStep(this, "Main document"); // Handle the target document creation first maybeCreate(documentReference, templateDocumentReference); progressManager.startStep(this, "Template children"); // If both the target and template documents are non-terminal and also the operation is deep, handle // possible children of the template document. if (this.request.isDeep() && isSpaceHomeReference(documentReference) && templateDocumentReference != null && isSpaceHomeReference(templateDocumentReference)) { process(documentReference.getLastSpaceReference()); } progressManager.startStep(this, "Remove lock from the main document"); // Remove any existing lock of the user that started this job on the target document. this.modelBridge.removeLock(documentReference); } finally { // Done, go back to parent progress level this.progressManager.popLevelProgress(this); } } private void process(final SpaceReference newSpaceReference) { // The template, if specified, must be a space. SpaceReference extractedSpaceReference = null; if (this.request.getTemplateReference() != null && this.request.getTemplateReference().extractReference(EntityType.SPACE) != null) { extractedSpaceReference = new SpaceReference(this.request.getTemplateReference().extractReference(EntityType.SPACE)); } final SpaceReference templateSpaceReference = extractedSpaceReference; if (templateSpaceReference != null) { // Space from template space. visitDocuments(templateSpaceReference, new Visitor<DocumentReference>() { @Override public void visit(final DocumentReference templateDocumentReference) { DocumentReference newDocumentReference = templateDocumentReference.replaceParent(templateSpaceReference, newSpaceReference); maybeCreate(newDocumentReference, templateDocumentReference); } }); } else { // Empty space (webhome document). DocumentReference newSpaceWebHomeReference = new DocumentReference("WebHome", newSpaceReference); maybeCreate(newSpaceWebHomeReference, null); } } private void maybeCreate(DocumentReference newDocumentReference, DocumentReference templateDocumentReference) { if (request.getSkippedEntities().contains(newDocumentReference)) { this.logger.debug("Skipping creation of document [{}], as specified in the request.", newDocumentReference); } else if (this.modelBridge.exists(newDocumentReference)) { // TODO: Ask the user if it's OK to override. For now, just log. this.logger.warn("Skipping creation of document [{}] because it already exists.", newDocumentReference); } else if (!hasAccess(Right.EDIT, newDocumentReference)) { this.logger.error("You are not allowed to create the document [{}].", newDocumentReference); } else if (templateDocumentReference == null) { // If no template is specified, then we are just creating an empty document. this.modelBridge.create(newDocumentReference); } else if (!hasAccess(Right.VIEW, templateDocumentReference)) { this.logger.error("You are not allowed to view the template document [{}].", templateDocumentReference); } else if (!this.modelBridge.exists(templateDocumentReference)) { // Should generally not happen, but you never know. this.logger.error("Template document [{}] does not exist.", templateDocumentReference); } else { this.modelBridge.copy(templateDocumentReference, newDocumentReference); } } }