001/*
002 * (C) Copyright 2014-2016 Nuxeo SA (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.lang.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    /** Modify this to get right mime types depending on the file input */
189    protected String getMimeType(String name) {
190        // Dummy MimeType detection : plug nuxeo Real MimeType service to
191        // have better results
192
193        if (name == null) {
194            return "application/octet-stream";
195            /* OpenOffice.org 2.x document types */
196        } else if (name.endsWith(".odp")) {
197            return "application/vnd.oasis.opendocument.presentation";
198        } else if (name.endsWith(".otp")) {
199            return "application/vnd.oasis.opendocument.presentation-template";
200        } else if (name.endsWith(".otg")) {
201            return "application/vnd.oasis.opendocument.graphics-template";
202        } else if (name.endsWith(".odg")) {
203            return "application/vnd.oasis.opendocument.graphics";
204        } else if (name.endsWith(".odt")) {
205            return "application/vnd.oasis.opendocument.text";
206        } else if (name.endsWith(".ott")) {
207            return "application/vnd.oasis.opendocument.text-template";
208        } else if (name.endsWith(".ods")) {
209            return "application/vnd.oasis.opendocument.spreadsheet";
210        } else if (name.endsWith(".ots")) {
211            return "application/vnd.oasis.opendocument.spreadsheet-template";
212            /* Microsoft Office document */
213        } else if (name.endsWith(".doc")) {
214            return "application/msword";
215        } else if (name.endsWith(".xls")) {
216            return "application/vnd.ms-excel";
217        } else if (name.endsWith(".ppt")) {
218            return "application/vnd.ms-powerpoint";
219            /* Ms Office 2007 */
220        } else if (name.endsWith(".xlsx")) {
221            return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
222        } else if (name.endsWith(".pptx")) {
223            return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
224        } else if (name.endsWith(".docx")) {
225            return "application/vnd.openxmlformats-officedocument.wordprocessingml.template";
226            /* Other */
227        } else if (name.endsWith(".tar")) {
228            return "application/x-gtar";
229        } else if (name.endsWith(".gz")) {
230            return "application/x-gtar";
231        } else if (name.endsWith(".csv")) {
232            return "text/csv";
233        } else if (name.endsWith(".pdf")) {
234            return "application/pdf";
235        } else if (name.endsWith(".txt")) {
236            return "text/plain";
237        } else if (name.endsWith(".html")) {
238            return "text/html";
239        } else if (name.endsWith(".xml")) {
240            return "text/xml";
241        } else if (name.endsWith(".png")) {
242            return "image/png";
243        } else if (name.endsWith(".jpg")) {
244            return "image/jpg";
245        } else if (name.endsWith(".jpeg")) {
246            return "image/jpeg";
247        } else if (name.endsWith(".gif")) {
248            return "image/gif";
249        } else if (name.endsWith(".zip")) {
250            return "application/zip";
251        } else {
252            return "application/octet-stream";
253        }
254    }
255
256    public void setFolderishType(String folderishType) {
257        this.folderishType = folderishType;
258    }
259
260    public void setLeafType(String leafType) {
261        this.leafType = leafType;
262    }
263
264}