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