/*******************************************************************************
 * Copyright (c) 2008, 2020 Code 9 and others.
 *
 * This
 * program and the accompanying materials are made available under the terms of
 * the Eclipse Public License 2.0 which accompanies this distribution, and is
 * available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *   Code 9 - initial API and implementation
 *   IBM - ongoing development
 *   Sonatype, Inc. - transport split
 *   Red Hat Inc. - 383795 (bundle element)
 ******************************************************************************/
package org.eclipse.equinox.internal.p2.updatesite;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.repository.Transport;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil;
import org.eclipse.equinox.p2.metadata.expression.IExpression;
import org.eclipse.equinox.p2.publisher.*;
import org.eclipse.equinox.p2.publisher.eclipse.*;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.IRepositoryReference;
import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor;
import org.eclipse.equinox.p2.repository.spi.RepositoryReference;
import org.eclipse.equinox.spi.p2.publisher.LocalizationHelper;
import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;

/**
 * Action which processes a site.xml and generates categories. The
 * categorization process relies on IUs for the various features to have already
 * been generated.
 */
public class SiteXMLAction extends AbstractPublisherAction {
	static final private String QUALIFIER = "qualifier"; //$NON-NLS-1$
	static final private String P_STATS_URI = "p2.statsURI"; //$NON-NLS-1$
	static final private String P_STATS_MARKER = "download.stats"; //$NON-NLS-1$
	private static final VersionSuffixGenerator versionSuffixGenerator = new VersionSuffixGenerator();
	protected UpdateSite updateSite;
	private SiteCategory defaultCategory;
	private HashSet<SiteCategory> defaultCategorySet;
	protected URI location;
	private String categoryQualifier = null;
	private Version categoryVersion = null;

	/**
	 * Creates a SiteXMLAction from a Location (URI) with an optional qualifier to
	 * use for category names
	 * 
	 * @param location          The location of the update site
	 * @param categoryQualifier The qualifier to prepend to categories. This
	 *                          qualifier is used to ensure that the category IDs
	 *                          are unique between update sites. If <b>null</b> a
	 *                          default qualifier will be generated
	 */
	public SiteXMLAction(URI location, String categoryQualifier) {
		this.location = location;
		this.categoryQualifier = categoryQualifier;
	}

	/**
	 * Creates a SiteXMLAction from an Update site with an optional qualifier to use
	 * for category names
	 * 
	 * @param updateSite        The update site
	 * @param categoryQualifier The qualifier to prepend to categories. This
	 *                          qualifier is used to ensure that the category IDs
	 *                          are unique between update sites. If <b>null</b> a
	 *                          default qualifier will be generated
	 */
	public SiteXMLAction(UpdateSite updateSite, String categoryQualifier) {
		this.updateSite = updateSite;
		this.categoryQualifier = categoryQualifier;
	}

	public void setCategoryVersion(String version) {
		categoryVersion = Version.parseVersion(version);
	}

	private void initialize() {
		if (defaultCategory != null)
			return;
		defaultCategory = new SiteCategory();
		defaultCategory.setDescription("Default category for otherwise uncategorized features"); //$NON-NLS-1$
		defaultCategory.setLabel("Uncategorized"); //$NON-NLS-1$
		defaultCategory.setName("Default"); //$NON-NLS-1$
		defaultCategorySet = new HashSet<>(1);
		defaultCategorySet.add(defaultCategory);
	}

	@Override
	public IStatus perform(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) {
		if (updateSite == null) {
			try {
				updateSite = UpdateSite.load(location,
						publisherInfo.getMetadataRepository().getProvisioningAgent().getService(Transport.class),
						monitor);
			} catch (ProvisionException e) {
				return new Status(IStatus.ERROR, Activator.ID, Messages.Error_generating_siteXML, e);
			} catch (OperationCanceledException e) {
				return Status.CANCEL_STATUS;
			}
		}
		initialize();
		initializeRepoFromSite(publisherInfo);
		IStatus markingStats = markStatsArtifacts(publisherInfo, results, monitor);
		if (markingStats.isOK()) {
			return generateCategories(publisherInfo, results, monitor);
		}
		return markingStats;
	}

