1 /******************************************************************************* 2 * Copyright (c) 2009, 2013 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.pde.api.tools.internal.search; 15 16 import java.util.TreeSet; 17 18 import org.eclipse.osgi.service.resolver.BundleDescription; 19 import org.eclipse.osgi.service.resolver.ResolverError; 20 import org.eclipse.osgi.service.resolver.VersionConstraint; 21 import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent; 22 import org.eclipse.pde.api.tools.internal.provisional.model.IApiElement; 23 24 public class SkippedComponent implements IApiElement { 25 /** 26 * the id of of the skipped component 27 */ 28 private String componentid; 29 /** 30 * The version of the component 31 */ 32 private String version; 33 /** 34 * the set of resolution errors barring the component from being scanned 35 */ 36 private ResolverError[] errors = null; 37 38 /** 39 * Constructor 40 * 41 * @param componentid 42 * @param version 43 * @param errors the {@link ResolverError}s, if any, that prevented this 44 * component from being scanned 45 */ SkippedComponent(String componentid, String version, ResolverError[] errors)46 public SkippedComponent(String componentid, String version, ResolverError[] errors) { 47 this.componentid = componentid; 48 this.version = version; 49 this.errors = errors; 50 } 51 52 @Override equals(Object obj)53 public boolean equals(Object obj) { 54 if (obj instanceof SkippedComponent) { 55 return this.componentid.equals(((SkippedComponent) obj).componentid); 56 } 57 return false; 58 } 59 60 @Override hashCode()61 public int hashCode() { 62 return this.componentid.hashCode(); 63 } 64 65 /** 66 * @return the component id of the skipped component 67 */ getComponentId()68 public String getComponentId() { 69 return this.componentid; 70 } 71 72 /** 73 * @return true if the component was skipped because it appeared in an 74 * exclude list 75 */ wasExcluded()76 public boolean wasExcluded() { 77 return this.errors == null; 78 } 79 80 /** 81 * @return true if the the component had resolution errors 82 */ hasResolutionErrors()83 public boolean hasResolutionErrors() { 84 return this.errors != null; 85 } 86 87 /** 88 * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiElement#getAncestor(int) 89 */ 90 @Override getAncestor(int ancestorType)91 public IApiElement getAncestor(int ancestorType) { 92 return null; 93 } 94 95 /** 96 * @return the version 97 */ getVersion()98 public String getVersion() { 99 return this.version; 100 } 101 102 /** 103 * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiElement#getApiComponent() 104 */ 105 @Override getApiComponent()106 public IApiComponent getApiComponent() { 107 return null; 108 } 109 110 /** 111 * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiElement#getName() 112 */ 113 @Override getName()114 public String getName() { 115 return this.componentid; 116 } 117 118 /** 119 * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiElement#getParent() 120 */ 121 @Override getParent()122 public IApiElement getParent() { 123 return null; 124 } 125 126 /** 127 * @see org.eclipse.pde.api.tools.internal.provisional.model.IApiElement#getType() 128 */ 129 @Override getType()130 public int getType() { 131 return IApiElement.COMPONENT; 132 } 133 134 /** 135 * @return the errors 136 */ getErrors()137 public ResolverError[] getErrors() { 138 return this.errors; 139 } 140 141 /** 142 * Resolves the root errors for the given set of errors 143 * 144 * @param rerrors 145 * @param collector 146 * @return the resolved leaf set of problem messages 147 */ resolveRootErrors(ResolverError[] rerrors)148 private String[] resolveRootErrors(ResolverError[] rerrors) { 149 TreeSet<String> collector = new TreeSet<>((o1, o2) -> (o1).compareTo(o2)); 150 ResolverError error = null; 151 VersionConstraint[] constraints = null; 152 BundleDescription[] bundle = new BundleDescription[1]; 153 for (ResolverError rerror : rerrors) { 154 error = rerror; 155 if (error.getType() != ResolverError.MISSING_REQUIRE_BUNDLE) { 156 collector.add(error.toString()); 157 } 158 bundle[0] = error.getBundle(); 159 constraints = bundle[0].getContainingState().getStateHelper().getUnsatisfiedLeaves(bundle); 160 if (constraints.length == 0) { 161 collector.add(error.toString()); 162 } 163 for (VersionConstraint constraint : constraints) { 164 collector.add(constraint.toString()); 165 } 166 } 167 return collector.toArray(new String[collector.size()]); 168 } 169 170 /** 171 * @return the formatted details of why the component was skipped 172 */ getErrorDetails()173 public String getErrorDetails() { 174 if (this.errors != null) { 175 StringBuilder buffer = new StringBuilder(); 176 String[] problems = resolveRootErrors(this.errors); 177 for (String problem : problems) { 178 buffer.append(problem).append("<br/>"); //$NON-NLS-1$ 179 } 180 return buffer.toString(); 181 } 182 return SearchMessages.SkippedComponent_component_was_excluded; 183 } 184 }