[566026] The version builder produces errors when a project has multiple
products

https://bugs.eclipse.org/bugs/show_bug.cgi?id=566026
diff --git a/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/Element.java b/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/Element.java
index b8adaa3..867b958 100644
--- a/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/Element.java
+++ b/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/Element.java
@@ -33,6 +33,8 @@
 
   private final String name;
 
+  private final String id;
+
   private Version version;
 
   private final boolean fragment;
@@ -43,34 +45,36 @@
 
   private Set<IElement> allChildren;
 
-  public Element(Element.Type type, String name, Version version)
+  public Element(Element.Type type, String name, String id, Version version)
   {
-    this(type, name, version, false);
+    this(type, name, id, version, false);
   }
 
-  public Element(Element.Type type, String name, Version version, boolean fragment)
+  public Element(Element.Type type, String name, String id, Version version, boolean fragment)
   {
     this.type = type;
     this.name = name;
+    this.id = id;
     this.fragment = fragment;
     this.version = VersionUtil.normalize(version);
   }
 
-  public Element(Element.Type type, String name, String version)
+  public Element(Element.Type type, String name, String id, String version)
   {
-    this(type, name, version, false);
+    this(type, name, id, version, false);
   }
 
-  public Element(Element.Type type, String name, String version, boolean fragment)
+  public Element(Element.Type type, String name, String id, String version, boolean fragment)
   {
-    this(type, name, new Version(version), fragment);
+    this(type, name, id, new Version(version), fragment);
   }
 
-  public Element(Type type, String name, boolean fragment)
+  public Element(Type type, String name, String id, boolean fragment)
   {
     this.type = type;
     this.name = name;
     this.fragment = fragment;
+    this.id = id;
     version = Version.emptyVersion;
   }
 
@@ -89,6 +93,11 @@
     return name;
   }
 
+  public String getID()
+  {
+    return id;
+  }
+
   public Version getVersion()
   {
     return version;
@@ -190,6 +199,7 @@
   {
     return "Element[type=" + type + //$NON-NLS-1$
         ", name=" + name + //$NON-NLS-1$
+        (id == null ? "" : ", id=" + id) + //$NON-NLS-1$ //$NON-NLS-2$
         (licenseFeature ? ", licenseFeature=true" : "") + //$NON-NLS-1$ //$NON-NLS-2$
         (fragment ? ", fragment=true" : "") + //$NON-NLS-1$ //$NON-NLS-2$
         ", version=" //$NON-NLS-1$
@@ -203,6 +213,7 @@
     int result = 1;
     result = prime * result + (name == null ? 0 : name.hashCode());
     result = prime * result + (getType() == null ? 0 : getType().hashCode());
+    result = prime * result + (id == null ? 0 : id.hashCode());
     return result;
   }
 
@@ -237,6 +248,18 @@
       return false;
     }
 