	private IStatus markStatsArtifacts(IPublisherInfo publisherInfo, IPublisherResult results,
			IProgressMonitor monitor) {
		IArtifactRepository artifactRepo = publisherInfo.getArtifactRepository();
		SiteModel site = updateSite.getSite();
		// process all features listed and mark artifacts
		SiteFeature[] features = site.getStatsFeatures();
		if (features != null && artifactRepo != null) {
			for (SiteFeature feature : features) {
				if (monitor.isCanceled())
					return Status.CANCEL_STATUS;
				Collection<IInstallableUnit> ius = getFeatureIU(feature, publisherInfo, results);
				if (ius != null) {
					for (IInstallableUnit iu : ius) {
						IArtifactKey key = FeaturesAction.createFeatureArtifactKey(feature.getFeatureIdentifier(),
								iu.getVersion().toString());
						IArtifactDescriptor[] descriptors = artifactRepo.getArtifactDescriptors(key);
						if (descriptors.length > 0 && descriptors[0] instanceof ArtifactDescriptor) {
							HashMap<String, String> map = new HashMap<>();
							map.put(P_STATS_MARKER, feature.getFeatureIdentifier());
							((ArtifactDescriptor) descriptors[0]).addProperties(map);
						}
					}
				}
			}
		}
		// process all bundles listed and mark artifacts
		SiteBundle[] bundles = site.getStatsBundles();
		if (bundles != null && artifactRepo != null) {
			for (SiteBundle bundle : bundles) {
				if (monitor.isCanceled())
					return Status.CANCEL_STATUS;
				Collection<IInstallableUnit> ius = getBundleIU(bundle, publisherInfo, results);
				if (ius != null) {
					for (IInstallableUnit iu : ius) {
						IArtifactKey key = BundlesAction.createBundleArtifactKey(iu.getId(),
								iu.getVersion().toString());
						IArtifactDescriptor[] descriptors = artifactRepo.getArtifactDescriptors(key);
						if (descriptors.length > 0 && descriptors[0] instanceof ArtifactDescriptor) {
							HashMap<String, String> map = new HashMap<>();
							map.put(P_STATS_MARKER, iu.getId());
							((ArtifactDescriptor) descriptors[0]).addProperties(map);
						}
					}
				}
			}
		}
		// If there was no artifact repository available and stats were to be tracked,
		// issue
		// a warning.
		boolean markingBundles = bundles != null && bundles.length > 0;
		boolean markingFeatures = features != null && features.length > 0;
		if (artifactRepo == null && (markingBundles || markingFeatures))
			return new Status(IStatus.WARNING, Activator.ID,
					"Artifact repository was not specified so stats properties could not be published."); //$NON-NLS-1$
		return Status.OK_STATUS;

	}

