001/*
002 * (C) Copyright 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 *     Kevin Leturc
018 */
019package org.nuxeo.automation.scripting.internals;
020
021import java.util.ArrayList;
022import java.util.Arrays;
023import java.util.List;
024import java.util.stream.Collectors;
025
026import org.nuxeo.ecm.automation.core.util.BlobList;
027import org.nuxeo.ecm.core.api.Blob;
028import org.nuxeo.ecm.core.api.CoreSession;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.api.DocumentModelList;
031import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
032
033import jdk.nashorn.api.scripting.ScriptObjectMirror;
034import jdk.nashorn.internal.objects.NativeArray;
035
036/**
037 * @since 8.4
038 */
039public class WrapperHelper {
040
041    private WrapperHelper() {
042        // empty
043    }
044
045    public static Object wrap(Object object, CoreSession session) {
046        if (object instanceof DocumentModel) {
047            return new DocumentScriptingWrapper(session, (DocumentModel) object);
048        } else if (object instanceof DocumentModelList) {
049            List<DocumentScriptingWrapper> docs = new ArrayList<>();
050            for (DocumentModel doc : (DocumentModelList) object) {
051                docs.add(new DocumentScriptingWrapper(session, doc));
052            }
053            return docs;
054        }
055        return object;
056    }
057
058    public static Object unwrap(Object object) {
059        // First unwrap object if it's a nashorn object
060        Object result = object;
061        if (result instanceof ScriptObjectMirror) {
062            result = ScriptObjectMirrors.unwrap((ScriptObjectMirror) result);
063        }
064        // TODO: not sure if this code is used, but we shouldn't use NativeArray as it's an internal class of nashorn
065        if (result instanceof NativeArray) {
066            result = Arrays.asList(((NativeArray) result).asObjectArray());
067        }
068        // Second unwrap object
069        if (result instanceof DocumentScriptingWrapper) {
070            result = ((DocumentScriptingWrapper) result).getDoc();
071        } else if (result instanceof List<?>) {
072            List<?> l = (List<?>) result;
073            // Several possible cases here:
074            // - l is of type DocumentModelList or BlobList -> already in right type
075            // - l is a list of DocumentScriptingWrapper -> elements need to be unwrapped into a DocumentModelList
076            // - l is a list of DocumentWrapper -> l needs to be converted to DocumentModelList
077            // - l is a list of Blob -> l needs to be converted to BlobList
078            // - l is a list -> do nothing
079            if (l.size() > 0 && !(result instanceof DocumentModelList || result instanceof BlobList)) {
080                Object first = l.get(0);
081                if (first instanceof DocumentModel) {
082                    result = l.stream()
083                              .map(DocumentModel.class::cast)
084                              .collect(Collectors.toCollection(DocumentModelListImpl::new));
085                } else if (first instanceof Blob) {
086                    result = l.stream().map(Blob.class::cast).collect(Collectors.toCollection(BlobList::new));
087                } else if (first instanceof DocumentScriptingWrapper) {
088                    result = l.stream()
089                              .map(DocumentScriptingWrapper.class::cast)
090                              .map(DocumentScriptingWrapper::getDoc)
091                              .collect(Collectors.toCollection(DocumentModelListImpl::new));
092                }
093            }
094        }
095        return result;
096    }
097
098}