+    if (id == null)
+    {
+      if (other.id != null)
+      {
+        return false;
+      }
+    }
+    else if (!id.equals(other.id))
+    {
+      return false;
+    }
+
     if (getType() != other.getType())
     {
       return false;
@@ -255,7 +278,7 @@
 
   public IElement trimVersion()
   {
-    Element element = new Element(type, name, fragment);
+    Element element = new Element(type, name, id, fragment);
     if (isLicenseFeature())
     {
       element.setLicenseFeature(true);
diff --git a/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/Release.java b/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/Release.java
index 34f7a34..214079e 100644
--- a/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/Release.java
+++ b/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/Release.java
@@ -56,6 +56,8 @@
 
   public static final String NAME_ATTRIBUTE = "name"; //$NON-NLS-1$
 
+  public static final String ID_ATTRIBUTE = "id"; //$NON-NLS-1$
+
   public static final String VERSION_ATTRIBUTE = "version"; //$NON-NLS-1$
 
   public static final String FRAGMENT_ATTRIBUTE = "fragment"; //$NON-NLS-1$
@@ -183,9 +185,12 @@
     String name = element.getName();
     Version version = element.getVersion();
 
-    builder
-        .append(indent + "<" + element.getTag() + " " + NAME_ATTRIBUTE + "=\"" + name + "\" " + (element.isFragment() ? FRAGMENT_ATTRIBUTE + "=\"true\" " : "") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
-            + VERSION_ATTRIBUTE + "=\"" + version + "\"" + (element.isLicenseFeature() ? " license=\"true\"" : "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+    builder.append(indent + "<" + element.getTag() + " " + // //$NON-NLS-1$ //$NON-NLS-2$
+        NAME_ATTRIBUTE + "=\"" + name + "\" " + // //$NON-NLS-1$ //$NON-NLS-2$
+        (element.isFragment() ? FRAGMENT_ATTRIBUTE + "=\"true\" " : "") + // //$NON-NLS-1$ //$NON-NLS-2$
+        (element.getID() != null ? ID_ATTRIBUTE + "=\"" + element.getID() + "\" " : "") + // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        VERSION_ATTRIBUTE + "=\"" + version + "\"" + // //$NON-NLS-1$ //$NON-NLS-2$
+        (element.isLicenseFeature() ? " license=\"true\"" : "")); //$NON-NLS-1$ //$NON-NLS-2$
 
     List<IElement> content = element.getChildren();
     if (content.isEmpty())
@@ -301,9 +306,10 @@
     private IElement createElement(IElement.Type type, Attributes attributes) throws SAXException
     {
       String name = getString(attributes, NAME_ATTRIBUTE);
+      String id = getString(attributes, ID_ATTRIBUTE);
       Version version = new Version(getString(attributes, VERSION_ATTRIBUTE));
       boolean isFragment = "true".equals(getString(attributes, FRAGMENT_ATTRIBUTE)); //$NON-NLS-1$
-      Element element = new Element(type, name, version, isFragment);
+      Element element = new Element(type, name, id, version, isFragment);
 
       String license = getString(attributes, LICENSE_ATTRIBUTE);
       if ("true".equals(license)) //$NON-NLS-1$
@@ -326,7 +332,7 @@
     private String getString(Attributes attributes, String name) throws SAXException
     {
       String value = attributes.getValue(name);
-      if (value != null || LICENSE_ATTRIBUTE.equals(name) || FRAGMENT_ATTRIBUTE.equals(name))
+      if (value != null || LICENSE_ATTRIBUTE.equals(name) || FRAGMENT_ATTRIBUTE.equals(name) || ID_ATTRIBUTE.equals(name))
       {
         return value;
       }
diff --git a/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/ReleaseManager.java b/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/ReleaseManager.java
index b34f686..4ccbd23 100644
--- a/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/ReleaseManager.java
+++ b/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/ReleaseManager.java
@@ -202,7 +202,7 @@
 
       String name = description.getSymbolicName();
       Version version = description.getVersion();
-      return new Element(Type.PLUGIN, name, version, pluginModel instanceof IFragmentModel);
+      return new Element(Type.PLUGIN, name, null, version, pluginModel instanceof IFragmentModel);
     }
 
     if (componentModel instanceof org.eclipse.pde.internal.core.ifeature.IFeatureModel)
@@ -222,7 +222,7 @@
     String name = feature.getId();
     String versionValue = feature.getVersion();
     Version version = new Version(StringUtil.isEmpty(versionValue) ? "1.0.0.qualifier" : versionValue); //$NON-NLS-1$
-    IElement element = new Element(Type.FEATURE, name, version);
+    IElement element = new Element(Type.FEATURE, name, null, version);
 
     if (withContent)
     {
@@ -231,7 +231,7 @@
       String licenseFeatureID = feature.getLicenseFeatureID();
       if (!StringUtil.isEmpty(licenseFeatureID))
       {
-        Element child = new Element(IElement.Type.FEATURE, licenseFeatureID, feature.getLicenseFeatureVersion());
+        Element child = new Element(IElement.Type.FEATURE, licenseFeatureID, null, feature.getLicenseFeatureVersion());
         if (resolve)
         {
           child.resolveVersion();
@@ -243,7 +243,7 @@
 
       for (org.eclipse.pde.internal.core.ifeature.IFeatureChild versionable : feature.getIncludedFeatures())
       {
-        Element child = new Element(IElement.Type.FEATURE, versionable.getId(), versionable.getVersion());
+        Element child = new Element(IElement.Type.FEATURE, versionable.getId(), null, versionable.getVersion());
         if (resolve)
         {
           child.resolveVersion();
@@ -254,7 +254,7 @@
 
       for (org.eclipse.pde.internal.core.ifeature.IFeaturePlugin versionable : feature.getPlugins())
       {
-        Element child = new Element(IElement.Type.PLUGIN, versionable.getId(), versionable.getVersion(), versionable.isFragment());
+        Element child = new Element(IElement.Type.PLUGIN, versionable.getId(), null, versionable.getVersion(), versionable.isFragment());
         if (resolve)
         {
           child.resolveVersion();
@@ -281,7 +281,7 @@
     String name = product.getId();
     String versionValue = product.getVersion();
     Version version = new Version(StringUtil.isEmpty(versionValue) ? "1.0.0.qualifier" : versionValue); //$NON-NLS-1$
-    IElement element = new Element(Type.PRODUCT, name, version);
+    IElement element = new Element(Type.PRODUCT, name, product.getProductId(), version);
     List<IElement> children = element.getChildren();
 
     for (org.eclipse.pde.internal.core.iproduct.IProductFeature versionable : product.getFeatures())
@@ -292,7 +292,7 @@
         featureVersion = "0.0.0"; //$NON-NLS-1$
       }
 
-      Element child = new Element(IElement.Type.FEATURE, versionable.getId(), featureVersion);
+      Element child = new Element(IElement.Type.FEATURE, versionable.getId(), null, featureVersion);
       if (resolve)
       {
         child.resolveVersion();
@@ -309,7 +309,7 @@
         pluginVersion = "0.0.0"; //$NON-NLS-1$
       }
 
-      Element child = new Element(IElement.Type.PLUGIN, versionable.getId(), pluginVersion, versionable.isFragment());
+      Element child = new Element(IElement.Type.PLUGIN, versionable.getId(), null, pluginVersion, versionable.isFragment());
       if (resolve)
       {
         child.resolveVersion();
diff --git a/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/VersionBuilder.java b/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/VersionBuilder.java
index 46948ed..4604e1c 100644
--- a/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/VersionBuilder.java
+++ b/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/internal/version/VersionBuilder.java
@@ -758,7 +758,7 @@
         {
           for (BundleDescription requiredBundleDescription : requiredBundles)
           {
-            IElement element = new Element(Type.PLUGIN, requiredBundleDescription.getSymbolicName(), false);
+            IElement element = new Element(Type.PLUGIN, requiredBundleDescription.getSymbolicName(), null, false);
             IProject childProject = getProject(element);
             if (childProject != null)
             {
@@ -1138,7 +1138,7 @@
     {
       Markers.deleteAllMarkers(file, Markers.MAVEN_POM_PROBLEM);
 
-      final String componentName = element.getName();
+      final String componentName = element.getID() == null ? element.getName() : element.getID();
       final String componentVersion = StringUtil.removeSuffix(element.getVersion().toString(), ".qualifier"); //$NON-NLS-1$
       final String componentType = element.getType().toString().toLowerCase();
 
@@ -1547,7 +1547,7 @@
           BundleDescription supplierBundle = supplier.getSupplier();
           if (supplierBundle != null)
           {
-            IElement element = resolveElement(new Element(Type.PLUGIN, supplierBundle.getName(), supplierBundle.getHost() != null));
+            IElement element = resolveElement(new Element(Type.PLUGIN, supplierBundle.getName(), null, supplierBundle.getHost() != null));
             if (element != null)
             {
               IModel componentModel = ReleaseManager.INSTANCE.getComponentModel(element.trimVersion());
diff --git a/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/version/IElement.java b/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/version/IElement.java
index 2fd02a2..4526daf 100644
--- a/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/version/IElement.java
+++ b/plugins/org.eclipse.oomph.version/src/org/eclipse/oomph/version/IElement.java
@@ -30,6 +30,8 @@
 
   public String getName();
 
+  public String getID();
+
   public Version getVersion();
 
   public Version getResolvedVersion();