blob: daa0b87026c78e2608148a84ed43f32da55850e8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2018 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink (Obeo) - Add complete ocl registry to enable export and re-use CompleteOCL files
*******************************************************************************/
package org.eclipse.ocl.xtext.completeocl.utilities;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.Model;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.internal.ecore.es2as.Ecore2AS;
import org.eclipse.ocl.pivot.internal.manager.MetamodelManagerInternal;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal;
import org.eclipse.ocl.pivot.internal.utilities.External2AS;
import org.eclipse.ocl.pivot.internal.utilities.OCLInternal;
import org.eclipse.ocl.pivot.internal.utilities.PivotObjectImpl;
import org.eclipse.ocl.pivot.internal.validation.PivotEObjectValidator;
import org.eclipse.ocl.pivot.resource.CSResource;
import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
import org.eclipse.ocl.pivot.utilities.MetamodelManager;
import org.eclipse.ocl.pivot.utilities.ParserException;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.ocl.xtext.completeocl.CompleteOCLStandaloneSetup;
public abstract class CompleteOCLLoader
{ // FIXME This is a pragmatic re-use. Redesign as part of a coherent API.
protected final @NonNull OCLInternal ocl;
protected final @NonNull List<Model> oclModels = new ArrayList<Model>();
protected final @NonNull Set<EPackage> mmPackages;
public CompleteOCLLoader(@NonNull EnvironmentFactory environmentFactory) {
this.ocl = OCLInternal.newInstance((EnvironmentFactoryInternal)environmentFactory);
this.mmPackages = new HashSet<EPackage>();
}
public void dispose() {
ocl.dispose();
}
public @NonNull EnvironmentFactory getEnvironmentFactory() {
return ocl.getEnvironmentFactory();
}
public @NonNull MetamodelManager getMetamodelManager() {
return ocl.getMetamodelManager();
}
public boolean loadMetamodels() {
for (Resource resource : ocl.getResourceSet().getResources()) {
assert resource != null;
External2AS ecore2as = Ecore2AS.findAdapter(resource, ocl.getEnvironmentFactory());
if (ecore2as == null) { // Pivot has its own validation
for (TreeIterator<EObject> tit = resource.getAllContents(); tit.hasNext(); ) {
EObject eObject = tit.next();
EClass eClass = eObject.eClass();
if (eClass != null) {
EPackage mmPackage = eClass.getEPackage();
if (mmPackage != null) {
mmPackages.add(mmPackage);
}
}
}
}
}
Set<Resource> mmResources = new HashSet<Resource>();
for (@SuppressWarnings("null")@NonNull EPackage mmPackage : mmPackages) {
Resource mmResource = EcoreUtil.getRootContainer(mmPackage).eResource();
if (mmResource != null) {
mmResources.add(mmResource);
}
}
for (Resource mmResource : mmResources) {
assert mmResource != null;
try {
Element pivotModel = ocl.getEnvironmentFactory().loadResource(mmResource, null);
if (pivotModel != null) {
List<org.eclipse.emf.ecore.resource.Resource.Diagnostic> errors = pivotModel.eResource().getErrors();
assert errors != null;
String message = PivotUtil.formatResourceDiagnostics(errors, "", "\n");
if (message != null) {
return error("Failed to load Pivot from '" + mmResource.getURI(), message);
}
}
else {
return error("Failed to load Pivot from '" + mmResource.getURI(), "");
}
} catch (ParserException e) {
return error("Failed to load Pivot from '" + mmResource.getURI(), e.getMessage());
}
}
return true;
}
protected abstract boolean error(@NonNull String primaryMessage, @Nullable String detailMessage);
public void installPackages() {
//
// Install validation for all the complemented packages
//
PivotEObjectValidator.install(ocl.getResourceSet(), ocl.getEnvironmentFactory());
for (EPackage mmPackage : mmPackages) {
assert mmPackage != null;
PivotEObjectValidator.install(mmPackage, oclModels);
}
}
public boolean loadDocument(@NonNull URI oclURI) {
Resource resource = loadResource(oclURI);
if (resource == null) {
return false;
}
//
// Identify the packages which the Complete OCL document complements.
//
MetamodelManagerInternal metamodelManager = ocl.getMetamodelManager();
for (TreeIterator<EObject> tit = resource.getAllContents(); tit.hasNext(); ) {
EObject eObject = tit.next();
if (eObject instanceof org.eclipse.ocl.pivot.Package) {
org.eclipse.ocl.pivot.Package aPackage = metamodelManager.getPrimaryPackage((org.eclipse.ocl.pivot.Package)eObject);
if (aPackage instanceof PivotObjectImpl) {
EObject mmPackage = ((PivotObjectImpl)aPackage).getESObject();
if (mmPackage instanceof EPackage) {
mmPackages.add((EPackage)mmPackage);
}
}
}
else if (eObject instanceof Type) {
tit.prune();
}
else if (eObject instanceof Model) {
oclModels .add((Model)eObject);
}
}
return true;
}
/**
* Load the Xtext resource from oclURI, then convert it to a pivot representation and return it.
* Return null after invoking error() to display any errors in a pop-up.
*/
public Resource loadResource(@NonNull URI oclURI) {
CSResource xtextResource = null;
CompleteOCLStandaloneSetup.init();
ResourceSet resourceSet = ocl.getResourceSet();
try {
xtextResource = (CSResource) resourceSet.getResource(oclURI, true);
}
catch (WrappedException e) {
URI retryURI = null;
Throwable cause = e.getCause();
if (cause instanceof CoreException) {
IStatus status = ((CoreException)cause).getStatus();
if ((status.getCode() == IResourceStatus.RESOURCE_NOT_FOUND) && status.getPlugin().equals(ResourcesPlugin.PI_RESOURCES)) {
if (oclURI.isPlatformResource()) {
retryURI = URI.createPlatformPluginURI(oclURI.toPlatformString(false), false);
}
}
}
if (retryURI != null) {
xtextResource = (CSResource) resourceSet.getResource(retryURI, true);
}
else {
throw e;
}
}
List<org.eclipse.emf.ecore.resource.Resource.Diagnostic> errors = xtextResource.getErrors();
assert errors != null;
String message = PivotUtil.formatResourceDiagnostics(errors, "", "\n");
if (message != null) {
error("Failed to load '" + oclURI, message);
return null;
}
Resource asResource = xtextResource.getASResource();
errors = asResource.getErrors();
assert errors != null;
message = PivotUtil.formatResourceDiagnostics(errors, "", "\n");
if (message != null) {
error("Failed to load Pivot from '" + oclURI, message);
return null;
}
return asResource;
}
}