blob: 6a36dd36c72aae4c584cc73fa334337c816b850e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.stem.model.ui.editor;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
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.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.stem.model.metamodel.Package;
import org.eclipse.stem.model.metamodel.Transition;
import org.eclipse.stem.model.ui.editor.vismodel.CanvasPackage;
import org.eclipse.stem.model.xtext.XtextUtils;
import org.eclipse.ui.IFileEditorInput;
public class VisualModelLoader
{
private ResourceSet rs = new ResourceSetImpl();
private IFileEditorInput input;
private Package metamodel;
private CanvasPackage vismodel;
private IPath metamodelFile, vismodelFile;
private Resource metamodelResource, vismodelResource;
// private EditingDomain metamodelEditingDomain;
public VisualModelLoader(IFileEditorInput input)
{
this.input = input;
}
// public EditingDomain getMetamodelEditingDomain()
// {
// return metamodelEditingDomain;
// }
public void destroy()
{
for (Resource r : rs.getResources()) {
r.unload();
}
rs = null;
input = null;
metamodel = null;
vismodel = null;
vismodelResource = null;
metamodelResource = null;
}
public Package getMetamodel()
{
return metamodel;
}
public CanvasPackage getVisualModel()
{
return vismodel;
}
public void load() throws ModelLoadException
{
IFile file = input.getFile();
if (file.getName().endsWith(".metamodel")) {
metamodelFile = file.getFullPath();
// Load for metamodel
loadForMetamodel();
}
if (file.getName().endsWith(".vmm")) {
// load for visual model
loadForVismodel(file);
}
}
private static URI getUriForPath(IPath path) {
return URI.createPlatformResourceURI(path.toString(), true);
}
private void initializeXtextExpressions(Package pkg) {
TreeIterator<EObject> iterator = pkg.eAllContents();
while (iterator.hasNext()) {
EObject obj = iterator.next();
if (obj instanceof Transition) {
XtextUtils.loadAndResolveXtextResourceForTransition((Transition)obj);
}
}
}
private Package loadMetamodel(IPath file) throws ModelLoadException
{
URI mmURI = getUriForPath(file);
try {
metamodelResource = rs.getResource(mmURI, true);
} catch (Exception ioe) {
throw new ModelLoadException("Error loading metamodel for "+ mmURI.toString(), metamodelResource, ioe);
}
if (metamodelResource.getContents().size() > 0) {
EObject obj = metamodelResource.getContents().get(0);
EcoreUtil.resolveAll(obj);
if (obj instanceof Package) {
initializeXtextExpressions((Package)obj);
return (Package) obj;
}
}
throw new ModelLoadException("The metamodel file did not contain a model package. Check for parse errors.", metamodelResource);
}
private CanvasPackage loadVisualModel(URI visualModelUri) throws ModelLoadException
{
vismodelResource = rs.createResource(visualModelUri);
try {
vismodelResource.load(null);
} catch (IOException ioe) {
throw new ModelLoadException("Error loading visual model for "+ visualModelUri.toString(), vismodelResource, ioe);
}
if (vismodelResource.getContents().size() > 0) {
EObject obj = vismodelResource.getContents().get(0);
EcoreUtil.resolveAll(obj);
if (obj instanceof CanvasPackage) {
return (CanvasPackage) obj;
}
}
throw new ModelLoadException("The visual model file did not contain a canvas package. Check for parse errors.", vismodelResource);
}
private CanvasPackage loadVisualModel(IFile file) throws ModelLoadException
{
return loadVisualModel(getUriForPath(file.getFullPath()));
}
private IPath[] getVisualModelSearchPaths(IPath metamodelFile)
{
IPath[] paths = new IPath[2];
paths[0] = metamodelFile.removeFileExtension().addFileExtension("vmm");
String hiddenVmmFile = "."+paths[0].lastSegment();
paths[1] = metamodelFile.removeLastSegments(1).append(hiddenVmmFile);
return paths;
}
private void findAndLoadVisualModelForMetamodel()
{
// Load from metamodel reference
/*if (metamodel.getVisualModel() != null) {
URI vismodelUri = metamodel.getVisualModel();
}*/
final IWorkspaceRoot wsr = ResourcesPlugin.getWorkspace().getRoot();
for (IPath path : getVisualModelSearchPaths(metamodelFile)) {
IResource resource = wsr.findMember(path);
if (resource instanceof IFile) {
// we have something. Try and load
try {
CanvasPackage vismodel = loadVisualModel((IFile)resource);
if (vismodel != null) {
this.vismodelFile = resource.getFullPath();
this.vismodel = vismodel;
}
} catch (ModelLoadException mle) {
// continue
}
}
}
}
private void initializeVisualModelForMetamodel() throws ModelLoadException {
vismodel = VisualModelReconciler.initializeForMetamodel(metamodel);
vismodelFile = getDefaultVisualModelPath();
try {
if (vismodelFile != null) {
// Add vismodel to resource set
vismodelResource = rs.createResource(getUriForPath(vismodelFile));
vismodelResource.getContents().add(vismodel);
saveVisualModel();
print(vismodelResource);
} else {
throw new IOException("Coldn't find serialization path for the visual model file");
}
} catch (IOException ioe) {
throw new ModelLoadException("Unable to initialize the visual model", null, ioe);
}
}
private IPath getDefaultVisualModelPath() {
if (metamodelFile != null) {
IPath path = metamodelFile;
String filename = path.removeFileExtension().lastSegment();
return path.removeLastSegments(1).append("."+filename+".vmm");
}
if (input != null && metamodel != null) {
return input.getFile().getFullPath().removeLastSegments(1).append("."+metamodel.getName() +".vmm");
}
return null;
}
private void loadForMetamodel() throws ModelLoadException
{
metamodel = loadMetamodel(metamodelFile);
findAndLoadVisualModelForMetamodel();
if (vismodel == null) {
initializeVisualModelForMetamodel();
} else {
reconcileVisualModel();
print(vismodelResource);
}
}
private void reconcileVisualModel() throws ModelLoadException {
VisualModelReconciler reconciler = new VisualModelReconciler(metamodel, vismodel);
reconciler.reconcile();
if (reconciler.isVismodelChanged()) {
try {
saveVisualModel();
} catch (IOException ioe) {
throw new ModelLoadException("Error saving reconciled visual model", null, ioe);
}
}
}
private void loadForVismodel(IFile file) throws ModelLoadException
{
}
public void save() throws IOException
{
saveMetamodel();
saveVisualModel();
//((BasicCommandStack)metamodelEditingDomain.getCommandStack()).saveIsDone();
}
private void saveMetamodel() throws IOException {
if (metamodelResource != null) {
metamodelResource.save(Collections.EMPTY_MAP);
//print(metamodelResource);
}
}
private void saveVisualModel() throws IOException {
if (vismodelResource != null) {
vismodelResource.save(Collections.EMPTY_MAP);
//print(vismodelResource);
}
}
private static void print(Resource r) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
r.save(baos, Collections.EMPTY_MAP);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public static class ModelLoadException extends Exception
{
Resource resource;
/**
*
*/
private static final long serialVersionUID = -3367244339543539764L;
public ModelLoadException(String message)
{
this(message,(Resource)null,(Throwable)null);
}
public ModelLoadException(String message, Resource resource)
{
this(message,resource,null);
}
public ModelLoadException(String message, Resource resource, Throwable cause)
{
super(message,cause);
this.resource = resource;
}
}
}