001/* 002 * (C) Copyright 2013-2017 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Thomas Roger 018 */ 019package org.nuxeo.ecm.webapp.bulkedit; 020 021import java.io.Serializable; 022import java.util.ArrayList; 023import java.util.List; 024import java.util.Locale; 025import java.util.Map; 026 027import org.apache.commons.lang3.StringUtils; 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030import org.nuxeo.ecm.core.api.CoreSession; 031import org.nuxeo.ecm.core.api.DocumentModel; 032import org.nuxeo.ecm.core.api.VersioningOption; 033import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; 034import org.nuxeo.runtime.api.Framework; 035import org.nuxeo.runtime.logging.DeprecationLogger; 036import org.nuxeo.runtime.model.ComponentInstance; 037import org.nuxeo.runtime.model.DefaultComponent; 038 039/** 040 * Default implementation of {@link BulkEditService}. 041 * 042 * @since 5.7.3 043 */ 044public class BulkEditServiceImpl extends DefaultComponent implements BulkEditService { 045 046 public static final String VERSIONING_EP = "versioning"; 047 048 /** 049 * @deprecated since 9.1 automatic versioning mechanism has been moved to versioning service, this field is not used 050 * anymore 051 */ 052 @Deprecated 053 public static final VersioningOption DEFAULT_VERSIONING_OPTION = VersioningOption.MINOR; 054 055 private static final Log log = LogFactory.getLog(BulkEditServiceImpl.class); 056 057 /** 058 * @deprecated since 9.1 automatic versioning mechanism has been moved to versioning service, this field is not used 059 * anymore 060 */ 061 @Deprecated 062 protected VersioningOption defaultVersioningOption = DEFAULT_VERSIONING_OPTION; 063 064 @Override 065 public void updateDocuments(CoreSession session, DocumentModel sourceDoc, List<DocumentModel> targetDocs) 066 { 067 List<String> propertiesToCopy = getPropertiesToCopy(sourceDoc); 068 if (propertiesToCopy.isEmpty()) { 069 return; 070 } 071 072 for (DocumentModel targetDoc : targetDocs) { 073 074 for (String propertyToCopy : propertiesToCopy) { 075 try { 076 targetDoc.setPropertyValue(propertyToCopy, sourceDoc.getPropertyValue(propertyToCopy)); 077 } catch (PropertyNotFoundException e) { 078 String message = "%s property does not exist on %s"; 079 log.warn(String.format(message, propertyToCopy, targetDoc)); 080 } 081 } 082 targetDoc.putContextData(CoreSession.SOURCE, "bulkEdit"); 083 session.saveDocument(targetDoc); 084 } 085 } 086 087 /** 088 * Extracts the properties to be copied from {@code sourceDoc}. The properties are stored in the ContextData of 089 * {@code sourceDoc}: the key is the xpath property, the value is {@code true} if the property has to be copied, 090 * {@code false otherwise}. 091 */ 092 protected List<String> getPropertiesToCopy(DocumentModel sourceDoc) { 093 List<String> propertiesToCopy = new ArrayList<>(); 094 for (Map.Entry<String, Serializable> entry : sourceDoc.getContextData().entrySet()) { 095 String key = entry.getKey(); 096 if (key.startsWith(BULK_EDIT_PREFIX)) { 097 String[] properties = key.replace(BULK_EDIT_PREFIX, "").split(" "); 098 Serializable value = entry.getValue(); 099 if (value instanceof Boolean && (Boolean) value) { 100 for (String property : properties) { 101 if (!property.startsWith(CONTEXT_DATA)) { 102 propertiesToCopy.add(property); 103 } 104 } 105 } 106 } 107 } 108 return propertiesToCopy; 109 } 110 111 /** 112 * @deprecated since 7.3. The option is passed to the CoreSession#saveDocument method. 113 */ 114 @Deprecated 115 protected void checkIn(DocumentModel doc) { 116 if (defaultVersioningOption != null && defaultVersioningOption != VersioningOption.NONE) { 117 if (doc.isCheckedOut()) { 118 doc.checkIn(defaultVersioningOption, null); 119 } 120 } 121 } 122 123 @Override 124 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 125 if (VERSIONING_EP.equals(extensionPoint)) { 126 String message = "Extension point 'versioning' has been deprecated and corresponding behavior removed from " 127 + "Nuxeo Platform. Please use versioning policy instead."; 128 DeprecationLogger.log(message, "9.1"); 129 Framework.getRuntime().getMessageHandler().addWarning(message); 130 VersioningDescriptor desc = (VersioningDescriptor) contribution; 131 String defaultVer = desc.getDefaultVersioningOption(); 132 if (!StringUtils.isBlank(defaultVer)) { 133 try { 134 defaultVersioningOption = VersioningOption.valueOf(defaultVer.toUpperCase(Locale.ENGLISH)); 135 } catch (IllegalArgumentException e) { 136 log.warn(String.format("Illegal versioning option: %s, using %s instead", defaultVer, 137 DEFAULT_VERSIONING_OPTION)); 138 defaultVersioningOption = DEFAULT_VERSIONING_OPTION; 139 } 140 } 141 } 142 } 143 144 @Override 145 public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 146 if (VERSIONING_EP.equals(extensionPoint)) { 147 defaultVersioningOption = DEFAULT_VERSIONING_OPTION; 148 } 149 } 150 151}