When there are several versions of a bundle in the repo, add the last one to the dependency management POM
Add a warning to the analysis if there are several versions of a bundle in the repo
Support for Warning.MISSING_BINARY_BUNDLE_FOR_SOURCES
diff --git a/data/expected/dependency-management-3.7.0.pom b/data/expected/dependency-management-3.7.0.pom
index d8d72f9..e08ab79 100644
--- a/data/expected/dependency-management-3.7.0.pom
+++ b/data/expected/dependency-management-3.7.0.pom
@@ -28,6 +28,11 @@
                 <artifactId>org.eclipse.birt.core</artifactId>
                 <version>2.6.1</version>
             </dependency>
+            <dependency>
+                <groupId>org.eclipse.core</groupId>
+                <artifactId>org.eclipse.core.runtime</artifactId>
+                <version>3.6.0</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 </project>
diff --git a/src/main/groovy/m4e/AnalyzeCmd.groovy b/src/main/groovy/m4e/AnalyzeCmd.groovy
index 7a972b1..8d81d3e 100644
--- a/src/main/groovy/m4e/AnalyzeCmd.groovy
+++ b/src/main/groovy/m4e/AnalyzeCmd.groovy
@@ -61,6 +61,8 @@
     Calendar timestamp
     Set<Glob> ignores = new HashSet()
     Set<Glob> ignoreMissingSources = new HashSet()
+    Set<Glob> ignoreMissingBinaries = new HashSet()
+    List<String> missingBinaries = []
     
     Analyzer( File repo, Calendar timestamp ) {
         this.repo = repo.canonicalFile
@@ -88,12 +90,10 @@
             if( line.startsWith( 'MissingSources ' ) ) {
                 line = line.substringAfter( ' ' )
                 ignoreMissingSources << new Glob( line, manyRegexp )
+            } else if( line.startsWith( 'MissingBinary ' ) ) {
+                line = line.substringAfter( ' ' )
+                ignoreMissingBinaries << new Glob( '*/' + line )
             } else {
-                if( line.startsWith( 'ProblemSameKeyDifferentVersion ' ) ) {
-                    String pattern = line.substringAfter( ' ' )
-                    ignores << new Glob( 'TwoVersionsProblem ' + pattern, manyRegexp )
-                }
-            
                 ignores << new Glob( line, manyRegexp )
             }
         }
@@ -127,6 +127,24 @@
             }
         }
         
+        if( missingBinaries ) {
+            def l = missingBinaries.findResults {
+                def key = it
+                
+                for( Glob g : ignoreMissingBinaries ) {
+                    if( g.matches( key ) ) {
+                        return null
+                    }
+                }
+                
+                return it
+            }
+            
+            if( l ) {
+                problems << new MissingBinaries( l )
+            }
+        }
+        
         log.info( 'Found {} POM files. Looking for problems...', poms.size() )
         validate()
         
@@ -147,6 +165,10 @@
             }
             return
         }
+        
+        if( !file.exists() ) {
+            return
+        }
 
         try {
             log.debug( 'Loading {}', file.absolutePath )
@@ -192,7 +214,7 @@
         } else if( 'E' == code[0] ) {
             e = Error.fromCode( code )
         } else {
-            throw new RuntimeException( "Unsupported code ${code}" )
+            throw new RuntimeException( "Unsupported enum ${code}" )
         }
         
         def problem
@@ -218,6 +240,14 @@
             problem = BinaryDifference.create( node )
             break
             
+        case Warning.SEVERAL_VERSIONS:
+            problem = SeveralVersionsProblem.create( node )
+            break
+            
+        case Warning.MISSING_BINARY_BUNDLE_FOR_SOURCES:
+            missingBinaries << node.'@path'.toString()
+            return
+            
         default:
             log.warn( "Unsupported code ${code} ${e}" )
             return 
@@ -743,6 +773,23 @@
     }
 }
 
+class SeveralVersionsProblem extends CommandProblem {
+    
+    static SeveralVersionsProblem create( node ) {
+        
+        String shortKey = node.'@shortKey'
+        String usedVersion = node.'@usedVersion'
+        String versions = node.'@versions'
+        String key = "${shortKey} ${usedVersion}"
+            
+        String message = "The artifact ${shortKey} exists with several versions: ${versions}. Used ${usedVersion}"
+            
+        def result = new SeveralVersionsProblem( key: key, message: message )
+        
+        return result
+    }
+}
+
 class MissingManifest extends CommandProblem {
     
     String jar
@@ -862,6 +909,56 @@
     }
 }
 
