001/*
002 * (C) Copyright 2006-2014 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 *     Thierry Delprat
018 *     Florent Guillaume
019 */
020
021package org.nuxeo.ecm.automation.core.operations.execution;
022
023import java.util.Arrays;
024import java.util.Collection;
025import java.util.HashMap;
026import java.util.Map;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.nuxeo.ecm.automation.AutomationService;
031import org.nuxeo.ecm.automation.OperationContext;
032import org.nuxeo.ecm.automation.OperationException;
033import org.nuxeo.ecm.automation.core.Constants;
034import org.nuxeo.ecm.automation.core.annotations.Context;
035import org.nuxeo.ecm.automation.core.annotations.Operation;
036import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
037import org.nuxeo.ecm.automation.core.annotations.Param;
038import org.nuxeo.ecm.core.api.CoreSession;
039import org.nuxeo.ecm.core.api.DocumentModel;
040import org.nuxeo.ecm.core.api.NuxeoException;
041import org.nuxeo.runtime.transaction.TransactionHelper;
042
043/**
044 * @deprecated since 6.0. Use instead {@link RunOperationOnList} with ID 'Context.RunOperationOnList'. Run an embedded
045 *             operation chain inside separated transactions using the current input. The output is undefined (Void)
046 * @since 5.7.2
047 */
048@Deprecated
049@Operation(id = RunOperationOnListInNewTransaction.ID, category = Constants.CAT_SUBCHAIN_EXECUTION, label = "Run For Each in new TX", description = "Run an operation/chain in a new Transaction for each element from the list defined by the 'list' parameter. The 'list' parameter is pointing to a context variable that represents the list which will be iterated. The 'itemName' parameter represents the name of the context variable which will point to the current element in the list at each iteration. You can use the 'isolate' parameter to specify whether or not the evalution context is the same as the parent context or a copy of it. If the 'isolate' parameter is 'true' then a copy of the current context is used and so that modifications in this context will not affect the parent context. Any input is accepted. The input is returned back as output when operation terminates.", deprecatedSince = "6.0", aliases = { "Context.RunOperationOnListInNewTx" })
050public class RunOperationOnListInNewTransaction {
051
052    protected static Log log = LogFactory.getLog(RunOperationOnListInNewTransaction.class);
053
054    public static final String ID = "RunOperationOnListInNewTx";
055
056    @Context
057    protected OperationContext ctx;
058
059    @Context
060    protected AutomationService service;
061
062    @Context
063    protected CoreSession session;
064
065    @Param(name = "id")
066    protected String chainId;
067
068    @Param(name = "list")
069    protected String listName;
070
071    @Param(name = "itemName", required = false, values = "item")
072    protected String itemName = "item";
073
074    @Param(name = "isolate", required = false, values = "true")
075    protected boolean isolate = true;
076
077    @OperationMethod
078    public void run() throws OperationException {
079        Map<String, Object> vars = isolate ? new HashMap<String, Object>(ctx.getVars()) : ctx.getVars();
080
081        Collection<?> list = null;
082        if (ctx.get(listName) instanceof Object[]) {
083            list = Arrays.asList((Object[]) ctx.get(listName));
084        } else if (ctx.get(listName) instanceof Collection<?>) {
085            list = (Collection<?>) ctx.get(listName);
086        } else {
087            throw new UnsupportedOperationException(ctx.get(listName).getClass() + " is not a Collection");
088        }
089
090        // commit the current transaction
091        TransactionHelper.commitOrRollbackTransaction();
092
093        // execute on list in separate transactions
094        for (Object value : list) {
095            try {
096                TransactionHelper.runInNewTransaction(() -> {
097                    try (OperationContext subctx = ctx.getSubContext(isolate, ctx.getInput())) {
098                        subctx.push(itemName, value);
099                        try {
100                            service.run(subctx, chainId);
101                        } finally {
102                            subctx.pop(itemName);
103                        }
104                    } catch (OperationException e) {
105                        throw new NuxeoException(e);
106                    }
107                });
108            } catch (NuxeoException e) {
109                if (e.getCause() instanceof OperationException) {
110                    throw (OperationException) e.getCause();
111                }
112                throw e;
113            }
114        }
115
116        TransactionHelper.startTransaction();
117
118        // reconnect documents in the context
119        if (!isolate) {
120            for (String varName : vars.keySet()) {
121                if (!ctx.getVars().containsKey(varName)) {
122                    ctx.put(varName, vars.get(varName));
123                } else {
124                    Object value = vars.get(varName);
125                    if (session != null && value != null && value instanceof DocumentModel) {
126                        ctx.getVars().put(varName, session.getDocument(((DocumentModel) value).getRef()));
127                    } else {
128                        ctx.getVars().put(varName, value);
129                    }
130                }
131            }
132        }
133    }
134
135}