/**
* Copyright (c) 2011 Cloudsmith Inc. and other contributors, as listed below.
* 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
*
* Contributors:
* Cloudsmith
*
*/
package org.cloudsmith.geppetto.pp.dsl.linking;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.resource.IEObjectDescription;
import com.google.common.collect.Lists;
/**
* notes:
* rootURI - URI to file:: root, used to make paths relative if URI is an absolute file uri
*
*
*/
public class PPSearchPath {
public interface IConfigurableProvider {
/**
* Configure the search path provider so it knows the container of (distro) pptp, and
* root for absolute files (may be null).
*
* @param rootDirectory
*/
public void configure(URI rootPath, String defalutPath, String environment);
}
public interface ISearchPathProvider {
public PPSearchPath get(Resource r);
}
public static PPSearchPath fromString(String path, URI root) {
List<IPath> p = Lists.newArrayList();
if(path != null)
path = path.trim();
if(path == null || path.length() == 0)
path = "*"; // everything
// split the string on ':', and create a path per segment
String[] paths = path.split(":");
for(String s : paths) {
if(s.length() == 0)
continue; // skip empty segments
p.add(new Path(s));
}
return new PPSearchPath(p, root);
}
private final URI rootURI;
private List<IPath> searchPath;
private PPSearchPath(List<IPath> p, URI root) {
this.searchPath = p;
this.rootURI = root;
}
public PPSearchPath(URI root) {
searchPath = Lists.newArrayList();
this.rootURI = root;
}
/**
* Evaluates the search path by replacing every occurrence of '$environment' with the
* given value.
*
* @param environment
* @return a new PPSearchPath if there were replacements.
*/
public PPSearchPath evaluate(String environment) {
int replacements = 0;
ArrayList<IPath> newSearchPath = Lists.newArrayList(searchPath);
for(IPath p : searchPath) {
String s = p.toPortableString();
if(s.contains("$environment")) {
s = s.replace("$environment", environment);
p = new Path(s);
replacements++;
}
newSearchPath.add(p);
}
if(replacements > 0)
return new PPSearchPath(newSearchPath, this.rootURI);
return this;
}
public boolean isMatch(IPath candidate, IPath p) {
final int candidateLimit = candidate.segmentCount();
final int pLimit = p.segmentCount();
for(int i = 0; i < pLimit; i++) {
String s = p.segment(i);
// * matches any remaining segments of candidate, including no segements
if("*".equals(s))
return true;
// if more segments in candidate required than what it has
if(i >= candidateLimit)
return false;
if(!s.equals(candidate.segment(i)))
return false;
}
// all segments in p matched, there should only be one remaining segment in candidate
// (if p does not end with *, only paths in p's final directory are matched
if(candidateLimit - pLimit > 1)
return false;
return true;
}
public int searchIndexOf(IEObjectDescription d) {
URI uri = EcoreUtil.getURI(d.getEObjectOrProxy());
if(uri.isFile() && rootURI != null) {
uri = uri.deresolve(rootURI.appendSegment(""));
}
return searchIndexOf(uri);
}
/**
* Computes the path position of the given URI, or -1 if not found.
* The pptp is always on the search path with index 0. TODO: This is wrong!
* It is only the distro path that is on 0, other pptp contributions are subject to filtering (i.e.
* ruby code).
*
* @param uri
* @return search path index or -1 if not found
*/
public int searchIndexOf(URI uri) {
String uriPath = uri.path();
IPath p = new Path(uriPath);
if("pptp".equals(p.getFileExtension()))
return 0; // All pptp are searched first - ALWAYS
if(uri.isPlatformResource())
p = p.removeFirstSegments(2);
for(int idx = 0; idx < searchPath.size(); idx++) {
IPath q = searchPath.get(idx);
if(isMatch(p, q))
return idx + 1;
}
return -1;
}
}