+class MissingBinaries extends Problem {
+    
+    List<String> artifacts
+    
+    MissingBinaries( List<String> artifacts ) {
+        super( null, "${artifacts.size()} source artifact are without compiled code" )
+        
+        this.artifacts = artifacts
+    }
+    
+    @Override
+    public String sortKey() {
+        return "MissingBinaries";
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder buffer = new StringBuilder()
+        buffer << message
+        buffer << ':\n'
+        
+        artifacts.each() {
+            buffer << "    ${it}\n"
+        }
+        
+        return buffer;
+
+        return message
+    }
+    
+    void render( MarkupBuilder builder ) {
+        builder.div( 'class': 'problem' ) {
+            p "Missing code artifact for ${artifacts.size()} source artifact"
+            ul {
+                for( String path in artifacts ) {
+                    li {
+                        String name = path.substringAfterLast( '/' )
+                        span( 'class': 'ignoreKey', 'MissingBinary ' + name )
+                        div( 'class': 'path', path )
+                    }
+                }
+            }
+        }
+    }
+    
+    int problemCount() {
+        return artifacts.size()
+    }
+}
+
 class PathProblem extends Problem {
     
     File expected
@@ -1165,8 +1262,10 @@
     ProblemSnaphotVersion( 'Snapshot Versions', 'Release Repositories should not contain SNAPSHOTs' ),
     PathProblem( 'Path Problems', 'These POMs are not where they should be' ),
     TwoVersionsProblem( 'Artifacts With Several Versions', null, Error.TWO_VERSIONS.url() ),
+    SeveralVersionsProblem( 'Artifacts With Several Versions', null, Warning.SEVERAL_VERSIONS.url() ),
     MultipleNestedJarsProblem( 'Multiple Nested JARs', "At the moment, MT4E can only handle a single nested JAR", Warning.MULTIPLE_NESTED_JARS.url() ),
-    MissingSources( 'Missing Sources' )
+    MissingSources( 'Missing Sources' ),
+    MissingBinaries( 'Missing Binary for Sources', null, Warning.MISSING_BINARY_BUNDLE_FOR_SOURCES.url() )
     
     final String title
     final String description
diff --git a/src/main/groovy/m4e/DependencyManagementCmd.groovy b/src/main/groovy/m4e/DependencyManagementCmd.groovy
index 57ce487..b862a69 100644
--- a/src/main/groovy/m4e/DependencyManagementCmd.groovy
+++ b/src/main/groovy/m4e/DependencyManagementCmd.groovy
@@ -62,8 +62,7 @@
     }
     
     /** short key -> version */
-    Map<String, String> versions = [:]
-    Set<String> duplicates = []
+    Map<String, List<String>> versions = [:].withDefault {[]}
     
     void collectArtifacts() {
         MavenRepositoryTools.eachPom( repo ) {
@@ -81,29 +80,8 @@
         String version = pom.version()
 
         String key = "${groupId}:${artifactId}"
-        if( key in duplicates ) {
-            return
-        }
 
-        String old = versions.put( key, version )
-        if( null != old ) {
-            duplicates << key
-            versions.remove( key )
-            twoVersionsError( pom, old )
-        }
-    }
-
-    void twoVersionsError( Pom pom, String oldVersion ) {
-        
-        def versions = VersionUtils.sort( [ pom.version(), oldVersion ] )
-        
-        def xml = [
-            artifact: pom.key(),
-            shortKey: pom.shortKey(),
-            version1: versions[0],
-            version2: versions[1],
-        ]
-        error( Error.TWO_VERSIONS, "The repository contains (at least) two versions of ${pom.shortKey()}: ${versions[0]} and ${versions[1]}. Omitting both.", xml )
+        versions.get( key ) << version
     }
 
     void createPom() {
@@ -147,14 +125,34 @@
 
         for( String key : keys ) {
             String[] parts = key.split( ':', -1 )
+            List<String> versionList = versions[key]
+            versionList = VersionUtils.sort( versionList )
+            String version = versionList[-1]
+            
+            if( versionList.size() > 1 ) {
+                severalVersions( key, versionList, version )
+            }
 
             writer << """\
             <dependency>
                 <groupId>${parts[0]}</groupId>
                 <artifactId>${parts[1]}</artifactId>
-                <version>${versions[key]}</version>
+                <version>${version}</version>
             </dependency>
 """
         }
     }
+
+    void severalVersions( String key, List<String> versionList, String used ) {
+        
+        String[] parts = key.split( ':', -1 )
+        
+        def xml = [
+            artifact: parts[0],
+            shortKey: parts[1],
+            usedVersion: used,
+            versions: versionList.join( ',' ),
+        ]
+        warn( Warning.SEVERAL_VERSIONS, "The repository contains ${versionList.size()} versions of ${key}: ${versionList.join( ', ' )}. Using ${used}", xml )
+    }
 }
