org.eclipse.xtext.mwe.Reader Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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
*******************************************************************************/
package org.eclipse.xtext.mwe;
import java.io.File;
import java.util.Collection;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.mwe.core.WorkflowContext;
import org.eclipse.emf.mwe.core.WorkflowInterruptedException;
import org.eclipse.emf.mwe.core.issues.Issues;
import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
import org.eclipse.xtext.ISetup;
import org.eclipse.xtext.resource.IResourceServiceProvider;
import org.eclipse.xtext.resource.containers.DelegatingIAllContainerAdapter;
import org.eclipse.xtext.resource.containers.IAllContainersState;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
/**
*
* A Reader used to read EMF resources from a set of pathes.
* A path can point to a folder or an archive (zips and jars are supported).
* Those pathes are recursively scanned and all resources for which an {@link IResourceServiceProvider} is
* registered in the {@link org.eclipse.xtext.resource.IResourceServiceProvider.Registry} will be available.
*
*
*
* The {@link ISetup} of an Xtext language registers such an {@link IResourceServiceProvider} automatically. If you want to integrate with non Xtext-based models,
* make sure to add {@link IResourceServiceProvider} manually. The easiest way might be to implement an {@link ISetup}.
*
*
* A {@link SlotEntry} is responsible for selecting certain EObjects from the loaded resources.
* It supports selecting EObjects by their name (see {@link org.eclipse.xtext.resource.IEObjectDescription}) or by an EClass.
* In many cases such selction returns multiple EObjects, if you're only interested in one element set the firstOnly
flag to true
.
*
*
* You might want to populate multiple workflow slots with model elements.
*
*
* Below an example of a usage in the MWE XML syntax:
*
*
* <component class="org.eclipse.xtext.mwe.Reader" useJavaClassPath="true">
* <register class="foo.bar.MyLanguageSetandaloneSetup"/>
* <load slot="types" type="Type"/>
* <validate/>
* </component>
*
* It supports fetching elements by type
* {@link IResourceServiceProvider#getResourceDescriptionManager()} is used to identify model elements within these resources.
*
* @author Sven Efftinge - Initial contribution and API
*/
public class Reader extends AbstractReader {
protected final static Logger log = Logger.getLogger(Reader.class.getName());
protected List pathes = Lists.newArrayList();
/**
*
* A path pointing to a folder, jar or zip which contains EMF resources.
*
* Example use:
*
*
* <path value="./foo/bar.jar"/>
*
*/
public void addPath(String path) {
this.pathes.add(path);
}
public List getPathes() {
return pathes;
}
/**
*
* Automatically adds all class path entries of the current process (more specifically uses 'java.class.path' system property).
*
* Example use:
*
*
* <useJavaClassPath value="true"/>
*
*/
public void setUseJavaClassPath(boolean isUse) {
if (isUse) {
String classPath = System.getProperty("java.class.path");
String separator = System.getProperty("path.separator");
String[] strings = classPath.split(separator);
for (String path : strings) {
addPath(path);
}
}
}
private UriFilter filter;
/**
* Optionally set a filter that specifies which URIs are valid to be read.
* A common use-case for filters is a file-name based selection of valid
* URIs.
*/
public void setUriFilter(UriFilter filter) {
this.filter = filter;
}
public UriFilter getUriFilter() {
return filter;
}
private ContainersStateFactory containersStateFactory = new ContainersStateFactory();
public void setContainersStateFactory(ContainersStateFactory containersStateFactory) {
this.containersStateFactory = containersStateFactory;
}
public ContainersStateFactory getContainersStateFactory() {
return containersStateFactory;
}
@Override
protected void checkConfigurationInternal(Issues issues) {
super.checkConfigurationInternal(issues);
if (pathes.isEmpty()) {
issues.addWarning("No path set, using java class path entries (useJavaClassPath='true').");
setUseJavaClassPath(true);
}
if (log.isDebugEnabled()) {
log.debug("Resource Pathes : " + pathes);
}
for (String path : pathes) {
if (!new File(path).exists())
issues.addWarning("Skipping the path '" + path + "', because it does not exist.");
}
}
@Override
protected void invokeInternal(WorkflowContext ctx, ProgressMonitor monitor, Issues issues) {
ResourceSet resourceSet = getResourceSet();
Multimap uris = getPathTraverser().resolvePathes(pathes, new Predicate() {
public boolean apply(URI input) {
boolean result = true;
if (getUriFilter() != null)
result = getUriFilter().matches(input);
if (result)
result = getRegistry().getResourceServiceProvider(input) != null;
return result;
}
});
IAllContainersState containersState = containersStateFactory.getContainersState(pathes, uris);
installAsAdapter(resourceSet, containersState);
populateResourceSet(resourceSet, uris);
getValidator().validate(resourceSet, getRegistry(), issues);
addModelElementsToContext(ctx, resourceSet);
}
protected PathTraverser getPathTraverser() {
return new PathTraverser();
}
protected void populateResourceSet(ResourceSet set, Multimap uris) {
Collection values = Sets.newHashSet(uris.values());
for (URI uri : values) {
set.createResource(uri);
}
}
protected void installAsAdapter(ResourceSet set, IAllContainersState containersState)
throws WorkflowInterruptedException {
set.eAdapters().add(new DelegatingIAllContainerAdapter(containersState));
}
}