blob: a2741f8a04f12f81bcdc57eff843e588693b1b9c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2021 Borland Software Corporation 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:
* Borland Software Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.project.builder;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.m2m.internal.qvt.oml.common.MDAConstants;
import org.eclipse.m2m.internal.qvt.oml.compiler.BlackboxUnitResolver;
import org.eclipse.m2m.internal.qvt.oml.compiler.CompositeUnitResolver;
import org.eclipse.m2m.internal.qvt.oml.compiler.DelegatingUnitResolver;
import org.eclipse.m2m.internal.qvt.oml.compiler.ResolverUtils;
import org.eclipse.m2m.internal.qvt.oml.compiler.UnitContents;
import org.eclipse.m2m.internal.qvt.oml.compiler.UnitProvider;
import org.eclipse.m2m.internal.qvt.oml.compiler.UnitProxy;
import org.eclipse.m2m.internal.qvt.oml.compiler.UnitResolver;
import org.eclipse.m2m.internal.qvt.oml.emf.util.URIUtils;
import org.eclipse.m2m.internal.qvt.oml.project.QVTOProjectPlugin;
import org.eclipse.m2m.internal.qvt.oml.runtime.project.DeployedImportResolver;
import org.eclipse.m2m.internal.qvt.oml.runtime.project.ProjectDependencyTracker;
public class WorkspaceUnitResolver extends DelegatingUnitResolver implements UnitProvider {
private final List<IContainer> fRoots;
public WorkspaceUnitResolver(List<IContainer> sourceContainers) {
if(sourceContainers == null || sourceContainers.contains(null)) {
throw new IllegalArgumentException("null source container"); //$NON-NLS-1$
}
IProject project = null;
for (IContainer container : sourceContainers) {
if(project != null) {
if(project != container.getProject()) {
throw new IllegalArgumentException("source containers must be from single project"); //$NON-NLS-1$
}
} else {
project = container.getProject();
}
if(!container.exists()) {
throw new IllegalArgumentException("Unexisting source container"); //$NON-NLS-1$
}
}
fRoots = new ArrayList<IContainer>(sourceContainers);
if(project != null) {
setParent(new CompositeUnitResolver(
getReferencedProjectsResolver(project, new HashMap<IProject, UnitResolver>()),
new BlackboxUnitResolver(URIUtils.getResourceURI(project)),
DeployedImportResolver.INSTANCE));
}
}
private WorkspaceUnitResolver(IContainer sourceContainer, Map<IProject, UnitResolver> analizedProjects) {
fRoots = Collections.singletonList(sourceContainer);
IProject project = sourceContainer.getProject();
setParent(new CompositeUnitResolver(
getReferencedProjectsResolver(project, analizedProjects),
new BlackboxUnitResolver(URIUtils.getResourceURI(project)),
DeployedImportResolver.INSTANCE));
}
private UnitResolver getReferencedProjectsResolver(IProject project, Map<IProject, UnitResolver> analyzedProjects) {
analyzedProjects.put(project, this);
List<UnitResolver> resolvers = Collections.emptyList();
try {
Set<IProject> referencedProjects = ProjectDependencyTracker.getAllReferencedProjects(project, false);
resolvers = new ArrayList<UnitResolver>(referencedProjects.size());
for (IProject referenced : referencedProjects) {
if (analyzedProjects.containsKey(referenced)) {
resolvers.add(analyzedProjects.get(referenced));
continue;
}
if (referenced == null || !referenced.isAccessible()) {
continue;
}
IContainer sourceContainer = QVTOBuilderConfig.getConfig(referenced).getSourceContainer();
if (sourceContainer == null || !sourceContainer.exists()) {
continue;
}
resolvers.add(new WorkspaceUnitResolver(sourceContainer, analyzedProjects));
}
} catch (CoreException e) {
QVTOProjectPlugin.log(e.getStatus());
}
return new CompositeUnitResolver(resolvers.toArray(new UnitResolver[resolvers.size()]));
}
@Override
protected UnitProxy doResolveUnit(String qualifiedName) {
if(qualifiedName == null) {
throw new IllegalArgumentException("null qualified name"); //$NON-NLS-1$
}
IResource member = null;
for (IContainer nextContainer : fRoots) {
member = resolveResource(nextContainer, qualifiedName, true);
if(member != null) {
return createFileUnit(nextContainer.getFullPath(), member.getFullPath());
}
}
return null;
}
public void accept(UnitProvider.UnitVisitor visitor, String scopeQualifiedName, int depth, boolean includeExternal) {
if(visitor == null) {
throw new IllegalArgumentException();
}
for (IContainer nextContainer : fRoots) {
IResource resourceToVisit = nextContainer;
if(scopeQualifiedName != null) {
resourceToVisit = resolveResource(nextContainer, scopeQualifiedName, false);
if(resourceToVisit == null) {
// nothing to visit
continue;
}
}
try {
ResourceVisitor resourceVisitor = new ResourceVisitor(visitor,
nextContainer, resourceToVisit.getFullPath(), depth);
resourceToVisit.accept(resourceVisitor, IResource.NONE);
} catch(CoreException e) {
// FIXME - log the problem
}
}
}
private IResource resolveResource(IContainer container, String qualifiedName, boolean isUnit) {
IPath unitPath = qName2Path(qualifiedName);
if(!isUnit) {
unitPath = unitPath.removeFileExtension();
}
return container.findMember(unitPath);
}
private FileUnit createFileUnit(IPath sourceContainer, IPath unitPath) {
String unitName = unitPath.removeFileExtension().lastSegment();
String namespace = ResolverUtils.getNamespace(unitPath.removeLastSegments(1), sourceContainer);
URI uri = URI.createPlatformResourceURI(unitPath.toString(), true);
return new FileUnit(namespace, unitName, uri);
}
private static IPath qName2Path(String qname) {
assert qname != null;
String pathStr = ResolverUtils.toNamespaceRelativeUnitFilePath(qname);
return new Path(pathStr);
}
private class ResourceVisitor implements IResourceProxyVisitor {
private UnitProvider.UnitVisitor fUnitVisitor;
private IContainer fContainer;
private IPath fScope;
private int fDepth;
ResourceVisitor(UnitProvider.UnitVisitor unitVisitor, IContainer srcContainer, IPath scope, int depth) {
assert unitVisitor != null;
assert srcContainer != null;
assert scope != null;
fUnitVisitor = unitVisitor;
fContainer = srcContainer;
fScope = scope;
fDepth = depth;
}
public boolean visit(IResourceProxy proxy) throws CoreException {
String name = proxy.getName();
int type = proxy.getType();
if(type == IResource.FILE && name.endsWith(MDAConstants.QVTO_FILE_EXTENSION_WITH_DOT)) {
IPath path = proxy.requestFullPath();
String unitName = path.removeFileExtension().lastSegment();
String namespace = ResolverUtils.getNamespace(path.removeLastSegments(1), fContainer.getFullPath());
URI uri = URI.createPlatformResourceURI(path.toString(), true);
UnitProxy unit = new FileUnit(namespace, unitName, uri);
return fUnitVisitor.visitUnit(unit);
}
else if(type == IResource.FOLDER || type == IResource.PROJECT) {
if(fDepth == UnitProvider.UnitVisitor.DEPTH_ZERO) {
return false;
}
if(fDepth == UnitProvider.UnitVisitor.DEPTH_ONE) {
IPath visitedPath = proxy.requestFullPath();
if(!fScope.equals(visitedPath)) {
return false;
}
}
return true;
}
return false;
}
}
private class FileUnit extends UnitProxy {
public FileUnit(String namespace, String unitName, URI uri) {
super(namespace, unitName, uri);
assert uri.isPlatformResource();
}
@Override
public int getContentType() {
return UnitProxy.TYPE_CST_STREAM;
}
@Override
public UnitResolver getResolver() {
return WorkspaceUnitResolver.this;
}
@Override
public UnitContents getContents() throws IOException {
URI uri = getURI();
String wsRelativePath = uri.toPlatformString(true);
final IFile sourceFile = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(wsRelativePath));
if(!sourceFile.exists()) {
throw new IOException("File does not exist, URI: " + sourceFile.getFullPath()); //$NON-NLS-1$
}
return new UnitContents.CSTContents() {
public Reader getContents() throws IOException {
try {
return new InputStreamReader(sourceFile.getContents(), sourceFile.getCharset());
} catch(CoreException e) {
// FIME - log the problem
throw new IOException(e.getLocalizedMessage());
}
}
};
}
}
// public static List<String> getRequiredPlugins(Bundle bundle) {
// Dictionary<?, ?> headers = bundle.getHeaders();
// String requireBundleHeader = headers.get(Constants.REQUIRE_BUNDLE).toString();
// if(requireBundleHeader == null) {
// return Collections.emptyList();
// }
//
// ManifestElement[] parsedElements = null;
// try {
// parsedElements = ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, requireBundleHeader);
// } catch (BundleException e) {
// // do nothing
// }
//
// if(parsedElements == null) {
// return Collections.emptyList();
// }
//
// List<String> bundles = new ArrayList<String>(parsedElements.length);
// for (ManifestElement element : parsedElements) {
// String value = element.getValue();
// if(value != null) {
// bundles.add(element.getValue());
// }
// }
//
// return bundles;
// }
}