org.bonitasoft.studio.data.operation.RefactorDataOperation.java Source code

Java tutorial

Introduction

Here is the source code for org.bonitasoft.studio.data.operation.RefactorDataOperation.java

Source

/**
 * Copyright (C) 2012 BonitaSoft S.A.
 * BonitaSoft, 31 rue Gustave Eiffel - 38000 Grenoble
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2.0 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.bonitasoft.studio.data.operation;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.bonitasoft.studio.common.AbstractRefactorOperation;
import org.bonitasoft.studio.common.DataUtil;
import org.bonitasoft.studio.common.ExpressionConstants;
import org.bonitasoft.studio.common.emf.tools.ExpressionHelper;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.common.refactoring.BonitaGroovyRefactoringAction;
import org.bonitasoft.studio.data.i18n.Messages;
import org.bonitasoft.studio.model.expression.Expression;
import org.bonitasoft.studio.model.expression.ExpressionPackage;
import org.bonitasoft.studio.model.process.AbstractProcess;
import org.bonitasoft.studio.model.process.Data;
import org.bonitasoft.studio.model.process.MultiInstantiation;
import org.bonitasoft.studio.model.process.Pool;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.operation.IRunnableWithProgress;

/**
 * @author Romain Bioteau
 *
 */
public class RefactorDataOperation implements IRunnableWithProgress {

    private AbstractProcess parentProcess;
    private Data newData;
    private Data oldData;
    private EditingDomain domain;
    private boolean updateDataReferences = false;
    private CompoundCommand finalCommand;
    private List<Expression> scriptExpressions;
    private boolean canExecute = true;
    private int operationType;

    public boolean isCanExecute() {
        return canExecute;
    }

    public void setCanExecute(boolean canExecute) {
        this.canExecute = canExecute;
    }

    public RefactorDataOperation(int operationType) {
        this.scriptExpressions = new ArrayList<Expression>();
        this.operationType = operationType;
    }

    @Override
    public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
        Assert.isNotNull(parentProcess);
        Assert.isNotNull(oldData);
        Assert.isNotNull(domain);
        Assert.isNotNull(finalCommand);
        monitor.beginTask(Messages.refactoringData, IProgressMonitor.UNKNOWN);
        //CompoundCommand finalCommand=new CompoundCommand("Refactor Data Command");
        //CompoundCommand cc = new CompoundCommand("Refactor Data Command") ;
        //finalCommand.append(cc);
        if (newData != null && canExecute) {
            //TODO : find an intelligent way to search references to the oldData and replace them with the new one instead of writing specific code for each usecase
            updateDataReferenceInVariableExpressions(finalCommand);
            //domain.getCommandStack().execute(cc) ;
            //   cc =  new CompoundCommand("Refactor Data Command") ;
            //finalCommand.append(cc);
            updateDataReferenceInExpressions(finalCommand);
            if (updateDataReferences) {
                //   cc =  new CompoundCommand("Refactor Data Command") ;
                //   finalCommand.append(cc);
                updateDataInListsOfData(finalCommand);
                //domain.getCommandStack().execute(cc) ;
                //   cc =  new CompoundCommand("Refactor Data Command") ;
                //finalCommand.append(cc);
                updateDataReferenceInMultinstanciation(finalCommand);
                //domain.getCommandStack().execute(cc) ;
            }
        } else {
            removeAllDataReferences(finalCommand);
        }

