Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » Papyrus » How to get an image out of a Papyrus diagram ?
How to get an image out of a Papyrus diagram ? [message #1733117] Tue, 24 May 2016 13:39 Go to next message
Laurent Le Moux is currently offline Laurent Le MouxFriend
Messages: 44
Registered: June 2015
Member
Hi all,

I wrote a program to load a diagram which was created and stored in CDO with Papyrus.
It uses GMF DiagramRenderUtil.renderToSWTImage() facility to produce the diagram image.
The resulting image does however contain 'Invalid view - remove from diagram' messages instead of the class and connection names (see attached image).
index.php/fa/25999/0/
Apparently, the reason is the rendering is using default edit parts implementation like 'DefaultConnectionEditPart' and 'DefaultNodeEditPart'.

I guess I should rather use CopyToImageUtil.copyToImageByteArray providing the correct diagram edit part...

Is this right ? Can anybody tell what Papyrus Diagram edit part to use ?
Or is there a better way to achieve this image generation out of diagram ?

Regards,

Laurent
  • Attachment: diagram.bmp
    (Size: 1.02MB, Downloaded 2032 times)
Re: How to get an image out of a Papyrus diagram ? [message #1733192 is a reply to message #1733117] Wed, 25 May 2016 09:35 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille LetavernierFriend
Messages: 926
Registered: February 2011
Senior Member
Hi Laurent,

The Papyrus plug-in 'org.eclipse.papyrus.infra.gmfdiag.export' should provide the API you need

It exports all diagrams of a model to images. If you want to select specific Diagrams, the API may need to be improved, but that's a good place to start

Regards,
Camille


Camille Letavernier
Re: How to get an image out of a Papyrus diagram ? [message #1733358 is a reply to message #1733192] Thu, 26 May 2016 19:12 Go to previous messageGo to next message
Laurent Le Moux is currently offline Laurent Le MouxFriend
Messages: 44
Registered: June 2015
Member
Hi Camille,
Thank you for your answer. I changed my code to reproduce the behavior of Papyrus 'ExportAllDiagramsEngine' as follow (where the diagramName string is actually a path like '/path/to/model'...) :
// Copy / paste of ExportAllDiagramsEngine.initialiseModelSet()
ServicesRegistry service = new ServicesRegistry();

// Add service factory for Model Set
ServiceDescriptor descriptor = new ServiceDescriptor(ModelSet.class, ModelSetServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10);
descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
service.add(descriptor);

// Add factory for editing domain
descriptor = new ServiceDescriptor(TransactionalEditingDomain.class, EditingDomainServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(ModelSet.class.getName()));
descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
service.add(descriptor);

try {
	service.startRegistry();
} catch (ServiceMultiException e) {
	throw new BirtException(e.getMessage());
}

ModelSet modelSet = null;
try {
	modelSet = ServiceUtils.getInstance().getModelSet(service);
} catch (ServiceException e) {
	throw new BirtException(e.getMessage());
}

// Add CDO resources in order for modelSet.loadModels not to fail...
CDOResource diResource = view.getResource(diagramName + ".di");
modelSet.getResources().add(diResource);
modelSet.getResources().add(view.getResource(diagramName + ".notation"));
modelSet.getResources().add(view.getResource(diagramName + ".uml"));

// Read all Model from selected file
ModelsReader modelsReader = new ModelsReader();
modelsReader.readModel(modelSet);
try {
	modelSet.loadModels(diResource.getURI());
} catch (ModelMultiException e) {
	throw new BirtException(e.getMessage());
}

// Initialize an editing domain
modelSet.getTransactionalEditingDomain();

// Copy / paste of ExportAllDiagramsEngine.initialiseServiceRegistry()
ServicesRegistry service1 = ModelSetServiceFactory.getServiceRegistry(modelSet);

try {

	service1.add(MarkersMonitorService.class, 10, new MarkersMonitorService());
	service1.add(CssMarkerEventManagerService.class, 10, new CssMarkerEventManagerService());
	service1.add(MarkerToPseudoSelectorMappingService.class, 10, new MarkerToPseudoSelectorMappingService());
	service1.add(ValidationMarkersService.class, 10, new ValidationMarkersService());
	service1.add(DecorationService.class, 10, new DecorationService());
	service1.startRegistry();

	// Di model services
	ServiceDescriptor descriptor1 = new ServiceDescriptor(DiSashModelManager.class, DiSashModelManagerServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(TransactionalEditingDomain.class.getName()));
	descriptor1.setServiceTypeKind(ServiceTypeKind.serviceFactory);
	service1.add(descriptor1);

	// Page Manager services
	descriptor1 = new ServiceDescriptor(IPageManager.class, PageMngrServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(DiSashModelManager.class.getName()));
	descriptor1.setServiceTypeKind(ServiceTypeKind.serviceFactory);
	service1.add(descriptor1);
	service1.startRegistry();

} catch (ServiceException e) {
	throw new BirtException(e.getMessage());
}

ExportAllDiagramsParameter parameter = new ExportAllDiagramsParameter(modelSet);
parameter.setExportFormat(ImageFileFormat.BMP.toString());
String path = "/";
URI uri = URI.createPlatformResourceURI(path, true);
IResource outputDirectory = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(uri.toPlatformString(true)));
parameter.setOutputDirectory(outputDirectory);
parameter.setQualifiedName(true);

ExportAllDiagramsEngine exportAllDiagrams = new ExportAllDiagramsEngine();
exportAllDiagrams.initialise(parameter);
exportAllDiagrams.exportDiagramsToImages();

Unfortunately, I get exactly the same result...
Any idea what's wrong ? I'm not a GMF expert but I had a look at my model.notation and - for example - the class names that should be displayed in the diagram image are not shipped within the model.
So my understanding is that model.notation is not 'self contained'. Therefore, to get the diagram image correctly rendered, one needs to link 'model.notation' to the corresponding 'model.uml' somehow.
Hence, my previous question about the need to provide the right diagram edit part ? And, if so, how ?
Regards,
Laurent
Re: How to get an image out of a Papyrus diagram ? [message #1733394 is a reply to message #1733358] Fri, 27 May 2016 08:34 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille LetavernierFriend
Messages: 926
Registered: February 2011
Senior Member
Hi,

As far as I can tell, this works fine in Papyrus. I'd say something is wrong with your resource management

In Papyrus, the ModelSet is responsible for identifying the main 3-files model (*.di, *.notation, *.uml). But, in your code, you use custom code to load these resources, before the ModelSet is actually loaded; so it probably doesn't properly register them

There is an extra plug-in for Papyrus, to integrate with CDO. Especially, this plug-in provides a "CDOAwareModelSet", I'm not familiar with this integration, but I suspect it's mandatory for Papyrus to work properly with CDO

HTH,
Camille


Camille Letavernier
Re: How to get an image out of a Papyrus diagram ? [message #1733424 is a reply to message #1733394] Fri, 27 May 2016 11:17 Go to previous messageGo to next message
Laurent Le Moux is currently offline Laurent Le MouxFriend
Messages: 44
Registered: June 2015
Member
Hi again,

Thank you for the tip. I changed my code in order to remove my custom CDO resource loading and use CDOAwareModelSet instead :
		// Copy / paste of ExportAllDiagramsEngine.initialiseModelSet()
		ServicesRegistry service = new ServicesRegistry();

		// Add service factory for Model Set
		ServiceDescriptor descriptor = new ServiceDescriptor(ModelSet.class, ModelSetServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10);
		descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
		service.add(descriptor);

		// Add factory for editing domain
		descriptor = new ServiceDescriptor(TransactionalEditingDomain.class, EditingDomainServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(ModelSet.class.getName()));
		descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
		service.add(descriptor);

		try {
			service.startRegistry();
		} catch (ServiceMultiException e) {
			throw new BirtException(e.getMessage());
		}

		CDOAwareModelSet modelSet = new CDOAwareModelSet();
		try {
			ModelSetServiceFactory.setServiceRegistry(modelSet, service);
		} catch (ServiceException e) {
			throw new BirtException(e.getMessage());
		}

		// Read all Model from selected file
		ModelsReader modelsReader = new ModelsReader();
		modelsReader.readModel(modelSet);
		try {
			modelSet.loadModels(view.getResource(diPath).getURI());
		} catch (ModelMultiException e) {
			throw new BirtException(e.getMessage());
		}

		// Initialize an editing domain
		modelSet.getTransactionalEditingDomain();

		// Copy / paste of ExportAllDiagramsEngine.initialiseServiceRegistry()
		ServicesRegistry service1 = ModelSetServiceFactory.getServiceRegistry(modelSet);

		try {
			service1.add(MarkersMonitorService.class, 10, new MarkersMonitorService());
			service1.add(CssMarkerEventManagerService.class, 10, new CssMarkerEventManagerService());
			service1.add(MarkerToPseudoSelectorMappingService.class, 10, new MarkerToPseudoSelectorMappingService());
			service1.add(ValidationMarkersService.class, 10, new ValidationMarkersService());
			service1.add(DecorationService.class, 10, new DecorationService());
			service1.startRegistry();

			// Di model services
			ServiceDescriptor descriptor1 = new ServiceDescriptor(DiSashModelManager.class, DiSashModelManagerServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(TransactionalEditingDomain.class.getName()));
			descriptor1.setServiceTypeKind(ServiceTypeKind.serviceFactory);
			service1.add(descriptor1);

			// Page Manager services
			descriptor1 = new ServiceDescriptor(IPageManager.class, PageMngrServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(DiSashModelManager.class.getName()));
			descriptor1.setServiceTypeKind(ServiceTypeKind.serviceFactory);
			service1.add(descriptor1);
			service1.startRegistry();

		} catch (ServiceException e) {
			throw new BirtException(e.getMessage());
		}

		ExportAllDiagramsParameter parameter = new ExportAllDiagramsParameter(modelSet);
		parameter.setExportFormat(ImageFileFormat.BMP.toString());
		String path = "/";
		URI uri = URI.createPlatformResourceURI(path, true);
		IResource outputDirectory = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(uri.toPlatformString(true)));
		parameter.setOutputDirectory(outputDirectory);
		parameter.setQualifiedName(true);

		ExportAllDiagramsEngine exportAllDiagrams = new ExportAllDiagramsEngine();
		exportAllDiagrams.initialise(parameter);
		exportAllDiagrams.exportDiagramsToImages();


Good news is that the services seem to react. But I now get the following exception with the last 'service1.startRegistry()' call...
org.eclipse.papyrus.infra.core.services.ServiceMultiException: Multiple exceptions
----- exceptions : ----------
org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageManager : Can't start DiSashModelManagerServiceFactory'. Required model (SashModel) should be loaded prior starting the service.
org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.DiSashModelManager : Can't start DiSashModelManagerServiceFactory'. Required model (SashModel) should be loaded prior starting the service.
org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageManager : Bad state for service 'org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageManager'. Expected 'initialized' found 'error'.


I looked at ExportAllDiagramsEngine again but I see no difference with my copy/paste.
Any idea what's wrong ? Is there maybe a dedicated algorythm used on CDO side (as for the dedicated model set) ?

Regards,

Laurent
Re: How to get an image out of a Papyrus diagram ? [message #1733426 is a reply to message #1733117] Fri, 27 May 2016 11:51 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille LetavernierFriend
Messages: 926
Registered: February 2011
Senior Member
Hi,

I think the issue is that your ServicesRegistry is associated to your ModelSet, but not the other way round. So when your ServicesRegistry tries to find your ModelSet, it can't. In the Papyrus Tests, we use the following code:

servicesRegistry.add(ModelSet.class, 10, modelSet);		
servicesRegistry.startServicesByClassKeys(ModelSet.class);


So in your case, this might look like:

		CDOAwareModelSet modelSet = new CDOAwareModelSet();
		try {
			service.add(ModelSet.class, 10, modelSet);		
			service.startServicesByClassKeys(ModelSet.class);
			ModelSetServiceFactory.setServiceRegistry(modelSet, service);
		} catch (ServiceException e) {
			throw new BirtException(e.getMessage());
		}

		// Read all Model from selected file
		ModelsReader modelsReader = new ModelsReader();
		modelsReader.readModel(modelSet);


Then the other Papyrus services depending on the ModelSet will be able to find it

HTH,
Camille


Camille Letavernier
Re: How to get an image out of a Papyrus diagram ? [message #1733436 is a reply to message #1733426] Fri, 27 May 2016 12:47 Go to previous messageGo to next message
Laurent Le Moux is currently offline Laurent Le MouxFriend
Messages: 44
Registered: June 2015
Member
Hi again,
I applied your code with the following changes:
CDOAwareModelSet modelSet = new CDOAwareModelSet();
try {
	service.add(ModelSet.class, 11, modelSet);
	service.startServicesByClassKeys(ModelSet.class);
	ModelSetServiceFactory.setServiceRegistry(modelSet, service);
	service.add(TransactionalEditingDomain.class, 11, modelSet.getTransactionalEditingDomain());
	service.startServicesByClassKeys(TransactionalEditingDomain.class);
} catch (ServiceException e) {
	throw new BirtException(e.getMessage());
}


Code execution was complaining about two model set services registered with the same priority so I changed your registration priority to 11.
There was also a problem with the necessity for the execution to take place in a transaction.
So I mimicked your code to register the CDOAwareModelSet internal transactional editing domain (also with an 11 priority...).

All this brings slightly further as I now have an error at the last step : 'exportAllDiagrams.exportDiagramsToImages()'
!ENTRY org.eclipse.core.jobs 4 2 2016-05-27 14:31:07.554
!MESSAGE An internal error occurred during: "Generate".
!STACK 0
org.eclipse.emf.common.util.BasicEList$BasicIndexOutOfBoundsException: index=0, size=0
	at org.eclipse.emf.common.util.BasicEList.get(BasicEList.java:346)
	at org.eclipse.emf.internal.cdo.CDOObjectImpl$TransientStore.get(CDOObjectImpl.java:1469)
	at org.eclipse.emf.ecore.impl.EStoreEObjectImpl$BasicEStoreEList.delegateGet(EStoreEObjectImpl.java:241)
	at org.eclipse.emf.common.util.DelegatingEList.get(DelegatingEList.java:230)
	at org.eclipse.papyrus.infra.gmfdiag.export.engine.ExportAllDiagramsEngine.export(ExportAllDiagramsEngine.java:216)
	at org.eclipse.papyrus.infra.gmfdiag.export.engine.ExportAllDiagramsEngine.access$0(ExportAllDiagramsEngine.java:174)
	at org.eclipse.papyrus.infra.gmfdiag.export.engine.ExportAllDiagramsEngine$1.runInWorkspace(ExportAllDiagramsEngine.java:157)
	at org.eclipse.core.internal.resources.InternalWorkspaceJob.run(InternalWorkspaceJob.java:39)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

The line 216 in ExportAllDiagramsEngine.export corresponds to:
ILocalPageService service = new ExportDiagramLocalPageService(UmlUtils.getUmlResource(modelSet).getContents().get(0));

One more advice Wink ?
Re: How to get an image out of a Papyrus diagram ? [message #1733441 is a reply to message #1733436] Fri, 27 May 2016 14:19 Go to previous messageGo to next message
Laurent Le Moux is currently offline Laurent Le MouxFriend
Messages: 44
Registered: June 2015
Member
I continue with my copy/paste...
// Step 3 : Get all diagram
ILocalPageService service2 = new ExportDiagramLocalPageService(
		view.getResource(modelPath + ".uml").getContents().get(0)); //$NON-NLS-1$
List<Object> pagesList = pageManager.allLocalPages(service2);
List<Diagram> diagrams = new ArrayList<Diagram>();

for (Object page : pagesList) {
	if (page instanceof Diagram) {
		diagrams.add((Diagram) page);
	}
}


UmlUtils.getUmlResource(modelSet) actually relies on the provided modelSet to get the UML model and return its resource.
For whatever reason, the returned resource content is empty...
So I 'forced' loading this content directly from CDO using a view and I now provide a so-called root element to the ExportDiagramLocalPageService constructor.
It is apparently not good enough as pageManager then returns an empty page list and, therefore, no diagram to convert...

My guess is the model set and/or the services are still not correctly initialized...
Re: How to get an image out of a Papyrus diagram ? [message #1733604 is a reply to message #1733441] Mon, 30 May 2016 11:48 Go to previous messageGo to next message
Laurent Le Moux is currently offline Laurent Le MouxFriend
Messages: 44
Registered: June 2015
Member
Hi again,

I keep struggling with my problem and I'm a step further.
I now get an image back where the classes and the connection names are not displayed.
index.php/fa/26033/0/
Here's the new code version :
// Copy / paste of ExportAllDiagramsEngine.initialiseModelSet()
ServicesRegistry serviceRegistry = new ServicesRegistry();

// Add service factory for Model Set
ServiceDescriptor descriptor = new ServiceDescriptor(ModelSet.class, ModelSetServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10);
descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
serviceRegistry.add(descriptor);

// Add factory for editing domain
descriptor = new ServiceDescriptor(TransactionalEditingDomain.class, EditingDomainServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(ModelSet.class.getName()));
descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
serviceRegistry.add(descriptor);

try {
	serviceRegistry.startRegistry();
} catch (ServiceMultiException e) {
	throw new BirtException(e.getMessage());
}

CDOAwareModelSet modelSet = new CDOAwareModelSet();
try {
	serviceRegistry.add(ModelSet.class, 11, modelSet);
	serviceRegistry.startServicesByClassKeys(ModelSet.class);
	ModelSetServiceFactory.setServiceRegistry(modelSet, serviceRegistry);
	serviceRegistry.add(TransactionalEditingDomain.class, 11, modelSet.getTransactionalEditingDomain());
	serviceRegistry.startServicesByClassKeys(TransactionalEditingDomain.class);
} catch (ServiceException e) {
	throw new BirtException(e.getMessage());
}

// Read all Model from selected file
ModelsReader modelsReader = new ModelsReader();
modelsReader.readModel(modelSet);
try {
	modelSet.loadModels(view.getResource(modelPath + ".di").getURI()); //$NON-NLS-1$
} catch (ModelMultiException e) {
	throw new BirtException(e.getMessage());
}

// Initialize an editing domain
modelSet.getTransactionalEditingDomain();

// Copy / paste of ExportAllDiagramsEngine.initialiseServiceRegistry()
serviceRegistry = ModelSetServiceFactory.getServiceRegistry(modelSet);

try {
	serviceRegistry.add(MarkersMonitorService.class, 10, new MarkersMonitorService());
	serviceRegistry.add(CssMarkerEventManagerService.class, 10, new CssMarkerEventManagerService());
	serviceRegistry.add(MarkerToPseudoSelectorMappingService.class, 10, new MarkerToPseudoSelectorMappingService());
	serviceRegistry.add(ValidationMarkersService.class, 10, new ValidationMarkersService());
	serviceRegistry.add(DecorationService.class, 10, new DecorationService());
	serviceRegistry.startRegistry();

	// Di model services
	descriptor = new ServiceDescriptor(DiSashModelManager.class, DiSashModelManagerServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(TransactionalEditingDomain.class.getName()));
	descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
	serviceRegistry.add(descriptor);
} catch (ServiceException e) {
	throw new BirtException(e.getMessage());
}

// Loading the diagram from the model.notation resource
for (EObject element : view.getResource(modelPath + ".notation").getContents())
	if (element instanceof Diagram) {
		convertedDiagram = (Diagram) element;
		modelSet.getTransactionalEditingDomain().getResourceSet().getResources().add(convertedDiagram.eResource()); // To avoid NPE at image generation
		break;
	}

// Launch conversion based on the Papyrus 'BasicEditPartProvider' declared in the plug-in extensions.
Display.getDefault().syncExec(new Runnable() {
	@Override
	public void run() {
		diagramImage  = DiagramRenderUtil.renderToSWTImage(convertedDiagram);
	}
});
ByteArrayOutputStream result = new ByteArrayOutputStream();
ImageLoader imageLoader = new ImageLoader();
imageLoader.data = new ImageData[] { diagramImage.getImageData() };
imageLoader.save(result, getFormat());
diagramImage.dispose();

		return new ByteArrayInputStream(result.toByteArray());


I declared the following extension in my plugin.xml which apparently makes the difference :
   <extension
         point="org.eclipse.gmf.runtime.diagram.ui.editpartProviders">
      <editpartProvider
            class="org.eclipse.papyrus.uml.diagram.common.providers.BasicEditPartProvider">
         <Priority
               name="Lowest">
         </Priority>
      </editpartProvider>
   </extension>


Any idea what's still missing ?

Regards,

Laurent
Re: How to get an image out of a Papyrus diagram ? [message #1733608 is a reply to message #1733604] Mon, 30 May 2016 12:05 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille LetavernierFriend
Messages: 926
Registered: February 2011
Senior Member
Hi Laurent,


I think you're on the wrong track. There's definitely something wrong with the way your resources are loaded. The following lines should not be required:

// Loading the diagram from the model.notation resource
for (EObject element : view.getResource(modelPath + ".notation").getContents())
	if (element instanceof Diagram) {
		convertedDiagram = (Diagram) element;
		modelSet.getTransactionalEditingDomain().getResourceSet().getResources().add(convertedDiagram.eResource()); // To avoid NPE at image generation
		break;
	}


All further bugs are caused by this resource loading issue, so I'd suggest investigating on this rather than trying to "reinstantiate" all Papyrus providers (So all plugin.xml changes should be reverted as well).

Focus on this:

try {
	modelSet.loadModels(view.getResource(modelPath + ".di").getURI()); //$NON-NLS-1$
} catch (ModelMultiException e) {
	throw new BirtException(e.getMessage());
}


After these instructions, UML and Notation resources should be present in the ModelSet, and should not be empty. If not, then something went wrong (And anything you may try after that will only be dirty workarounds, causing more problems).

However, you're trying to load CDO models, and I'm not familiar with CDO and the Papyrus integration of CDO, so I can't help you any further. All I can say is that, when the resources are properly loaded in the model set, things should work much better. You should try putitng a breakpoint on this instruction then try to understand why the resulting resources are empty:

modelSet.loadModels(view.getResource(modelPath + ".di").getURI()); //$NON-NLS-1$



HTH,
Camille


Camille Letavernier
Re: How to get an image out of a Papyrus diagram ? [message #1733732 is a reply to message #1733608] Tue, 31 May 2016 09:47 Go to previous messageGo to next message
Laurent Le Moux is currently offline Laurent Le MouxFriend
Messages: 44
Registered: June 2015
Member
Hi Camille,

You are right. Since the beginning, I have problems with loading the CDO resources as they are in 'Transient' state.

I noticed that using a normal model set or a CDO aware one makes not difference.
I had a closer look to the called method. COAwareModelSet takes care of dirty resources situations and relies on a CDO export view.
In my case, I use a read-only view to load the resources from the repository. And no CDO export is involved...

Trying to cope with that CDO resources loading problem, I did override ModelSet.createResource down the calling stack to 'gently' load them.
I now get a model set with resources in a nice state.
		// Copy / paste of ExportAllDiagramsEngine.initialiseModelSet()
		ServicesRegistry serviceRegistry = new ServicesRegistry();

		// Add service factory for Model Set
		ServiceDescriptor descriptor = new ServiceDescriptor(ModelSet.class, ModelSetServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10);
		descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
		serviceRegistry.add(descriptor);

		// Add factory for editing domain
		descriptor = new ServiceDescriptor(TransactionalEditingDomain.class, EditingDomainServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(ModelSet.class.getName()));
		descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
		serviceRegistry.add(descriptor);

		try {
			serviceRegistry.startRegistry();
		} catch (ServiceMultiException e) {
			throw new BirtException(e.getMessage());
		}

		final CDOView modelSetView = view;
		ModelSet modelSet = new ModelSet() {
			/**
			 * Properly load the cdo resources to avoid a transient state.
			 */
			@Override
			public Resource createResource(URI uri, String contentType) {
				if (uri.scheme().compareTo("cdo") == 0) { //$NON-NLS-1$
					Resource r = modelSetView.getResource(uri.path());
					getResources().add(r);
					return r;
				} else
					return super.createResource(uri, contentType);
			}
		};

		try {
			serviceRegistry.add(ModelSet.class, 11, modelSet);
			serviceRegistry.startServicesByClassKeys(ModelSet.class);
			ModelSetServiceFactory.setServiceRegistry(modelSet, serviceRegistry);
			serviceRegistry.add(TransactionalEditingDomain.class, 11, modelSet.getTransactionalEditingDomain());
			serviceRegistry.startServicesByClassKeys(TransactionalEditingDomain.class);
		} catch (ServiceException e) {
			throw new BirtException(e.getMessage());
		}

		// Read all Model from selected file
		ModelsReader modelsReader = new ModelsReader();
		modelsReader.readModel(modelSet);
		try {
			modelSet.loadModels(CDOURIUtil.createResourceURI(view, modelPath + ".di")); //$NON-NLS-1$
		} catch (ModelMultiException e) {
			throw new BirtException(e.getMessage());
		}

		// Initialize an editing domain
		modelSet.getTransactionalEditingDomain();

		// Copy / paste of ExportAllDiagramsEngine.initialiseServiceRegistry()
		serviceRegistry = ModelSetServiceFactory.getServiceRegistry(modelSet);

		try {
			serviceRegistry.add(MarkersMonitorService.class, 10, new MarkersMonitorService());
			serviceRegistry.add(CssMarkerEventManagerService.class, 10, new CssMarkerEventManagerService());
			serviceRegistry.add(MarkerToPseudoSelectorMappingService.class, 10, new MarkerToPseudoSelectorMappingService());
			serviceRegistry.add(ValidationMarkersService.class, 10, new ValidationMarkersService());
			serviceRegistry.add(DecorationService.class, 10, new DecorationService());
			serviceRegistry.startRegistry();

			// Di model services
			descriptor = new ServiceDescriptor(DiSashModelManager.class, DiSashModelManagerServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(TransactionalEditingDomain.class.getName()));
			descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
			serviceRegistry.add(descriptor);
		} catch (ServiceException e) {
			throw new BirtException(e.getMessage());
		}

		// Loading the diagram from the model.notation resource
		Resource diagramResource = null;
		for (Resource r : modelSet.getResources())
			if (r.getURI().path().compareTo(modelPath + ".notation") == 0) {
				diagramResource = r;
				break;
			}
				
		for (EObject element : diagramResource.getContents())
			if (element instanceof Diagram) {
				convertedDiagram = (Diagram) element;
				break;
			}

		// Launch conversion based on the Papyrus 'BasicEditPartProvider' declared in the plug-in extensions.
		Display.getDefault().syncExec(new Runnable() {
			@Override
			public void run() {
				diagramImage  = DiagramRenderUtil.renderToSWTImage(convertedDiagram);
			}
		});
		ByteArrayOutputStream result = new ByteArrayOutputStream();
		ImageLoader imageLoader = new ImageLoader();
		imageLoader.data = new ImageData[] { diagramImage.getImageData() };
		imageLoader.save(result, getFormat());
		diagramImage.dispose();

		return new ByteArrayInputStream(result.toByteArray());


But image generation still display the 'Invalid view - remove from diagram' message...

I then launched Papyrus itself in debug mode with a breakpoint after CDOAwareModelSet.loadModels() call.
I get the following resources list :
org.eclipse.papyrus.cdo.core.resource.CDOAwareModelSet@73bbf337 resources=[CDOResource@OID125("cdo.checkout://1/home/llemoux/model2.notation"), CDOResource@OID127("cdo.checkout://1/home/llemoux/model2.uml"), CDOResource@OID126("cdo.checkout://1/home/llemoux/model2.di"), org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl@62e70e74 uri='file:/C:/Users/llm/Documents/runtime-Papyrusfordebug/.metadata/.plugins/org.eclipse.papyrus.infra.core/1/home/llemoux/model2.sash']


The same action with my adapted model set gives the following result :
resources=[CDOResource@OID125("cdo://repo1/home/llemoux/model2.notation"), CDOResource@OID126("cdo://repo1/home/llemoux/model2.di"), CDOResource@OID127("cdo://repo1/home/llemoux/model2.uml"), org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl@4aa2bbce uri='file:/C:/Users/llm/Documents/runtime-BIRT.product/.metadata/.plugins/org.eclipse.papyrus.cdo.core/sashidx/home/llemoux/model2.sash']


You can see that - surprisingly - the model2.sash resource is not stored under the same plug-in...

Could this be the reason with the image is not correctly rendered ?

Regards,

Laurent
Re: How to get an image out of a Papyrus diagram ? [message #1733746 is a reply to message #1733732] Tue, 31 May 2016 11:05 Go to previous messageGo to next message
Camille Letavernier is currently offline Camille LetavernierFriend
Messages: 926
Registered: February 2011
Senior Member
Hi,

The *.sash model, by default, is stored in the user's workspace (It is not meant to be shared amongst users, so it's explicitly excluded from the workspace or CDO repos). So, that's not the problem.

If your resources are now properly loaded, then I would look further into the order of the instructions, and the way the ModelSet is associated to the services registry:

ServiceDescriptor descriptor = new ServiceDescriptor(ModelSet.class, ModelSetServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10);
descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
serviceRegistry.add(descriptor);


This will create a ModelSet when the services registry is started. Since you're providing your own ModelSet later on, these instructions should be removed

		// Add factory for editing domain
		descriptor = new ServiceDescriptor(TransactionalEditingDomain.class, EditingDomainServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(ModelSet.class.getName()));
		descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
		serviceRegistry.add(descriptor);


This will create a TransactionalEditingDomain for the ModelSet registered in the ServicesRegistry, as soon as the registry is started. This is required, but you need to be careful about the order (i.e. ensure your ModelSet is properly registered before the ServicesRegistry is started, so that the TransactionalEditingDomain can find it on startup)

try {
			serviceRegistry.startRegistry();
		} catch (ServiceMultiException e) {
			throw new BirtException(e.getMessage());
		}


This starts all "startup" services. So your ModelSet needs to be registered before this point

final CDOView modelSetView = view;
		ModelSet modelSet = new ModelSet() {
			/**
			 * Properly load the cdo resources to avoid a transient state.
			 */
			@Override
			public Resource createResource(URI uri, String contentType) {
				if (uri.scheme().compareTo("cdo") == 0) { //$NON-NLS-1$
					Resource r = modelSetView.getResource(uri.path());
					getResources().add(r);
					return r;
				} else
					return super.createResource(uri, contentType);
			}
		};

		try {
			serviceRegistry.add(ModelSet.class, 11, modelSet);
			serviceRegistry.startServicesByClassKeys(ModelSet.class);
			ModelSetServiceFactory.setServiceRegistry(modelSet, serviceRegistry);
			serviceRegistry.add(TransactionalEditingDomain.class, 11, modelSet.getTransactionalEditingDomain());
			serviceRegistry.startServicesByClassKeys(TransactionalEditingDomain.class);
		} catch (ServiceException e) {
			throw new BirtException(e.getMessage());
		}


For the reason above, this should be moved before the ServicesRegistry is started

		try {
			serviceRegistry.add(MarkersMonitorService.class, 10, new MarkersMonitorService());
			serviceRegistry.add(CssMarkerEventManagerService.class, 10, new CssMarkerEventManagerService());
			serviceRegistry.add(MarkerToPseudoSelectorMappingService.class, 10, new MarkerToPseudoSelectorMappingService());
			serviceRegistry.add(ValidationMarkersService.class, 10, new ValidationMarkersService());
			serviceRegistry.add(DecorationService.class, 10, new DecorationService());
			serviceRegistry.startRegistry();

			// Di model services
			descriptor = new ServiceDescriptor(DiSashModelManager.class, DiSashModelManagerServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(TransactionalEditingDomain.class.getName()));
			descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
			serviceRegistry.add(descriptor);
		} catch (ServiceException e) {
			throw new BirtException(e.getMessage());
		}


This code starts the ServicesRegistry again. Feels suspicious. These services are probably required for rendering the diagram during export, but then the registration (serviceRegistry.add(*)) should happen before the ServicesRegistry is started. The ServicesRegistry should be started only once. The last service descriptor should also be added before the ServicesRegistry is started


Camille Letavernier

[Updated on: Tue, 31 May 2016 11:05]

Report message to a moderator

Re: How to get an image out of a Papyrus diagram ? [message #1733759 is a reply to message #1733746] Tue, 31 May 2016 13:15 Go to previous messageGo to next message
Laurent Le Moux is currently offline Laurent Le MouxFriend
Messages: 44
Registered: June 2015
Member
Camille,

Here is the resulting simplified version of the code.
I followed your instructions but I had to call modelSet.loadModels before all the registering to avoid a NPE in DiSashModelManager at service startup due to the missing sash model.
final CDOView modelSetView = view;
ModelSet modelSet = new ModelSet() {
	/**
	 * Properly load the cdo resources to avoid a transient state.
	 */
	@Override
	public Resource createResource(URI uri, String contentType) {
if (uri.scheme().compareTo("cdo") == 0) { //$NON-NLS-1$
	Resource r = modelSetView.getResource(uri.path());
	getResources().add(r);
	return r;
} else
	return super.createResource(uri, contentType);
	}
};

// Read all Models from selected source
ModelsReader modelsReader = new ModelsReader();
modelsReader.readModel(modelSet);
try {
	modelSet.loadModels(CDOURIUtil.createResourceURI(view, modelPath + ".di")); //$NON-NLS-1$
} catch (ModelMultiException e) {
	throw new BirtException(e.getMessage());
}

ServicesRegistry serviceRegistry = new ServicesRegistry();
try {
	// Register the model set first
	serviceRegistry.add(ModelSet.class, 10, modelSet);
	serviceRegistry.startServicesByClassKeys(ModelSet.class);
	ModelSetServiceFactory.setServiceRegistry(modelSet, serviceRegistry);

	// Register the TED
	serviceRegistry.add(TransactionalEditingDomain.class, 10, modelSet.getTransactionalEditingDomain());
	serviceRegistry.startServicesByClassKeys(TransactionalEditingDomain.class);

	serviceRegistry.add(MarkersMonitorService.class, 10, new MarkersMonitorService());
	serviceRegistry.add(CssMarkerEventManagerService.class, 10, new CssMarkerEventManagerService());
	serviceRegistry.add(MarkerToPseudoSelectorMappingService.class, 10, new MarkerToPseudoSelectorMappingService());
	serviceRegistry.add(ValidationMarkersService.class, 10, new ValidationMarkersService());
	serviceRegistry.add(DecorationService.class, 10, new DecorationService());

	// Di model services
	ServiceDescriptor descriptor = new ServiceDescriptor(DiSashModelManager.class, DiSashModelManagerServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10, Collections.singletonList(TransactionalEditingDomain.class.getName()));
	descriptor.setServiceTypeKind(ServiceTypeKind.serviceFactory);
	serviceRegistry.add(descriptor);
} catch (ServiceException e) {
	throw new BirtException(e.getMessage());
}

try {
	serviceRegistry.startRegistry();
} catch (ServiceMultiException e) {
	e.printStackTrace();
	throw new BirtException(e.getMessage());
}

// Loading the diagram from the model.notation resource
Resource diagramResource = null;
for (Resource r : modelSet.getResources())
	if (r.getURI().path().compareTo(modelPath + ".notation") == 0) {
diagramResource = r;
break;
	}

for (EObject element : diagramResource.getContents())
	if (element instanceof Diagram) {
convertedDiagram = (Diagram) element;
break;
	}

// Launch conversion based on the Papyrus 'BasicEditPartProvider' declared in the plug-in extensions.
Display.getDefault().syncExec(new Runnable() {
	@Override
	public void run() {
diagramImage  = DiagramRenderUtil.renderToSWTImage(convertedDiagram);
	}
});
ByteArrayOutputStream result = new ByteArrayOutputStream();
ImageLoader imageLoader = new ImageLoader();
imageLoader.data = new ImageData[] { diagramImage.getImageData() };
imageLoader.save(result, getFormat());
diagramImage.dispose();

return new ByteArrayInputStream(result.toByteArray());

The result remains however the same Sad
Re: How to get an image out of a Papyrus diagram ? [message #1733885 is a reply to message #1733759] Wed, 01 June 2016 19:46 Go to previous messageGo to next message
Laurent Le Moux is currently offline Laurent Le MouxFriend
Messages: 44
Registered: June 2015
Member
Hi Camille,

I finally got the diagram generated. I was missing the Papyrus plug-ins implementing and declaring the extensions for the necessary edit parts:
 org.eclipse.papyrus.uml.diagram.common;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.activity;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.clazz;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.communication;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.component;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.composite;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.deployment;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.profile;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.sequence;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.statemachine;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.timing;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.usecase;bundle-version="1.1.4",
 org.eclipse.papyrus.sysml.diagram.blockdefinition;bundle-version="1.1.4",
 org.eclipse.papyrus.sysml.diagram.internalblock;bundle-version="1.1.4",
 org.eclipse.papyrus.sysml.diagram.parametric;bundle-version="1.1.4",
 org.eclipse.papyrus.sysml.diagram.requirement;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.interactionoverview;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.stereotype.edition;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.symbols;bundle-version="1.1.4",
 org.eclipse.papyrus.infra.gmfdiag.common;bundle-version="1.1.4",

However, there's still a difference between the generation result and what's displayed in Papyrus when opening the editor.
index.php/fa/26046/0/
The background color (blue) and class symbol are missing in the generated image.
index.php/fa/26047/0/
Moreover, I get the following error message:
!ENTRY org.eclipse.papyrus.infra.gmfdiag.common 4 0 2016-06-01 21:15:01.254
!MESSAGE Unexpected Error
!STACK 0
org.eclipse.papyrus.infra.core.services.ServiceNotFoundException: No service registered under 'interface org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor'
	at org.eclipse.papyrus.infra.core.services.ServicesRegistry.getService(ServicesRegistry.java:408)
	at org.eclipse.papyrus.infra.core.utils.AbstractServiceUtils.getService(AbstractServiceUtils.java:153)
	at org.eclipse.papyrus.infra.gmfdiag.common.editpart.PapyrusDiagramEditPart.refresh(PapyrusDiagramEditPart.java:91)
	at org.eclipse.gef.editparts.AbstractEditPart.addNotify(AbstractEditPart.java:253)
	at org.eclipse.gef.editparts.AbstractGraphicalEditPart.addNotify(AbstractGraphicalEditPart.java:223)
	at org.eclipse.gef.editparts.AbstractEditPart.addChild(AbstractEditPart.java:212)
	at org.eclipse.gef.editparts.SimpleRootEditPart.setContents(SimpleRootEditPart.java:105)
	at org.eclipse.gef.ui.parts.AbstractEditPartViewer.setContents(AbstractEditPartViewer.java:617)
	at org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer.setContents(DiagramGraphicalViewer.java:352)
	at org.eclipse.gef.ui.parts.AbstractEditPartViewer.setContents(AbstractEditPartViewer.java:626)
	at org.eclipse.gmf.runtime.diagram.ui.OffscreenEditPartFactory.createDiagramEditPart(OffscreenEditPartFactory.java:128)
	at org.eclipse.gmf.runtime.diagram.ui.OffscreenEditPartFactory.createDiagramEditPart(OffscreenEditPartFactory.java:77)
	at org.eclipse.gmf.runtime.diagram.ui.render.util.DiagramRenderUtil.renderToSWTImage(DiagramRenderUtil.java:79)
	at org.eclipse.birt.gmf.reporting.GMFDiagramPresentationImpl$3.run(GMFDiagramPresentationImpl.java:218)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4155)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3772)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$4.run(PartRenderingEngine.java:1127)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:337)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1018)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:156)
	at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:694)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:337)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:606)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)
	at org.eclipse.birt.report.designer.ui.rcp.DesignerApplication.run(DesignerApplication.java:37)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.equinox.internal.app.EclipseAppContainer.callMethodWithException(EclipseAppContainer.java:587)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:198)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:669)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:608)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1515)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1488)

It's apparently a problem you already faced :
https://dev.eclipse.org/mhonarc/lists/mdt-papyrus.dev/msg01691.html
Is it the cause of the difference ?
Regards,
Laurent
Re: How to get an image out of a Papyrus diagram ? [message #1734105 is a reply to message #1733885] Fri, 03 June 2016 20:22 Go to previous message
Laurent Le Moux is currently offline Laurent Le MouxFriend
Messages: 44
Registered: June 2015
Member
Hi again,

Adding the following plug-ins to my dependencies and refreshing them all once did solve the last problem:
 org.eclipse.papyrus.infra.gmfdiag.css.theme;bundle-version="1.1.4",
 org.eclipse.papyrus.sysml.diagram.css;bundle-version="1.1.4",
 org.eclipse.papyrus.uml.diagram.css;bundle-version="1.1.4"

The CSS are now applied to the generated diagram image.
Thanks Camille for all your support that helped me find my way out !

Regards,

Laurent
Previous Topic:Using Search View to automatically find Papyrus elements
Next Topic:adding new compartment for opaque action in Activity Diagra
Goto Forum:
  


Current Time: Thu Aug 13 01:18:36 GMT 2020

Powered by FUDForum. Page generated in 0.02290 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top