com.mentor.nucleus.bp.core.common.Transaction.java Source code

Java tutorial

Introduction

Here is the source code for com.mentor.nucleus.bp.core.common.Transaction.java

Source

//=====================================================================
//
//File:      $RCSfile: Transaction.java,v $
//Version:   $Revision: 1.25 $
//Modified:  $Date: 2013/01/17 03:39:27 $
//
//(c) Copyright 2005-2014 by Mentor Graphics Corp. All rights reserved.
//
//=====================================================================
// Licensed under the Apache License, Version 2.0 (the "License"); you may not 
// use this file except in compliance with the License.  You may obtain a copy 
// of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   See the 
// License for the specific language governing permissions and limitations under
// the License.
//=====================================================================

package com.mentor.nucleus.bp.core.common;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.ui.PlatformUI;

import com.mentor.nucleus.bp.core.CorePlugin;
import com.mentor.nucleus.bp.core.EclipseOoaofooa;
import com.mentor.nucleus.bp.core.Modeleventnotification_c;
import com.mentor.nucleus.bp.core.Ooaofooa;
import com.mentor.nucleus.bp.core.ui.Selection;
import com.mentor.nucleus.bp.core.util.OoaofgraphicsUtil;

public class Transaction {
    public static final String DEFAULT_TYPE = "__default";

    public static final String UNDO_TYPE = "__undo";

    public static final String REDO_TYPE = "__redo";

    public static final String DELETE_TRANS = "Delete";

    public static final String AUTORECONCILE_TYPE = "Auto-Reconcile";

    private boolean undoable = true;

    long id;

    String type;

    String displayName;

    Map<ModelRoot, Object> deltasMap = new HashMap<ModelRoot, Object>();

    TransactionManager manager = null;

    IDeltaCollector deltaCollector;

    public boolean memoryOnly = false;

    public boolean forceCompletion = false;

    protected Transaction(String aDisplayName, IDeltaCollector aDeltaCollector, String aType, boolean isUndoable,
            TransactionManager p_Manager) {
        displayName = aDisplayName;
        id = System.currentTimeMillis();
        deltaCollector = aDeltaCollector;
        type = aType;
        undoable = isUndoable;
        manager = p_Manager;
    }

    public String getType() {
        return type;
    }

    public TransactionManager getTransactionManager() {
        return manager;
    }

    public long getID() {
        return id;
    }

    public String getDisplayName() {
        return displayName;
    }

    public ModelRoot getParticipatingModelRoot(Class<?> type) {
        for (Iterator<ModelRoot> iterator = deltasMap.keySet().iterator(); iterator.hasNext();) {
            Object modelRoot = iterator.next();
            if (type == modelRoot.getClass()) {
                return (ModelRoot) modelRoot;
            }
        }
        return null;
    }

    public ModelRoot[] getParticipatingModelRoots() {
        ModelRoot[] roots = (ModelRoot[]) deltasMap.keySet().toArray(new ModelRoot[0]);
        ArrayList<ModelRoot> list = new ArrayList<ModelRoot>();
        for (int i = 0; i < roots.length; i++) {
            if (roots[i] instanceof Ooaofooa) {
                list.add(roots[i]);
            }
        }
        for (int i = 0; i < roots.length; i++) {
            if (!(roots[i] instanceof Ooaofooa)) {
                list.add(roots[i]);
            }
        }
        return list.toArray(new ModelRoot[0]);
    }

    public ModelRoot[] getParticipatingModelRoots(Class<?> type) {
        List<ModelRoot> modelRoots = new ArrayList<ModelRoot>();
        for (Iterator<ModelRoot> iterator = deltasMap.keySet().iterator(); iterator.hasNext();) {
            ModelRoot modelRoot = iterator.next();
            if (type == modelRoot.getClass()) {
                modelRoots.add(modelRoot);
            }
        }

        if (modelRoots.size() > 0) {
            return (ModelRoot[]) modelRoots.toArray(new ModelRoot[modelRoots.size()]);
        } else {
            return new ModelRoot[0];
        }
    }

    public IModelDelta[] getDeltas(ModelRoot modelRoot) {
        return (IModelDelta[]) deltasMap.get(modelRoot);
    }

    protected void setDeltas(ModelRoot modelRoot, IModelDelta[] deltas) {
        deltasMap.put(modelRoot, deltas);
    }

    protected IDeltaCollector getDeltaCollector() {
        return deltaCollector;
    }

    public boolean isUndoable() {
        return undoable;
    }

