001/*
002 * (C) Copyright 2014-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 *     Nuxeo - initial API and implementation
018 *     Thibaud Arguillere (Nuxeo)
019 */
020package org.nuxeo.ecm.platform.importer.factories;
021
022import java.io.IOException;
023import java.io.Serializable;
024import java.util.Collections;
025import java.util.List;
026import java.util.Map;
027
028import org.apache.commons.lang3.StringUtils;
029import org.nuxeo.ecm.core.api.Blob;
030import org.nuxeo.ecm.core.api.CoreSession;
031import org.nuxeo.ecm.core.api.DocumentModel;
032import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
033import org.nuxeo.ecm.platform.importer.source.SourceNode;
034
035/**
036 * Default implementation for DocumentModel factory The default empty constructor create Folder for folderish file and
037 * File for other. But you can specify them using the other constructor. Also, if you are using .properties files to
038 * setup metada, you can use the ecm:primaryType xpath to specify the type of document to create. This will override the
039 * default ones, and works for files and folders. If no .properties file is provided of it the current node has a
040 * .properties file but no ecm:primaryType, the default types are created. This works for leafType but also for
041 * folderish type.
042 *
043 * @author Thierry Delprat
044 * @author Daniel Tellez
045 * @author Thibaud Arguillere
046 */
047public class DefaultDocumentModelFactory extends AbstractDocumentModelFactory {
048
049    public static final String DOCTYPE_KEY_NAME = "ecm:primaryType";
050
051    public static final String FACETS_KEY_NAME = "ecm:mixinTypes";
052
053    protected String folderishType;
054
055    protected String leafType;
056
057    /**
058     * Instantiate a DefaultDocumentModelFactory that creates Folder and File
059     */
060    public DefaultDocumentModelFactory() {
061        this("Folder", "File");
062    }
063
064    /**
065     * Instantiate a DefaultDocumentModelFactory that creates specified types doc
066     *
067     * @param folderishType the folderish type
068     * @param leafType the other type
069     */
070    public DefaultDocumentModelFactory(String folderishType, String leafType) {
071        this.folderishType = folderishType;
072        this.leafType = leafType;
073    }
074
075    /*
076     * (non-Javadoc)
077     * @seeorg.nuxeo.ecm.platform.importer.base.ImporterDocumentModelFactory#
078     * createFolderishNode(org.nuxeo.ecm.core.api.CoreSession, org.nuxeo.ecm.core.api.DocumentModel,
079     * org.nuxeo.ecm.platform.importer.base.SourceNode)
080     */
081    @Override
082    public DocumentModel createFolderishNode(CoreSession session, DocumentModel parent, SourceNode node)
083            throws IOException {
084
085        String name = getValidNameFromFileName(node.getName());
086
087        BlobHolder bh = node.getBlobHolder();
088        String folderishTypeToUse = getDocTypeToUse(bh);
089        if (folderishTypeToUse == null) {
090            folderishTypeToUse = folderishType;
091        }
092        List<String> facets = getFacetsToUse(bh);
093
094        DocumentModel doc = session.createDocumentModel(parent.getPathAsString(), name, folderishTypeToUse);
095        for (String facet : facets) {
096            doc.addFacet(facet);
097        }
098        doc.setProperty("dublincore", "title", node.getName());
099        doc = session.createDocument(doc);
100        if (bh != null) {
101            doc = setDocumentProperties(session, bh.getProperties(), doc);
102        }
103
104        return doc;
105    }
106
107    /*
108     * (non-Javadoc)
109     * @seeorg.nuxeo.ecm.platform.importer.base.ImporterDocumentModelFactory#
110     * createLeafNode(org.nuxeo.ecm.core.api.CoreSession, org.nuxeo.ecm.core.api.DocumentModel,
111     * org.nuxeo.ecm.platform.importer.base.SourceNode)
112     */
113    @Override
114    public DocumentModel createLeafNode(CoreSession session, DocumentModel parent, SourceNode node) throws IOException {
115        return defaultCreateLeafNode(session, parent, node);
116    }
117
118    protected DocumentModel defaultCreateLeafNode(CoreSession session, DocumentModel parent, SourceNode node)
119            throws IOException {
120
121        Blob blob = null;
122        Map<String, Serializable> props = null;
123        String leafTypeToUse = leafType;
124        BlobHolder bh = node.getBlobHolder();
125        if (bh != null) {
126            blob = bh.getBlob();
127            props = bh.getProperties();
128            String bhType = getDocTypeToUse(bh);
129            if (bhType != null) {
130                leafTypeToUse = bhType;
131            }
132        }
133        String fileName = node.getName();
134        String name = getValidNameFromFileName(fileName);
135        DocumentModel doc = session.createDocumentModel(parent.getPathAsString(), name, leafTypeToUse);
136        for (String facet : getFacetsToUse(bh)) {
137            doc.addFacet(facet);
138        }
139        doc.setProperty("dublincore", "title", node.getName());
140        if (blob != null && blob.getLength() > 0) {
141            blob.setFilename(fileName);
142            doc.setProperty("file", "content", blob);
143        }
144        doc = session.createDocument(doc);
145        if (props != null) {
146            doc = setDocumentProperties(session, props, doc);
147        }
148        return doc;
149    }
150
151    /*
152     * Return null if DOCTYPE_KEY_NAME is not in the properties or has been set to nothing.
153     */
154    protected String getDocTypeToUse(BlobHolder inBH) {
155        String type = null;
156
157        if (inBH != null) {
158            Map<String, Serializable> props = inBH.getProperties();
159            if (props != null) {
160                type = (String) props.get(DOCTYPE_KEY_NAME);
161                if (type != null && type.isEmpty()) {
162                    type = null;
163                }
164            }
165        }
166
167        return type;
168    }
169
170    protected List<String> getFacetsToUse(BlobHolder inBH) {
171        if (inBH != null) {
172            Map<String, Serializable> props = inBH.getProperties();
173            if (props != null) {
174                Serializable ob = props.get(FACETS_KEY_NAME);
175                if (ob instanceof String) {
176                    String facet = (String) ob;
177                    if (StringUtils.isNotBlank(facet)) {
178                        return Collections.singletonList(facet);
179                    }
180                } else if (ob != null) {
181                    return (List<String>) ob;
182                }
183            }
184        }
185        return Collections.emptyList();
186    }
187
188    /**
189     * Modify this to get right mime types depending on the file input
190     *
191     * @deprecated since 10.1 seems unused
192     */
193    @Deprecated
194    protected String getMimeType(String name) {
195        // Dummy MimeType detection : plug nuxeo Real MimeType service to
196        // have better results
197
198        if (name == null) {
199            return "application/octet-stream";
200            /* OpenOffice.org 2.x document types */
201        } else if (name.endsWith(".odp")) {
202            return "application/vnd.oasis.opendocument.presentation";
203        } else if (name.endsWith(".otp")) {
204            return "application/vnd.oasis.opendocument.presentation-template";
205        } else if (name.endsWith(".otg")) {
206            return "application/vnd.oasis.opendocument.graphics-template";
207        } else if (name.endsWith(".odg")) {
208            return "application/vnd.oasis.opendocument.graphics";
209        } else if (name.endsWith(".odt")) {
210            return "application/vnd.oasis.opendocument.text";
211        } else if (name.endsWith(".ott")) {
212            return "application/vnd.oasis.opendocument.text-template";
213        } else if (name.endsWith(".ods")) {
214            return "application/vnd.oasis.opendocument.spreadsheet";
215        } else if (name.endsWith(".ots")) {
216            return "application/vnd.oasis.opendocument.spreadsheet-template";
217            /* Microsoft Office document */
218        } else if (name.endsWith(".doc")) {
219            return "application/msword";
220        } else if (name.endsWith(".xls")) {
221            return "application/vnd.ms-excel";
222        } else if (name.endsWith(".ppt")) {
223            return "application/vnd.ms-powerpoint";
224            /* Ms Office 2007 */
225        } else if (name.endsWith(".xlsx")) {
226            return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
227        } else if (name.endsWith(".pptx")) {
228            return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
229        } else if (name.endsWith(".docx")) {
230            return "application/vnd.openxmlformats-officedocument.wordprocessingml.template";
231            /* Other */
232        } else if (name.endsWith(".tar")) {
233            return "application/x-gtar";
234        } else if (name.endsWith(".gz")) {
235            return "application/x-gtar";
236        } else if (name.endsWith(".csv")) {
237            return "text/csv";
238        } else if (name.endsWith(".pdf")) {
239            return "application/pdf";
240        } else if (name.endsWith(".txt")) {
241            return "text/plain";
242        } else if (name.endsWith(".html")) {
243            return "text/html";
244        } else if (name.endsWith(".xml")) {
245            return "text/xml";
246        } else if (name.endsWith(".png")) {
247            return "image/png";
248        } else if (name.endsWith(".jpg")) {
249            return "image/jpg";
250        } else if (name.endsWith(".jpeg")) {
251            return "image/jpeg";
252        } else if (name.endsWith(".gif")) {
253            return "image/gif";
254        } else if (name.endsWith(".zip")) {
255            return "application/zip";
256        } else {
257            return "application/octet-stream";
258        }
259    }
260
261    public void setFolderishType(String folderishType) {
262        this.folderishType = folderishType;
263    }
264
265    public void setLeafType(String leafType) {
266        this.leafType = leafType;
267    }
268
269}