	private IStatus generateCategories(IPublisherInfo publisherInfo, IPublisherResult results,
			IProgressMonitor monitor) {
		Map<SiteCategory, Set<IInstallableUnit>> categoriesToIUs = new HashMap<>();
		Map<SiteFeature, Set<SiteCategory>> featuresToCategories = getFeatureToCategoryMappings(publisherInfo);
		for (SiteFeature feature : featuresToCategories.keySet()) {
			if (monitor.isCanceled())
				return Status.CANCEL_STATUS;
			Collection<IInstallableUnit> ius = getFeatureIU(feature, publisherInfo, results);
			if (ius == null)
				continue;
			Set<SiteCategory> categories = featuresToCategories.get(feature);
			// if there are no categories for this feature then add it to the default
			// category.
			if (categories == null || categories.isEmpty())
				categories = defaultCategorySet;
			for (SiteCategory category : categories) {
				Set<IInstallableUnit> iusInCategory = categoriesToIUs.get(category);
				if (iusInCategory == null) {
					iusInCategory = new HashSet<>();
					categoriesToIUs.put(category, iusInCategory);
				}
				iusInCategory.addAll(ius);
			}
		}
		// Bundles -- bug 378338
		Map<SiteBundle, Set<SiteCategory>> bundlesToCategories = getBundleToCategoryMappings(publisherInfo);
		for (SiteBundle bundle : bundlesToCategories.keySet()) {
			if (monitor.isCanceled())
				return Status.CANCEL_STATUS;
			Collection<IInstallableUnit> ius = getBundleIU(bundle, publisherInfo, results);
			if (ius == null)
				continue;
			Set<SiteCategory> categories = bundlesToCategories.get(bundle);
			// if there are no categories for this feature then add it to the default
			// category.
			if (categories == null || categories.isEmpty())
				categories = defaultCategorySet;
			for (SiteCategory category : categories) {
				Set<IInstallableUnit> iusInCategory = categoriesToIUs.get(category);
				if (iusInCategory == null) {
					iusInCategory = new HashSet<>();
					categoriesToIUs.put(category, iusInCategory);
				}
				iusInCategory.addAll(ius);
			}
		}

		addSiteIUsToCategories(categoriesToIUs, publisherInfo, results);
		generateCategoryIUs(categoriesToIUs, results);
		return Status.OK_STATUS;
	}

	private void addSiteIUsToCategories(Map<SiteCategory, Set<IInstallableUnit>> categoriesToIUs,
			IPublisherInfo publisherInfo, IPublisherResult results) {
		Map<SiteIU, Set<SiteCategory>> iusToCategories = getIUToCategoryMappings(publisherInfo);
		SiteModel site = updateSite.getSite();
		if (site == null)
			return;
		SiteIU[] siteIUs = site.getIUs();
		for (SiteIU siteIU : siteIUs) {
			Collection<IInstallableUnit> ius = getIUs(siteIU, publisherInfo, results);
			if (ius == null)
				continue;
			Set<SiteCategory> categories = iusToCategories.get(siteIU);
			// if there are no categories for this feature then add it to the default
			// category.
			if (categories == null || categories.isEmpty())
				categories = defaultCategorySet;
			for (SiteCategory category : categories) {
				Set<IInstallableUnit> iusInCategory = categoriesToIUs.get(category);
				if (iusInCategory == null) {
					iusInCategory = new HashSet<>();
					categoriesToIUs.put(category, iusInCategory);
				}
				iusInCategory.addAll(ius);
			}
		}
	}

	private Map<SiteIU, Set<SiteCategory>> getIUToCategoryMappings(IPublisherInfo publisherInfo) {
		HashMap<SiteIU, Set<SiteCategory>> mappings = new HashMap<>();
		if (updateSite == null)
			return mappings;
		SiteModel site = updateSite.getSite();
		if (site == null)
			return mappings;

		SiteIU[] ius = site.getIUs();
		for (SiteIU iu : ius) {
			// add a mapping for each category this feature belongs to
			String[] categoryNames = iu.getCategoryNames();
			Set<SiteCategory> categories = new HashSet<>();
			mappings.put(iu, categories);
			for (String categoryName : categoryNames) {
				SiteCategory category = site.getCategory(categoryName);
				if (category != null)
					categories.add(category);
			}
		}
		return mappings;

	}

	private Collection<IInstallableUnit> getIUs(SiteIU siteIU, IPublisherInfo publisherInfo, IPublisherResult results) {
		String id = siteIU.getID();
		String range = siteIU.getRange();
		String type = siteIU.getQueryType();
		String expression = siteIU.getQueryExpression();
		Object[] params = siteIU.getQueryParams();
		if (id == null && (type == null || expression == null))
			return Collections.emptyList();
		IQuery<IInstallableUnit> query = null;
		if (id != null) {
			VersionRange vRange = VersionRange.create(range);
			query = QueryUtil.createIUQuery(id, vRange);
		} else if (type.equals("context")) { //$NON-NLS-1$
			query = QueryUtil.createQuery(expression, params);
		} else if (type.equals("match")) //$NON-NLS-1$
			query = QueryUtil.createMatchQuery(expression, params);
		if (query == null)
			return Collections.emptyList();
		IQueryResult<IInstallableUnit> queryResult = results.query(query, null);
		if (queryResult.isEmpty())
			queryResult = publisherInfo.getMetadataRepository().query(query, null);
		if (queryResult.isEmpty() && publisherInfo.getContextMetadataRepository() != null)
			queryResult = publisherInfo.getContextMetadataRepository().query(query, null);

		return queryResult.toUnmodifiableSet();
	}