    /**
     * Get the number of deltas involved with the given transaction
     */
    public int getDeltaCount() {
        ModelRoot[] modelRoots = getParticipatingModelRoots();
        int deltaCount = 0;
        // determine how many deltas are part of
        // the given transaction
        for (int i = 0; i < modelRoots.length; i++) {
            deltaCount = deltaCount + getDeltas(modelRoots[i]).length;
        }
        return deltaCount;
    }

    void revert() {
        revert(false);
    }

    /**
     * Wrapper method to create a progress dialog if necessary, that is if the
     * amount of deltas is over a certain size
     *
     * @param transactionType
     */
    void revert(final boolean inMemoryOnly) {
        int deltaCount = getDeltaCount();
        if (deltaCount > 200) {
            ProgressMonitorDialog pmDialog = new ProgressMonitorDialog(
                    PlatformUI.getWorkbench().getDisplay().getActiveShell());
            try {
                pmDialog.run(false, false, new IRunnableWithProgress() {

                    public void run(IProgressMonitor monitor)
                            throws InvocationTargetException, InterruptedException {
                        revert(monitor, inMemoryOnly);
                    }

                });
            } catch (InvocationTargetException e) {
                CorePlugin.logError("Unable to invoke undo of the last transaction.", e);
            } catch (InterruptedException e) {
                CorePlugin.logError("The undo of the last transaction was interrupted.", e);
            }
        } else {
            revert(new NullProgressMonitor(), inMemoryOnly);
        }
    }

    /**
     * This method takes a transaction and reverses the changes that were made
     * by it.
     *
     * @param pm
     */

    void revert(IProgressMonitor pm, boolean inMemoryOnly) {

        ModelRoot[] modelRoots = getParticipatingModelRoots();

        if (inMemoryOnly) {
            ModelRoot.disableChangeNotification();
        }
        try {
            int deltaCount = getDeltaCount();

            pm.beginTask("Restoring model...", deltaCount);

            for (int i = 0; i < modelRoots.length; i++) {

                IModelDelta[] deltas = getDeltas(modelRoots[i]);
                // process each delta set
                for (int j = deltas.length - 1; j >= 0; j--) {
                    ModelElement modelElement = deltas[j].getModelElement();
                    NonRootModelElement nrme = (NonRootModelElement) modelElement;

                    // restore any deletions contained in the
                    // delta set
                    if (deltas[j].getKind() == Modeleventnotification_c.DELTA_DELETE) {
                        if (nrme.getModelRoot() instanceof Ooaofooa) {
                            // if the element is a container to a model root, we must
                            // add that model root and the graphical one back into the
                            // model root map
                            Ooaofooa foundInstance = EclipseOoaofooa.findInstance(nrme.getModelRoot().getId());
                            if (foundInstance == null) {
                                EclipseOoaofooa.addInstance(nrme.getModelRoot());
                                Object graphicsRoot = locateGraphicsRoot(nrme);
                                if (graphicsRoot != null)
                                    OoaofgraphicsUtil.addInstance(graphicsRoot);
                            }
                        } else {
                            if (nrme.getModelRoot().getClass() == OoaofgraphicsUtil.getGraphicsClass()) {
                                Object foundInstance = OoaofgraphicsUtil.findInstance(nrme.getModelRoot().getId());
                                if (foundInstance == null) {
                                    OoaofgraphicsUtil.addInstance(nrme.getModelRoot());
                                }
                            }
                        }
                        // if the element deleted was converted to a proxy
                        if (nrme.isProxy()) {
                            // convert it to a non proxy
                            nrme.convertFromProxy();
                        }
                        InstanceList instanceList = nrme.getModelRoot().getInstanceList(nrme.getClass());
                        synchronized (instanceList) {
                            instanceList.add(nrme);
                        }
                        nrme.addInstanceToMap(nrme.getInstanceKey());
                        if (nrme instanceof ActiveObject_c)
                            Activepoller_c.register((ActiveObject_c) nrme);
                        modelRoots[i].fireModelElementCreated(
                                new BaseModelDelta(Modeleventnotification_c.DELTA_NEW, nrme));
                    }

                    // restore all previous attribute values
                    if (deltas[j] instanceof AttributeChangeModelDelta) {
                        AttributeChangeModelDelta delta = (AttributeChangeModelDelta) deltas[j];
                        String setMethod = "set" + delta.getAttributeName(); // $NON-NLS-1$
                        Method method = null;
                        try {
                            Object oldValue = delta.getOldValue();
                            Class<?> attributeClass = oldValue != null
                                    ? getPrimitiveClass(delta.getOldValue().getClass())
                                    : new Object().getClass();
                            method = nrme.getClass().getMethod(setMethod, new Class[] { attributeClass });
                            Object[] arg = { delta.getOldValue() };
                            method.invoke(modelElement, arg);
                        } catch (Exception e) {
                            CorePlugin.logError("Unable to find or invoke set method.", e);
                        }
                    }

                    // restore all relationship changes that were made
                    if (deltas[j] instanceof RelationshipChangeModelDelta) {
                        RelationshipChangeModelDelta delta = (RelationshipChangeModelDelta) deltas[j];
                        NonRootModelElement dest = (NonRootModelElement) delta.getDestinationModelElement();

                        String direction = "To"; // $NON-NLS-1$
                        String relationship = "relate"; // $NON-NLS-1$

                        if (delta.getKind() == Modeleventnotification_c.DELTA_ELEMENT_RELATED) {
                            direction = "From"; // $NON-NLS-1$
                            relationship = "unrelate"; // $NON-NLS-1$
                        }

                        // build the method name from the delta information
                        String relateMethod = relationship + "AcrossR" // $NON-NLS-1$
                                + delta.getRelationName() + direction + delta.getRelationDirectionPhrase();

                        // find the method of that name and invoke it
                        try {
                            Method method = nrme.getClass().getMethod(relateMethod,
                                    new Class[] { dest.getClass() });
                            Object[] arg = new Object[1];
                            arg[0] = dest;
                            method.invoke(nrme, arg);
                        } catch (Exception e) {
                            CorePlugin.logError("Unable to find or invoke relate method.", e);
                        }
                    }

                    // remove any elements that were created during the
                    // transaction
                    if (deltas[j].getKind() == Modeleventnotification_c.DELTA_NEW) {
                        if (nrme.delete()) {
                            modelRoots[i].fireModelElementDeleted(
                                    new BaseModelDelta(Modeleventnotification_c.DELTA_DELETE, nrme));
                        }
                        // remove the PMC if it exists and we are reverting
                        // in memory, otherwise it will be removed by the
                        // ComponentTransactionListener
                        if (inMemoryOnly) {
                            if (nrme.getPersistableComponent() != null) {
                                if (nrme.getPersistableComponent().getRootModelElement() == nrme) {
                                    nrme.getPersistableComponent().deleteSelf();
                                }
                            }
                        }

                        // remove the element from the current selection,
                        // as would be done if the deletion was done by a delete-action
                        Selection.getInstance().removeFromSelection(nrme);
                    }

                    pm.worked(1);
                }
            }
        } finally {
            if (inMemoryOnly) {
                ModelRoot.enableChangeNotification();
            }
        }
        pm.done();
    }

