001/*
002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others.
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 *     Thierry Delprat <tdelprat@nuxeo.com>
016 *     Vladimir Pasquier <vpasquier@nuxeo.com>
017 */
018package org.nuxeo.automation.scripting.internals;
019
020import java.io.Serializable;
021import java.util.ArrayList;
022import java.util.HashMap;
023import java.util.List;
024import java.util.Map;
025
026import jdk.nashorn.api.scripting.ScriptObjectMirror;
027
028import org.nuxeo.ecm.automation.AutomationService;
029import org.nuxeo.ecm.automation.OperationContext;
030import org.nuxeo.ecm.automation.core.scripting.DocumentWrapper;
031import org.nuxeo.ecm.automation.core.util.DataModelProperties;
032import org.nuxeo.ecm.automation.core.util.Properties;
033import org.nuxeo.ecm.core.api.CoreSession;
034import org.nuxeo.ecm.core.api.DocumentModel;
035import org.nuxeo.ecm.core.api.DocumentModelList;
036import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
037import org.nuxeo.runtime.api.Framework;
038
039/**
040 * Class injected/published in Nashorn engine to execute automation service.
041 *
042 * @since 7.2
043 */
044public class AutomationMapper {
045
046    protected final CoreSession session;
047
048    public OperationContext ctx;
049
050    public AutomationMapper(CoreSession session, OperationContext operationContext) {
051        this.session = session;
052        ctx = operationContext;
053    }
054
055    public Object executeOperation(String opId, Object input, ScriptObjectMirror parameters) throws Exception {
056        AutomationService automationService = Framework.getService(AutomationService.class);
057        unwrapContext(ctx, input);
058        Map<String, Object> params = unwrapParameters(parameters);
059        Object output = automationService.run(ctx, opId, params);
060        return wrapContextAndOutput(output);
061    }
062
063    public void unwrapContext(OperationContext ctx, Object inputOutput) {
064        if (inputOutput instanceof ScriptObjectMirror) {
065            ctx.setInput(extractProperties((ScriptObjectMirror) inputOutput));
066        } else if (inputOutput instanceof DocumentWrapper) {
067            ctx.setInput(((DocumentWrapper) inputOutput).getDoc());
068        } else if (inputOutput instanceof List<?>) {
069            DocumentModelList docs = new DocumentModelListImpl();
070            List<?> l = (List<?>) inputOutput;
071            for (Object item : l) {
072                if (item instanceof DocumentWrapper) {
073                    docs.add(((DocumentWrapper) item).getDoc());
074                }
075            }
076            if (docs.size() == l.size() && docs.size() > 0) {
077                ctx.setInput(docs);
078            }
079        } else {
080            ctx.setInput(inputOutput);
081        }
082        for (String entryId : ctx.keySet()) {
083            Object entry = ctx.get(entryId);
084            if (entry instanceof DocumentWrapper) {
085                ctx.put(entryId, ((DocumentWrapper) entry).getDoc());
086            } else if (ctx.get(entryId) instanceof List<?>) {
087                DocumentModelList docs = new DocumentModelListImpl();
088                List<?> l = (List<?>) entry;
089                for (Object item : l) {
090                    if (ctx.get(entryId) instanceof DocumentWrapper) {
091                        docs.add(((DocumentWrapper) item).getDoc());
092                    }
093                }
094                if (docs.size() == l.size() && docs.size() > 0) {
095                    ctx.put(entryId, ((DocumentWrapper) entry).getDoc());
096                }
097            }
098        }
099    }
100
101    protected Properties extractProperties(ScriptObjectMirror parameters) {
102        DataModelProperties props = new DataModelProperties();
103        Map<String, Object> data = MarshalingHelper.unwrapMap(parameters);
104        for (String k : data.keySet()) {
105            props.getMap().put(k, (Serializable) data.get(k));
106        }
107        return props;
108    }
109
110    protected Object wrapContextAndOutput(Object output) {
111        for (String entryId : ctx.keySet()) {
112            Object entry = ctx.get(entryId);
113            if (entry instanceof DocumentModel) {
114                ctx.put(entryId, new DocumentWrapper(ctx.getCoreSession(), (DocumentModel) entry));
115            }
116            if (entry instanceof DocumentModelList) {
117                List<DocumentWrapper> docs = new ArrayList<>();
118                for (DocumentModel doc : (DocumentModelList) entry) {
119                    docs.add(new DocumentWrapper(ctx.getCoreSession(), doc));
120                }
121                ctx.put(entryId, docs);
122            }
123        }
124        if (output instanceof DocumentModel) {
125            return new DocumentWrapper(ctx.getCoreSession(), (DocumentModel) output);
126        } else if (output instanceof DocumentModelList) {
127            List<DocumentWrapper> docs = new ArrayList<>();
128            for (DocumentModel doc : (DocumentModelList) output) {
129                docs.add(new DocumentWrapper(ctx.getCoreSession(), doc));
130            }
131            return docs;
132        }
133        return output;
134    }
135
136    protected Map<String, Object> unwrapParameters(ScriptObjectMirror parameters) {
137        Map<String, Object> params = new HashMap<String, Object>();
138        for (String k : parameters.keySet()) {
139            Object value = parameters.get(k);
140            if (value instanceof ScriptObjectMirror) {
141                ScriptObjectMirror jso = (ScriptObjectMirror) value;
142                if (jso.isArray()) {
143                    params.put(k, MarshalingHelper.unwrap(jso));
144                } else {
145                    params.put(k, extractProperties(jso));
146                }
147            } else if (value instanceof DocumentWrapper) {
148                params.put(k, ((DocumentWrapper) value).getDoc());
149            } else if (value instanceof List<?>) {
150                DocumentModelList docs = new DocumentModelListImpl();
151                List<?> l = (List<?>) value;
152                for (Object item : l) {
153                    if (item instanceof DocumentWrapper) {
154                        docs.add(((DocumentWrapper) item).getDoc());
155                    }
156                }
157                if (docs.size() == l.size() && docs.size() > 0) {
158                    params.put(k, docs);
159                }
160            } else {
161                params.put(k, value);
162            }
163        }
164        return params;
165    }
166
167}