blob: fbe9248bcf7c560e122e316e4f8d24b1c60bb7c1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2019 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 - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.internal.resource;
import java.util.List;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EContentAdapter;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IDisposable;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.ocl.pivot.Library;
import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal;
import org.eclipse.ocl.pivot.internal.utilities.OCLInternal;
import org.eclipse.ocl.pivot.resource.BasicProjectManager;
import org.eclipse.ocl.pivot.resource.ProjectManager;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.OCL;
/**
* An OCLAdapter extends an EnvironmentFactoryAdapter so that the lifetime
* of the OCL for a ResourceSet terminates with the ResourceSet adapter. If the
* ResourceSet is the AdapterFactoryEditingDomainResourceSet of an Ecore Editor,
* an AdapterFactory is registered to ensure that the OCLAdapter disposes with
* the editor rather than locking it into memory.
*/
public class OCLAdapter extends EnvironmentFactoryAdapter implements AdapterFactory, IDisposable
{
public static @NonNull EnvironmentFactoryInternal createEnvironmentFactory(@NonNull ProjectManager projectManager, @NonNull Notifier notifier) {
OCLInternal ocl = OCLInternal.newInstance(projectManager, null); // FIXME Two StandaloneProjectMap intances
OCLAdapter adapter = new OCLAdapter(ocl, notifier);
notifier.eAdapters().add(adapter);
return adapter.getEnvironmentFactory();
}
public static @NonNull EnvironmentFactoryInternal createEnvironmentFactory( @NonNull Notifier notifier) {
return createEnvironmentFactory(BasicProjectManager.createDefaultProjectManager(), notifier);
}
public static @NonNull OCLAdapter getAdapter(@NonNull ResourceSet resourceSet) {
@SuppressWarnings("null")@NonNull List<Adapter> eAdapters = resourceSet.eAdapters();
OCLAdapter oclAdapter = ClassUtil.getAdapter(OCLAdapter.class, eAdapters);
if (oclAdapter == null) {
EnvironmentFactoryAdapter environmentFactoryAdapter = ClassUtil.getAdapter(EnvironmentFactoryAdapter.class, resourceSet);
if (environmentFactoryAdapter != null) {
oclAdapter = new OCLAdapter(OCLInternal.newInstance(environmentFactoryAdapter.getEnvironmentFactory()), resourceSet);
}
else {
OCLInternal ocl = OCLInternal.newInstance(BasicProjectManager.createDefaultProjectManager(), resourceSet);
oclAdapter = new OCLAdapter(ocl, resourceSet);
}
eAdapters.add(oclAdapter);
}
return oclAdapter;
}
protected OCL ocl; // Set null once disposed
protected OCLAdapter(@NonNull OCLInternal ocl, @NonNull Notifier notifier) {
super(ocl.getEnvironmentFactory(), notifier);
this.ocl = ocl;
//
// Ecore Editors do not unload their ResourceSet, so try to install this as an AdapterFactory to detect Ecore Editor dispose().
//
if (notifier instanceof IEditingDomainProvider) {
EditingDomain editingDomain = ((IEditingDomainProvider)notifier).getEditingDomain();
if (editingDomain instanceof AdapterFactoryEditingDomain) {
AdapterFactory adapterFactory = ((AdapterFactoryEditingDomain)editingDomain).getAdapterFactory();
if (adapterFactory instanceof ComposedAdapterFactory) {
ComposedAdapterFactory composedAdapterFactory = (ComposedAdapterFactory)adapterFactory;
composedAdapterFactory.addAdapterFactory(this);
}
}
}
}
@Override
public Adapter adapt(Notifier target, Object type) {
return null;
}
@Override
public Object adapt(Object object, Object type) {
return null;
}
@Override
public void adaptAllNew(Notifier notifier) {
}
@Override
public Adapter adaptNew(Notifier target, Object type) {
return null;
}
@Override
public void dispose() {
notifier.eAdapters().remove(this);
}
@Override
public boolean isFactoryForType(Object type) {
return super.isAdapterForType(type) || (type == OCLAdapter.class);
}
@Override
public void unsetTarget(Notifier oldTarget) {
super.unsetTarget(oldTarget);
OCL ocl2 = ocl;
if (ocl2 != null) {
ocl = null;
if (notifier instanceof IEditingDomainProvider) {
for (Adapter eAdapter : notifier.eAdapters()) {
if (eAdapter instanceof EContentAdapter) {
for (Library asLibrary : ((PivotMetamodelManager)ocl2.getMetamodelManager()).getLibraries()) {
Resource resource = asLibrary.eResource();
if ((resource != null) && (resource.getResourceSet() == null)){
resource.eAdapters().remove(eAdapter);
}
}
}
}
}
ocl2.dispose();
}
}
}