    private Object locateGraphicsRoot(NonRootModelElement nrme) {
        IModelDelta[] deltas = getDeltas((ModelRoot) OoaofgraphicsUtil
                .getGraphicsRoot(Ooaofooa.getDefaultInstance().getId(), OoaofgraphicsUtil.getGraphicsClass()));
        if (deltas == null) {
            return null;
        }
        for (int i = 0; i < deltas.length; i++) {
            // locate a matching GraphicalElement_c
            NonRootModelElement modelElement = (NonRootModelElement) deltas[i].getModelElement();
            if (modelElement.getModelRoot().getId().equals(nrme.getModelRoot().getId())) {
                return modelElement.getModelRoot();
            }
        }
        return null;
    }

    /**
      * Returns the class of the primitive type which corresponds to the
      * given primitive-wrapping type (e.g. Integer, Boolean, etc.).
      * For non-primitive-wrapping types, the String class is returned
      * when it is the one given, and the Object class is returned for all
      * others.
      */
    public static Class<?> getPrimitiveClass(Class<?> clazz) {
        if (clazz == Float.class)
            return Float.TYPE;
        if (clazz == Integer.class)
            return Integer.TYPE;
        if (clazz == Long.class)
            return Long.TYPE;
        if (clazz == Boolean.class)
            return Boolean.TYPE;
        if (clazz == String.class)
            return clazz;
        if (clazz == UUID.class)
            return clazz;

        return Object.class;
    }

    public void updateParticipatingModelRoot(ModelRoot newRoot, ModelRoot oldRoot) {
        Object object = deltasMap.get(oldRoot);
        deltasMap.put(newRoot, object);
        deltasMap.remove(oldRoot);
    }

    public void setModelDeltas(IModelDelta[] deltas, ModelRoot root) {
        deltasMap.clear();
        deltasMap.put(root, deltas);
    }
}