metabup.change.trace.ChangeTracer.java Source code

Java tutorial

Introduction

Here is the source code for metabup.change.trace.ChangeTracer.java

Source

/*******************************************************************************
 * Copyright (c) 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package metabup.change.trace;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EModelElement;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.preference.IPreferenceStore;

import History.*;
import metabup.metamodel.AnnotatedElement;
import metabup.metamodel.Attribute;
import metabup.metamodel.Feature;
import metabup.metamodel.MetaClass;
import metabup.metamodel.Reference;

public class ChangeTracer {
    private List<Object[]> index;
    private EPackage ePackage = null;

    public ChangeTracer(EPackage ePackage) {
        super();
        index = new ArrayList<Object[]>();
        this.ePackage = ePackage;
    }

    public ChangeTracer() {
        super();
        index = new ArrayList<Object[]>();
    }

    private boolean indexPut(Object i[]) {
        if (i.length != 4)
            return false;

        if (i[0] instanceof String) {
            String op = ((String) i[0]);
            if (!op.equals("") && !op.equals("add") && !op.equals("delete") && !op.equals("update"))
                return false;
        } else
            return false;

        if (!(i[1] instanceof AnnotatedElement))
            return false;
        if (!(i[2] instanceof EModelElement))
            return false;

        return index.add(i);
    }

    private void indexRemove(Object i[], boolean recursive) {
        if (this.getByID(((AnnotatedElement) i[1]).getId()) == null)
            return;
        String id = ((AnnotatedElement) i[1]).getId();
        //if(recursive) for(Object j[] : index) if(j[3]!=null && ((String)j[3]).equals(id)) index.remove(j);      
        index.remove(i);
        return;
    }

    /*private void indexRemove(String id, boolean recursive){
       if(this.getByID(id) == null) return;
       if(recursive) for(Object j[] : index) if(((String)j[3]).equals(id)) index.remove(j);
       for(Object i[] : index) if(((AnnotatedElement)i[1]).getId().equals(id)) index.remove(i);                              
       return;
    }*/

    /*private boolean indexRemove(String id, String op){
       for(Object i[] : index) if(((String)i[0]).equals(op) && ((AnnotatedElement)i[1]).getId().equals(id)){         
     return index.remove(i);
       }
           
       return false;
    }*/

    private boolean indexReplace(Object old[], Object neu[]) {
        if (old == null || neu == null)
            return false;
        if (!index.contains(old))
            return false;
        if (neu.length != 4)
            return false;
        if (!(neu[0] instanceof String))
            return false;
        if (!(neu[1] instanceof AnnotatedElement))
            return false;
        if (!(neu[2] instanceof EModelElement))
            return false;
        String op = (String) neu[0];
        if (!op.equals("") && !op.equals("add") && !op.equals("delete") && !op.equals("update"))
            return false;

        if (!index.remove(old))
            return false;
        return index.add(neu);
    }

    public static Object[] wrap(String op, AnnotatedElement ae, EModelElement eme, String re) {
        if (!op.equals("") && !op.equals("add") && !op.equals("delete") && !op.equals("update"))
            return null;
        if (ae == null || eme == null)
            return null;

        Object i[] = new Object[4];
        i[0] = op;
        i[1] = ae;
        i[2] = eme;
        i[3] = re;

        return i;
    }

    public void load(AnnotatedElement ae, EModelElement eme) {
        if (isLoad(ae))
            return;

        if (ae != null && eme != null) {
            Object in[] = { "", ae, eme, null };

            /*if(ae instanceof Feature){
               in[3] = ((MetaClass)ae.eContainer()).getId();
            }
            else in[3] = null;*/

            this.indexPut(in);
        } else {
            //System.out.println("null element input. not loaded");
        }
    }

    public void refreshIndex() {
        List<Object[]> old = new ArrayList<Object[]>();
        List<Object[]> neu = new ArrayList<Object[]>();

        for (Object[] i : index) {
            if (i[3] == null && i[1] instanceof Feature) {
                for (Object[] j : index) {
                    if (j[1] instanceof MetaClass) {
                        MetaClass mc = (MetaClass) j[1];

                        for (Feature f : mc.getFeatures()) {
                            if (f.getId().equals(((Feature) i[1]).getId())) {
                                old.add(i);
                                Object newi[] = { i[0], i[1], i[2], mc.getId() };
                                neu.add(newi);
                            }
                        }
                    }
                }
            }
        }

        for (int i = 0; i < old.size(); i++) {
            this.indexReplace(old.get(i), neu.get(i));
        }
    }

    private List<Object[]> getLoads() {
        List<Object[]> loads = new ArrayList<Object[]>();
        for (Object i[] : index)
            if (((String) i[0]).equals(""))
                loads.add(i);
        return loads;
    }

    private boolean isLoad(AnnotatedElement ae) {
        for (Object i[] : index)
            if (((String) i[0]).equals("") && ((AnnotatedElement) i[1]).getId().equals(ae.getId()))
                return true;
        return false;
    }

    public void add(AnnotatedElement ae) {
        if (ae == null)
            return;

        Object in[] = new Object[4];
        in[0] = "add";
        in[1] = ae;
        in[2] = this.getEVersion(ae);

        if (ae instanceof Feature) {
            in[3] = ((MetaClass) ae.eContainer()).getId();
            ////System.out.println("Referred element located: " + ((MetaClass)ae.eContainer()).getId());
        } else
            in[3] = null;

        if (this.getByID(ae.getId()) == null) {
            this.indexPut(in);
            //   //System.out.println("insert by addition " + ae);
        } else {
            this.indexReplace(this.getByID(ae.getId()), in);
            //   //System.out.println("insert by replacement " + ae);
        }
    }

    private EModelElement getEVersion(AnnotatedElement ae) {
        EModelElement eme = null;

        if (ae instanceof MetaClass)
            eme = MetaClass2EClass((MetaClass) ae);
        else if (ae instanceof Reference)
            eme = Reference2EReference((Reference) ae);
        else if (ae instanceof Attribute)
            eme = Attribute2EAttribute((Attribute) ae);

        return eme;
    }

    private List<Object[]> getAdds() {
        List<Object[]> adds = new ArrayList<Object[]>();
        for (Object i[] : index)
            if (((String) i[0]).equals("add"))
                adds.add(i);
        return adds;
    }

    private boolean isAdd(AnnotatedElement ae) {
        for (Object i[] : index)
            if (((String) i[0]).equals("add") && ((AnnotatedElement) i[1]).getId().equals(ae.getId()))
                return true;
        return false;
    }

    public void delete(AnnotatedElement ae) {
        if (ae == null)
            return;
        Object old[] = this.getByID(ae.getId());
        if (old == null)
            return;

        int op = -1;
        if (isLoad(ae))
            op = 0;
        else if (isAdd(ae))
            op = 1;
        else if (isDelete(ae))
            op = 2;
        else if (isUpdate(ae))
            op = 3;

        switch (op) {
        case 0:
            this.indexReplace(old,
                    wrap("delete", (AnnotatedElement) old[1], (EModelElement) old[2], (String) old[3]));
            break;

        case 1:
            this.indexRemove(old, true);
            break;

        case 2:
            // delete over an element to be deleted has no effect
            break;

        case 3:
            this.indexReplace(old,
                    wrap("delete", (AnnotatedElement) old[1], (EModelElement) old[2], (String) old[3]));
            break;

        default:
            break;
        }
    }

    private List<Object[]> getDeletes() {
        List<Object[]> adds = new ArrayList<Object[]>();
        for (Object i[] : index)
            if (((String) i[0]).equals("delete"))
                adds.add(i);
        return adds;
    }

    private boolean isDelete(AnnotatedElement ae) {
        for (Object i[] : index)
            if (((String) i[0]).equals("delete") && ((AnnotatedElement) i[1]).getId().equals(ae.getId()))
                return true;
        return false;
    }

    public void update(AnnotatedElement ae) {
        if (ae == null)
            return;
        Object old[] = this.getByID(ae.getId());
        if (old == null)
            return;

        int op = -1;
        if (isLoad(ae))
            op = 0;
        else if (isAdd(ae))
            op = 1;
        else if (isDelete(ae))
            op = 2;
        else if (isUpdate(ae))
            op = 3;

        switch (op) {
        case 0:
            this.indexReplace(old, wrap("update", ae, this.getEVersion(ae), (String) old[3]));
            break;

        case 1:
            this.indexReplace(old, wrap("add", ae, this.getEVersion(ae), (String) old[3]));
            break;

        case 2:
            // update over an element to be deleted has no effect
            break;

        case 3:
            this.indexReplace(old, wrap("update", ae, this.getEVersion(ae), (String) old[3]));
            break;

        default:
            break;
        }
    }

    private List<Object[]> getUpdates() {
        List<Object[]> adds = new ArrayList<Object[]>();
        for (Object i[] : index)
            if (((String) i[0]).equals("update"))
                adds.add(i);
        return adds;
    }

    private boolean isUpdate(AnnotatedElement ae) {
        for (Object i[] : index)
            if (((String) i[0]).equals("update") && ((AnnotatedElement) i[1]).getId().equals(ae.getId()))
                return true;
        return false;
    }

    public void exportToCollaboro(IFile chFile) {
        ResourceSetImpl rs = new ResourceSetImpl();
        rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put(Resource.Factory.Registry.DEFAULT_EXTENSION,
                new XMIResourceFactoryImpl());
        Resource chResource = new XMIResourceImpl(URI.createURI(chFile.getLocationURI().toString()));

        IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
        IProject project = chFile.getProject();
        IFile ecoreFile = project.getFile(chFile.getName().substring(0, chFile.getName().indexOf(".")) + ".ecore");
        Resource ecoreResource = null;

        if (ecoreFile.exists()) {
            ecoreResource = new XMIResourceImpl(URI.createURI(ecoreFile.getLocationURI().toString()));
            rs.getResources().add(ecoreResource);
        } else //System.out.println("No ecore file found. It might carry future problems with serialization");

            rs.getResources().add(chResource);

        if (!chFile.exists()) {
            History collHistory = HistoryFactory.eINSTANCE.createHistory();

            String username = metabup.preferences.PreferenceConstants.P_COLLABORO_USERNAME;

            if (username.equals("")) {
                InputDialog ipDialog = new InputDialog(null, "Collaboro username required",
                        "Enter your collaboro username: ",
                        metabup.preferences.PreferenceConstants.P_COLLABORO_USERNAME, null);
                if (ipDialog.open() == InputDialog.OK) {
                    username = ipDialog.getValue();
                    IPreferenceStore store = metabup.preferences.Activator.getDefault().getPreferenceStore();
                    store.setDefault(metabup.preferences.PreferenceConstants.P_COLLABORO_USERNAME, username);
                }
            }

            User user = HistoryFactory.eINSTANCE.createUser();
            user.setId(username);

            VersionHistory vh = HistoryFactory.eINSTANCE.createVersionHistory();
            vh.setType(VersionHistoryType.TRUNK);

            Version version = HistoryFactory.eINSTANCE.createVersion();
            version.setId("1.0");

            Proposal proposal = HistoryFactory.eINSTANCE.createProposal();
            proposal.setProposedBy(user);
            proposal.setRationale("metabup-based proposal");
            proposal.setId("n0");

            Solution solution = HistoryFactory.eINSTANCE.createSolution();
            solution.setProposedBy(user);

            /* root ePackage generation in case there's no one available */
            if (ePackage == null) {
                InputDialog ipDialog = new InputDialog(null, "Main EPackage name required",
                        "Name the EPackage that will contain your Metaclasses",
                        chFile.getName().substring(0, chFile.getName().lastIndexOf(".")), null);
                if (ipDialog.open() == InputDialog.OK) {
                    ePackage = EcoreFactory.eINSTANCE.createEPackage();
                    ePackage.setName(ipDialog.getValue());

                    Add add = HistoryFactory.eINSTANCE.createAdd();

                    NewAbstractSyntaxElement nase = HistoryFactory.eINSTANCE.createNewAbstractSyntaxElement();
                    nase.setElement(ePackage);
                    add.setTarget(nase);

                    add.setSolution(solution);
                    solution.getChanges().add(add);
                }
            }

            solution.getChanges().addAll(this.getCollaboroAdds(solution));
            solution.getChanges().addAll(this.getCollaboroDeletes(solution));
            solution.getChanges().addAll(this.getCollaboroUpdates(solution));

            proposal.getSols().add(solution);
            version.getProposals().add(proposal);
            vh.getVersions().add(version);
            collHistory.getUsers().add(user);
            collHistory.getHistories().add(vh);

            chResource.getContents().add(collHistory);

            try {
                chFile.create(null, true, null);
                chFile.refreshLocal(1, null);
                chResource.save(null);
            } catch (CoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else {
            //WindowDialog.openError();
            //System.out.println("The file already exists");
        }
    }

    private List<Add> getCollaboroAdds(Solution solution) {
        List<Add> adds = new ArrayList<Add>();

        for (Object i[] : this.getAdds()) {
            Add add = HistoryFactory.eINSTANCE.createAdd();
            EModelElement eme2 = null;
            ExistingAbstractSyntaxElement ease = HistoryFactory.eINSTANCE.createExistingAbstractSyntaxElement();
            ;

            /* EClass elements addition */
            if (i[2] instanceof EClass) {
                eme2 = EcoreFactory.eINSTANCE.createEClass();
                eme2 = (EClass) i[2];

                ease.setElement(ePackage);
                add.setReferredElement(ease);
            } else {
                EClass contClass = EcoreFactory.eINSTANCE.createEClass();

                if (i[2] instanceof EReference) {
                    eme2 = EcoreFactory.eINSTANCE.createEReference();
                    eme2 = (EReference) i[2];
                    ((EReference) eme2)
                            .setEType((EClass) this.getByID(((Reference) i[1]).getReference().getId())[2]);
                } else {
                    if (i[2] instanceof EAttribute) {
                        eme2 = EcoreFactory.eINSTANCE.createEAttribute();
                        eme2 = (EAttribute) i[2];
                    }
                }

                // assign the container metaclass as the referred element
                contClass = (EClass) this.getByID(((String) i[3]))[2];
                ease.setElement(contClass);
                add.setReferredElement(ease);

            }

            NewAbstractSyntaxElement nase = HistoryFactory.eINSTANCE.createNewAbstractSyntaxElement();
            nase.setElement(eme2);
            add.setTarget(nase);

            add.setSolution(solution);
            adds.add(add);
        }

        return adds;
    }

    private List<Delete> getCollaboroDeletes(Solution solution) {
        List<Delete> dels = new ArrayList<Delete>();

        for (Object i[] : this.getDeletes()) {
            Delete del = HistoryFactory.eINSTANCE.createDelete();
            EModelElement eme2 = null;
            ExistingAbstractSyntaxElement ease = HistoryFactory.eINSTANCE.createExistingAbstractSyntaxElement();
            ;

            /* EClass elements deletion */
            if (i[2] instanceof EClass) {
                eme2 = EcoreFactory.eINSTANCE.createEClass();
                eme2 = (EClass) i[2];

                ease.setElement(ePackage);
                del.setReferredElement(ease);
            } else {
                EClass contClass = EcoreFactory.eINSTANCE.createEClass();

                if (i[2] instanceof EReference) {
                    eme2 = EcoreFactory.eINSTANCE.createEReference();
                    eme2 = (EReference) i[2];
                    ((EReference) eme2)
                            .setEType((EClass) this.getByID(((Reference) i[1]).getReference().getId())[2]);
                } else {
                    if (i[2] instanceof EAttribute) {
                        eme2 = EcoreFactory.eINSTANCE.createEAttribute();
                        eme2 = (EAttribute) i[2];
                    }
                }

                // assign the container metaclass as the referred element
                contClass = (EClass) this.getByID(((String) i[3]))[2];
                ease.setElement(contClass);
                del.setReferredElement(ease);

            }

            NewAbstractSyntaxElement nase = HistoryFactory.eINSTANCE.createNewAbstractSyntaxElement();
            nase.setElement(eme2);
            del.setTarget(nase);

            del.setSolution(solution);
            dels.add(del);
        }

        return dels;
    }

    private List<Update> getCollaboroUpdates(Solution solution) {
        List<Update> upds = new ArrayList<Update>();

        for (Object i[] : this.getUpdates()) {
            Update upd = HistoryFactory.eINSTANCE.createUpdate();
            EModelElement eme2 = null;
            ExistingAbstractSyntaxElement ease = HistoryFactory.eINSTANCE.createExistingAbstractSyntaxElement();

            /* EClass elements update */
            if (i[2] instanceof EClass) {
                eme2 = EcoreFactory.eINSTANCE.createEClass();
                eme2 = (EClass) i[2];

                ease.setElement(ePackage);
                upd.setReferredElement(ease);
            } else {
                EClass contClass = EcoreFactory.eINSTANCE.createEClass();

                if (i[2] instanceof EReference) {
                    eme2 = EcoreFactory.eINSTANCE.createEReference();
                    eme2 = (EReference) i[2];
                    ((EReference) eme2)
                            .setEType((EClass) this.getByID(((Reference) i[1]).getReference().getId())[2]);
                } else {
                    if (i[2] instanceof EAttribute) {
                        eme2 = EcoreFactory.eINSTANCE.createEAttribute();
                        eme2 = (EAttribute) i[2];
                    }
                }

                // assign the container metaclass as the referred element
                contClass = (EClass) this.getByID(((String) i[3]))[2];
                ease.setElement(contClass);
                upd.setReferredElement(ease);

            }

            NewAbstractSyntaxElement nase = HistoryFactory.eINSTANCE.createNewAbstractSyntaxElement();
            nase.setElement(eme2);
            upd.setTarget(nase);

            upd.setSolution(solution);
            upds.add(upd);
        }

        return upds;
    }

    private Object[] getByID(String id) {
        for (Object i[] : index) {
            if (((AnnotatedElement) (i[1])).getId().equals(id))
                return i;
        }

        return null;
    }

    private Object[] getFeatureContainer(Object[] f) {
        if (f == null)
            return null;
        if (!(f[1] instanceof Feature))
            return null;
        for (Object[] i : index) {
            if (i[0].equals("") || i[0].equals("add"))
                if (i[1] instanceof MetaClass) {
                    MetaClass mc = (MetaClass) i[1];
                    for (Feature mcf : mc.getFeatures()) {
                        if (((Feature) f[1]).getId().equals(mcf.getId()))
                            return i;
                    }
                }
        }

        return null;
    }

    public EClass MetaClass2EClass(MetaClass mc) {
        /* seek the EClass in the original ePackage */
        /*if(this.ePackage != null){
           for(EObject eo : ePackage.eContents()){
        if(eo instanceof EClass){
           EClass ec = (EClass)eo;
           if(ec.getName().equals(mc.getName())) return ec;
        }
           }
        }*/

        /* create a new one if not found before */
        EClass ec = EcoreFactory.eINSTANCE.createEClass();
        ec.setName(mc.getName());
        ec.setAbstract(mc.getIsAbstract());
        return ec;
    }

    public EReference Reference2EReference(Reference ref) {
        /*if(this.ePackage != null){
           for(EObject eo : ePackage.eContents()){
        if(eo instanceof EReference){               
           EReference er = (EReference)eo;
           if(er.getName().equals(ref.getName())){
              if(er.eContainer() instanceof EClass){
                 if(((EClass)er.eContainer()).getName().equals(((MetaClass)ref.eContainer()).getName())) return er;                     
              }
           }
        }
           }
        }*/

        EReference eref = EcoreFactory.eINSTANCE.createEReference();
        eref.setName(ref.getName());
        eref.setLowerBound(ref.getMin());
        eref.setUpperBound(ref.getMax());
        eref.setEType(MetaClass2EClass(ref.getReference()));
        return eref;
    }

    public EAttribute Attribute2EAttribute(Attribute att) {
        /*if(this.ePackage != null){
           for(EObject eo : ePackage.eContents()){
        if(eo instanceof EAttribute){               
           EAttribute ea = (EAttribute)eo;
           if(ea.getName().equals(att.getName())){
              if(ea.eContainer() instanceof EClass){
                 if(((EClass)ea.eContainer()).getName().equals(((MetaClass)att.eContainer()).getName())) return ea;                     
              }
           }
        }
           }
        }*/

        EAttribute eatt = EcoreFactory.eINSTANCE.createEAttribute();
        eatt.setName(att.getName());
        eatt.setLowerBound(att.getMin());
        eatt.setUpperBound(att.getMax());

        String typename = att.getPrimitiveType();

        if (typename.equals("StringType"))
            eatt.setEType(EcorePackage.eINSTANCE.getEString());
        else if (typename.equals("IntType"))
            eatt.setEType(EcorePackage.eINSTANCE.getEInt());
        else if (typename.equals("DoubleType"))
            eatt.setEType(EcorePackage.eINSTANCE.getEDouble());
        else if (typename.equals("BooleanType"))
            eatt.setEType(EcorePackage.eINSTANCE.getEBoolean());
        else
            eatt.setEType(EcorePackage.eINSTANCE.getEString());

        return eatt;
    }

    public void printIndex() {
        for (Object i[] : index) {
            String name = "", ename = "", type = "";
            if (i[1] instanceof MetaClass) {
                name = ((MetaClass) i[1]).getName();
                ename = ((EClass) i[2]).getName();
                type = "MetaClass";
            } else {
                if (i[1] instanceof Reference) {
                    name = ((Reference) i[1]).getName();
                    ename = ((EReference) i[2]).getName();
                    type = "Reference";
                } else {
                    if (i[1] instanceof Attribute) {
                        name = ((Attribute) i[1]).getName();
                        ename = ((EAttribute) i[2]).getName();
                        type = "Attribute";
                    }
                }
            }

            //System.out.println("\n" + i[0] + "\t" + name + "\t" + ename + "\t" + type);
        }
    }
}