/*******************************************************************************
* Copyright (c) 2008, 2013
* 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:
* Javier Canovas (javier.canovas@inria.fr)
*******************************************************************************/
package fr.inria.atlanmod.collaboro.ui;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EModelElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.viewers.TreeViewer;
import fr.inria.atlanmod.collaboro.history.AbstractSyntaxElement;
import fr.inria.atlanmod.collaboro.history.Add;
import fr.inria.atlanmod.collaboro.history.Collaboration;
import fr.inria.atlanmod.collaboro.history.Comment;
import fr.inria.atlanmod.collaboro.history.ConcreteSyntaxElement;
import fr.inria.atlanmod.collaboro.history.Delete;
import fr.inria.atlanmod.collaboro.history.ExistingAbstractSyntaxElement;
import fr.inria.atlanmod.collaboro.history.History;
import fr.inria.atlanmod.collaboro.history.HistoryFactory;
import fr.inria.atlanmod.collaboro.history.ModelChange;
import fr.inria.atlanmod.collaboro.history.NewAbstractSyntaxElement;
import fr.inria.atlanmod.collaboro.history.Proposal;
import fr.inria.atlanmod.collaboro.history.Solution;
import fr.inria.atlanmod.collaboro.history.SyntaxElement;
import fr.inria.atlanmod.collaboro.history.Update;
import fr.inria.atlanmod.collaboro.history.User;
import fr.inria.atlanmod.collaboro.history.Version;
import fr.inria.atlanmod.collaboro.history.VersionHistory;
import fr.inria.atlanmod.collaboro.history.Vote;
import fr.inria.atlanmod.collaboro.notation.Definition;
import fr.inria.atlanmod.collaboro.notation.NotationElement;
import fr.inria.atlanmod.collaboro.notation.NotationFactory;
import fr.inria.atlanmod.collaboro.ui.views.CollaborationView;
import fr.inria.atlanmod.collaboro.ui.views.VersionView;
/**
* Main class controlling the Collaborto Plugin
*
* @author Javier Canovas (javier.canovas@inria.fr)
*
*/
/**
* @author Javier Canovas (javier.canovas@inria.fr)
*
*/
public class Controller {
// Default plugin IDs
public static final String ECORE_PLUGIN_ID = "org.eclipse.emf.ecore.presentation.EcoreEditorID";
public static final String PACKAGE_EXPLORER_PLUGIN_ID = "org.eclipse.jdt.ui.PackageExplorer";
public static final String REFLECTIVE_EDITOR_PLUGIN_ID = "org.eclipse.emf.ecore.presentation.ReflectiveEditorID";
public static final String NOTATION_EDITOR_PLUGIN_ID = "fr.inria.atlanmod.collaboro.notation.presentation.NotationEditorID";
public static final Object PROJECT_EXPLORER_PLUGIN_ID = "org.eclipse.ui.navigator.ProjectExplorer";
// Singleton instance
public static Controller INSTANCE = new Controller();
// Extensions for the models supported
public static final String HISTORY_EXTENSION = "history";
public static final String NOTATION_EXTENSION = "notation";
public static final String ECORE_EXTENSION = "ecore";
public static final String MODEL_EXTENSION = "xmi";
// Variables to control the state of the plugin
private User loggedUser = null;
private int lastIndex = 0;
private int historyTracked = 0;
private int versionTracked = 0;
/**
* The controller knows some views, this is temporal, I have to discover
* how to use better the event control in Eclipse
*/
private VersionView versionView;
private TreeViewer changes;
private CollaborationView.VoteUpdater voteUpdater;
ModelManagerFactory modelManagerFactory = new ModelManagerFactory();
ModelManager modelManager = modelManagerFactory.createEmptyModelManager();
public ModelManager getModelManager() {
return modelManager;
}
private Controller () { }
/**
* Testing method to reset the information
*/
public void reset() {
loggedUser = null;
lastIndex = 0;
historyTracked = 0;
versionTracked = 0;
}
public User getLoggedUser() {
return loggedUser;
}
public History getHistory() {
return modelManager.getHistory();
}
public EPackage getEcoreModel() {
return modelManager.getEcoreModel();
}
public Definition getNotation() {
return modelManager.getNotation();
}
/**
* Loads a new History model
*
* @param resource to be tracked
*/
public void loadHistory(Object resource) {
reset();
modelManager = modelManagerFactory.createModelManager(resource);
calculateLastIndexProposal();
if(getHistory() != null)
versionTracked = getHistory().getHistories().get(historyTracked).getVersions().size() - 1;
}
private void calculateLastIndexProposal() {
lastIndex = 0;
if(getHistory() != null) {
for(Proposal proposal : getHistory().getHistories().get(getHistoryTracked()).getVersions().get(getVersionTracked()).getProposals()) {
String idProposal = proposal.getId();
int valueProposal = Integer.valueOf(idProposal.substring(1, idProposal.length()));
if(valueProposal > lastIndex)
lastIndex = valueProposal;
for(Comment comment : proposal.getComments()) {
String idComment = comment.getId();
int valueComment = Integer.valueOf(idComment.substring(1, idComment.length()));
if(valueComment > lastIndex)
lastIndex = valueComment;
}
for(Solution solution : proposal.getSols()) {
String idSolution = solution.getId();
int valueSolution = Integer.valueOf(idSolution.substring(1, idSolution.length()));
if(valueSolution > lastIndex)
lastIndex = valueSolution;
for(Comment comment : solution.getComments()) {
String idCommentSol = comment.getId();
int valueCommentSol = Integer.valueOf(idCommentSol.substring(1, idCommentSol.length()));
if(valueCommentSol > lastIndex)
lastIndex = valueCommentSol;
}
}
}
}
}
/**
* Loads an ecore model. Normally the model conforms to the metamodel being tracked.
*
* @param modelPath
* @return
*/
public EObject loadModel(File modelPath) {
if(modelManager == null) return null;
return modelManager.loadModel(modelPath);
}
/**
* Sets the user logged in the application.
*
* @param userName
* @return True if the user was found, false if not
*/
public boolean loginUser(String userName) {
boolean found = false;
if(getHistory() != null) {
for (User user : getHistory().getUsers()) {
if(user.getId().equals(userName)) {
loggedUser = user;
found = true;
break;
}
}
}
return found;
}
/**
* Indicates if the user is logged
* @return
*/
public boolean isLogged() {
return !(loggedUser == null);
}
public void createVoteNegative(Collaboration collaboration) {
if(collaboration.getProposedBy().getId().equals(loggedUser.getId()))
return;
Vote newVote = null;
for(Vote vote : collaboration.getVotes()) {
if(vote.getUser().getId().equals(loggedUser.getId())) {
newVote = vote;
break;
}
}
if(newVote == null) {
newVote = HistoryFactory.eINSTANCE.createVote();
Comment newComment = HistoryFactory.eINSTANCE.createComment();
newComment.setProposedBy(loggedUser);
newComment.setId("n" + ++lastIndex);
collaboration.getComments().add(newComment);
newVote.setComment(newComment);
collaboration.getVotes().add(newVote);
}
newVote.setAgreement(false);
newVote.setUser(loggedUser);
modelManager.saveHistory();
modelManager.saveNotation();
refreshVersionView();
refreshVoteUpdater();
}
public void createVotePositive(Collaboration collaboration) {
if(collaboration.getProposedBy().getId().equals(loggedUser.getId()))
return;
Vote newVote = null;
for(Vote vote : collaboration.getVotes()) {
if(vote.getUser().getId().equals(loggedUser.getId())) {
newVote = vote;
break;
}
}
if(newVote == null) {
newVote = HistoryFactory.eINSTANCE.createVote();
collaboration.getVotes().add(newVote);
}
newVote.setAgreement(true);
newVote.setUser(loggedUser);
modelManager.saveHistory();
modelManager.saveNotation();
refreshVersionView();
refreshVoteUpdater();
}
public void createSolution(Proposal proposal) {
Solution newSolution = HistoryFactory.eINSTANCE.createSolution();
newSolution.setProposedBy(loggedUser);
newSolution.setId("n" + ++lastIndex);
proposal.getSols().add(newSolution);
modelManager.saveHistory();
modelManager.saveNotation();
refreshVersionView();
}
public void createProposal() {
Proposal newProposal = HistoryFactory.eINSTANCE.createProposal();
newProposal.setId("n" + ++lastIndex);
newProposal.setProposedBy(loggedUser);
getProposals().add(newProposal);
Version version = getHistory().getHistories().get(getHistoryTracked()).getVersions().get(getVersionTracked());
version.getProposals().add(newProposal);
modelManager.saveHistory();
modelManager.saveNotation();
refreshVersionView();
}
public void createComment(Collaboration collaboration) {
Comment newComment = HistoryFactory.eINSTANCE.createComment();
newComment.setProposedBy(loggedUser);
newComment.setId("n" + ++lastIndex);
collaboration.getComments().add(newComment);
modelManager.saveHistory();
modelManager.saveNotation();
refreshVersionView();
}
public void createAdd(Solution solution) {
Add newAdd = HistoryFactory.eINSTANCE.createAdd();
solution.getChanges().add(newAdd);
modelManager.saveHistory();
modelManager.saveNotation();
refreshChanges();
}
public void createUpdate(Solution solution) {
Update newUpdate = HistoryFactory.eINSTANCE.createUpdate();
solution.getChanges().add(newUpdate);
modelManager.saveHistory();
modelManager.saveNotation();
refreshChanges();
}
public void createDelete(Solution solution) {
Delete newDelete = HistoryFactory.eINSTANCE.createDelete();
solution.getChanges().add(newDelete);
modelManager.saveHistory();
modelManager.saveNotation();
refreshChanges();
}
public void setVersionView(VersionView viewer) {
this.versionView = viewer;
}
public void refreshVersionView() {
if(this.versionView != null)
this.versionView.refresh();
}
public void setChanges(TreeViewer changes) {
this.changes = changes;
}
public void refreshChanges() {
if(this.changes != null)
this.changes.refresh();
}
public void setVoteUpdater(CollaborationView.VoteUpdater voteUpdater) {
this.voteUpdater = voteUpdater;
}
public void refreshVoteUpdater() {
if(this.voteUpdater != null)
this.voteUpdater.update();
}
public int getHistoryTracked() {
return historyTracked;
}
public int getVersionTracked() {
return versionTracked;
}
/**
* Looks for a ConcreteSyntaxElement linked with the Eclassifier received
*
* @param modelElement
* @return
*/
public NotationElement getNotation(EClassifier modelElement) {
if(getHistory() == null) return null;
List<Proposal> proposals = getHistory().getHistories().get(getHistoryTracked()).getVersions().get(getVersionTracked()).getProposals();
for(Proposal proposal : proposals) {
List<Solution> solutions = proposal.getSols();
for(Solution solution : solutions) {
List<ModelChange> changes = solution.getChanges();
for(ModelChange change : changes) {
if(change.getReferredElement() instanceof AbstractSyntaxElement && change.getTarget() instanceof ConcreteSyntaxElement) {
EModelElement refModelElement = null;
if (change.getReferredElement() instanceof ExistingAbstractSyntaxElement) {
refModelElement = ((ExistingAbstractSyntaxElement) change.getReferredElement()).getElement();
}
if (change.getReferredElement() instanceof NewAbstractSyntaxElement) {
refModelElement = ((NewAbstractSyntaxElement) change.getReferredElement()).getElement();
}
if(refModelElement != null) {
if (refModelElement instanceof EClassifier) {
EClassifier classifier = (EClassifier) refModelElement;
if(classifier.getName().equals(modelElement.getName())) {
ConcreteSyntaxElement concreteElement = (ConcreteSyntaxElement) change.getTarget();
NotationElement result = concreteElement.getElement();
return result;
}
}
}
}
}
}
}
return null;
}
public List<Proposal> getProposals() {
List<Proposal> result = new ArrayList<Proposal>();
if(getHistory() != null && getHistory().getHistories() != null) {
VersionHistory versionHistory = getHistory().getHistories().get(getHistoryTracked());
if(versionHistory != null && getHistory().getHistories().get(getHistoryTracked()).getVersions() != null) {
Version version = getHistory().getHistories().get(getHistoryTracked()).getVersions().get(getVersionTracked());
if(version != null) {
result = getHistory().getHistories().get(getHistoryTracked()).getVersions().get(getVersionTracked()).getProposals();
}
}
}
return result;
}
public List<NotationElement> getAllNotationElements() {
List<NotationElement> result = new ArrayList<NotationElement>();
List<Proposal> proposals = getHistory().getHistories().get(getHistoryTracked()).getVersions().get(getVersionTracked()).getProposals();
for(Proposal proposal : proposals) {
List<Solution> solutions = proposal.getSols();
for(Solution solution : solutions) {
List<ModelChange> changes = solution.getChanges();
for(ModelChange change : changes) {
if(change.getReferredElement() instanceof ConcreteSyntaxElement) {
if(!result.contains(change.getReferredElement()))
result.add(((ConcreteSyntaxElement) change.getReferredElement()).getElement());
}
if(change.getTarget() instanceof ConcreteSyntaxElement) {
if(!result.contains(change.getTarget()))
result.add(((ConcreteSyntaxElement) change.getTarget()).getElement());
}
}
}
}
return result;
}
public List<EObject> getAllNotationMetaElements() {
List<EObject> result = new ArrayList<EObject>();
result.add(NotationFactory.eINSTANCE.createComposite());
result.add(NotationFactory.eINSTANCE.createKeyword());
result.add(NotationFactory.eINSTANCE.createToken());
result.add(NotationFactory.eINSTANCE.createReferenceValue());
result.add(NotationFactory.eINSTANCE.createAttributeValue());
result.add(NotationFactory.eINSTANCE.createSyntaxOf());
return result;
}
public List<EObject> getAllEcoreElements() {
List<EObject> result = new ArrayList<EObject>();
result.add(EcoreFactory.eINSTANCE.createEClass());
result.add(EcoreFactory.eINSTANCE.createEEnum());
result.add(EcoreFactory.eINSTANCE.createEAttribute());
return result;
}
public void openNotationEditor(NotationElement notationElement) {
// if (modelManager.getNotation() != null && modelManager.getNotationFile().exists() && modelManager.getNotationFile().isFile()) {
// String path = modelManager.getNotationFile().getAbsolutePath();
// IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
// try {
// java.net.URI fromString = org.eclipse.core.runtime.URIUtil.fromString("file://" + path);
// NotationEditor openEditor = (NotationEditor) IDE.openEditor(page, fromString, NOTATION_EDITOR_PLUGIN_ID, true);
// IEditorInput editorInput = openEditor.getEditorInput();
//
// EditingDomain editingDomain = openEditor.getEditingDomain();
// URI uri = EcoreUtil.getURI(notationElement);
// EObject editObject = editingDomain.getResourceSet().getEObject(uri, true);
// if(editObject != null) {
// openEditor.setSelectionToViewer(Collections.singleton(editObject));
// }
//
// } catch ( PartInitException e ) {
// e.printStackTrace();
// } catch (URISyntaxException e) {
// e.printStackTrace();
// }
// }
}
public void openAbstractSyntaxEditor(EClass eClass) {
// if (modelManager.getEcoreModel() != null && modelManager.getEcoreModelFile().exists() && modelManager.getEcoreModelFile().isFile()) {
// String path = modelManager.getEcoreModelFile().getAbsolutePath();
// IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
// try {
// java.net.URI fromString = org.eclipse.core.runtime.URIUtil.fromString("file://" + path);
// IEditorPart openEditor = IDE.openEditor(page, fromString, ECORE_PLUGIN_ID, true);
// IEditorInput editorInput = openEditor.getEditorInput();
// } catch ( PartInitException e ) {
// e.printStackTrace();
// } catch (URISyntaxException e) {
// e.printStackTrace();
// }
// }
// String abstractModelFileName = ecoreModel.getName();
// IEditorDescriptor descriptor = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(abstractModelFileName);
//
// if (ecoreModel.exists() && ecoreModel.isFile()) {
// String path = ecoreModel.getAbsolutePath();
// IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
// try {
// java.net.URI fromString = org.eclipse.core.runtime.URIUtil.fromString("file://" + path);
// EcoreEditor ecoreEditor = (EcoreEditor) IDE.openEditor(page, fromString, ECORE_PLUGIN_ID, true);
//
// EditingDomain editingDomain = ecoreEditor.getEditingDomain();
// URI uri = EcoreUtil.getURI(eClass);
// EObject editObject = editingDomain.getResourceSet().getEObject(uri, true);
// if(editObject != null) {
// ecoreEditor.setSelectionToViewer(Collections.singleton(editObject));
// }
//
// } catch ( PartInitException e ) {
// e.printStackTrace();
// } catch (URISyntaxException e) {
// e.printStackTrace();
// }
// }
}
public void addNotationElement(NotationElement selectedElement) {
if(getNotation() != null & selectedElement != null) {
getNotation().getElements().add(selectedElement);
modelManager.saveNotation();
}
}
private static boolean inNotation = false;
public void inNotation() {
inNotation = true;
}
public void outNotation() {
if(inNotation) {
inNotation = false;
modelManager.loadHistory();
modelManager.loadNotation();
if(changes != null) changes.refresh();
}
}
public void deleteCollaboration(Collaboration collaboration) {
if (collaboration instanceof Proposal) {
Proposal proposal = (Proposal) collaboration;
deleteProposal(proposal);
} else if (collaboration instanceof Solution) {
Solution solution = (Solution) collaboration;
deleteSolution(solution);
} else if (collaboration instanceof Comment) {
Comment comment = (Comment) collaboration;
deleteComment(comment);
}
modelManager.saveHistory();
modelManager.saveNotation();
calculateLastIndexProposal();
}
private void deleteProposal(Proposal proposalToDelete) {
getHistory().getHistories().get(getHistoryTracked()).getVersions().get(getVersionTracked()).getProposals().remove(proposalToDelete);
proposalToDelete.setVersion(null);
proposalToDelete.setProposedBy(null);
}
private void deleteSolution(Solution solutionToDelete) {
EObject eObject = solutionToDelete.eContainer();
if (eObject instanceof Proposal) {
Proposal proposal = (Proposal) eObject;
proposal.getSols().remove(solutionToDelete);
}
}
private void deleteComment(Comment commentToDelete) {
EObject eObject = commentToDelete.eContainer();
if (eObject instanceof Collaboration) {
Collaboration collaboration = (Collaboration) eObject;
collaboration.getComments().remove(commentToDelete);
}
}
public void deleteModelChange(ModelChange modelChange) {
EObject eObject = modelChange.eContainer();
if (eObject instanceof Solution) {
Solution solution = (Solution) eObject;
solution.getChanges().remove(modelChange);
}
modelManager.saveHistory();
modelManager.saveNotation();
}
public List<ModelChange> applyChanges() {
List<ModelChange> appliedChanges = new ArrayList<ModelChange>();
if(getHistory() == null) return appliedChanges;
for(Proposal proposal : getHistory().getHistories().get(getHistoryTracked()).getVersions().get(getVersionTracked()).getProposals()) {
if(proposal.isAccepted()) {
Solution solution = proposal.getSelected();
if(solution != null) {
for(ModelChange change : solution.getChanges()) {
if (change instanceof Add) {
Add add = (Add) change;
SyntaxElement referred = add.getReferredElement();
SyntaxElement target = add.getTarget();
if (referred instanceof ExistingAbstractSyntaxElement) {
ExistingAbstractSyntaxElement refExistingElement = (ExistingAbstractSyntaxElement) referred;
EObject refEObject = refExistingElement.getElement();
if (target instanceof NewAbstractSyntaxElement) {
NewAbstractSyntaxElement tgtNewElement = (NewAbstractSyntaxElement) target;
EObject tgtEObject = tgtNewElement.getElement();
if (tgtEObject instanceof EAttribute) {
EAttribute newAttribute = (EAttribute) tgtEObject;
if (refEObject instanceof EClass) {
EClass eClass = (EClass) refEObject;
eClass.getEStructuralFeatures().add(newAttribute);
appliedChanges.add(change);
}
}
if(tgtEObject instanceof EClass) {
EClass eClass = (EClass) tgtEObject;
if (refEObject instanceof EPackage) {
EPackage ePackage = (EPackage) refEObject;
ePackage.getEClassifiers().add(eClass);
appliedChanges.add(change);
}
}
if(tgtEObject instanceof EEnum) {
EEnum eEnum = (EEnum) tgtEObject;
if (refEObject instanceof EPackage) {
EPackage ePackage = (EPackage) refEObject;
ePackage.getEClassifiers().add(eEnum);
appliedChanges.add(change);
}
}
}
}
} else if (change instanceof Delete) {
Delete delete = (Delete) change;
SyntaxElement referred = delete.getReferredElement();
SyntaxElement target = delete.getTarget();
if (referred instanceof ExistingAbstractSyntaxElement) {
ExistingAbstractSyntaxElement refExistingElement = (ExistingAbstractSyntaxElement) referred;
EObject refEObject = refExistingElement.getElement();
if (target instanceof ExistingAbstractSyntaxElement) {
ExistingAbstractSyntaxElement toDelete = (ExistingAbstractSyntaxElement) target;
EObject tgtEObject = toDelete.getElement();
if(tgtEObject instanceof EAttribute) {
EAttribute eAttribute = (EAttribute) tgtEObject;
if (refEObject instanceof EClass) {
EClass eClass = (EClass) refEObject;
eClass.getEStructuralFeatures().remove(eAttribute);
appliedChanges.add(change);
}
}
if(tgtEObject instanceof EClass) {
EClass eClass = (EClass) tgtEObject;
if (refEObject instanceof EPackage) {
EPackage ePackage = (EPackage) refEObject;
ePackage.getEClassifiers().remove(eClass);
appliedChanges.add(change);
}
}
if(tgtEObject instanceof EEnum) {
EEnum eEnum = (EEnum) tgtEObject;
if (refEObject instanceof EPackage) {
EPackage ePackage = (EPackage) refEObject;
ePackage.getEClassifiers().remove(eEnum);
appliedChanges.add(change);
}
}
}
}
}
}
}
}
}
modelManager.saveEcoreModel();
return appliedChanges;
}
public void saveHistory() {
modelManager.saveHistory();
}
public void changeVersion(Version version) {
if(getHistory() == null) return;
List<Version> versions = getHistory().getHistories().get(getHistoryTracked()).getVersions();
int indexOfVersion = versions.indexOf(version);
versionTracked = indexOfVersion;
versionView.refresh();
}
public void logout() {
modelManager.closeConnection();
loggedUser = null;
}
}