001/* 002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Thomas Roger 016 */ 017 018package org.nuxeo.ecm.webapp.bulkedit; 019 020import java.io.Serializable; 021import java.util.ArrayList; 022import java.util.List; 023import java.util.Locale; 024import java.util.Map; 025 026import org.apache.commons.lang.StringUtils; 027import org.apache.commons.logging.Log; 028import org.apache.commons.logging.LogFactory; 029import org.nuxeo.ecm.core.api.CoreSession; 030import org.nuxeo.ecm.core.api.DocumentModel; 031import org.nuxeo.ecm.core.api.VersioningOption; 032import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; 033import org.nuxeo.ecm.core.versioning.VersioningService; 034import org.nuxeo.runtime.model.ComponentInstance; 035import org.nuxeo.runtime.model.DefaultComponent; 036 037/** 038 * Default implementation of {@link BulkEditService}. 039 * 040 * @since 5.7.3 041 */ 042public class BulkEditServiceImpl extends DefaultComponent implements BulkEditService { 043 044 public static final String VERSIONING_EP = "versioning"; 045 046 public static final VersioningOption DEFAULT_VERSIONING_OPTION = VersioningOption.MINOR; 047 048 private static final Log log = LogFactory.getLog(BulkEditServiceImpl.class); 049 050 protected VersioningOption defaultVersioningOption = DEFAULT_VERSIONING_OPTION; 051 052 @Override 053 public void updateDocuments(CoreSession session, DocumentModel sourceDoc, List<DocumentModel> targetDocs) 054 { 055 List<String> propertiesToCopy = getPropertiesToCopy(sourceDoc); 056 if (propertiesToCopy.isEmpty()) { 057 return; 058 } 059 060 for (DocumentModel targetDoc : targetDocs) { 061 062 for (String propertyToCopy : propertiesToCopy) { 063 try { 064 targetDoc.setPropertyValue(propertyToCopy, sourceDoc.getPropertyValue(propertyToCopy)); 065 } catch (PropertyNotFoundException e) { 066 String message = "%s property does not exist on %s"; 067 log.warn(String.format(message, propertyToCopy, targetDoc)); 068 } 069 } 070 targetDoc.putContextData(VersioningService.VERSIONING_OPTION, defaultVersioningOption); 071 session.saveDocument(targetDoc); 072 } 073 } 074 075 /** 076 * Extracts the properties to be copied from {@code sourceDoc}. The properties are stored in the ContextData of 077 * {@code sourceDoc}: the key is the xpath property, the value is {@code true} if the property has to be copied, 078 * {@code false otherwise}. 079 */ 080 protected List<String> getPropertiesToCopy(DocumentModel sourceDoc) { 081 List<String> propertiesToCopy = new ArrayList<String>(); 082 for (Map.Entry<String, Serializable> entry : sourceDoc.getContextData().entrySet()) { 083 String key = entry.getKey(); 084 if (key.startsWith(BULK_EDIT_PREFIX)) { 085 String[] properties = key.replace(BULK_EDIT_PREFIX, "").split(" "); 086 Serializable value = entry.getValue(); 087 if (value instanceof Boolean && (Boolean) value) { 088 for (String property : properties) { 089 if (!property.startsWith(CONTEXT_DATA)) { 090 propertiesToCopy.add(property); 091 } 092 } 093 } 094 } 095 } 096 return propertiesToCopy; 097 } 098 099 /** 100 * @deprecated since 7.3. The option is passed to the CoreSession#saveDocument method. 101 */ 102 @Deprecated 103 protected void checkIn(DocumentModel doc) { 104 if (defaultVersioningOption != null && defaultVersioningOption != VersioningOption.NONE) { 105 if (doc.isCheckedOut()) { 106 doc.checkIn(defaultVersioningOption, null); 107 } 108 } 109 } 110 111 @Override 112 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 113 if (VERSIONING_EP.equals(extensionPoint)) { 114 VersioningDescriptor desc = (VersioningDescriptor) contribution; 115 String defaultVer = desc.getDefaultVersioningOption(); 116 if (!StringUtils.isBlank(defaultVer)) { 117 try { 118 defaultVersioningOption = VersioningOption.valueOf(defaultVer.toUpperCase(Locale.ENGLISH)); 119 } catch (IllegalArgumentException e) { 120 log.warn(String.format("Illegal versioning option: %s, using %s instead", defaultVer, 121 DEFAULT_VERSIONING_OPTION)); 122 defaultVersioningOption = DEFAULT_VERSIONING_OPTION; 123 } 124 } 125 } 126 } 127 128 @Override 129 public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 130 if (VERSIONING_EP.equals(extensionPoint)) { 131 defaultVersioningOption = DEFAULT_VERSIONING_OPTION; 132 } 133 } 134 135}