/*******************************************************************************
 * Copyright (c) 2008, 2010 Code 9 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:
 *   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<SiteCategory>(1);
		defaultCategorySet.add(defaultCategory);
	}

	public IStatus perform(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) {
		if (updateSite == null) {
			try {
				updateSite = UpdateSite.load(location, (Transport) publisherInfo.getMetadataRepository().getProvisioningAgent().getService(Transport.SERVICE_NAME), 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<String, String>();
							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<String, String>();
							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<SiteCategory, Set<IInstallableUnit>>();
		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<IInstallableUnit>();
					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<IInstallableUnit>();
					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) {
		if (updateSite == null)
			return;
		SiteModel site = updateSite.getSite();
		if (site == null)
			return;
		SiteIU[] siteIUs = site.getIUs();
		for (SiteIU siteIU : siteIUs) {
			String[] categoryNames = siteIU.getCategoryNames();
			if (categoryNames.length == 0)
				continue;
			Collection<IInstallableUnit> ius = getIUs(siteIU, publisherInfo, results);
			if (ius.size() == 0)
				continue;
			for (String categoryName : categoryNames) {
				SiteCategory category = site.getCategory(categoryName);
				if (category == null)
					continue;
				Set<IInstallableUnit> categoryIUs = categoriesToIUs.get(category);
				if (categoryIUs == null) {
					categoryIUs = new HashSet<IInstallableUnit>();
					categoriesToIUs.put(category, categoryIUs);
				}
				categoryIUs.addAll(ius);
			}
		}
	}

	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.<IInstallableUnit> emptyList();
		IQuery<IInstallableUnit> query = null;
		if (id != null) {
			VersionRange vRange = new VersionRange(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.<IInstallableUnit> 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<SiteFeature, Set<SiteCategory>>();
		if (updateSite == null)
			return mappings;
		SiteModel site = updateSite.getSite();
		if (site == null)
			return mappings;

		SiteFeature[] features = site.getFeatures();
		for (int i = 0; i < features.length; i++) {
			//add a mapping for each category this feature belongs to
			String[] categoryNames = features[i].getCategoryNames();
			Set<SiteCategory> categories = mappings.get(features[i]);
			if (categories == null) {
				categories = new HashSet<SiteCategory>();
				mappings.put(features[i], categories);
			}
			for (int j = 0; j < categoryNames.length; j++) {
				SiteCategory category = site.getCategory(categoryNames[j]);
				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<SiteBundle, Set<SiteCategory>>();
		if (updateSite == null)
			return mappings;
		SiteModel site = updateSite.getSite();
		if (site == null)
			return mappings;

		SiteBundle[] bundles = site.getBundles();
		for (int i = 0; i < bundles.length; i++) {
			//add a mapping for each category this feature belongs to
			String[] categoryNames = bundles[i].getCategoryNames();
			Set<SiteCategory> categories = new HashSet<SiteCategory>();
			mappings.put(bundles[i], categories);
			for (int j = 0; j < categoryNames.length; j++) {
				SiteCategory category = site.getCategory(categoryNames[j]);
				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<IRepositoryReference>(associatedSites.length * 2);
			for (int i = 0; i < associatedSites.length; i++) {
				URLEntry associatedSite = associatedSites[i];
				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<IRepositoryReference>(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<String, SiteCategory>();
		for (SiteCategory category : this.updateSite.getSite().getCategories()) {
			nameToCategory.put(category.getName(), category);
		}
		final Map<SiteCategory, Set<SiteCategory>> categoryToNestedCategories = new HashMap<SiteCategory, Set<SiteCategory>>();
		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<SiteCategory>());
				}
				categoryToNestedCategories.get(parentCategory).add(category);
			}
		}

		List<SiteCategory> categories = new ArrayList<SiteCategory>(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>() {
			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;
			}
		};
		Collections.sort(categories, isNestedCategoryComparator);

		// Then create categories in the right order
		Map<String, IInstallableUnit> nameToCategoryIU = new HashMap<String, IInstallableUnit>();
		for (SiteCategory category : categories) {
			Set<IInstallableUnit> units = categoriesToIUs.get(category);
			if (units == null) {
				units = new HashSet<IInstallableUnit>();
			}
			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<IInstallableUnit>();
		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.<IVersionedId> 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.<IVersionedId> 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<IRequirement>(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<IProvidedCapability>();
		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 (Transport) repo.getProvisioningAgent().getService(Transport.SERVICE_NAME);
	}
}