        //   domain.getCommandStack().execute(finalCommand) ;
        monitor.done();
    }

    private void updateDataReferenceInExpressions(CompoundCommand finalCommand) {
        List<Expression> expressions = ModelHelper.getAllItemsOfType(parentProcess,
                ExpressionPackage.Literals.EXPRESSION);
        for (Expression exp : expressions) {
            //CompoundCommand cc =  new CompoundCommand("Refactor Data Command") ;
            for (EObject dependency : exp.getReferencedElements()) {
                if (dependency instanceof Data) {
                    if (((Data) dependency).getName().equals(oldData.getName())) {
                        finalCommand.append(RemoveCommand.create(domain, exp,
                                ExpressionPackage.Literals.EXPRESSION__REFERENCED_ELEMENTS, dependency));
                        finalCommand.append(AddCommand.create(domain, exp,
                                ExpressionPackage.Literals.EXPRESSION__REFERENCED_ELEMENTS,
                                ExpressionHelper.createDependencyFromEObject(newData)));
                    }
                }
            }
            //      if(!cc.isEmpty()){
            //            for(org.eclipse.emf.common.command.Command c :cc.getCommandList()){
            //               if(c.canExecute()){
            //                  domain.getCommandStack().execute(c) ;
            //               }
            //            }
            //         finalCommand.append(cc);
            //         }
        }
    }

    private void removeAllDataReferences(CompoundCommand cc) {
        List<Expression> expressions = null;
        if (oldData.eContainer() instanceof Pool) {
            expressions = ModelHelper.getAllItemsOfType(parentProcess, ExpressionPackage.Literals.EXPRESSION);
        } else {
            expressions = ModelHelper.getAllItemsOfType(oldData.eContainer(),
                    ExpressionPackage.Literals.EXPRESSION);
        }
        for (Expression exp : expressions) {
            if (ExpressionConstants.VARIABLE_TYPE.equals(exp.getType())
                    && exp.getName().equals(oldData.getName())) {
                //update name and content
                cc.append(SetCommand.create(domain, exp, ExpressionPackage.Literals.EXPRESSION__NAME, ""));
                cc.append(SetCommand.create(domain, exp, ExpressionPackage.Literals.EXPRESSION__CONTENT, ""));
                //update return type
                cc.append(SetCommand.create(domain, exp, ExpressionPackage.Literals.EXPRESSION__RETURN_TYPE,
                        String.class.getName()));
                cc.append(SetCommand.create(domain, exp, ExpressionPackage.Literals.EXPRESSION__TYPE,
                        ExpressionConstants.CONSTANT_TYPE));
                //update referenced data
                cc.append(RemoveCommand.create(domain, exp,
                        ExpressionPackage.Literals.EXPRESSION__REFERENCED_ELEMENTS, exp.getReferencedElements()));
            } else if (ExpressionConstants.SCRIPT_TYPE.equals(exp.getType())
                    || ExpressionConstants.CONDITION_TYPE.equals(exp.getType())) {
                Set<EObject> toRemove = new HashSet<EObject>();
                for (EObject dep : exp.getReferencedElements()) {
                    if (dep instanceof Data) {
                        if (oldData.getName().equals(((Data) dep).getName())
                                && dep.eClass().equals(oldData.eClass())) {
                            toRemove.add(dep);
                        }
                    }
                }
                if (!toRemove.isEmpty()) {
                    cc.append(RemoveCommand.create(domain, exp,
                            ExpressionPackage.Literals.EXPRESSION__REFERENCED_ELEMENTS, toRemove));
                }
            } else {
                if (ExpressionConstants.CONDITION_TYPE.equals(exp.getType())) {

                }
            }

        }
    }

    protected void updateDataInListsOfData(CompoundCommand cc) {
        List<Data> data = ModelHelper.getAllItemsOfType(parentProcess, ProcessPackage.Literals.DATA);
        for (Data d : data) {
            if (!d.equals(newData) && d.getName().equals(oldData.getName())) {
                Data copy = EcoreUtil.copy(newData);
                EObject container = d.eContainer();
                EReference eContainmentFeature = d.eContainmentFeature();
                if (container != null && container.eGet(eContainmentFeature) instanceof Collection<?>) {
                    List<?> dataList = (List<?>) container.eGet(eContainmentFeature);
                    int index = dataList.indexOf(d);
                    cc.append(RemoveCommand.create(domain, container, eContainmentFeature, d));
                    cc.append(AddCommand.create(domain, container, eContainmentFeature, copy, index));
                } else if (container != null && container.eGet(eContainmentFeature) instanceof Data) {
                    cc.append(SetCommand.create(domain, container, eContainmentFeature, copy));
                }
            }
        }
    }

    protected void updateDataReferenceInVariableExpressions(CompoundCommand cc) {
        List<Expression> expressions = ModelHelper.getAllItemsOfType(parentProcess,
                ExpressionPackage.Literals.EXPRESSION);
        for (Expression exp : expressions) {
            if (ExpressionConstants.VARIABLE_TYPE.equals(exp.getType())
                    && exp.getName().equals(oldData.getName())) {
                //update name and content
                cc.append(SetCommand.create(domain, exp, ExpressionPackage.Literals.EXPRESSION__NAME,
                        newData.getName()));
                cc.append(SetCommand.create(domain, exp, ExpressionPackage.Literals.EXPRESSION__CONTENT,
                        newData.getName()));
                //update return type
                cc.append(SetCommand.create(domain, exp, ExpressionPackage.Literals.EXPRESSION__RETURN_TYPE,
                        DataUtil.getTechnicalTypeFor(newData)));
            }
        }
    }

    protected void updateDataReferenceInMultinstanciation(CompoundCommand cc) {
        List<MultiInstantiation> multiInstanciations = ModelHelper.getAllItemsOfType(parentProcess,
                ProcessPackage.Literals.MULTI_INSTANTIATION);
        for (MultiInstantiation multiInstantiation : multiInstanciations) {
            final Data inputData = multiInstantiation.getInputData();
            if (inputData != null && inputData.equals(oldData)) {
                cc.append(SetCommand.create(domain, multiInstantiation,
                        ProcessPackage.Literals.MULTI_INSTANTIATION__INPUT_DATA, newData));
            }
            final Data outputData = multiInstantiation.getOutputData();
            if (outputData != null && outputData.equals(oldData)) {
                cc.append(SetCommand.create(domain, multiInstantiation,
                        ProcessPackage.Literals.MULTI_INSTANTIATION__OUTPUT_DATA, newData));
            }
            final Data collectionToMultiinstanciateData = multiInstantiation.getCollectionDataToMultiInstantiate();
            if (collectionToMultiinstanciateData != null && collectionToMultiinstanciateData.equals(oldData)) {
                cc.append(SetCommand.create(domain, multiInstantiation,
                        ProcessPackage.Literals.MULTI_INSTANTIATION__COLLECTION_DATA_TO_MULTI_INSTANTIATE,
                        newData));
            }
            final Data listDataContainingOutputResults = multiInstantiation.getListDataContainingOutputResults();
            if (listDataContainingOutputResults != null && listDataContainingOutputResults.equals(oldData)) {
                cc.append(SetCommand.create(domain, multiInstantiation,
                        ProcessPackage.Literals.MULTI_INSTANTIATION__LIST_DATA_CONTAINING_OUTPUT_RESULTS, newData));
            }
        }
    }

    public void setContainer(AbstractProcess parentProcess) {
        this.parentProcess = parentProcess;
    }

    public void setNewData(Data newData) {
        this.newData = newData;
    }

    public void setEditingDomain(EditingDomain domain) {
        this.domain = domain;
    }

    public void setOldData(Data oldData) {
        this.oldData = oldData;
    }

    public void setUpdateDataReferences(boolean updateDataReferences) {
        this.updateDataReferences = updateDataReferences;
    }

    public void setCompoundCommand(CompoundCommand finalCommand) {
        this.finalCommand = finalCommand;
    }

    public void updateReferencesInScripts() {
        String newName = null;
        if (newData != null) {
            newName = newData.getName();
        } else {
            newName = AbstractRefactorOperation.EMPTY_VALUE;
        }
        scriptExpressions = ModelHelper
                .findAllScriptAndConditionsExpressionWithReferencedElement(oldData.eContainer(), oldData);
        if (!scriptExpressions.isEmpty() && !oldData.getName().equals(newName)) {
            try {
                BonitaGroovyRefactoringAction action = new BonitaGroovyRefactoringAction(oldData.getName(), newName,
                        scriptExpressions, finalCommand, domain, operationType);
                action.run(null);
                canExecute = action.getStatus();
                //if (canExecute){
                //   for (Expression script:scriptExpressions){
                //   Object referencedObject = getDataToRemove(script);
                //   finalCommand.append(RemoveCommand.create(domain, script, ExpressionPackage.Literals.EXPRESSION__REFERENCED_ELEMENTS  , referencedObject));
                //   finalCommand.append(AddCommand.create(domain, script, ExpressionPackage.Literals.EXPRESSION__REFERENCED_ELEMENTS  ,EcoreUtil.copy(newData)));
                //   }
                //}
            } catch (JavaModelException e) {
                BonitaStudioLog.error(e);
            }
        } else {
            canExecute = true;
        }
    }

    public EObject getDataToRemove(Expression expr) {
        for (EObject object : expr.getReferencedElements()) {
            if (object instanceof Data && ((Data) object).getName().equals(oldData.getName())) {
                return object;
            }
        }
        return null;
    }

}