blob: 60c1f2610f82f3060159d0a6d8a2284ef69efd70 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2014, 2017 CEA LIST.
*
*
* 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:
* Patrick Tessier (CEA LIST) patrick.tessier@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.revision.tool.core;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.compare.CompareFactory;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.EMFCompare;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.match.DefaultComparisonFactory;
import org.eclipse.emf.compare.match.DefaultEqualityHelperFactory;
import org.eclipse.emf.compare.match.DefaultMatchEngine;
import org.eclipse.emf.compare.match.IComparisonFactory;
import org.eclipse.emf.compare.match.IMatchEngine;
import org.eclipse.emf.compare.match.eobject.IEObjectMatcher;
import org.eclipse.emf.compare.match.impl.MatchEngineFactoryImpl;
import org.eclipse.emf.compare.match.impl.MatchEngineFactoryRegistryImpl;
import org.eclipse.emf.compare.scope.DefaultComparisonScope;
import org.eclipse.emf.compare.scope.IComparisonScope;
import org.eclipse.emf.compare.utils.UseIdentifiers;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.resource.NotFoundException;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.ui.editor.IMultiDiagramEditor;
import org.eclipse.papyrus.revision.tool.Activator;
import org.eclipse.papyrus.revision.tool.dialogs.CreateAuthorDialog;
import org.eclipse.papyrus.revision.tool.dialogs.CreateOrSelectReviewModelDialog;
import org.eclipse.papyrus.revision.tool.preference.RevisionPreferenceConstants;
import org.eclipse.papyrus.uml.extensionpoints.profile.RegisteredProfile;
import org.eclipse.papyrus.uml.extensionpoints.utils.Util;
import org.eclipse.papyrus.uml.tools.model.UmlModel;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.uml2.uml.Actor;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.Dependency;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.UMLFactory;
/**
* This class is used to manage the resource about the reviews and revisions.
* It contains several important methods:
*- load or get the current review model
*- start and stop revision the connect or disconnect listener to register modification in the working model
*- method to access to the ServiceRegistry
*/
public class ReviewResourceManager {
protected Model UMLWorkingModel;
protected ModelSet modelSet;
protected Model reviewModel;
protected Actor currentAuthor;
protected AddingDiffListener addingDiffListener=null;
protected RefreshFigureListener refreshFigureListener=null;
protected Comparison diffModel=null;
protected boolean modeRevisionRunning=false;
/**
* constructor
*/
public ReviewResourceManager(){
this.addingDiffListener= new AddingDiffListener(this);
this.refreshFigureListener= new RefreshFigureListener(this);
}
/**
* used before kill the the resourcemanager, it remove listeners...
*/
public void dispose(){
if(addingDiffListener!=null){
getDomain().removeResourceSetListener(addingDiffListener);
}
if(refreshFigureListener!=null){
getDomain().removeResourceSetListener(refreshFigureListener);
}
modeRevisionRunning=false;
refreshFigureListener=null;
diffModel=null;
reviewModel=null;
currentAuthor=null;
UMLWorkingModel=null;
modelSet=null;
}
/**
* used to get the the current workbenchPart
* @return
*/
protected IWorkbenchPart getBootstrapPart() {
IWorkbenchPart part = null;
try {
IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (activeWorkbenchWindow != null) {
IWorkbenchPage activePage = activeWorkbenchWindow.getActivePage();
if (activePage != null) {
part = activePage.getActiveEditor();
}
}
} catch (NullPointerException e) {
// An element is not active yet
return null;
}
if (isImportant(part)) {
return part;
}
// The current active part is not for us.
return null;
}
/**
*
* @return the current Review model, maybe null
*/
public Model getCurrentReviewModelWithoutLoading(){
return reviewModel;
}
/**
*
* @return the current Review model,if null load it with GUI
*/
public Model getCurrentReviewModel(){
if( reviewModel==null){
CreateOrSelectReviewModelDialog dialog=new CreateOrSelectReviewModelDialog(new Shell(), this);
dialog.open();
getDomain().addResourceSetListener(refreshFigureListener);
}
return reviewModel;
}
/**
*
* @return the EMF compare Diff model
*/
public Comparison getDiffModel(){
if( diffModel==null){
getCurrentReviewModel();
Resource reviewResource= getCurrentReviewModel().eResource();
for (EObject currentRoot : reviewResource.getContents()) {
if( currentRoot instanceof Comparison){
diffModel= (Comparison)currentRoot;
}
}
if( diffModel==null){
diffModel= CompareFactory.eINSTANCE.createComparison();
Match match= CompareFactory.eINSTANCE.createMatch();
match.setLeft(getWorkingModel());
reviewResource.getContents().add(diffModel);
}
}
return diffModel;
}
/**
*
* @return the editing domain of papyrus
*/
public TransactionalEditingDomain getDomain(){
return getCurrentModelSet().getTransactionalEditingDomain();
}
/**
* used to add a review in the review model
* @param element the container of the review
*/
public void addAReview(final Element element){
getCurrentReviewModel();
final Actor theauthor=getCurrentAuthor();
RecordingCommand cmd= new RecordingCommand(getDomain(), "createAReview") {
@Override
protected void doExecute() {
Comment cmt= UMLFactory.eINSTANCE.createComment();
cmt.setBody("Your review");
if(element instanceof Comment ){
((Comment)element).getOwnedComments().add(cmt);
}
else{ reviewModel.getOwnedComments().add(cmt);}
Stereotype review= cmt.getApplicableStereotype(I_ReviewStereotype.REVIEW_STEREOTYPE);
cmt.applyStereotype(review);
cmt.setValue(review, I_ReviewStereotype.COMMENT_SUBJECT_ATT, "subject");
Stereotype authorStereotype= theauthor.getApplicableStereotype(I_VersioningStereotype.AUTHOR_STEREOTYPE);
cmt.setValue(review, I_VersioningStereotype.VERSIONINGELEMENT_AUTHOR_ATT, theauthor.getStereotypeApplication(authorStereotype));
// add tthe date
Date today = new Date();
DateFormat shortDateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT);
cmt.setValue(review, I_VersioningStereotype.VERSIONINGELEMENT_DATE_ATT, shortDateFormat.format(today));
}
};
getDomain().getCommandStack().execute(cmd);
}
/**
*
* @return the author construct from preferences
*/
public Actor getCurrentAuthor(){
if(currentAuthor==null||currentAuthor.eContainer()==null){
//1. test if the author of preferences is not anonymous
final IPreferenceStore store = Activator.getDefault().getPreferenceStore();
final String authorNamefromPreference=store.getString(RevisionPreferenceConstants.AUTHOR_NAME);
if( authorNamefromPreference.equals(RevisionPreferenceConstants.ANONYMOUS_AUTHOR)){
CreateAuthorDialog authorDialog= new CreateAuthorDialog(new Shell());
authorDialog.open();
}
final String authorName=store.getString(RevisionPreferenceConstants.AUTHOR_NAME).trim();
final Model reviewModel=getCurrentReviewModel();
NamedElement author=reviewModel.getPackagedElement(authorName);
if( author==null||!(author instanceof Actor)){
final RecordingCommand cmd= new RecordingCommand(getDomain(), "createReviewModel") {
@Override
protected void doExecute() {
currentAuthor=UMLFactory.eINSTANCE.createActor();
currentAuthor.setName(authorName.trim());
reviewModel.getPackagedElements().add(currentAuthor);
Stereotype authorStereotype= currentAuthor.getApplicableStereotype(I_VersioningStereotype.AUTHOR_STEREOTYPE);
currentAuthor.applyStereotype(authorStereotype);
currentAuthor.setValue(authorStereotype, I_VersioningStereotype.AUTHOR_LANGUAGE_ATT, store.getString(RevisionPreferenceConstants.AUTHOR_LANGUAGE));
RGB authorColor=PreferenceConverter.getColor(store, RevisionPreferenceConstants.AUTHOR_COLOR);
String colorString=authorColor.red+":"+authorColor.green+":"+authorColor.blue;
currentAuthor.setValue(authorStereotype, I_VersioningStereotype.AUTHOR_COLOR_ATT, colorString);
}
};
getDomain().getCommandStack().execute(cmd);
}
else{
currentAuthor=(Actor)author;
}
}
return currentAuthor;
}
/**
* used to load a review model
* @return the obtained review model
*/
public Model loadReviewModel(){
ElementTreeSelectionDialog dialog= new ElementTreeSelectionDialog(Display.getDefault().getActiveShell(), new WorkbenchLabelProvider(), new BaseWorkbenchContentProvider());
dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
PatternFilter UMLPattern= new PatternFilter(){
@Override
public boolean isElementVisible(Viewer viewer, Object element) {
if(viewer!=null){
return super.isElementVisible(viewer, element);
}
return true;
}};
UMLPattern.setPattern("*.uml");
dialog.setAllowMultiple(false);
dialog.addFilter( UMLPattern);
dialog.open();
if(dialog.getResult().length>0){
Object object=dialog.getResult()[0];
if(object instanceof IFile){
IFile aReviewModel=((IFile)object);
Resource tmpResource = getCurrentModelSet().getResource(URI.createPlatformResourceURI(aReviewModel.getFullPath().toOSString(), true),true);
for (EObject contentEObject : tmpResource.getContents()) {
if( contentEObject instanceof Model && (((Model)contentEObject).getAppliedStereotype(I_ReviewStereotype.REVIEWREPOSITORY_STEREOTYPE))!=null){
reviewModel=(Model)contentEObject;
}
}
}
}
getDomain().addResourceSetListener(refreshFigureListener);
return reviewModel;
}
/**
* create a review model
* @param reviewModelName the name of the review model that will be created
* @return the review model
*/
public Model createReviewModel(final String reviewModelName){
RecordingCommand cmd= new RecordingCommand(getDomain(), "createReviewModel") {
@Override
protected void doExecute() {
URI umlModel_URI=getWorkingModel().eResource().getURI();
String tmpURI=umlModel_URI.toString().replaceAll(umlModel_URI.lastSegment().toString(), reviewModelName+".uml");
URI reviewURI=URI.createURI(tmpURI);
Resource resource = getCurrentModelSet().createResource(reviewURI);
reviewModel = UMLFactory.eINSTANCE.createModel();
reviewModel.setName(reviewModelName);
// apply profile review
{
RegisteredProfile registeredProfile=(RegisteredProfile)RegisteredProfile.getRegisteredProfile("ReviewProfile");
URI reviewProfileUri = registeredProfile.uri;
final Resource modelResource = getCurrentModelSet().getResource(reviewProfileUri, true);
Profile reviewProfile=(Profile) modelResource.getContents().get(0);
reviewModel.applyProfile(reviewProfile);
reviewModel.applyStereotype(reviewModel.getApplicableStereotype(I_ReviewStereotype.REVIEWREPOSITORY_STEREOTYPE));
EObject stereappl=reviewModel.getStereotypeApplication(reviewModel.getApplicableStereotype(I_ReviewStereotype.REVIEWREPOSITORY_STEREOTYPE));
resource.getContents().add(stereappl);
}
//apply profile versioning
{
RegisteredProfile registeredProfile=(RegisteredProfile)RegisteredProfile.getRegisteredProfile("VersioningProfile");
URI reviewProfileUri = registeredProfile.uri;
final Resource modelResource = getCurrentModelSet().getResource(reviewProfileUri, true);
Profile reviewProfile=(Profile) modelResource.getContents().get(0);
reviewModel.applyProfile(reviewProfile);
}
Dependency dependency= UMLFactory.eINSTANCE.createDependency();
dependency.getSuppliers().add(getWorkingModel());
dependency.getClients().add(reviewModel);
dependency.setName("WorkingModelDependency");
reviewModel.getPackagedElements().add(dependency);
resource.getContents().add(reviewModel);
diffModel= CompareFactory.eINSTANCE.createComparison();
Match match= CompareFactory.eINSTANCE.createMatch();
match.setLeft(getWorkingModel());
resource.getContents().add(diffModel);
}
};
getDomain().getCommandStack().execute(cmd);
getDomain().addResourceSetListener(refreshFigureListener);
return reviewModel;
}
/**
* get the working model
* @return the model that is modified inside papyrus
*/
public Model getWorkingModel(){
if(UMLWorkingModel!=null){
return UMLWorkingModel;
}
modelSet = getCurrentModelSet();
UmlModel IUMLModel=(UmlModel)modelSet.getModel(UmlModel.MODEL_ID);
try {
UMLWorkingModel = (Model)IUMLModel.lookupRoot();
} catch (NotFoundException e) {
e.printStackTrace();
}
return UMLWorkingModel;
}
/**
*
* @return the current model set of papyrus.
*/
public ModelSet getCurrentModelSet(){
if(modelSet!=null){
return modelSet;
}
IWorkbenchPart part=getBootstrapPart();
if (part instanceof IMultiDiagramEditor){
ServicesRegistry registry=((IMultiDiagramEditor)part).getServicesRegistry();
try {
modelSet = registry.getService(ModelSet.class);
} catch (ServiceException e) {
e.printStackTrace();
}
}
return modelSet;
}
/**
* @return current service registry
*/
public ServicesRegistry getServiceRegistry(){
IWorkbenchPart part=getBootstrapPart();
if (part instanceof IMultiDiagramEditor){
ServicesRegistry registry=((IMultiDiagramEditor)part).getServicesRegistry();
return registry;
}
return null;
}
/**
* return true if the activated part is a {@link IMultiDiagramEditor}.
*
* @see org.eclipse.ui.part.PageBookView#isImportant(org.eclipse.ui.IWorkbenchPart)
*
* @param part
* @return
*/
protected boolean isImportant(IWorkbenchPart part) {
if (part instanceof IMultiDiagramEditor) {
return true;
}
return false;
}
protected void compare(final Model modelBefore, Model modelAfter) {
IEObjectMatcher matcher = DefaultMatchEngine.createDefaultEObjectMatcher(UseIdentifiers.NEVER);
IComparisonFactory comparisonFactory = new DefaultComparisonFactory(new DefaultEqualityHelperFactory());
final IMatchEngine thematchEngine = new DefaultMatchEngine(matcher , comparisonFactory);
IMatchEngine.Factory.Registry registry = MatchEngineFactoryRegistryImpl.createStandaloneInstance();
IMatchEngine.Factory engineFactory = new MatchEngineFactoryImpl() {
public IMatchEngine getMatchEngine() {
return thematchEngine;
}
};
engineFactory.setRanking(20); // default engine ranking is 10, must be higher to override.
registry.add(engineFactory);
IComparisonScope scope = new DefaultComparisonScope(modelBefore,modelAfter,null);
final Comparison comparison = EMFCompare.builder().setMatchEngineFactoryRegistry(registry).build().compare(scope);
List<Diff> differences = comparison.getDifferences();
for (Diff diff : differences) {
final Diff diffRef= diff;
System.out.println(diff);
}
RecordingCommand cmd= new RecordingCommand(getDomain(), "saveSnaphsot") {
@Override
protected void doExecute() {
URI umlModel_URI=getWorkingModel().eResource().getURI();
String tmpURI=umlModel_URI.toString().replaceAll(umlModel_URI.lastSegment().toString(), "diff.xmi");
URI reviewURI=URI.createURI(tmpURI);
Resource resourcesnapshot = Util.createTemporaryResourceSet().createResource(reviewURI);
resourcesnapshot.getContents().add(comparison);
try {
resourcesnapshot.save(null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
getDomain().getCommandStack().execute(cmd);
}
/**
* used to save compare model as another file
*/
public void savediff(){
RecordingCommand cmd= new RecordingCommand(getDomain(), "savediff") {
@Override
protected void doExecute() {
URI umlModel_URI=getWorkingModel().eResource().getURI();
String tmpURIresultDiff=umlModel_URI.toString().replaceAll(umlModel_URI.lastSegment().toString(), "resultDiff.xmi");
URI resultDiffURI=URI.createURI(tmpURIresultDiff);
Resource resourceresultDiff = Util.createTemporaryResourceSet().createResource(resultDiffURI);
resourceresultDiff.getContents().add(diffModel);
try {
resourceresultDiff.save(null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
//getDomain().getCommandStack().execute(cmd);
}
/**
*
* @return true is the revison mode is running
*/
public boolean modeRevisionRunning(){
return modeRevisionRunning;
}
/**
* start the mode revision is order to register modif
*/
public void startModeRevision(){
modeRevisionRunning=true;
RecordingCommand cmd= new RecordingCommand(getDomain(), "savediff") {
@Override
protected void doExecute() {
//getDiffModel().getConflicts().clear();
//getDiffModel().getDifferences().clear();
//getDiffModel().getMatches().clear();
if( getDiffModel().getMatches().size()==0){
Match match= CompareFactory.eINSTANCE.createMatch();
match.setLeft(getWorkingModel());
getDiffModel().getMatches().add(match);
}
}
};
getDomain().getCommandStack().execute(cmd);
getDomain().addResourceSetListener(addingDiffListener);
}
/**
* stop the revision model and stop listening modifications
*/
public void stopModelRevision(){
modeRevisionRunning=false;
getDomain().removeResourceSetListener(addingDiffListener);
}
}