001/*
002 * (C) Copyright 2006-2019 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 *     Nuxeo - initial API and implementation
018 *     Thierry Delprat (td@nuxeo.com)
019 *     Nuno Cunha (ncunha@nuxeo.com)
020 */
021
022package org.nuxeo.ecm.platform.dublincore.service;
023
024import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.ABOUT_TO_CREATE;
025import static org.nuxeo.ecm.core.api.security.SecurityConstants.SYSTEM_USERNAME;
026import static org.nuxeo.ecm.platform.dublincore.constants.DublinCoreConstants.DUBLINCORE_CONTRIBUTORS_PROPERTY;
027import static org.nuxeo.ecm.platform.dublincore.constants.DublinCoreConstants.DUBLINCORE_CREATED_DATE_PROPERTY;
028import static org.nuxeo.ecm.platform.dublincore.constants.DublinCoreConstants.DUBLINCORE_CREATOR_PROPERTY;
029import static org.nuxeo.ecm.platform.dublincore.constants.DublinCoreConstants.DUBLINCORE_ISSUED_DATE_PROPERTY;
030import static org.nuxeo.ecm.platform.dublincore.constants.DublinCoreConstants.DUBLINCORE_LAST_CONTRIBUTOR_PROPERTY;
031import static org.nuxeo.ecm.platform.dublincore.constants.DublinCoreConstants.DUBLINCORE_MODIFIED_DATE_PROPERTY;
032
033import java.io.Serializable;
034import java.util.ArrayList;
035import java.util.Arrays;
036import java.util.Calendar;
037import java.util.List;
038import java.util.Objects;
039import java.util.stream.Collectors;
040
041import org.apache.commons.lang3.ArrayUtils;
042import org.nuxeo.ecm.core.api.DocumentModel;
043import org.nuxeo.ecm.core.api.NuxeoPrincipal;
044import org.nuxeo.ecm.core.api.SystemPrincipal;
045import org.nuxeo.ecm.core.event.Event;
046import org.nuxeo.runtime.api.Framework;
047import org.nuxeo.runtime.model.DefaultComponent;
048
049/**
050 * DublinCore Storage Service Implementation.
051 *
052 * @since 10.2
053 */
054public class DublinCoreStorageServiceImpl extends DefaultComponent implements DublinCoreStorageService {
055
056    @Override
057    public void setCreationDate(DocumentModel doc, Calendar creationDate) {
058        Framework.doPrivileged(() -> doc.setPropertyValue(DUBLINCORE_CREATED_DATE_PROPERTY, creationDate));
059    }
060
061    @Override
062    public void setIssuedDate(DocumentModel doc, Calendar issuedDate) {
063        doc.setPropertyValue(DUBLINCORE_ISSUED_DATE_PROPERTY, issuedDate);
064    }
065
066    @Override
067    public void setModificationDate(DocumentModel doc, Calendar modificationDate) {
068        Framework.doPrivileged(() -> {
069            doc.setPropertyValue(DUBLINCORE_MODIFIED_DATE_PROPERTY, modificationDate);
070            if (doc.getPropertyValue(DUBLINCORE_CREATED_DATE_PROPERTY) == null) {
071                setCreationDate(doc, modificationDate);
072            }
073        });
074    }
075
076    @Override
077    public void addContributor(DocumentModel doc, Event event) {
078        NuxeoPrincipal principal = Objects.requireNonNull(event.getContext().getPrincipal());
079
080        String principalName = principal.getActingUser();
081        if (principal instanceof SystemPrincipal && SYSTEM_USERNAME.equals(principalName)
082                && !ABOUT_TO_CREATE.equals(event.getName())) {
083            return;
084        }
085
086        List<String> contributorsList = getSanitizedExistingContributors(doc);
087        if (!contributorsList.contains(principalName)) {
088            contributorsList.add(principalName);
089        }
090
091        Framework.doPrivileged(() -> {
092            if (doc.getPropertyValue(DUBLINCORE_CREATOR_PROPERTY) == null) {
093                doc.setPropertyValue(DUBLINCORE_CREATOR_PROPERTY, principalName);
094            }
095            doc.setPropertyValue(DUBLINCORE_CONTRIBUTORS_PROPERTY, (Serializable) contributorsList);
096            doc.setPropertyValue(DUBLINCORE_LAST_CONTRIBUTOR_PROPERTY, principalName);
097        });
098    }
099
100    /**
101     * Returns a "Sanitized" list of contributors according to NXP-25005
102     *
103     * @param doc The document from which the contributors list will be retrieved.
104     * @return A list of contributors without repetitions and prefixed entries.
105     */
106    protected List<String> getSanitizedExistingContributors(DocumentModel doc) {
107        String[] contributorsArray = (String[]) doc.getPropertyValue(DUBLINCORE_CONTRIBUTORS_PROPERTY);
108        if (ArrayUtils.isEmpty(contributorsArray)) {
109            return new ArrayList<>();
110        }
111        return Arrays.stream(contributorsArray)
112                     .map(DublinCoreStorageServiceImpl::stripPrincipalPrefix)
113                     .distinct()
114                     .collect(Collectors.toList());
115    }
116
117    protected static String stripPrincipalPrefix(String principal) {
118        if (principal.startsWith(NuxeoPrincipal.PREFIX)) {
119            return principal.substring(NuxeoPrincipal.PREFIX.length());
120        } else {
121            return principal;
122        }
123    }
124
125}