	private static final IExpression qualifierMatchExpr = ExpressionUtil.parse("id == $0 && version ~= $1"); //$NON-NLS-1$

	private Collection<IInstallableUnit> getFeatureIU(SiteFeature feature, IPublisherInfo publisherInfo,
			IPublisherResult results) {
		String id = feature.getFeatureIdentifier() + ".feature.group"; //$NON-NLS-1$
		String versionString = feature.getFeatureVersion();
		Version version = versionString != null && versionString.length() > 0 ? Version.create(versionString)
				: Version.emptyVersion;
		IQuery<IInstallableUnit> query = null;
		if (version.equals(Version.emptyVersion)) {
			query = QueryUtil.createIUQuery(id);
		} else {
			String qualifier;
			try {
				qualifier = PublisherHelper.toOSGiVersion(version).getQualifier();
			} catch (UnsupportedOperationException e) {
				qualifier = null;
			}
			if (qualifier != null && qualifier.endsWith(QUALIFIER)) {
				VersionRange range = createVersionRange(version.toString());
				IQuery<IInstallableUnit> qualifierQuery = QueryUtil.createMatchQuery(qualifierMatchExpr, id, range);
				query = qualifierQuery;
			} else {
				query = QueryUtil.createLimitQuery(QueryUtil.createIUQuery(id, version), 1);
			}
		}

		IQueryResult<IInstallableUnit> queryResult = results.query(query, null);
		if (queryResult.isEmpty())
			queryResult = publisherInfo.getMetadataRepository().query(query, null);
		if (queryResult.isEmpty() && publisherInfo.getContextMetadataRepository() != null)
			queryResult = publisherInfo.getContextMetadataRepository().query(query, null);

		if (!queryResult.isEmpty())
			return queryResult.toUnmodifiableSet();
		return null;
	}

	private Collection<IInstallableUnit> getBundleIU(SiteBundle bundle, IPublisherInfo publisherInfo,
			IPublisherResult results) {
		String id = bundle.getBundleIdentifier();
		String versionString = bundle.getBundleVersion();
		Version version = versionString != null && versionString.length() > 0 ? Version.create(versionString)
				: Version.emptyVersion;
		IQuery<IInstallableUnit> query = null;
		if (version.equals(Version.emptyVersion)) {
			query = QueryUtil.createIUQuery(id);
		} else {
			String qualifier;
			try {
				qualifier = PublisherHelper.toOSGiVersion(version).getQualifier();
			} catch (UnsupportedOperationException e) {
				qualifier = null;
			}
			if (qualifier != null && qualifier.endsWith(QUALIFIER)) {
				VersionRange range = createVersionRange(version.toString());
				IQuery<IInstallableUnit> qualifierQuery = QueryUtil.createMatchQuery(qualifierMatchExpr, id, range);
				query = qualifierQuery;
			} else {
				query = QueryUtil.createLimitQuery(QueryUtil.createIUQuery(id, version), 1);
			}
		}

		IQueryResult<IInstallableUnit> queryResult = results.query(query, null);
		if (queryResult.isEmpty())
			queryResult = publisherInfo.getMetadataRepository().query(query, null);
		if (queryResult.isEmpty() && publisherInfo.getContextMetadataRepository() != null)
			queryResult = publisherInfo.getContextMetadataRepository().query(query, null);

		if (!queryResult.isEmpty())
			return queryResult.toUnmodifiableSet();
		return null;
	}

