001/*
002 * (C) Copyright 2012-2018 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 */
019
020package org.nuxeo.ecm.csv.core;
021
022import static org.nuxeo.ecm.core.api.LifeCycleConstants.INITIAL_LIFECYCLE_STATE_OPTION_NAME;
023
024import java.io.Serializable;
025import java.util.ArrayList;
026import java.util.Arrays;
027import java.util.Collections;
028import java.util.List;
029import java.util.Map;
030import java.util.UUID;
031
032import org.apache.commons.lang3.StringUtils;
033import org.nuxeo.common.utils.Path;
034import org.nuxeo.ecm.core.api.CoreSession;
035import org.nuxeo.ecm.core.api.DocumentModel;
036import org.nuxeo.ecm.core.api.DocumentRef;
037import org.nuxeo.ecm.core.api.NuxeoException;
038import org.nuxeo.ecm.core.api.PathRef;
039import org.nuxeo.ecm.core.api.impl.DocumentModelImpl;
040import org.nuxeo.ecm.core.query.sql.NXQL;
041import org.nuxeo.ecm.csv.core.CSVImporterOptions.ImportMode;
042
043/**
044 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a>
045 * @since 5.7
046 */
047public class DefaultCSVImporterDocumentFactory implements CSVImporterDocumentFactory {
048
049    private static final long serialVersionUID = 1L;
050
051    public static final String DC_CREATOR = "dc:creator";
052
053    public static final String DC_CONTRIBUTORS = "dc:contributors";
054
055    public static final List<String> IGNORE_FIELDS_ON_UPDATE = Collections.singletonList(NXQL.ECM_LIFECYCLESTATE);
056
057    protected CSVImporterOptions importerOptions = CSVImporterOptions.DEFAULT_OPTIONS;
058
059    @Override
060    public void createDocument(CoreSession session, String parentPath, String name, String type,
061            Map<String, Serializable> values) {
062        values = prepareValues(values);
063        DocumentModel doc = session.createDocumentModel(parentPath, name, type);
064        if (values.containsKey(NXQL.ECM_LIFECYCLESTATE)) {
065            doc.putContextData(INITIAL_LIFECYCLE_STATE_OPTION_NAME, values.get(NXQL.ECM_LIFECYCLESTATE));
066            values.remove(NXQL.ECM_LIFECYCLESTATE);
067        }
068        if (importerOptions.importMode.equals(ImportMode.IMPORT)) {
069            if (values.containsKey(NXQL.ECM_UUID)) {
070                ((DocumentModelImpl) doc).setId((String) values.get(NXQL.ECM_UUID));
071                values.remove(NXQL.ECM_UUID);
072            } else {
073                ((DocumentModelImpl) doc).setId(UUID.randomUUID().toString());
074            }
075            for (Map.Entry<String, Serializable> entry : values.entrySet()) {
076                doc.setPropertyValue(entry.getKey(), entry.getValue());
077            }
078            session.importDocuments(Collections.singletonList(doc));
079        } else {
080            if (values.containsKey(NXQL.ECM_UUID)) {
081                throw new NuxeoException("CSV file contains UUID. Import using Import Mode to avoid overwriting.");
082            }
083            for (Map.Entry<String, Serializable> entry : values.entrySet()) {
084                doc.setPropertyValue(entry.getKey(), entry.getValue());
085            }
086            session.createDocument(doc);
087        }
088    }
089
090    protected Map<String, Serializable> prepareValues(Map<String, Serializable> values) {
091        if (values.containsKey(DC_CREATOR)) {
092            // make sure the creator is part of the contributors
093            String creator = (String) values.get(DC_CREATOR);
094            String[] contributorsArray = (String[]) values.get(DC_CONTRIBUTORS);
095            List<String> contributors = contributorsArray == null ? new ArrayList<>()
096                    : new ArrayList<>(Arrays.asList(contributorsArray));
097            if (StringUtils.isNotBlank(creator) && !contributors.contains(creator)) {
098                contributors.add(creator);
099            }
100            values.put(DC_CONTRIBUTORS, contributors.toArray(new String[contributors.size()]));
101        }
102        return values;
103    }
104
105    @Override
106    public void updateDocument(CoreSession session, DocumentRef docRef, Map<String, Serializable> values) {
107        DocumentModel doc = session.getDocument(docRef);
108        for (Map.Entry<String, Serializable> entry : values.entrySet()) {
109            if (!IGNORE_FIELDS_ON_UPDATE.contains(entry.getKey())) {
110                doc.setPropertyValue(entry.getKey(), entry.getValue());
111            }
112        }
113        session.saveDocument(doc);
114    }
115
116    @Override
117    public boolean exists(CoreSession session, String parentPath, String name, Map<String, Serializable> values) {
118        String targetPath = new Path(parentPath).append(name).toString();
119        DocumentRef docRef = new PathRef(targetPath);
120        return session.exists(docRef);
121    }
122
123    @Override
124    @Deprecated
125    public boolean exists(CoreSession session, String parentPath, String name, String type,
126            Map<String, Serializable> values) {
127        return exists(session, parentPath, name, null);
128    }
129
130    @Override
131    public void setImporterOptions(CSVImporterOptions importerOptions) {
132        this.importerOptions = importerOptions;
133    }
134
135}