blob: fa1738a7caef79a3b364327dd87bc5cf0b04d4d0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2019 Mia-Software 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:
* Fabien Giquel (Mia-Software) - initial API and implementation
* Nicolas Bros (Mia-Software) - Bug 335003 - [Discoverer] : Existing Discoverers Refactoring based on new framework
*******************************************************************************/
package org.eclipse.modisco.kdm.source.extension.discovery;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.Resource.IOWrappedException;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.modisco.infra.common.core.logging.MoDiscoLogger;
import org.eclipse.modisco.infra.discovery.core.AbstractModelDiscoverer;
import org.eclipse.modisco.infra.discovery.core.exception.DiscoveryException;
import org.eclipse.modisco.kdm.source.discoverer.DiscoverSourceModelFromJavaElement;
import org.eclipse.modisco.kdm.source.discoverer.DiscoverSourceModelFromResource;
import org.eclipse.modisco.kdm.source.extension.Activator;
/**
* This abstract discoverer can be used for writing composite discoverers where one KDM inventory
* leaf model is involved in model composition.
*
* It proposes a discovery process and some common code related to the KDM inventory model.
*
* See Help Contents or http://wiki.eclipse.org/MoDisco/Components/KDMSourceExtension
*/
public abstract class AbstractComposedKDMSourceDiscoverer2<T> extends AbstractModelDiscoverer<T> {
private static final int FLUSH_LIMIT_SHIFT = 16;
private static final Integer FLUSH_LIMIT = Integer
.valueOf(1 << AbstractComposedKDMSourceDiscoverer2.FLUSH_LIMIT_SHIFT);
private Resource kdmSourceModelResource = null;
protected void setKdmSourceModelResource(final Resource kdmSourceModelResource) {
this.kdmSourceModelResource = kdmSourceModelResource;
}
protected Resource getKdmSourceModelResource() {
return this.kdmSourceModelResource;
}
/**
* The global discovery process. Should not be overridden in most cases.
*
* The process includes four steps : composite model initialization, KDM inventory model
* discovery, discovery of other leaf models, composite model completion.
*
* Creating links between models may be done during the last step, or during the discovery of
* leaf models (e.g. using {@link SourceVisitListener}).
*/
@Override
protected void basicDiscoverElement(final T source, final IProgressMonitor monitor)
throws DiscoveryException {
// Step 1
initializeCompositeModel(source, monitor);
if (monitor.isCanceled()) {
return;
}
monitor.worked(1);
// Step 2
discoverOtherLeafModels(source, monitor);
if (monitor.isCanceled()) {
return;
}
monitor.worked(1);
// Step 3
discoverKDMSourceModel(source, monitor);
if (monitor.isCanceled()) {
return;
}
monitor.worked(1);
// Step 4
finishBuildingModel(source, monitor);
}
/**
* The initialization should create a {@link Resource} and root element for the composite model.
* It may also initialize a {@link SourceVisitListener} if some of the leaf discoverers
* implement {@link AbstractRegionDiscoverer}.
*/
protected abstract void initializeCompositeModel(final T source, final IProgressMonitor monitor);
/**
* This should call leaf discoverers, retrieve the resulting resources and move them to the
* global resource set.
*/
protected abstract void discoverOtherLeafModels(final T source, final IProgressMonitor monitor);
/** Optional operations to complete the discovery (weaving, saving, ...) */
protected abstract void finishBuildingModel(final T source, final IProgressMonitor monitor);
/**
* Standard KDM inventory model discovery process.
*
* @throws DiscoveryException
*/
protected Resource discoverKDMSourceModel(final T source, final IProgressMonitor monitor)
throws DiscoveryException {
monitor.subTask(Messages.AbstractComposedKDMSourceDiscoverer_1);
if (source instanceof IResource) {
IResource resource = (IResource) source;
DiscoverSourceModelFromResource discoverer = new DiscoverSourceModelFromResource();
discoverer.setSerializeTarget(isSerializeKDMResource());
discoverer.setTargetURI(getKDMResourceTargetURI());
discoverer.discoverElement(resource, monitor);
if (discoverer.getTargetModel().getURI() == null) {
discoverer.getTargetModel().setURI(discoverer.getDefaultTargetURI());
}
getResourceSet().getResources().add(discoverer.getTargetModel());
this.kdmSourceModelResource = discoverer.getTargetModel();
return this.kdmSourceModelResource;
} else if (source instanceof IJavaElement) {
IJavaElement javaElement = (IJavaElement) source;
DiscoverSourceModelFromJavaElement discoverer = new DiscoverSourceModelFromJavaElement();
discoverer.setSerializeTarget(isSerializeKDMResource());
discoverer.setTargetURI(getKDMResourceTargetURI());
discoverer.discoverElement(javaElement, monitor);
if (discoverer.getTargetModel().getURI() == null) {
discoverer.getTargetModel().setURI(discoverer.getDefaultTargetURI());
}
getResourceSet().getResources().add(discoverer.getTargetModel());
this.kdmSourceModelResource = discoverer.getTargetModel();
return this.kdmSourceModelResource;
} else {
throw new IllegalArgumentException("source type not handled: " //$NON-NLS-1$
+ source.getClass().getName());
}
}
protected abstract boolean isSerializeKDMResource();
protected abstract URI getKDMResourceTargetURI();
protected static void saveResource(final Resource resource) throws IOException {
Map<String, Object> options = new HashMap<String, Object>();
options.put(XMLResource.OPTION_FLUSH_THRESHOLD,
AbstractComposedKDMSourceDiscoverer2.FLUSH_LIMIT);
options.put(XMLResource.OPTION_USE_FILE_BUFFER, Boolean.TRUE);
if (resource.getURI() == null) {
MoDiscoLogger.logError("Cannot save a Resource without URI." //$NON-NLS-1$
, Activator.getDefault());
return;
}
try {
resource.save(options);
} catch (IOWrappedException e) {
// TODO here is a temporary fix for Bug 323247
if (e.getCause() != null && (e.getCause() instanceof CoreException)) {
MoDiscoLogger.logWarning(e, "XMI serialization has failed on '" + resource.getURI() //$NON-NLS-1$
+ "'. Trying again without File Buffer.", //$NON-NLS-1$
Activator.getDefault());
options.clear();
resource.save(options);
MoDiscoLogger.logInfo("XMI serialization is done for " + resource.getURI(), //$NON-NLS-1$
Activator.getDefault());
} else {
throw e;
}
}
}
}