diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2')
21 files changed, 1876 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/AbstractCatalogSource.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/AbstractCatalogSource.java new file mode 100644 index 000000000..49bc9d9de --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/AbstractCatalogSource.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery; + +import java.net.URL; + + +/** + * @author David Green + */ +public abstract class AbstractCatalogSource { + + private Policy policy = Policy.defaultPolicy(); + + /** + * an identifier that can be used to determine the origin of the source, typically for logging purposes. + */ + public abstract Object getId(); + + /** + * get a resource by an URL relative to the root of the source. + * + * @param relativeUrl + * the relative resource name + * @return an URL to the resource, or null if it is known that the resource does not exist. + */ + public abstract URL getResource(String resourceName); + + public Policy getPolicy() { + return policy; + } + + public void setPolicy(Policy policy) { + this.policy = policy; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/AbstractDiscoveryStrategy.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/AbstractDiscoveryStrategy.java new file mode 100644 index 000000000..6ea71cd57 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/AbstractDiscoveryStrategy.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery; + +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.equinox.internal.p2.discovery.model.CatalogCategory; +import org.eclipse.equinox.internal.p2.discovery.model.CatalogItem; +import org.eclipse.equinox.internal.p2.discovery.model.Certification; +import org.eclipse.equinox.internal.p2.discovery.model.Tag; + +/** + * An abstraction of a strategy for discovering connectors and categories. Strategy design pattern. Note that strategies + * are not reusable and must be disposed. + * + * @author David Green + * @author Steffen Pingel + */ +public abstract class AbstractDiscoveryStrategy { + + protected List<CatalogCategory> categories; + + protected List<Certification> certifications; + + protected List<CatalogItem> items; + + protected List<Tag> tags; + + public void dispose() { + } + + public List<CatalogCategory> getCategories() { + return categories; + } + + public List<Certification> getCertifications() { + return certifications; + } + + public List<CatalogItem> getItems() { + return items; + } + + public List<Tag> getTags() { + return tags; + } + + /** + * Perform discovery and add discovered items to {@link #getCategories() categories} and {@link #getItems()}. + */ + public abstract void performDiscovery(IProgressMonitor monitor) throws CoreException; + + public void setCategories(List<CatalogCategory> categories) { + this.categories = categories; + } + + public void setCertifications(List<Certification> certifications) { + this.certifications = certifications; + } + + public void setItems(List<CatalogItem> connectors) { + this.items = connectors; + } + + public void setTags(List<Tag> itemKinds) { + this.tags = itemKinds; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/Catalog.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/Catalog.java new file mode 100644 index 000000000..c95dad39c --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/Catalog.java @@ -0,0 +1,334 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IBundleGroup; +import org.eclipse.core.runtime.IBundleGroupProvider; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; +import org.eclipse.equinox.internal.p2.discovery.model.AbstractCatalogItem; +import org.eclipse.equinox.internal.p2.discovery.model.CatalogCategory; +import org.eclipse.equinox.internal.p2.discovery.model.CatalogItem; +import org.eclipse.equinox.internal.p2.discovery.model.Certification; +import org.eclipse.equinox.internal.p2.discovery.model.FeatureFilter; +import org.eclipse.equinox.internal.p2.discovery.model.Tag; +import org.eclipse.osgi.service.resolver.VersionRange; +import org.eclipse.osgi.util.NLS; +import org.osgi.framework.Bundle; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.Version; + +/** + * A means of discovering connectors. + * + * @author David Green + */ +public class Catalog { + + private List<CatalogItem> items = Collections.emptyList(); + + private List<CatalogCategory> categories = Collections.emptyList(); + + private List<Certification> certifications = Collections.emptyList(); + + private List<CatalogItem> filteredItems = Collections.emptyList(); + + private final List<AbstractDiscoveryStrategy> discoveryStrategies = new ArrayList<AbstractDiscoveryStrategy>(); + + private List<Tag> tags = Collections.emptyList(); + + private Dictionary<Object, Object> environment = System.getProperties(); + + private boolean verifyUpdateSiteAvailability = false; + + private Map<String, Version> featureToVersion = null; + + public Catalog() { + } + + /** + * get the discovery strategies to use. + */ + public List<AbstractDiscoveryStrategy> getDiscoveryStrategies() { + return discoveryStrategies; + } + + /** + * Initialize this by performing discovery. Discovery may take a long time as it involves network access. + * PRECONDITION: must add at least one {@link #getDiscoveryStrategies() discovery strategy} prior to calling. + * + * @return + */ + public IStatus performDiscovery(IProgressMonitor monitor) { + MultiStatus status = new MultiStatus(DiscoveryCore.ID_PLUGIN, 0, + Messages.Catalog_Failed_to_discovery_all_Error, null); + if (discoveryStrategies.isEmpty()) { + throw new IllegalStateException(); + } + items = new ArrayList<CatalogItem>(); + filteredItems = new ArrayList<CatalogItem>(); + categories = new ArrayList<CatalogCategory>(); + certifications = new ArrayList<Certification>(); + + final int totalTicks = 100000; + final int discoveryTicks = totalTicks - (totalTicks / 10); + monitor.beginTask(Messages.Catalog_task_discovering_connectors, totalTicks); + try { + for (AbstractDiscoveryStrategy discoveryStrategy : discoveryStrategies) { + discoveryStrategy.setCategories(categories); + discoveryStrategy.setItems(items); + discoveryStrategy.setCertifications(certifications); + discoveryStrategy.setTags(tags); + try { + discoveryStrategy.performDiscovery(new SubProgressMonitor(monitor, discoveryTicks + / discoveryStrategies.size())); + } catch (CoreException e) { + status.add(new Status(IStatus.ERROR, DiscoveryCore.ID_PLUGIN, NLS.bind( + Messages.Catalog_Strategy_failed_Error, discoveryStrategy.getClass().getSimpleName()), e)); + } + } + + filterDescriptors(); + connectCategoriesToDescriptors(); + connectCertificationsToDescriptors(); + } finally { + monitor.done(); + } + return status; + } + + /** + * get the top-level categories + * + * @return the categories, or an empty list if there are none. + */ + public List<CatalogCategory> getCategories() { + return categories; + } + + /** + * get the connectors that were discovered and not filtered + * + * @return the connectors, or an empty list if there are none. + */ + public List<CatalogItem> getItems() { + return items; + } + + public List<Tag> getTags() { + return tags; + } + + /** + * get the connectors that were discovered but filtered + * + * @return the filtered connectors, or an empty list if there were none. + */ + public List<CatalogItem> getFilteredItems() { + return filteredItems; + } + + /** + * The environment used to resolve {@link AbstractCatalogItem#getPlatformFilter() platform filters}. Defaults to the + * current environment. + */ + public Dictionary<Object, Object> getEnvironment() { + return environment; + } + + /** + * The environment used to resolve {@link AbstractCatalogItem#getPlatformFilter() platform filters}. Defaults to the + * current environment. + */ + public void setEnvironment(Dictionary<Object, Object> environment) { + if (environment == null) { + throw new IllegalArgumentException(); + } + this.environment = environment; + } + + /** + * indicate if update site availability should be verified. The default is false. + * + * @see CatalogItem#getAvailable() + * @see #verifySiteAvailability(IProgressMonitor) + */ + public boolean isVerifyUpdateSiteAvailability() { + return verifyUpdateSiteAvailability; + } + + /** + * indicate if update site availability should be verified. The default is false. + * + * @see CatalogItem#getAvailable() + * @see #verifySiteAvailability(IProgressMonitor) + */ + public void setVerifyUpdateSiteAvailability(boolean verifyUpdateSiteAvailability) { + this.verifyUpdateSiteAvailability = verifyUpdateSiteAvailability; + } + + /** + * <em>not for general use: public for testing purposes only</em> A map of installed features to their version. Used + * to resolve {@link AbstractCatalogItem#getFeatureFilter() feature filters}. + */ + public Map<String, Version> getFeatureToVersion() { + return featureToVersion; + } + + /** + * <em>not for general use: public for testing purposes only</em> A map of installed features to their version. Used + * to resolve {@link AbstractCatalogItem#getFeatureFilter() feature filters}. + */ + public void setFeatureToVersion(Map<String, Version> featureToVersion) { + this.featureToVersion = featureToVersion; + } + + private void connectCertificationsToDescriptors() { + Map<String, Certification> idToCertification = new HashMap<String, Certification>(); + for (Certification certification : certifications) { + Certification previous = idToCertification.put(certification.getId(), certification); + if (previous != null) { + LogHelper.log(new Status(IStatus.ERROR, DiscoveryCore.ID_PLUGIN, NLS.bind( + "Duplicate certification id ''{0}'': declaring sources: {1}, {2}", //$NON-NLS-1$ + new Object[] { certification.getId(), certification.getSource().getId(), + previous.getSource().getId() }))); + } + } + + for (CatalogItem connector : items) { + if (connector.getCertificationId() != null) { + Certification certification = idToCertification.get(connector.getCertificationId()); + if (certification != null) { + connector.setCertification(certification); + } else { + LogHelper.log(new Status(IStatus.ERROR, DiscoveryCore.ID_PLUGIN, NLS.bind( + "Unknown category ''{0}'' referenced by connector ''{1}'' declared in {2}", new Object[] { //$NON-NLS-1$ + connector.getCertificationId(), connector.getId(), connector.getSource().getId() }))); + } + } + } + } + + private void connectCategoriesToDescriptors() { + Map<String, CatalogCategory> idToCategory = new HashMap<String, CatalogCategory>(); + for (CatalogCategory category : categories) { + CatalogCategory previous = idToCategory.put(category.getId(), category); + if (previous != null) { + LogHelper.log(new Status(IStatus.ERROR, DiscoveryCore.ID_PLUGIN, NLS.bind( + Messages.Catalog_duplicate_category_id, new Object[] { category.getId(), + category.getSource().getId(), previous.getSource().getId() }))); + } + } + + for (CatalogItem connector : items) { + CatalogCategory category = idToCategory.get(connector.getCategoryId()); + if (category != null) { + category.getItems().add(connector); + connector.setCategory(category); + } else { + LogHelper.log(new Status(IStatus.ERROR, DiscoveryCore.ID_PLUGIN, NLS.bind( + Messages.Catalog_bundle_references_unknown_category, new Object[] { connector.getCategoryId(), + connector.getId(), connector.getSource().getId() }))); + } + } + } + + /** + * eliminate any connectors whose {@link AbstractCatalogItem#getPlatformFilter() platform filters} don't match + */ + private void filterDescriptors() { + for (CatalogItem connector : new ArrayList<CatalogItem>(items)) { + if (connector.getPlatformFilter() != null && connector.getPlatformFilter().trim().length() > 0) { + boolean match = false; + try { + Filter filter = FrameworkUtil.createFilter(connector.getPlatformFilter()); + match = filter.match(environment); + } catch (InvalidSyntaxException e) { + LogHelper.log(new Status(IStatus.ERROR, DiscoveryCore.ID_PLUGIN, NLS.bind( + Messages.Catalog_illegal_filter_syntax, new Object[] { connector.getPlatformFilter(), + connector.getId(), connector.getSource().getId() }))); + } + if (!match) { + items.remove(connector); + filteredItems.add(connector); + } + } + for (FeatureFilter featureFilter : connector.getFeatureFilter()) { + if (featureToVersion == null) { + featureToVersion = computeFeatureToVersion(); + } + boolean match = false; + Version version = featureToVersion.get(featureFilter.getFeatureId()); + if (version != null) { + VersionRange versionRange = new VersionRange(featureFilter.getVersion()); + if (versionRange.isIncluded(version)) { + match = true; + } + } + if (!match) { + items.remove(connector); + filteredItems.add(connector); + break; + } + } + } + } + + private Map<String, Version> computeFeatureToVersion() { + Map<String, Version> featureToVersion = new HashMap<String, Version>(); + for (IBundleGroupProvider provider : Platform.getBundleGroupProviders()) { + for (IBundleGroup bundleGroup : provider.getBundleGroups()) { + for (Bundle bundle : bundleGroup.getBundles()) { + featureToVersion.put(bundle.getSymbolicName(), bundle.getVersion()); + } + } + } + return featureToVersion; + } + + public void dispose() { + for (final AbstractDiscoveryStrategy strategy : discoveryStrategies) { + SafeRunner.run(new ISafeRunnable() { + + public void run() throws Exception { + strategy.dispose(); + } + + public void handleException(Throwable exception) { + LogHelper.log(new Status(IStatus.ERROR, DiscoveryCore.ID_PLUGIN, + Messages.Catalog_exception_disposing + strategy.getClass().getName(), exception)); + } + }); + } + } + + public void setTags(List<Tag> tags) { + this.tags = new ArrayList<Tag>(tags); + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/DiscoveryCore.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/DiscoveryCore.java new file mode 100644 index 000000000..bcc6db461 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/DiscoveryCore.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.eclipse.core.runtime.IProduct; +import org.eclipse.core.runtime.Platform; + +/** + * @author David Green + */ +public abstract class DiscoveryCore { + + public static final String ID_PLUGIN = "org.eclipse.equinox.p2.discovery"; //$NON-NLS-1$ + + private DiscoveryCore() { + } + + public static Dictionary<Object, Object> createEnvironment() { + Dictionary<Object, Object> environment = new Hashtable<Object, Object>(System.getProperties()); + // add the installed Mylyn version to the environment so that we can + // have + // connectors that are filtered based on version of Mylyn + IProduct product = Platform.getProduct(); + if (product != null) { + environment.put("org.eclipse.product.id", product.getId()); //$NON-NLS-1$ + } + return environment; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/Messages.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/Messages.java new file mode 100644 index 000000000..a6bbe4fa4 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/Messages.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.discovery; + +import org.eclipse.osgi.util.NLS; + +/** + * @author David Green + */ +class Messages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.p2.discovery.messages"; //$NON-NLS-1$ + + public static String Catalog_bundle_references_unknown_category; + + public static String Catalog_duplicate_category_id; + + public static String Catalog_exception_disposing; + + public static String Catalog_Failed_to_discovery_all_Error; + + public static String Catalog_illegal_filter_syntax; + + public static String Catalog_Strategy_failed_Error; + + public static String Catalog_task_discovering_connectors; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/Policy.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/Policy.java new file mode 100644 index 000000000..63b3d64b1 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/Policy.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.discovery; + +/** + * A policy defines what is permitted. + * + * @author David Green + */ +public class Policy { + + /** + * Define system property <code>org.eclipse.mylyn.internal.discovery.core.model.Policy.permissive=true</code> to + * allow for categories to be permitted by anyone. For testing purposes. + */ + private static final boolean PERMISSIVE = Boolean.getBoolean(Policy.class.getName() + ".permissive"); //$NON-NLS-1$ + + private static final Policy DEFAULT = new Policy(false); + + private final boolean permitCategories; + + public Policy(boolean permitCategories) { + this.permitCategories = permitCategories; + } + + public boolean isPermitCategories() { + return permitCategories || PERMISSIVE; + } + + public static Policy defaultPolicy() { + return DEFAULT; + } +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/messages.properties b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/messages.properties new file mode 100644 index 000000000..c0f5d077a --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/messages.properties @@ -0,0 +1,17 @@ +############################################################################### +# Copyright (c) 2009 Tasktop Technologies and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Tasktop Technologies - initial API and implementation +############################################################################### +Catalog_bundle_references_unknown_category=Unknown category ''{0}'' referenced by connector ''{1}'' declared in {2} +Catalog_duplicate_category_id=Duplicate category id ''{0}'': declaring sources: {1}, {2} +Catalog_exception_disposing=exception disposing +Catalog_Failed_to_discovery_all_Error=Failed to discover all connectors. +Catalog_illegal_filter_syntax=Illegal filter syntax ''{0}'' in connector ''{1}'' declared in {2} +Catalog_Strategy_failed_Error={0} failed with an error +Catalog_task_discovering_connectors=Retrieving listing diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/AbstractCatalogItem.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/AbstractCatalogItem.java new file mode 100644 index 000000000..f70a962ad --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/AbstractCatalogItem.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.discovery.model; + +/** + * @author Steffen Pingel + */ +public class AbstractCatalogItem { + + private Object data; + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/CatalogCategory.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/CatalogCategory.java new file mode 100644 index 000000000..cf49711ea --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/CatalogCategory.java @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery.model; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.equinox.internal.p2.discovery.AbstractCatalogSource; + +/** + * @author David Green + */ +public class CatalogCategory extends AbstractCatalogItem { + + private AbstractCatalogSource source; + + private final List<CatalogItem> items = new ArrayList<CatalogItem>(); + + protected String id; + + protected String name; + + protected String description; + + protected String relevance; + + protected Icon icon; + + protected Overview overview; + + protected java.util.List<Group> group = new java.util.ArrayList<Group>(); + + public List<CatalogItem> getItems() { + return items; + } + + public AbstractCatalogSource getSource() { + return source; + } + + public void setSource(AbstractCatalogSource source) { + this.source = source; + } + + /** + * an id that uniquely identifies the category + */ + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + /** + * the name of the category, as it is displayed in the ui. + */ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + /** + * A description of the category + */ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + /** + * A relevance, which is a number from 0 to 100. Categories with higher relevance are displayed with preference in + * the UI. + */ + public String getRelevance() { + return relevance; + } + + public void setRelevance(String relevance) { + this.relevance = relevance; + } + + public Icon getIcon() { + return icon; + } + + public void setIcon(Icon icon) { + this.icon = icon; + } + + public Overview getOverview() { + return overview; + } + + public void setOverview(Overview overview) { + this.overview = overview; + } + + public java.util.List<Group> getGroup() { + return group; + } + + public void setGroup(java.util.List<Group> group) { + this.group = group; + } + + public void validate() throws ValidationException { + if (id == null || id.length() == 0) { + throw new ValidationException(Messages.CatalogCategory_must_specify_CatalogCategory_id); + } + if (name == null || name.length() == 0) { + throw new ValidationException(Messages.CatalogCategory_must_specify_CatalogCategory_name); + } + if (description == null || description.length() == 0) { + throw new ValidationException("Must specify connectorCategory/@description"); //$NON-NLS-1$ + } + if (icon != null) { + icon.validate(); + } + if (relevance != null) { + try { + int r = Integer.parseInt(relevance, 10); + if (r < 0 || r > 100) { + throw new NumberFormatException(); + } + } catch (NumberFormatException e) { + throw new ValidationException(Messages.CatalogCategory_CatalogCategory_relevance_invalid); + } + } + if (overview != null) { + overview.validate(); + } + for (Group groupItem : group) { + groupItem.validate(); + } + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/CatalogItem.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/CatalogItem.java new file mode 100644 index 000000000..a3738614e --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/CatalogItem.java @@ -0,0 +1,369 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery.model; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.net.MalformedURLException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.equinox.internal.p2.discovery.AbstractCatalogSource; + +/** + * @author David Green + */ +public class CatalogItem extends AbstractCatalogItem { + + private AbstractCatalogSource source; + + private CatalogCategory category; + + private boolean selected; + + private Boolean available; + + private Certification certification; + + private final PropertyChangeSupport changeSupport; + + private boolean installed; + + private Set<Tag> tags; + + protected String name; + + protected String provider; + + protected String license; + + protected String description; + + protected String siteUrl; + + protected String id; + + protected String categoryId; + + protected String platformFilter; + + protected String groupId; + + protected java.util.List<FeatureFilter> featureFilter = new java.util.ArrayList<FeatureFilter>(); + + protected java.util.List<String> installableUnits = new java.util.ArrayList<String>(); + + protected Icon icon; + + protected Overview overview; + + protected String certificationId; + + public CatalogItem() { + changeSupport = new PropertyChangeSupport(this); + } + + public CatalogCategory getCategory() { + return category; + } + + public void setCategory(CatalogCategory category) { + this.category = category; + } + + public AbstractCatalogSource getSource() { + return source; + } + + public void setSource(AbstractCatalogSource source) { + this.source = source; + } + + public Certification getCertification() { + return certification; + } + + public void setCertification(Certification certification) { + this.certification = certification; + } + + /** + * support selection + * + * @return true if the item is selected, otherwise false + */ + public boolean isSelected() { + return selected; + } + + /** + * support selection + * + * @param selected + * true if the item is selected, otherwise false + */ + public void setSelected(boolean selected) { + this.selected = selected; + } + + /** + * indicate if this connector is available + * + * @return true if available, false if not, or null if availability is unknown + */ + public Boolean getAvailable() { + return available; + } + + /** + * indicate if this connector is available + * + * @param available + * true if available, false if not, or null if availability is unknown + */ + public void setAvailable(Boolean available) { + if (available != this.available || (available != null && !available.equals(this.available))) { + Boolean previous = this.available; + this.available = available; + changeSupport.firePropertyChange("available", previous, this.available); //$NON-NLS-1$ + } + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + changeSupport.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + changeSupport.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + changeSupport.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + changeSupport.removePropertyChangeListener(propertyName, listener); + } + + /** + * the name of the connector including the name of the organization that produces the repository if appropriate, for + * example 'Mozilla Bugzilla'. + */ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + /** + * The name of the organization that supplies the connector. + */ + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } + + /** + * The short name of the license, for example 'EPL 1.0', 'GPL 2.0', or 'Commercial'. + */ + public String getLicense() { + return license; + } + + public void setLicense(String license) { + this.license = license; + } + + /** + * A description of the connector. Plug-ins should provide a description, especially if the description is not + * self-evident from the @name and + * + * @organization. + */ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + /** + * The URL of the update site containing the connector. + */ + public String getSiteUrl() { + return siteUrl; + } + + public void setSiteUrl(String siteUrl) { + this.siteUrl = siteUrl; + } + + /** + * The id of the feature that installs this connector + */ + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + /** + * the id of the connectorCategory in which this connector belongs + */ + public String getCategoryId() { + return categoryId; + } + + public void setCategoryId(String categoryId) { + this.categoryId = categoryId; + } + + public String getCertificationId() { + return certificationId; + } + + public void setCertificationId(String certificationId) { + this.certificationId = certificationId; + } + + /** + * E.g., "(& (osgi.os=macosx) (osgi.ws=carbon))" + */ + public String getPlatformFilter() { + return platformFilter; + } + + public void setPlatformFilter(String platformFilter) { + this.platformFilter = platformFilter; + } + + /** + * The id of the connectorCategory group. See group/@id for more details. + */ + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public java.util.List<FeatureFilter> getFeatureFilter() { + return featureFilter; + } + + public void setFeatureFilter(java.util.List<FeatureFilter> featureFilter) { + this.featureFilter = featureFilter; + } + + public Icon getIcon() { + return icon; + } + + public void setIcon(Icon icon) { + this.icon = icon; + } + + public Overview getOverview() { + return overview; + } + + public void setOverview(Overview overview) { + this.overview = overview; + } + + public void validate() throws ValidationException { + if (name == null || name.length() == 0) { + throw new ValidationException(Messages.CatalogItem_must_specify_CatalogItem_name); + } + if (provider == null || provider.length() == 0) { + throw new ValidationException(Messages.CatalogItem_must_specify_CatalogItem_provider); + } + if (license == null || license.length() == 0) { + throw new ValidationException(Messages.CatalogItem_must_specify_CatalogItem_license); + } + if (siteUrl == null || siteUrl.length() == 0) { + throw new ValidationException(Messages.CatalogItem_must_specify_CatalogItem_siteUrl); + } + try { + new java.net.URL(siteUrl); + } catch (MalformedURLException e) { + throw new ValidationException(Messages.CatalogItem_invalid_CatalogItem_siteUrl); + } + if (id == null || id.length() == 0) { + throw new ValidationException(Messages.CatalogItem_must_specify_CatalogItem_id); + } + if (categoryId == null || categoryId.length() == 0) { + throw new ValidationException(Messages.CatalogItem_must_specify_CatalogItem_categoryId); + } + for (FeatureFilter featureFilterItem : featureFilter) { + featureFilterItem.validate(); + } + if (icon != null) { + icon.validate(); + } + if (overview != null) { + overview.validate(); + } + } + + public java.util.List<String> getInstallableUnits() { + return installableUnits; + } + + public void setInstallableUnits(java.util.List<String> installableUnits) { + this.installableUnits = installableUnits; + } + + public boolean isInstalled() { + return installed; + } + + public void setInstalled(boolean installed) { + this.installed = installed; + } + + public Set<Tag> getTags() { + if (tags == null) { + return Collections.emptySet(); + } else { + return Collections.unmodifiableSet(tags); + } + } + + public boolean hasTag(Tag tag) { + return tags == null ? false : tags.contains(tag); + } + + public void addTag(Tag tag) { + if (tags == null) { + tags = new HashSet<Tag>(); + } + tags.add(tag); + } + + public boolean removeTag(Tag tag) { + if (tags == null) { + return false; + } + return tags.remove(tag); + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Certification.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Certification.java new file mode 100644 index 000000000..4122aa824 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Certification.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.discovery.model; + +import org.eclipse.equinox.internal.p2.discovery.AbstractCatalogSource; + +/** + * @author Steffen Pingel + */ +public class Certification { + + private AbstractCatalogSource source; + + protected String id; + + protected String name; + + protected String description; + + protected Icon icon; + + protected String url; + + public AbstractCatalogSource getSource() { + return source; + } + + public void setSource(AbstractCatalogSource source) { + this.source = source; + } + + /** + * an id that uniquely identifies the category + */ + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + /** + * the name of the category, as it is displayed in the ui. + */ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + /** + * A description of the category + */ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Icon getIcon() { + return icon; + } + + public void setIcon(Icon icon) { + this.icon = icon; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public void validate() throws ValidationException { + if (id == null || id.length() == 0) { + throw new ValidationException(Messages.CatalogCategory_must_specify_CatalogCategory_id); + } + if (name == null || name.length() == 0) { + throw new ValidationException(Messages.CatalogCategory_must_specify_CatalogCategory_name); + } + if (icon != null) { + icon.validate(); + } + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/FeatureFilter.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/FeatureFilter.java new file mode 100644 index 000000000..4e9d50b05 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/FeatureFilter.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery.model; + +/** + * A means of specifying that a feature must be present in order for the connectorDescriptor to be presented to the + * user. + * + * @author David Green + */ +public class FeatureFilter { + + protected String featureId; + + protected String version; + + protected CatalogItem item; + + public FeatureFilter() { + } + + /** + * The id of the feature to test + */ + public String getFeatureId() { + return featureId; + } + + public void setFeatureId(String featureId) { + this.featureId = featureId; + } + + /** + * A version specifier, specified in the same manner as version dependencies are specified in an OSGi manifest. For + * example: "[3.0,4.0)" + */ + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public CatalogItem getItem() { + return item; + } + + public void setItem(CatalogItem catalogItem) { + this.item = catalogItem; + } + + public void validate() throws ValidationException { + if (featureId == null || featureId.length() == 0) { + throw new ValidationException(Messages.FeatureFilter_must_specify_featureFilter_featureId); + } + if (version == null || version.length() == 0) { + throw new ValidationException(Messages.FeatureFilter_must_specify_featureFilter_version); + } + } +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Group.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Group.java new file mode 100644 index 000000000..d59aa8e38 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Group.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2009 Task top Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery.model; + +/** + * groups provide a way to anchor connectors in a grouping with other like entries. + * + * @author David Green + */ +public class Group { + + protected String id; + + protected CatalogCategory category; + + public Group() { + } + + /** + * An identifier that identifies the group. Must be unique for a particular connectorCategory. + */ + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public CatalogCategory getCategory() { + return category; + } + + public void setCategory(CatalogCategory category) { + this.category = category; + } + + public void validate() throws ValidationException { + if (id == null || id.length() == 0) { + throw new ValidationException(Messages.Group_must_specify_group_id); + } + } +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Icon.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Icon.java new file mode 100644 index 000000000..dc3edb6ff --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Icon.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery.model; + +/** + * @author David Green + */ +public class Icon { + + protected String image16; + + protected String image32; + + protected String image48; + + protected String image64; + + protected String image128; + + public Icon() { + } + + public String getImage16() { + return image16; + } + + public void setImage16(String image16) { + this.image16 = image16; + } + + public String getImage32() { + return image32; + } + + public void setImage32(String image32) { + this.image32 = image32; + } + + public String getImage48() { + return image48; + } + + public void setImage48(String image48) { + this.image48 = image48; + } + + public String getImage64() { + return image64; + } + + public void setImage64(String image64) { + this.image64 = image64; + } + + public String getImage128() { + return image128; + } + + public void setImage128(String image128) { + this.image128 = image128; + } + + public void validate() throws ValidationException { + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Messages.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Messages.java new file mode 100644 index 000000000..3446f4e04 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Messages.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.discovery.model; + +import org.eclipse.osgi.util.NLS; + +/** + * @author David Green + */ +class Messages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.p2.discovery.model.messages"; //$NON-NLS-1$ + + public static String CatalogCategory_CatalogCategory_relevance_invalid; + + public static String CatalogCategory_must_specify_CatalogCategory_id; + + public static String CatalogCategory_must_specify_CatalogCategory_name; + + public static String CatalogItem_invalid_CatalogItem_siteUrl; + + public static String CatalogItem_must_specify_CatalogItem_categoryId; + + public static String CatalogItem_must_specify_CatalogItem_id; + + public static String CatalogItem_must_specify_CatalogItem_license; + + public static String CatalogItem_must_specify_CatalogItem_name; + + public static String CatalogItem_must_specify_CatalogItem_provider; + + public static String CatalogItem_must_specify_CatalogItem_siteUrl; + + public static String FeatureFilter_must_specify_featureFilter_featureId; + + public static String FeatureFilter_must_specify_featureFilter_version; + + public static String Group_must_specify_group_id; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Overview.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Overview.java new file mode 100644 index 000000000..f1ab32c04 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Overview.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery.model; + +/** + * @author David Green + */ +public class Overview { + + protected String summary; + + protected String url; + + protected String screenshot; + + protected CatalogItem item; + + protected CatalogCategory category; + + public Overview() { + } + + /** + * A description providing detailed information about the item. Newlines can be used to format the text into + * multiple paragraphs if necessary. Text must fit into an area 320x240, otherwise it will be truncated in the UI. + * More lengthy descriptions can be provided on a web page if required, see @url. + */ + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + /** + * An URL that points to a web page with more information relevant to the connector or category. + */ + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + /** + * 320x240 PNG, JPEG or GIF + */ + public String getScreenshot() { + return screenshot; + } + + public void setScreenshot(String screenshot) { + this.screenshot = screenshot; + } + + public CatalogItem getItem() { + return item; + } + + public void setItem(CatalogItem item) { + this.item = item; + } + + public CatalogCategory getCategory() { + return category; + } + + public void setCategory(CatalogCategory category) { + this.category = category; + } + + public void validate() throws ValidationException { + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Tag.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Tag.java new file mode 100644 index 000000000..f4f1f8bc2 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/Tag.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.discovery.model; + +/** + * Provides means to tag items in the catalog. + * + * @author David Green + * @author Steffen Pingel + */ +public class Tag extends AbstractCatalogItem { + + private final Object classifier; + + private final String value; + + private final String label; + + public Tag(String value, String label) { + this(null, value, label); + } + + public Tag(Object tagClassifier, String value, String label) { + this.classifier = tagClassifier; + this.value = value; + this.label = label; + } + + /** + * the classifier, which places the tag in a logical category + * + * @return the classifier or null if this tag is not in any category + */ + public Object getTagClassifier() { + return classifier; + } + + /** + * Returns the value of the tag, not intended for display. + */ + public String getValue() { + return value; + } + + /** + * Returns a short user-visible value that is used by the user to identify the tag. + */ + public String getLabel() { + return label; + } + + @Override + public String toString() { + return "Tag [classifier=" + classifier + ", value=" + value + ", label=" + label + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } + + @Override + public int hashCode() { + // we don't include the label here + final int prime = 31; + int result = 1; + result = prime * result + ((classifier == null) ? 0 : classifier.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + // we don't consider the label when comparing equality + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Tag other = (Tag) obj; + if (classifier == null) { + if (other.classifier != null) { + return false; + } + } else if (!classifier.equals(other.classifier)) { + return false; + } + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/ValidationException.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/ValidationException.java new file mode 100644 index 000000000..189970cae --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/ValidationException.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery.model; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.equinox.internal.p2.discovery.DiscoveryCore; + +/** + * Indicate that a validation has occurred on the model. + * + * @author David Green + */ +public class ValidationException extends CoreException { + + private static final long serialVersionUID = -7542361242327905294L; + + public ValidationException(String message) { + super(new Status(IStatus.ERROR, DiscoveryCore.ID_PLUGIN, message)); + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/messages.properties b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/messages.properties new file mode 100644 index 000000000..8b0f42857 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/model/messages.properties @@ -0,0 +1,23 @@ +############################################################################### +# Copyright (c) 2009 Tasktop Technologies and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Tasktop Technologies - initial API and implementation +############################################################################### +CatalogCategory_CatalogCategory_relevance_invalid=connectorCategory/@relevance must be an integer >= 0 and <= 100 +CatalogCategory_must_specify_CatalogCategory_id=Must specify connectorCategory/@id +CatalogCategory_must_specify_CatalogCategory_name=Must specify connectorCategory/@name +CatalogItem_invalid_CatalogItem_siteUrl=Invalid connectorDescriptor/@siteUrl +CatalogItem_must_specify_CatalogItem_categoryId=Must specify connectorDescriptor/@categoryId +CatalogItem_must_specify_CatalogItem_id=Must specify connectorDescriptor/@id +CatalogItem_must_specify_CatalogItem_license=Must specify connectorDescriptor/@license +CatalogItem_must_specify_CatalogItem_name=Must specify connectorDescriptor/@name +CatalogItem_must_specify_CatalogItem_provider=Must specify connectorDescriptor/@provider +CatalogItem_must_specify_CatalogItem_siteUrl=Must specify connectorDescriptor/@siteUrl +FeatureFilter_must_specify_featureFilter_featureId=Must specify featureFilter/@featureId +FeatureFilter_must_specify_featureFilter_version=Must specify featureFilter/@version +Group_must_specify_group_id=Must specify group/@id diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/util/CatalogCategoryComparator.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/util/CatalogCategoryComparator.java new file mode 100644 index 000000000..14055bd39 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/util/CatalogCategoryComparator.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.discovery.util; + +import java.util.Comparator; + +import org.eclipse.equinox.internal.p2.discovery.model.CatalogCategory; + +/** + * A comparator that orders categories by relevance and name. + * + * @author David Green + * @author Steffen Pingel + */ +public class CatalogCategoryComparator implements Comparator<CatalogCategory> { + + public int compare(CatalogCategory o1, CatalogCategory o2) { + if (o1 == o2) { + return 0; + } + String r1 = o1.getRelevance(); + String r2 = o2.getRelevance(); + int i = 0; + if (r1 != null && r2 != null) { + // don't have to worry about format, since they were already validated + // note that higher relevance appears first, thus the reverse order of + // the comparison. + i = new Integer(r2).compareTo(new Integer(r1)); + } else if (r1 == null && r2 != null) { + return 1; + } else if (r2 == null && r1 != null) { + return -1; + } + if (i == 0) { + i = o1.getName().compareToIgnoreCase(o2.getName()); + if (i == 0) { + i = o1.getId().compareTo(o2.getId()); + } + } + return i; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/util/CatalogItemComparator.java b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/util/CatalogItemComparator.java new file mode 100644 index 000000000..ffffabe8f --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.discovery/src/org/eclipse/equinox/internal/p2/discovery/util/CatalogItemComparator.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2009 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.discovery.util; + +import java.util.Comparator; + +import org.eclipse.equinox.internal.p2.discovery.model.CatalogCategory; +import org.eclipse.equinox.internal.p2.discovery.model.CatalogItem; +import org.eclipse.equinox.internal.p2.discovery.model.Group; + +/** + * A comparator that orders connectors by group and alphabetically by their name. + * + * @author David Green + */ +public class CatalogItemComparator implements Comparator<CatalogItem> { + + /** + * compute the index of the group id + * + * @param groupId + * the group id or null + * @return the index, or -1 if not found + */ + private int computeGroupIndex(CatalogCategory category, String groupId) { + if (groupId != null) { + int index = -1; + for (Group group : category.getGroup()) { + ++index; + if (group.getId().equals(groupId)) { + return index; + } + } + } + return -1; + } + + public int compare(CatalogItem o1, CatalogItem o2) { + if (o1.getCategory() != o2.getCategory()) { + throw new IllegalArgumentException(); + } + if (o1 == o2) { + return 0; + } + int g1 = computeGroupIndex(o1.getCategory(), o1.getGroupId()); + int g2 = computeGroupIndex(o2.getCategory(), o2.getGroupId()); + int i; + if (g1 != g2) { + if (g1 == -1) { + i = 1; + } else if (g2 == -1) { + i = -1; + } else { + i = g1 - g2; + } + } else { + i = o1.getName().compareToIgnoreCase(o2.getName()); + if (i == 0) { + i = o1.getId().compareTo(o2.getId()); + } + } + return i; + } + +} |