001/*
002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bdelbosc
016 */
017package org.nuxeo.elasticsearch.io;
018
019import java.util.Map;
020
021import org.apache.commons.logging.Log;
022import org.apache.commons.logging.LogFactory;
023import org.elasticsearch.common.bytes.BytesArray;
024import org.elasticsearch.search.lookup.SourceLookup;
025import org.nuxeo.common.utils.Path;
026import org.nuxeo.ecm.core.api.CoreSession;
027import org.nuxeo.ecm.core.api.DocumentModel;
028import org.nuxeo.ecm.core.api.DocumentModelFactory;
029import org.nuxeo.ecm.core.api.IdRef;
030import org.nuxeo.ecm.core.api.PropertyException;
031import org.nuxeo.ecm.core.api.impl.DocumentModelImpl;
032import org.nuxeo.ecm.core.schema.DocumentType;
033import org.nuxeo.ecm.core.schema.SchemaManager;
034import org.nuxeo.ecm.core.schema.types.Schema;
035import org.nuxeo.runtime.api.Framework;
036
037/**
038 * Read a DocumentModel from an ES Json export.
039 *
040 * @since 5.9.5
041 */
042public class JsonDocumentModelReader {
043    private static final Log log = LogFactory.getLog(JsonDocumentModelReader.class);
044
045    private final Map<String, Object> source;
046
047    private String sid;
048
049    public JsonDocumentModelReader(String json) {
050        byte[] bytes = json.getBytes();
051        source = SourceLookup.sourceAsMap(new BytesArray(bytes, 0, bytes.length));
052    }
053
054    public JsonDocumentModelReader(Map<String, Object> source) {
055        this.source = source;
056    }
057
058    public JsonDocumentModelReader session(CoreSession session) {
059        sid = session.getSessionId();
060        return this;
061    }
062
063    public JsonDocumentModelReader sid(String sid) {
064        this.sid = sid;
065        return this;
066    }
067
068    public DocumentModel getDocumentModel() {
069        assert (source != null);
070        String type = getType();
071        String name = getPropertyAsString("ecm:name");
072        String id = getPropertyAsString("ecm:uuid");
073        String path = getPropertyAsString("ecm:path");
074        String parentId = getPropertyAsString("ecm:parentId");
075        String repository = getPropertyAsString("ecm:repository");
076
077        DocumentModelImpl doc = new DocumentModelImpl(sid, getType(), id, new Path(path), new IdRef(id),
078                new IdRef(parentId), null, null, null, repository, false);
079
080        // pre load datamodel to prevent DB access
081        DocumentType docType = Framework.getService(SchemaManager.class).getDocumentType(type);
082        for (Schema schema : docType.getSchemas()) {
083            doc.addDataModel(DocumentModelFactory.createDataModel(null, schema));
084        }
085
086        for (String prop : source.keySet()) {
087            String schema = prop.split(":")[0];
088            // schema = schema.replace("dc", "dublincore");
089            String key = prop.split(":")[1];
090            if (source.get(prop) == null) {
091                continue;
092            }
093            String value = getPropertyAsString(prop);
094            if (value.isEmpty() || "[]".equals(value)) {
095                continue;
096            }
097            // System.out.println( String.format("schema: %s, key %s = %s", schema, key, value));
098            if ("ecm".equals(schema)) {
099                switch (key) {
100                case "isProxy":
101                    doc.setIsProxy(Boolean.valueOf(value));
102                    break;
103                case "currentLifeCycleState":
104                    doc.prefetchCurrentLifecycleState(value);
105                    break;
106                case "versionLabel":
107                case "mixinType":
108                    // Can not be done via API
109                    break;
110                default:
111                    // not taken in account
112                }
113            } else {
114                try {
115                    doc.setPropertyValue(prop, value);
116                    // doc.setProperty(schema, key, value);
117                } catch (PropertyException e) {
118                    if (log.isDebugEnabled()) {
119                        log.debug(String.format("fetchDocFromEs can not set property %s to %s", key, value));
120                    }
121                }
122            }
123        }
124        doc.setIsImmutable(true);
125        return doc;
126    }
127
128    private String getType() {
129        return getPropertyAsString("ecm:primaryType");
130    }
131
132    private String getPropertyAsString(String name) {
133        Object prop = source.get(name);
134        return (prop == null) ? "" : prop.toString();
135    }
136}