In progress: [ Issue 40 ] Add support for import resolution across multiple folders
https://code.google.com/p/protobuf-dt/issues/detail?id=40

ImportUriFixer now verifies that the resolved URI corresponds to an existing file.
diff --git a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java
index 982eb39..1378b22 100644
--- a/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java
+++ b/com.google.eclipse.protobuf.test/src/com/google/eclipse/protobuf/scoping/ImportUriFixer_fixUri_Test.java
@@ -11,39 +11,47 @@
 import static org.eclipse.emf.common.util.URI.createURI;
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.*;
 
 import org.eclipse.emf.common.util.URI;
 import org.junit.Before;
 import org.junit.Test;
 
 /**
- * Tests for <code>{@link ImportUriFixer#fixUri(String, URI)}</code>.
+ * Tests for <code>{@link ImportUriFixer#fixUri(String, URI, ResourceChecker)}</code>.
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
 public class ImportUriFixer_fixUri_Test {
 
-  private ImportUriFixer fixer;
   private URI resourceUri;
+  private ResourceChecker resourceChecker;
+  private ImportUriFixer fixer;
 
   @Before public void setUp() {
     resourceUri = createURI("platform:/resource/testing/src/test.proto");
+    resourceChecker = mock(ResourceChecker.class);
     fixer = new ImportUriFixer();
   }
 
   @Test public void should_fix_import_URI_if_missing_scheme() {
-    String fixed = fixer.fixUri("folder1/test.proto", resourceUri);
-    assertThat(fixed, equalTo("platform:/resource/testing/src/folder1/test.proto"));  
+    String expected = "platform:/resource/testing/src/folder1/test.proto";
+    when(resourceChecker.resourceExists(expected)).thenReturn(true);
+    String fixed = fixer.fixUri("folder1/test.proto", resourceUri, resourceChecker);
+    assertThat(fixed, equalTo(expected));  
   }
 
   @Test public void should_not_fix_import_URI_if_not_missing_scheme() {
     String importUri = "platform:/resource/testing/src/folder1/test.proto";
-    String fixed = fixer.fixUri(importUri, resourceUri);
+    when(resourceChecker.resourceExists(importUri)).thenReturn(true);
+    String fixed = fixer.fixUri(importUri, resourceUri, resourceChecker);
     assertThat(fixed, equalTo(importUri));
   }
   
   @Test public void should_fix_import_URI_even_if_overlapping_folders_with_resource_URI() {
-    String fixed = fixer.fixUri("testing/src/folder1/test.proto", resourceUri);
-    assertThat(fixed, equalTo("platform:/resource/testing/src/folder1/test.proto"));  
+    String expected = "platform:/resource/testing/src/folder1/test.proto";
+    when(resourceChecker.resourceExists(expected)).thenReturn(true);
+    String fixed = fixer.fixUri("testing/src/folder1/test.proto", resourceUri, resourceChecker);
+    assertThat(fixed, equalTo(expected));  
   }
 }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java
index 09f8cc2..a13a9b1 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/labeling/Labels.java
@@ -8,7 +8,7 @@
  */
 package com.google.eclipse.protobuf.ui.labeling;
 
-import static com.google.eclipse.protobuf.scoping.ImportUriFixerAndResolver.URI_PREFIX;
+import static com.google.eclipse.protobuf.scoping.ProtobufImportUriResolver.URI_PREFIX;
 import static org.eclipse.jface.viewers.StyledString.DECORATIONS_STYLER;
 
 import org.eclipse.jface.viewers.StyledString;
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java
index 833d9db..8fbb052 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/ProtobufRuntimeModule.java
@@ -13,7 +13,7 @@
 import org.eclipse.xtext.scoping.impl.ImportUriResolver;
 
 import com.google.eclipse.protobuf.naming.ProtobufQualifiedNameProvider;
-import com.google.eclipse.protobuf.scoping.ImportUriFixerAndResolver;
+import com.google.eclipse.protobuf.scoping.ProtobufImportUriResolver;
 import com.google.eclipse.protobuf.validation.ProtobufSyntaxErrorMessageProvider;
 import com.google.inject.Binder;
 
