Skip to content

Commit

Permalink
[APITools] Handle multiple version correct when obtaining prerequisites
Browse files Browse the repository at this point in the history
ApiBaseline.getPrerequisiteComponents() didn't consider multiple
versions of a component.
Besides fixing that, this also unifies and simplifies the handling of
multiple versions.
  • Loading branch information
HannesWell committed Jul 13, 2024
1 parent 8bc60ea commit 770c2a2
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
Expand Down Expand Up @@ -381,14 +380,14 @@ private Document getProfileXML(IApiBaseline baseline) throws CoreException {
Element celement = null;
IApiComponent[] components = baseline.getApiComponents();
for (IApiComponent component : components) {
Set<IApiComponent> allComponentSet = new HashSet<>();
Set<IApiComponent> allComponentSet;
// if the baseline has multiple versions, persist all versions
Set<IApiComponent> multipleComponents = baseline.getAllApiComponents(component.getSymbolicName());
if (multipleComponents.isEmpty()) {
// no multiple version - add the current component
allComponentSet.add(component);
allComponentSet = Set.of(component);
} else {
allComponentSet.addAll(multipleComponents);
allComponentSet = multipleComponents;
}
for (IApiComponent iApiComponent : allComponentSet) {
if (!iApiComponent.isSystemComponent()) {
Expand All @@ -399,8 +398,6 @@ private Document getProfileXML(IApiBaseline baseline) throws CoreException {
root.appendChild(celement);
}
}
// clear the temporary hashset
allComponentSet.clear();
}
return document;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -894,22 +894,9 @@ void buildAll(IApiBaseline baseline, IApiBaseline wbaseline, IProgressMonitor mo
localMonitor.subTask(NLS.bind(BuilderMessages.building_workspace_profile, currentproject.getName()));
localMonitor.split(1);
String id = currentModel.getBundleDescription().getSymbolicName();
Version version = currentModel.getBundleDescription().getVersion();
// Compatibility checks
IApiComponent apiComponent = wbaseline.getApiComponent(id);
Set<IApiComponent> apiComponentMultiple = wbaseline.getAllApiComponents(id);
if (!apiComponentMultiple.isEmpty()) {
// add the exact match
for (IApiComponent iApiComponent : apiComponentMultiple) {
Version workspaceBaselineVersion = new Version(iApiComponent.getVersion());// removes
// qualifier
Version currentProjectVersion = currentModel.getBundleDescription().getVersion();
if (new Version(currentProjectVersion.getMajor(), currentProjectVersion.getMinor(),
currentProjectVersion.getMicro()).compareTo(workspaceBaselineVersion) == 0) {
apiComponent = iApiComponent;
break;
}
}
}
IApiComponent apiComponent = wbaseline.getApiComponent(id, version);
if (apiComponent != null) {
if (getAnalyzer() instanceof BaseApiAnalyzer) {
((BaseApiAnalyzer) getAnalyzer()).checkBaselineMismatch(baseline, wbaseline);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,20 +263,8 @@ void build(final IProject project, final IApiBaseline baseline, final IApiBaseli
IPluginModelBase currentModel = this.builder.getCurrentModel();
if (currentModel != null) {
String id = currentModel.getBundleDescription().getSymbolicName();
IApiComponent comp = wbaseline.getApiComponent(id);
Set<IApiComponent> apiComponentMultiple = wbaseline.getAllApiComponents(id);
if (!apiComponentMultiple.isEmpty()) {
// add the exact match
for (IApiComponent iApiComponent : apiComponentMultiple) {
Version workspaceBaselineVersion = new Version(iApiComponent.getVersion());// removes
// qualifier
Version currentProjectVersion = currentModel.getBundleDescription().getVersion();
if (new Version(currentProjectVersion.getMajor(), currentProjectVersion.getMinor(), currentProjectVersion.getMicro()).compareTo(workspaceBaselineVersion) == 0) {
comp = iApiComponent;
break;
}
}
}
Version version = currentModel.getBundleDescription().getVersion();
IApiComponent comp = wbaseline.getApiComponent(id, version);
if (comp == null) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,34 +323,27 @@ protected void addComponent(IApiComponent component) {
return;
}

IApiComponent comp = fComponentsById.get(component.getSymbolicName());

IApiComponent comp = fComponentsById.put(component.getSymbolicName(), component);
// if more than 1 components, store all of them
if (comp != null) {
if (fAllComponentsById.containsKey(component.getSymbolicName())) {
Set<IApiComponent> allComponents = fAllComponentsById.get(component.getSymbolicName());
if (!allComponents.contains(component)) {
allComponents.add(component);
}
} else {
TreeSet<IApiComponent> allComponents = new TreeSet<>(
(comp1, comp2) -> {
if (comp2.getVersion().equals(comp1.getVersion())) {
if (comp2.getVersion().contains("JavaSE")) { //$NON-NLS-1$
ApiPlugin.logInfoMessage("Multiple locations for the same Java = " //$NON-NLS-1$
+ comp1.getLocation() + comp2.getLocation());
Set<IApiComponent> allComponents = fAllComponentsById.computeIfAbsent(component.getSymbolicName(),
name -> new TreeSet<>((comp1, comp2) -> {
String version2 = comp2.getVersion();
String version1 = comp1.getVersion();
if (version2.equals(version1)) {
if (version2.contains("JavaSE")) { //$NON-NLS-1$
ApiPlugin.logInfoMessage("Multiple locations for the same Java = " + comp1.getLocation() //$NON-NLS-1$
+ comp2.getLocation());
}
return 0;
}
return 0;
}
return new Version(comp2.getVersion()).compareTo(new Version(comp1.getVersion()));
});
return new Version(version2).compareTo(new Version(version1));
}));
if (allComponents.isEmpty()) {
allComponents.add(comp);
allComponents.add(component);
fAllComponentsById.put(component.getSymbolicName(), allComponents);
}
allComponents.add(component);
}

fComponentsById.put(component.getSymbolicName(), component);
if (component instanceof ProjectComponent projectApiComponent) {
fComponentsByProjectNames.put(projectApiComponent.getJavaProject().getProject().getName(), component);
}
Expand Down Expand Up @@ -670,6 +663,25 @@ public IApiComponent getApiComponent(String id) {
return fComponentsById.get(id);
}

@Override
public IApiComponent getApiComponent(String id, Version version) {
loadBaselineInfos();
if (disposed) {
return null;
}
IApiComponent component = fComponentsById.get(id);
if (hasSameMMMVersion(version, component)) {
return component;
}
Set<IApiComponent> allComponents = fAllComponentsById.get(id);
return allComponents.stream().filter(c -> hasSameMMMVersion(version, c)).findFirst().orElse(null);
}

private static boolean hasSameMMMVersion(Version ref, IApiComponent component) {
Version v = new Version(component.getVersion());
return ref.getMajor() == v.getMajor() && ref.getMinor() == v.getMinor() && ref.getMicro() == v.getMicro();
}

@Override
public Set<IApiComponent> getAllApiComponents(String id) {
loadBaselineInfos();
Expand Down Expand Up @@ -859,9 +871,11 @@ public IApiComponent[] getPrerequisiteComponents(IApiComponent[] components) thr
}
}
Collection<BundleDescription> dependencies = BuildDependencyCollector.collectBuildRelevantDependencies(bundles);
return dependencies.stream().map(BundleDescription::getSymbolicName) //
.map(id -> getApiComponent(id)).filter(Objects::nonNull) //
.toArray(IApiComponent[]::new);
return dependencies.stream().map(bundle -> {
String id = bundle.getSymbolicName();
Version version = bundle.getVersion();
return getApiComponent(id, version);
}).filter(Objects::nonNull).toArray(IApiComponent[]::new);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.osgi.framework.Version;

/**
* A collection of related API components that together make up an
Expand Down Expand Up @@ -78,6 +79,15 @@ public interface IApiBaseline extends IApiElement {
*/
public IApiComponent getApiComponent(String id);

/**
* Returns the API component in this baseline with the given symbolic name and
* version or <code>null</code> if none.
*
* @param id component symbolic name
* @return API component or <code>null</code>
*/
public IApiComponent getApiComponent(String id, Version version);

/**
* Returns all the API components in this baseline (sorted from higher to
* lower version) with the given symbolic name or empty set if multiple
Expand Down

0 comments on commit 770c2a2

Please sign in to comment.