blob: cd7765782b8ee86d372d3f8a9f6322a26f9a7079 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 Laboratory for Internet Computing, University of Cyprus.
* 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
*
* Initial development of the original code was made for the
* CELAR project founded by European Union
* project number: FP7-317790 http://www.celarcloud.eu
*
* Contributors:
* Stalo Sofokleous - initial API and implementation
* Nicholas Loulloudes - API and implementation extensions
*
*******************************************************************************/
package org.eclipse.camf.tosca.editor;
import org.eclipse.camf.core.model.CloudModel;
import org.eclipse.camf.core.model.ICloudElement;
import org.eclipse.camf.tosca.DefinitionsType;
import org.eclipse.camf.tosca.DocumentRoot;
import org.eclipse.camf.tosca.ImplementationArtifactType;
import org.eclipse.camf.tosca.SourceElementType;
import org.eclipse.camf.tosca.TArtifactTemplate;
import org.eclipse.camf.tosca.TDeploymentArtifact;
import org.eclipse.camf.tosca.TNodeTemplate;
import org.eclipse.camf.tosca.TNodeTypeImplementation;
import org.eclipse.camf.tosca.TRelationshipTemplate;
import org.eclipse.camf.tosca.TServiceTemplate;
import org.eclipse.camf.tosca.TTopologyTemplate;
import org.eclipse.camf.tosca.TargetElementType;
import org.eclipse.camf.tosca.core.TOSCAResource;
import org.eclipse.camf.tosca.editor.listener.ToscaModelChangeListener;
import org.eclipse.camf.tosca.elasticity.TNodeTemplateExtension;
import org.eclipse.camf.tosca.elasticity.TServiceTemplateExtension;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.editparts.LayerManager;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.impl.AddConnectionContext;
import org.eclipse.graphiti.features.context.impl.AddContext;
import org.eclipse.graphiti.features.context.impl.AreaContext;
import org.eclipse.graphiti.mm.pictograms.Anchor;
import org.eclipse.graphiti.mm.pictograms.ChopboxAnchor;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.platform.IDiagramBehavior;
//import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.ui.editor.DiagramEditor;
import org.eclipse.graphiti.ui.editor.DiagramEditorInput;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
/**
* @author Nicholas Loulloudes
*
*/
public class ToscaDiagramEditor extends DiagramEditor {
private static GraphicalViewer gViewer;
public static IDiagramBehavior db = null;
private ToscaModelChangeListener toscaModelChangeListener;
private TransactionalEditingDomain transactionalEditingDomain;
private static IProject activeProject = null;
/**
* The Tosca Diagram Editor Constructor.
*/
public ToscaDiagramEditor () {
super ();
}
public static IProject getActiveProject(){
return activeProject;
}
protected void registerBusinessObjectsListener() {
this.toscaModelChangeListener = new ToscaModelChangeListener(this);
final TransactionalEditingDomain ted = getEditingDomain();
ted.addResourceSetListener(this.toscaModelChangeListener);
}
/* (non-Javadoc)
* @see org.eclipse.graphiti.ui.editor.DiagramEditor#getEditingDomain()
*/
@Override
public TransactionalEditingDomain getEditingDomain() {
TransactionalEditingDomain ted = super.getEditingDomain();
if (ted == null) {
ted = this.transactionalEditingDomain;
}
return ted;
}
@Override
public void init(final IEditorSite site, final IEditorInput input) throws PartInitException {
IEditorInput finalInput = null;
try {
if (input instanceof ToscaDiagramEditorInput) {
finalInput = input;
} else {
finalInput = createNewDiagramEditorInput(input);
}
} catch (CoreException exception) {
exception.printStackTrace();
}
if ( finalInput instanceof ToscaDiagramEditorInput ){
activeProject = ((ToscaDiagramEditorInput) finalInput).getToscaFile().getProject();
}
super.init(site, finalInput);
// Refresh Palette Compartments
ToscaDiagramEditor.db = getDiagramTypeProvider().getFeatureProvider().getDiagramTypeProvider().getDiagramBehavior();
getDiagramTypeProvider().getFeatureProvider().getDiagramTypeProvider().getDiagramBehavior().refreshPalette();
}
private ToscaDiagramEditorInput createNewDiagramEditorInput(final IEditorInput input) throws CoreException {
final IFile dataFile = ToscaFileService.getDataFileForInput(input);
// now generate the temporary diagram file
final IPath dataFilePath = dataFile.getFullPath();
// get or create the corresponding temporary folder
final IFolder tempFolder = ToscaFileService.getOrCreateTempFolder(dataFilePath);
// finally get the diagram file that corresponds to the data file
final IFile diagramFile = ToscaFileService.getTemporaryDiagramFile(dataFilePath, tempFolder);
// Create new temporary diagram file
ToscaDiagramCreator creator = new ToscaDiagramCreator();
return creator.createToscaDiagram(dataFile, diagramFile, this, false);
}
@Override
public void doSave(final IProgressMonitor monitor) {
super.doSave(monitor);
// final ToscaDiagramEditorInput tdei = (ToscaDiagramEditorInput) getEditorInput();
((BasicCommandStack) getEditingDomain().getCommandStack()).saveIsDone();
updateDirtyState();
}
@Override
public boolean isDirty() {
TransactionalEditingDomain editingDomain = getEditingDomain();
// Check that the editor is not yet disposed
if (editingDomain != null && editingDomain.getCommandStack() != null) {
return ((BasicCommandStack) editingDomain.getCommandStack()).isSaveNeeded();
}
return false;
}
@Override
protected void setInput(final IEditorInput input) {
super.setInput(input);
final ToscaDiagramEditorInput tdei = (ToscaDiagramEditorInput) input;
final IFile dataFile = tdei.getToscaFile();
final ToscaModelLayer model = new ToscaModelLayer(getDiagramTypeProvider().getFeatureProvider(), dataFile);
ModelHandler.addModel(EcoreUtil.getURI(getDiagramTypeProvider().getDiagram()), model);
DocumentRoot documentRoot = null;
TOSCAResource toscaResource = null ;
ICloudElement findElement = CloudModel.getRoot().findElement( dataFile );
if (findElement instanceof TOSCAResource) {
toscaResource = (TOSCAResource) findElement;
}
URI resourceURI = null;
//IEditorInput eInput = getEditorInput();
if( getEditorInput() instanceof ToscaDiagramEditorInput ) {
IFile modelFile = ((ToscaDiagramEditorInput) getEditorInput()).getToscaFile();
resourceURI = URI.createPlatformResourceURI( modelFile.getFullPath().toString(), false );
}
Exception exception = null;
Resource resource = null;
try {
/* Load the resource through the editing domain. */
resource = getEditingDomain().getResourceSet().getResource( resourceURI, true );
} catch( Exception e ) {
exception = e;
resource = getEditingDomain().getResourceSet().getResource( resourceURI, false );
}
Diagnostic diagnostic = analyzeResourceProblems( resource, exception );
if( diagnostic.getSeverity() != Diagnostic.OK ) {
//todo
} else {
documentRoot = getDocumentRoot( resource );
// documentRoot = toscaResource.getTOSCAModel().getDocumentRoot();
}
if( documentRoot != null ) {
model.setDocumentRoot( documentRoot );
BasicCommandStack basicCommandStack = ( BasicCommandStack )getEditingDomain().getCommandStack();
if( input instanceof DiagramEditorInput ) {
basicCommandStack.execute( new RecordingCommand( getEditingDomain() ) {
@Override
protected void doExecute() {
importDiagram( model );
}
} );
}
basicCommandStack.saveIsDone();
basicCommandStack.flush();
}
}
private final DocumentRoot getDocumentRoot( final Resource resource ) {
// Get an iterator to iterate through all contents of the resource.
TreeIterator<EObject> iterator = resource.getAllContents();
DocumentRoot result = null;
while( iterator.hasNext() ) {
EObject testElement = iterator.next();
/*
* Instance-of checks for each EObject that appears in the resource. We
* want to get the DocumentRoot EObject which is the root Element inside a
* Tosca Document.
*/
if( testElement instanceof DocumentRoot ) {
result = ( DocumentRoot ) testElement;
}
}
return result;
}
/**
* @param resource
* @param exception
* @return
*/
private Diagnostic analyzeResourceProblems( final Resource resource,
final Exception exception )
{
Diagnostic basicDiagnostic = null;
if( !resource.getErrors().isEmpty() || !resource.getWarnings().isEmpty() ) {
basicDiagnostic = new BasicDiagnostic( Diagnostic.ERROR,
Activator.PLUGIN_ID,
0,
String.format( Messages.getString( "ToscaEditor.CreateModelErrorMessage" ), //$NON-NLS-1$
resource.getURI() ),
new Object[]{
exception == null
? ( Object )resource
: exception
} );
( ( BasicDiagnostic )basicDiagnostic ).merge( EcoreUtil.computeDiagnostic( resource,
true ) );
} else if( exception != null ) {
basicDiagnostic = new BasicDiagnostic( Diagnostic.ERROR,
Activator.PLUGIN_ID,
0,
Messages.getString( "ToscaEditor.CreateModelErrorMessage" ), //$NON-NLS-1$
new Object[]{
exception
} );
} else {
basicDiagnostic = Diagnostic.OK_INSTANCE;
}
return basicDiagnostic;
}
protected void importDiagram( final ToscaModelLayer model ) {
final Diagram diagram = getDiagramTypeProvider().getDiagram();
diagram.setActive( true );
getEditingDomain().getCommandStack()
.execute( new RecordingCommand( getEditingDomain() ) {
@Override
protected void doExecute() {
if (model.getDocumentRoot() != null) {
DocumentRoot documentRoot = model.getDocumentRoot();
DefinitionsType definitionsType = documentRoot.getDefinitions();
EList<TServiceTemplate> serviceTemplates = definitionsType.getServiceTemplate();
EList<TNodeTypeImplementation> nodeTypesImplementation = definitionsType.getNodeTypeImplementation();
EList<TArtifactTemplate> artifactTemplates = definitionsType.getArtifactTemplate();
Boolean substitute = false;
ContainerShape containerShapeTST = null;
for (TServiceTemplate tst : serviceTemplates) {
if ( tst.getSubstitutableNodeType() != null ){
//tst is a group component
TServiceTemplateExtension tstG = (TServiceTemplateExtension) tst;
addContainerElement (tst, containerShapeTST, tstG.getX(), tstG.getY(), tstG.getWidth(), tstG.getHeight());
substitute = true;
}
else{
TServiceTemplateExtension tste = (TServiceTemplateExtension) tst;
addContainerElement (tst, diagram, 0, 0, tste.getWidth(), tste.getHeight());
containerShapeTST = ( ContainerShape )getDiagramTypeProvider().getFeatureProvider()
.getPictogramElementForBusinessObject( tst );
}
ContainerShape containerShape = ( ContainerShape )getDiagramTypeProvider().getFeatureProvider()
.getPictogramElementForBusinessObject( tst );
TTopologyTemplate topology = tst.getTopologyTemplate();
if (topology == null)
break;
for (TNodeTemplate tnt : topology.getNodeTemplate()) {
if ( (tnt.getType()!=null) && (tnt.getType().toString().contains( "substituteNode" )) ) {//$NON-NLS-1$
continue;
}
TNodeTemplateExtension tnte = (TNodeTemplateExtension) tnt;
addContainerElement( tnt, containerShape, tnte.getX(), tnte.getY(), tnte.getWidth(), tnte.getHeight() );
ContainerShape containerShapeTNT = ( ContainerShape )getDiagramTypeProvider().getFeatureProvider()
.getPictogramElementForBusinessObject( tnt );
//Add Deployment Artifacts
if ( tnt.getDeploymentArtifacts() != null && tnt.getDeploymentArtifacts().getDeploymentArtifact() != null ){
for (TDeploymentArtifact tda : tnt.getDeploymentArtifacts().getDeploymentArtifact() ){
addContainerElement( tda, containerShapeTNT, 0, 0, 0, 0 );
}
}
//Find NodeTypeImplementation
TNodeTypeImplementation nodeTypeImplementation = null;
for (TNodeTypeImplementation tempNodeImplementation : nodeTypesImplementation){
if (tnt.getName().equals( tempNodeImplementation.getNodeType().toString())){
nodeTypeImplementation = tempNodeImplementation;
break;
}
}
if (nodeTypeImplementation!=null && nodeTypeImplementation.getImplementationArtifacts()!=null){
EList<ImplementationArtifactType> implementationArtifacts = nodeTypeImplementation.getImplementationArtifacts().getImplementationArtifact();
for (ImplementationArtifactType tempImplementationArtifact : implementationArtifacts){
if (tempImplementationArtifact.getOperationName().equals( "execute" ))
{
for (TArtifactTemplate tempArtifactTemplate : artifactTemplates){
if (tempArtifactTemplate.getId().equals(tempImplementationArtifact.getArtifactRef().toString()))
addContainerElement( tempArtifactTemplate, containerShapeTNT, 0, 0, 0, 0 );
}
}
}
}
}
if ( substitute ){
//Composite Component Service Template
//Add deployment artifacts to composite component's service template
for (TServiceTemplate tempTst : serviceTemplates) {
for (TNodeTemplate tnt : tempTst.getTopologyTemplate().getNodeTemplate()) {
if ( tst.getSubstitutableNodeType() != null && (tnt.getType()!=null) && tnt.getType().toString().equals( tst.getSubstitutableNodeType().toString()) ){
//Found the service template that substitutes the specific node template
ContainerShape containerShapeTNT = ( ContainerShape )getDiagramTypeProvider().getFeatureProvider()
.getPictogramElementForBusinessObject( tst );
//Add Deployment Artifacts
if ( tnt.getDeploymentArtifacts() != null && tnt.getDeploymentArtifacts().getDeploymentArtifact() != null ){
for (TDeploymentArtifact tda : tnt.getDeploymentArtifacts().getDeploymentArtifact() ){
addContainerElement( tda, containerShapeTNT, 0, 0, 0, 0 );
}
}
break;
}
}
}
substitute = false;
}
else{
//Application Service Template
//Add deployment artifacts to application's service template
}
}
//Add Relationships
for (TServiceTemplate tst : serviceTemplates) {
if ( tst.getTopologyTemplate() == null )
continue;
for (TRelationshipTemplate trt : tst.getTopologyTemplate().getRelationshipTemplate()) {
SourceElementType se = trt.getSourceElement();
TargetElementType te = trt.getTargetElement();
String sourceID = se.getRef();
String targetID = te.getRef();
Anchor sourceAnchor = null, targetAnchor = null;
for (TServiceTemplate tstTemp : serviceTemplates) {
for (TNodeTemplate tnt : tstTemp.getTopologyTemplate().getNodeTemplate()) {
ContainerShape containerShapeTNT;
if ( tnt.getId().equals(sourceID) ){
if ( (tnt.getType()!=null) && (tnt.getType().toString().contains( "substituteNode" ) == true) ){
containerShapeTNT = getAnchorContainer(model, tnt);
}else{
containerShapeTNT = ( ContainerShape )getDiagramTypeProvider().getFeatureProvider()
.getPictogramElementForBusinessObject( tnt );
}
if ( containerShapeTNT.getAnchors() != null ){
for ( Anchor anchor : containerShapeTNT.getAnchors() ){
if (anchor instanceof ChopboxAnchor){
sourceAnchor = anchor;
break;
}
}
}
} else if ( tnt.getId().equals(targetID) ){
if ( ((tnt.getType()!=null)) && (tnt.getType().toString().contains( "substituteNode" ) == true) ){
containerShapeTNT = getAnchorContainer(model, tnt);
}else{
containerShapeTNT = ( ContainerShape )getDiagramTypeProvider().getFeatureProvider()
.getPictogramElementForBusinessObject( tnt );
}
if ( containerShapeTNT.getAnchors() != null ){
for ( Anchor anchor : containerShapeTNT.getAnchors() ){
if (anchor instanceof ChopboxAnchor){
targetAnchor = anchor;
break;
}
}
}
}
}
}
addRelationshipContainerElement( trt, sourceAnchor, targetAnchor );
}
}
}
}
} );
}
private ContainerShape getAnchorContainer(final ToscaModelLayer model, TNodeTemplate nodeTemplate){
// Find the substitute TServiceTemplate
TServiceTemplate substituteNode = null;
for (TServiceTemplate tempServiceTemplate : model.getDocumentRoot()
.getDefinitions()
.getServiceTemplate()){
if (tempServiceTemplate.getSubstitutableNodeType() != null &&
tempServiceTemplate.getId().equals(nodeTemplate.getId()))
{
substituteNode = tempServiceTemplate;
break;
}
}
return ( ContainerShape )getDiagramTypeProvider().getFeatureProvider()
.getPictogramElementForBusinessObject( substituteNode );
}
protected PictogramElement addContainerElement( final EObject element,
final ContainerShape parent, int x_axis, int y_axis, int width, int height )
{
final IFeatureProvider featureProvider = getDiagramTypeProvider().getFeatureProvider();
AddContext context = new AddContext( new AreaContext(), element );
IAddFeature addFeature = featureProvider.getAddFeature( context );
context.setNewObject( element );
context.setTargetContainer( parent );
context.setLocation(x_axis, y_axis);
context.setSize( width, height );
PictogramElement pictElement = null;
boolean canAdd = false;
if (addFeature != null) {
canAdd = addFeature.canAdd( context ) ;
}
if( canAdd ) {
pictElement = addFeature.add( context );
if (element instanceof TDeploymentArtifact && ((TDeploymentArtifact) element).getArtifactType().toString().compareTo( "MonitoringProbe" )==0){
//There is no pictogram element linked to the monitoring image
return pictElement;
}
else{
featureProvider.link( pictElement, new Object[]{ element } );
return pictElement;
}
}
return null;
}
protected PictogramElement addRelationshipContainerElement( final EObject element,
final Anchor sourceAnchor, final Anchor targetAnchor ){
if (sourceAnchor == null)
return null;
if (targetAnchor == null)
return null;
AddConnectionContext context = new AddConnectionContext(sourceAnchor, targetAnchor);
context.setNewObject( element );
final IFeatureProvider featureProvider = getDiagramTypeProvider().getFeatureProvider();
IAddFeature addFeature = featureProvider.getAddFeature( context );
PictogramElement pictElement = null;
boolean canAdd = addFeature.canAdd( context ) ;
if( canAdd ) {
pictElement = addFeature.add( context );
featureProvider.link( pictElement, new Object[]{ element } );
}
return pictElement;
}
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
// hides grid on diagram, but you can reenable it
if (getGraphicalViewer() != null && getGraphicalViewer().getEditPartRegistry() != null) {
ScalableFreeformRootEditPart rootEditPart = (ScalableFreeformRootEditPart) getGraphicalViewer().getEditPartRegistry().get(LayerManager.ID);
IFigure gridFigure = ((LayerManager) rootEditPart).getLayer(LayerConstants.GRID_LAYER);
gridFigure.setVisible(true);
}
// setPartName("MyDiagram2");
}
// @Override
// protected ContextMenuProvider createContextMenuProvider() {
// return new ActivitiEditorContextMenuProvider(getGraphicalViewer(), getActionRegistry(), getDiagramTypeProvider());
// }
public static GraphicalViewer getActiveGraphicalViewer() {
return gViewer;
}
@Override
public void dispose() {
super.dispose();
final ToscaDiagramEditorInput tdei = (ToscaDiagramEditorInput) getEditorInput();
ModelHandler.removeModel(EcoreUtil.getURI(getDiagramTypeProvider().getDiagram()));
ToscaDiagramCreator.dispose(tdei.getDiagramFile());
}
}