@@ -28,7 +28,7 @@
   }
 
   public void configureImportUriResolver(Binder binder) {
-    binder.bind(ImportUriResolver.class).to(ImportUriFixerAndResolver.class);
+    binder.bind(ImportUriResolver.class).to(ProtobufImportUriResolver.class);
   }
 
   public void configureSyntaxErrorMessageProvider(Binder binder) {
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java
index eec205d..c209724 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixer.java
@@ -2,9 +2,14 @@
 
 package com.google.eclipse.protobuf.scoping;
 
+import static org.eclipse.emf.common.util.URI.createURI;
+import static org.eclipse.xtext.util.Tuples.pair;
+
+import java.util.ArrayList;
 import java.util.List;
 
 import org.eclipse.emf.common.util.URI;
+import org.eclipse.xtext.util.Pair;
 
 /**
  * @author alruiz@google.com (Alex Ruiz)
@@ -30,26 +35,39 @@
    * If we import "folder/proto2.proto" into proto1.proto, proto1.proto will compile fine, but the editor will complain.
    * We need to have the import URI as "platform:/resource/protobuf-test/folder/proto2.proto" for the editor to see it.
    */
-  String fixUri(String importUri, URI resourceUri) {
+  String fixUri(String importUri, URI resourceUri, ResourceChecker checker) {
     if (importUri.startsWith(PREFIX)) return importUri;
-    String prefix = uriPrefix(URI.createURI(importUri).segmentsList(), resourceUri);
-    if (importUri.startsWith(prefix)) return importUri;
-    if (!prefix.endsWith(SEPARATOR)) prefix += SEPARATOR;
-    String fixed = prefix + importUri;
+    Pair<String, List<String>> importUriPair = pair(importUri, createURI(importUri).segmentsList());
+    String fixed = fixUri(importUriPair, resourceUri, checker);
+    if (fixed == null) return importUri;
     System.out.println(resourceUri + " : " + importUri + " : " + fixed);
     return fixed;
   }
+  
+  private String fixUri(Pair<String, List<String>> importUri, URI resourceUri, ResourceChecker checker) {
+    List<String> segments = resourceUri.segmentsList();
+    return fixUri(importUri, removeFirstAndLast(segments), checker);
+  }
 
-  private String uriPrefix(List<String> importUri, URI resourceUri) {
+  private List<String> removeFirstAndLast(List<String> list) {
+    if (list.isEmpty()) return list;
+    List<String> newList = new ArrayList<String>(list);
+    newList.remove(0);
+    newList.remove(newList.size() - 1);
+    return newList;
+  }
+  
+  private String fixUri(Pair<String, List<String>> importUri, List<String> resourceUri, ResourceChecker checker) {
     StringBuilder prefix = new StringBuilder();
     prefix.append(PREFIX);
-    String firstSegment = importUri.get(0);
-    List<String> segments = resourceUri.segmentsList();
-    int end = segments.size() - 1; // ignore file name (at the end of the URI)
-    for (int j = 1; j < end; j++) {
-      if (segments.get(j).equals(firstSegment)) break;
-      prefix.append(SEPARATOR).append(segments.get(j));
+    String firstSegment = importUri.getSecond().get(0);
+    for (String segment : resourceUri) {
+      if (segment.equals(firstSegment)) break;
+      prefix.append(SEPARATOR).append(segment);
     }
-    return prefix.toString();
+    prefix.append(SEPARATOR);
+    String fixed =  prefix.toString() + importUri.getFirst();
+    if (checker.resourceExists(fixed)) return fixed;
+    return null;
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixerAndResolver.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriResolver.java
similarity index 86%
rename from com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixerAndResolver.java
rename to com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriResolver.java
index 50a351d..e5c4332 100644
--- a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ImportUriFixerAndResolver.java
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ProtobufImportUriResolver.java
@@ -11,6 +11,7 @@
 import static com.google.eclipse.protobuf.scoping.ImportUriFixer.PREFIX;
 
 import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.xtext.scoping.impl.ImportUriResolver;
 
 import com.google.eclipse.protobuf.protobuf.Import;
@@ -27,7 +28,7 @@
  *
  * @author alruiz@google.com (Alex Ruiz)
  */
-public class ImportUriFixerAndResolver extends ImportUriResolver {
+public class ProtobufImportUriResolver extends ImportUriResolver {
 
   @Inject private ImportUriFixer uriFixer;
   
@@ -48,7 +49,8 @@
   }
 
   private void fixUri(Import i) {
-    String fixed = uriFixer.fixUri(i.getImportURI(), i.eResource().getURI());
+    Resource resource = i.eResource();
+    String fixed = uriFixer.fixUri(i.getImportURI(), resource.getURI(), new ResourceChecker(resource.getResourceSet()));
     i.setImportURI(fixed);
   }
 }
diff --git a/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ResourceChecker.java b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ResourceChecker.java
new file mode 100644
index 0000000..20c9a19
--- /dev/null
+++ b/com.google.eclipse.protobuf/src/com/google/eclipse/protobuf/scoping/ResourceChecker.java
@@ -0,0 +1,25 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+package com.google.eclipse.protobuf.scoping;
+
+import static org.eclipse.emf.common.util.URI.createURI;
+
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+class ResourceChecker {
+
+  private final ResourceSet resourceSet;
+
+  ResourceChecker(ResourceSet resourceSet) {
+    this.resourceSet = resourceSet;
+  }
+  
+  boolean resourceExists(String uri) {
+    Resource resource = resourceSet.getResource(createURI(uri), true);
+    return resource != null && resource.getErrors().isEmpty();
+  }
+}