	protected VersionRange createVersionRange(String versionId) {
		VersionRange range = null;
		if (versionId == null || "0.0.0".equals(versionId)) //$NON-NLS-1$
			range = VersionRange.emptyRange;
		else {
			int qualifierIdx = versionId.indexOf(QUALIFIER);
			if (qualifierIdx != -1) {
				String newVersion = versionId.substring(0, qualifierIdx);
				if (newVersion.endsWith(".")) //$NON-NLS-1$
					newVersion = newVersion.substring(0, newVersion.length() - 1);

				Version lower = Version.parseVersion(newVersion);
				Version upper = null;
				String newQualifier = VersionSuffixGenerator
						.incrementQualifier(PublisherHelper.toOSGiVersion(lower).getQualifier());
				org.osgi.framework.Version osgiVersion = PublisherHelper.toOSGiVersion(lower);
				if (newQualifier == null)
					upper = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(),
							osgiVersion.getMicro() + 1);
				else
					upper = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro(),
							newQualifier);
				range = new VersionRange(lower, true, upper, false);
			} else {
				range = new VersionRange(Version.parseVersion(versionId), true, Version.parseVersion(versionId), true);
			}
		}
		return range;
	}

	/**
	 * Computes the mapping of features to categories as defined in the site.xml, if
	 * available. Returns an empty map if there is not site.xml, or no categories.
	 * 
	 * @return A map of SiteFeature -> Set<SiteCategory>.
	 */
	protected Map<SiteFeature, Set<SiteCategory>> getFeatureToCategoryMappings(IPublisherInfo publisherInfo) {
		HashMap<SiteFeature, Set<SiteCategory>> mappings = new HashMap<>();
		if (updateSite == null)
			return mappings;
		SiteModel site = updateSite.getSite();
		if (site == null)
			return mappings;

		SiteFeature[] features = site.getFeatures();
		for (SiteFeature feature : features) {
			// add a mapping for each category this feature belongs to
			String[] categoryNames = feature.getCategoryNames();
			Set<SiteCategory> categories = mappings.get(feature);
			if (categories == null) {
				categories = new HashSet<>();
				mappings.put(feature, categories);
			}
			for (String categoryName : categoryNames) {
				SiteCategory category = site.getCategory(categoryName);
				if (category != null)
					categories.add(category);
			}
		}
		return mappings;
	}

	/**
	 * Computes the mapping of bundles to categories as defined in the site.xml, if
	 * available. Returns an empty map if there is not site.xml, or no categories.
	 * 
	 * @return A map of SiteBundle -> Set<SiteCategory>.
	 */
	protected Map<SiteBundle, Set<SiteCategory>> getBundleToCategoryMappings(IPublisherInfo publisherInfo) {
		HashMap<SiteBundle, Set<SiteCategory>> mappings = new HashMap<>();
		if (updateSite == null)
			return mappings;
		SiteModel site = updateSite.getSite();
		if (site == null)
			return mappings;

		SiteBundle[] bundles = site.getBundles();
		for (SiteBundle bundle : bundles) {
			// add a mapping for each category this feature belongs to
			String[] categoryNames = bundle.getCategoryNames();
			Set<SiteCategory> categories = new HashSet<>();
			mappings.put(bundle, categories);
			for (String categoryName : categoryNames) {
				SiteCategory category = site.getCategory(categoryName);
				if (category != null)
					categories.add(category);
			}
		}
		return mappings;
	}

	/**
	 * Initializes new p2 repository attributes such as mirror info, associate
	 * sites, localization...
	 * 
	 * @param publisherInfo configuration for output repository
	 */
	private void initializeRepoFromSite(IPublisherInfo publisherInfo) {
		SiteModel site = updateSite.getSite();
		// copy mirror information from update site to p2 repositories
		String mirrors = site.getMirrorsURI();
		if (mirrors != null) {
			// remove site.xml file reference
			int index = mirrors.indexOf("site.xml"); //$NON-NLS-1$
			if (index != -1)
				mirrors = mirrors.substring(0, index) + mirrors.substring(index + "site.xml".length()); //$NON-NLS-1$
			publisherInfo.getMetadataRepository().setProperty(IRepository.PROP_MIRRORS_URL, mirrors);
			// there does not really need to be an artifact repo but if there is, setup its
			// mirrors.
			if (publisherInfo.getArtifactRepository() != null)
				publisherInfo.getArtifactRepository().setProperty(IRepository.PROP_MIRRORS_URL, mirrors);
		}

		// publish associate sites as repository references
		URLEntry[] associatedSites = site.getAssociatedSites();
		if (associatedSites != null) {
			ArrayList<IRepositoryReference> refs = new ArrayList<>(associatedSites.length * 2);
			for (URLEntry associatedSite : associatedSites) {
				String siteLocation = associatedSite.getURL();
				try {
					URI associateLocation = new URI(siteLocation);
					String label = associatedSite.getAnnotation();
					refs.add(new RepositoryReference(associateLocation, label, IRepository.TYPE_METADATA,
							IRepository.ENABLED));
					refs.add(new RepositoryReference(associateLocation, label, IRepository.TYPE_ARTIFACT,
							IRepository.ENABLED));
				} catch (URISyntaxException e) {
					String message = "Invalid site reference: " + siteLocation; //$NON-NLS-1$
					LogHelper.log(new Status(IStatus.ERROR, Activator.ID, message));
				}
			}
			publisherInfo.getMetadataRepository().addReferences(refs);
		}

		// publish repository references from category file
		IRepositoryReference[] refs = site.getRepositoryReferences();
		if (refs != null) {
			ArrayList<IRepositoryReference> toAdd = new ArrayList<>(Arrays.asList(refs));
			publisherInfo.getMetadataRepository().addReferences(toAdd);
		}

		// publish download stats URL from category file
		String statsURI = site.getStatsURI();
		if (statsURI != null && statsURI.length() > 0) {
			if (publisherInfo.getArtifactRepository() != null)
				publisherInfo.getArtifactRepository().setProperty(P_STATS_URI, statsURI);
		}

		File siteFile = URIUtil.toFile(updateSite.getLocation());
		if (siteFile != null && siteFile.exists()) {
			File siteParent = siteFile.getParentFile();
			List<String> messageKeys = site.getMessageKeys();
			if (siteParent.isDirectory()) {
				String[] keyStrings = messageKeys.toArray(new String[messageKeys.size()]);
				site.setLocalizations(
						LocalizationHelper.getDirPropertyLocalizations(siteParent, "site", null, keyStrings)); //$NON-NLS-1$
			} else if (siteFile.getName().endsWith(".jar")) { //$NON-NLS-1$
				String[] keyStrings = messageKeys.toArray(new String[messageKeys.size()]);
				site.setLocalizations(
						LocalizationHelper.getJarPropertyLocalizations(siteParent, "site", null, keyStrings)); //$NON-NLS-1$
			}
		}
	}

	/**
	 * Generates IUs corresponding to update site categories.
	 * 
	 * @param categoriesToIUs Map of SiteCategory ->Set (Feature IUs in that
	 *                        category).
	 * @param result          The generator result being built
	 */
	protected void generateCategoryIUs(Map<SiteCategory, Set<IInstallableUnit>> categoriesToIUs,
			IPublisherResult result) {
		Map<String, SiteCategory> nameToCategory = new HashMap<>();
		for (SiteCategory category : this.updateSite.getSite().getCategories()) {
			nameToCategory.put(category.getName(), category);
		}
		final Map<SiteCategory, Set<SiteCategory>> categoryToNestedCategories = new HashMap<>();
		for (SiteCategory category : this.updateSite.getSite().getCategories()) {
			for (String parentCategoryName : category.getCategoryNames()) {
				SiteCategory parentCategory = nameToCategory.get(parentCategoryName);
				if (categoryToNestedCategories.get(parentCategory) == null) {
					categoryToNestedCategories.put(parentCategory, new HashSet<>());
				}
				categoryToNestedCategories.get(parentCategory).add(category);
			}
		}

		List<SiteCategory> categories = new ArrayList<>(Arrays.asList(this.updateSite.getSite().getCategories()));
		categories.add(this.defaultCategory);
		// sort category so they are processed in reverse order of dependency
		// (Nested categories go first)
		Comparator<SiteCategory> isNestedCategoryComparator = new Comparator<SiteCategory>() {
			@Override
			public int compare(SiteCategory category1, SiteCategory category2) {
				Set<SiteCategory> childrenOfCategory1 = categoryToNestedCategories.get(category1);
				Set<SiteCategory> childrenOfCategory2 = categoryToNestedCategories.get(category2);
				if (childrenOfCategory1 != null && childrenOfCategory1.contains(category2)) {
					// category2 nested in category1 => category2 < category1
					return +1;
				}
				if (childrenOfCategory2 != null && childrenOfCategory2.contains(category1)) {
					// category1 nested in category2 => category1 < category2
					return -1;
				}
				// Then recurse in childrenCategories for transitivity
				if (childrenOfCategory1 != null) {
					for (SiteCategory childOfCategory1 : childrenOfCategory1) {
						int res = this.compare(childOfCategory1, category2);
						if (res != 0) {
							return res;
						}
					}
				}
				if (childrenOfCategory2 != null) {
					for (SiteCategory childOfCategory2 : childrenOfCategory2) {
						int res = this.compare(category1, childOfCategory2);
						if (res != 0) {
							return res;
						}
					}
				}
				return 0;
			}
		};
		categories.sort(isNestedCategoryComparator);

		// Then create categories in the right order
		Map<String, IInstallableUnit> nameToCategoryIU = new HashMap<>();
		for (SiteCategory category : categories) {
			Set<IInstallableUnit> units = categoriesToIUs.get(category);
			if (units == null) {
				units = new HashSet<>();
			}
			Set<SiteCategory> nestedCategories = categoryToNestedCategories.get(category);
			if (nestedCategories != null) {
				for (SiteCategory nestedCategory : nestedCategories) {
					IInstallableUnit nestedCategoryIU = nameToCategoryIU.get(nestedCategory.getName());
					if (nestedCategoryIU != null) {
						units.add(nestedCategoryIU);
					}
				}
			}
			if (!units.isEmpty()) {
				IInstallableUnit categoryIU = createCategoryIU(category, units);
				result.addIU(categoryIU, IPublisherResult.NON_ROOT);
				nameToCategoryIU.put(category.getName(), categoryIU);
			}
		}
	}

	/**
	 * Creates an IU corresponding to an update site category
	 * 
	 * @param category       The category descriptor
	 * @param childrenIUs    The IUs of the children that belong to the category
	 *                       (can be bundle, feature or nested categories)
	 * @param nestedCategory A nested category (optional)
	 * @return an IU representing the category
	 * @deprecated use
	 *             {@link IInstallableUnit}{@link #createCategoryIU(SiteCategory, Set)}
	 *             instead
	 */
	@Deprecated
	public IInstallableUnit createCategoryIU(SiteCategory category, Set<IInstallableUnit> childrenIUs,
			IInstallableUnit nestedCategory) {
		Set<IInstallableUnit> allIUs = new HashSet<>();
		if (childrenIUs != null) {
			allIUs.addAll(childrenIUs);
		}
		if (nestedCategory != null) {
			allIUs.add(nestedCategory);
		}
		return createCategoryIU(category, allIUs);
	}

	/**
	 * Creates an IU corresponding to an update site category
	 * 
	 * @param category    The category descriptor
	 * @param childrenIUs The IUs of the children that belong to the category (can
	 *                    be bundle, feature or nested categories)
	 * @return an IU representing the category
	 */
	public IInstallableUnit createCategoryIU(SiteCategory category, Set<IInstallableUnit> childrenIUs) {
		InstallableUnitDescription cat = new MetadataFactory.InstallableUnitDescription();
		cat.setSingleton(true);
		String categoryId = buildCategoryId(category.getName());
		cat.setId(categoryId);
		if (categoryVersion == null)
			cat.setVersion(Version.createOSGi(1, 0, 0,
					versionSuffixGenerator.generateSuffix(childrenIUs, Collections.emptyList())));
		else {
			if (categoryVersion.isOSGiCompatible()) {
				org.osgi.framework.Version osgiVersion = PublisherHelper.toOSGiVersion(categoryVersion);
				String qualifier = osgiVersion.getQualifier();
				if (qualifier.endsWith(QUALIFIER)) {
					String suffix = versionSuffixGenerator.generateSuffix(childrenIUs, Collections.emptyList());
					qualifier = qualifier.substring(0, qualifier.length() - 9) + suffix;
					categoryVersion = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(),
							osgiVersion.getMicro(), qualifier);
				}
			}
			cat.setVersion(categoryVersion);
		}

		String label = category.getLabel();
		cat.setProperty(IInstallableUnit.PROP_NAME, label != null ? label : category.getName());
		cat.setProperty(IInstallableUnit.PROP_DESCRIPTION, category.getDescription());

		ArrayList<IRequirement> reqsConfigurationUnits = new ArrayList<>(childrenIUs.size());
		for (IInstallableUnit iu : childrenIUs) {
			VersionRange range = new VersionRange(iu.getVersion(), true, iu.getVersion(), true);
			reqsConfigurationUnits.add(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, iu.getId(),
					range, iu.getFilter(), false, false));
		}
		cat.setRequirements(reqsConfigurationUnits.toArray(new IRequirement[reqsConfigurationUnits.size()]));

		// Create set of provided capabilities
		ArrayList<IProvidedCapability> providedCapabilities = new ArrayList<>();
		providedCapabilities.add(PublisherHelper.createSelfCapability(categoryId, cat.getVersion()));

		Map<Locale, Map<String, String>> localizations = category.getLocalizations();
		if (localizations != null) {
			for (Entry<Locale, Map<String, String>> locEntry : localizations.entrySet()) {
				Locale locale = locEntry.getKey();
				Map<String, String> translatedStrings = locEntry.getValue();
				for (Entry<String, String> e : translatedStrings.entrySet()) {
					cat.setProperty(locale.toString() + '.' + e.getKey(), e.getValue());
				}
				providedCapabilities.add(PublisherHelper.makeTranslationCapability(categoryId, locale));
			}
		}

		cat.setCapabilities(providedCapabilities.toArray(new IProvidedCapability[providedCapabilities.size()]));

		cat.setArtifacts(new IArtifactKey[0]);
		cat.setProperty(InstallableUnitDescription.PROP_TYPE_CATEGORY, "true"); //$NON-NLS-1$
		return MetadataFactory.createInstallableUnit(cat);
	}

	/**
	 * Creates a qualified category id. This action's qualifier is used if one
	 * exists or an existing update site's location is used.
	 */
	private String buildCategoryId(String categoryName) {
		if (categoryQualifier != null) {
			if (categoryQualifier.length() > 0)
				return categoryQualifier + "." + categoryName; //$NON-NLS-1$
			return categoryName;
		}
		if (updateSite != null)
			return URIUtil.toUnencodedString(updateSite.getLocation()) + "." + categoryName; //$NON-NLS-1$
		return categoryName;
	}

	protected Transport getTransport(IPublisherInfo info) {
		@SuppressWarnings("rawtypes")
		IRepository repo = info.getMetadataRepository();
		if (repo == null)
			repo = info.getArtifactRepository();
		if (repo == null)
			throw new IllegalStateException("The transport service can not be found."); //$NON-NLS-1$
		return repo.getProvisioningAgent().getService(Transport.class);
	}
}