diff --git a/src/main/groovy/m4e/InstallCmd.groovy b/src/main/groovy/m4e/InstallCmd.groovy
index a04a7b9..bea88ed 100644
--- a/src/main/groovy/m4e/InstallCmd.groovy
+++ b/src/main/groovy/m4e/InstallCmd.groovy
@@ -328,7 +328,8 @@
                     parent.usefulDelete()
                 }
             } else {
-                installCmd.warn( Warning.MISSING_BINARY_BUNDLE_FOR_SOURCES, "No binary bundle for ${sourceJar.absolutePath}" )
+                String path = sourceJar.absolutePath
+                installCmd.warn( Warning.MISSING_BINARY_BUNDLE_FOR_SOURCES, "No binary bundle for ${path}", [ path: path ] )
             }
         }
     }
diff --git a/src/main/groovy/m4e/Warning.java b/src/main/groovy/m4e/Warning.java
index 32bd119..fc75677 100644
--- a/src/main/groovy/m4e/Warning.java
+++ b/src/main/groovy/m4e/Warning.java
@@ -20,7 +20,8 @@
     BINARY_DIFFERENCE( 3 ),
     MULTIPLE_NESTED_JARS( 4 ),
     UNABLE_TO_MERGE_MT4E_FILE( 5 ),
-    DUPLICATE_VERSION_MAPPING( 6 );
+    DUPLICATE_VERSION_MAPPING( 6 ),
+    SEVERAL_VERSIONS( 7 );
     
     public final static String BASE_URL = "http://wiki.eclipse.org/MT4E_";
     
diff --git a/src/test/groovy/m4e/DependencyManagementCmdTest.groovy b/src/test/groovy/m4e/DependencyManagementCmdTest.groovy
index bc5996f..9f53fef 100644
--- a/src/test/groovy/m4e/DependencyManagementCmdTest.groovy
+++ b/src/test/groovy/m4e/DependencyManagementCmdTest.groovy
@@ -25,7 +25,7 @@
         DependencyManagementCmd tool = new DependencyManagementCmd()
         
         List<String> errors = []
-        def log = [ error: { errors << it }, info: {} ] as Logger
+        def log = [ error: { errors << it }, info: {}, warn: { errors << it } ] as Logger
         tool.log = log
         
         tool.run([ 'dm', copy.path, 'org.eclipse.dash:dependency-management:3.7.0' ])
@@ -45,11 +45,11 @@
         actual = actual.replace( '3.5.0 and 3.6.0.', '3.6.0 and 3.5.0.' )
         
         assertEquals( '''\
-The repository contains (at least) two versions of org.eclipse.core:org.eclipse.core.runtime: 3.5.0 and 3.6.0. Omitting both.
-For details, see http://wiki.eclipse.org/MT4E_E0001'''
+The repository contains 2 versions of org.eclipse.core:org.eclipse.core.runtime: 3.5.0, 3.6.0. Using 3.6.0
+For details, see http://wiki.eclipse.org/MT4E_W0007'''
             , errors.join( '\n' ) )
         
-        assertEquals( 1, tool.errorCount )
-        assertEquals( 0, tool.warningCount )
+        assertEquals( 0, tool.errorCount )
+        assertEquals( 1, tool.warningCount )
     }
 }