/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.update.internal.operations;

import java.util.*;

import org.eclipse.core.boot.*;
import org.eclipse.core.runtime.*;
import org.eclipse.update.configuration.*;
import org.eclipse.update.core.*;
import org.eclipse.update.internal.core.*;
import org.eclipse.update.operations.*;

/**
 *
 */
public class OperationValidator implements IOperationValidator{
	private static final String KEY_ROOT_MESSAGE =
		"ActivityConstraints.rootMessage";
	private static final String KEY_ROOT_MESSAGE_INIT =
		"ActivityConstraints.rootMessageInitial";
	private static final String KEY_CHILD_MESSAGE =
		"ActivityConstraints.childMessage";
	private static final String KEY_PLATFORM = "ActivityConstraints.platform";
	private static final String KEY_PRIMARY = "ActivityConstraints.primary";
	private static final String KEY_OS = "ActivityConstraints.os";
	private static final String KEY_WS = "ActivityConstraints.ws";
	private static final String KEY_ARCH = "ActivityConstraints.arch";
	private static final String KEY_PREREQ = "ActivityConstraints.prereq";
	private static final String KEY_PREREQ_PLUGIN =
		"ActivityConstaints.prereq.plugin";
	private static final String KEY_PREREQ_FEATURE =
		"ActivityConstaints.prereq.feature";
	private static final String KEY_PREREQ_PERFECT =
		"ActivityConstraints.prereqPerfect";
	private static final String KEY_PREREQ_EQUIVALENT =
		"ActivityConstraints.prereqEquivalent";
	private static final String KEY_PREREQ_COMPATIBLE =
		"ActivityConstraints.prereqCompatible";
	private static final String KEY_PREREQ_GREATER =
		"ActivityConstraints.prereqGreaterOrEqual";
	private static final String KEY_PATCH_REGRESSION =
		"ActivityConstraints.patchRegression";
	private static final String KEY_PATCH_UNCONFIGURE =
		"ActivityConstraints.patchUnconfigure";
	private static final String KEY_PATCH_UNCONFIGURE_BACKUP =
		"ActivityConstraints.patchUnconfigureBackup";
	private static final String KEY_PATCH_MISSING_TARGET =
		"ActivityConstraints.patchMissingTarget";
	private static final String KEY_OPTIONAL_CHILD =
		"ActivityConstraints.optionalChild";
	private static final String KEY_CYCLE = "ActivityConstraints.cycle";
	private static final String KEY_CONFLICT = "ActivityConstraints.conflict";
	private static final String KEY_EXCLUSIVE = "ActivityConstraints.exclusive";
	private static final String KEY_WRONG_TIMELINE =
		"ActivityConstraints.timeline";
	private static final String KEY_NO_LICENSE =
		"ActivityConstraints.noLicense";

	/*
	 * Called by UI before performing operation
	 */
	public IStatus validatePendingInstall(IFeature oldFeature, IFeature newFeature) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		validateInstall(oldFeature, newFeature, status);

		// report status
		return createReportStatus(beforeStatus, status);
	}
	
	/*
	 * Called by UI before performing operation
	 */
	public IStatus validatePendingUnconfig(IFeature feature) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		validateUnconfigure(feature, status);

		// report status
		return createReportStatus(beforeStatus, status);
	}
	
	/*
	 * Called by UI before performing operation
	 */
	public IStatus validatePendingConfig(IFeature feature) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		validateConfigure(feature, status);

		// report status
		return createReportStatus(beforeStatus, status);
	}

	/**
	 * Called before performing operation.
	 */
	public IStatus validatePendingReplaceVersion(IFeature feature, IFeature anotherFeature) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		validateReplaceVersion(feature, anotherFeature, status);

		// report status
		return createReportStatus(beforeStatus, status);
	}
	
	/*
	 * Called by UI before processing a delta
	 */
	public IStatus validateSessionDelta(
		ISessionDelta delta,
		IFeatureReference[] deltaRefs) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		switch (delta.getType()) {
			case ISessionDelta.ENABLE :
				validateDeltaConfigure(delta, deltaRefs, status);
				break;
		}

		// report status
		return createReportStatus(beforeStatus, status);
	}

	/*
	 * Called by the UI before doing a revert/ restore operation
	 */
	public IStatus validatePendingRevert(IInstallConfiguration config) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		validateRevert(config, status);

		// report status
		return createReportStatus(beforeStatus, status);
	}

	/*
	 * Called by the UI before doing a batched processing of
	 * several pending changes.
	 */
	public IStatus validatePendingChanges(IInstallFeatureOperation[] jobs) {
		// check initial state
		ArrayList beforeStatus = new ArrayList();
		validateInitialState(beforeStatus);

		// check proposed change
		ArrayList status = new ArrayList();
		validatePendingChanges(jobs, status);

		// report status
		return createReportStatus(beforeStatus, status);
	}
	private IStatus createReportStatus(ArrayList beforeStatus, ArrayList status) {
		// report status
		if (status.size() > 0) {
			if (beforeStatus.size() > 0)
				return createMultiStatus(KEY_ROOT_MESSAGE_INIT, beforeStatus);
			else
				return createMultiStatus(KEY_ROOT_MESSAGE, status);
		}
		return null;
	}

	/*
	 * Check the current state.
	 */
	public IStatus validateCurrentState() {
		// check the state
		ArrayList status = new ArrayList();
		validateInitialState(status);

		// report status
		if (status.size() > 0)
			return createMultiStatus(KEY_ROOT_MESSAGE, status);
		return null;
	}

	/*
	 * Check to see if we are not broken even before we start
	 */
	private static void validateInitialState(ArrayList status) {
		try {
			ArrayList features = computeFeatures();
			checkConstraints(features, status);
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}

	/*
	 * handle unconfigure
	 */
	private static void validateUnconfigure(
		IFeature feature,
		ArrayList status) {
		try {
			if (validateUnconfigurePatch(feature, status))
				return;
			ArrayList features = computeFeatures();
			features = computeFeaturesAfterOperation(features, null, feature);
			checkConstraints(features, status);
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}

	private static boolean validateUnconfigurePatch(
		IFeature feature,
		ArrayList status)
		throws CoreException {
		if (feature.isPatch()) {
			IInstallConfiguration backup =
				UpdateUtils.getBackupConfigurationFor(feature);
			String msg;
			if (backup != null)
				msg =
					UpdateUtils.getFormattedMessage(
						KEY_PATCH_UNCONFIGURE_BACKUP,
						backup.getLabel());
			else
				msg = UpdateUtils.getString(KEY_PATCH_UNCONFIGURE);
			status.add(createStatus(feature, msg));
			return true;
		}
		return false;
	}

	/*
	 * handle configure
	 */
	private static void validateConfigure(IFeature feature, ArrayList status) {
		try {
			ArrayList features = computeFeatures();
			checkOptionalChildConfiguring(feature, status);
			features = computeFeaturesAfterOperation(features, feature, null);
			checkConstraints(features, status);

		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}
	
	/*
	 * handle replace version
	 */
	private static void validateReplaceVersion(
		IFeature feature,
		IFeature anotherFeature,
		ArrayList status) {
		try {
			ArrayList features = computeFeatures();
			features = computeFeaturesAfterOperation(features, anotherFeature, feature);
			checkConstraints(features, status);
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}


	/*
	 * handle install and update
	 */
	private static void validateInstall(
		IFeature oldFeature,
		IFeature newFeature,
		ArrayList status) {
		try {
			ArrayList features = computeFeatures();
			if (oldFeature == null && isPatch(newFeature))
				checkUnique(newFeature, features, status);
			features =
				computeFeaturesAfterOperation(features, newFeature, oldFeature);
			checkConstraints(features, status);
			checkLicense(newFeature, status);
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}

	/*
	 * handle revert and restore
	 */
	private static void validateRevert(
		IInstallConfiguration config,
		ArrayList status) {
		try {
			// check the timeline and don't bother
			// to check anything else if negative
			if (!checkTimeline(config, status))
				return;
			ArrayList features = computeFeaturesAfterRevert(config);
			checkConstraints(features, status);
			checkRevertConstraints(features, status);

		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}

	/*
	 * Handle delta addition
	 */
	private static void validateDeltaConfigure(
		ISessionDelta delta,
		IFeatureReference[] deltaRefs,
		ArrayList status) {
		try {
			ArrayList features = computeFeaturesAfterDelta(delta, deltaRefs);
			checkConstraints(features, status);

		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}

	/*
	 * Handle one-click changes as a batch
	 */
	private static void validatePendingChanges(
		IInstallFeatureOperation[] jobs,
		ArrayList status) {
		try {
			ArrayList features = computeFeatures();
			ArrayList savedFeatures = features;
			int nexclusives = 0;

			// pass 1: see if we can process the entire "batch"
			ArrayList tmpStatus = new ArrayList();
			for (int i = 0; i < jobs.length; i++) {
				IInstallFeatureOperation job = jobs[i];

				IFeature newFeature = job.getFeature();
				IFeature oldFeature = job.getOldFeature();
				checkLicense(newFeature, status);
				if (jobs.length > 1 && newFeature.isExclusive()) {
					nexclusives++;
					status.add(
						createStatus(
							newFeature,
							UpdateUtils.getString(KEY_EXCLUSIVE)));
					continue;
				}
				features =
					computeFeaturesAfterOperation(
						features,
						newFeature,
						oldFeature);
			}
			if (nexclusives > 0)
				return;
			checkConstraints(features, tmpStatus);
			if (tmpStatus.size() == 0) // the whole "batch" is OK
				return;

			// pass 2: we have conflicts
			features = savedFeatures;
			for (int i = 0; i < jobs.length; i++) {
				IInstallFeatureOperation job = jobs[i];
				IFeature newFeature = job.getFeature();
				IFeature oldFeature = job.getOldFeature();

				features =
					computeFeaturesAfterOperation(
						features,
						newFeature,
						oldFeature);
					
				checkConstraints(features, status);
				if (status.size() > 0) {
					IStatus conflict =
						createStatus(
							newFeature,
							UpdateUtils.getString(KEY_CONFLICT));
					status.add(0, conflict);
					return;
				}
			}
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
	}

	/*
	 * Compute a list of configured features
	 */
	private static ArrayList computeFeatures() throws CoreException {
		return computeFeatures(true);
	}
	/*
	 * Compute a list of configured features
	 */
	private static ArrayList computeFeatures(boolean configuredOnly)
		throws CoreException {
		ArrayList features = new ArrayList();
		ILocalSite localSite = SiteManager.getLocalSite();
		IInstallConfiguration config = localSite.getCurrentConfiguration();
		IConfiguredSite[] csites = config.getConfiguredSites();

		for (int i = 0; i < csites.length; i++) {
			IConfiguredSite csite = csites[i];

			IFeatureReference[] crefs;

			if (configuredOnly)
				crefs = csite.getConfiguredFeatures();
			else
				crefs = csite.getSite().getFeatureReferences();
			for (int j = 0; j < crefs.length; j++) {
				IFeatureReference cref = crefs[j];
				IFeature cfeature = cref.getFeature(null);
				features.add(cfeature);
			}
		}

		return features;
	}

	/*
	 * Compute the nested feature subtree starting at the specified base feature
	 */
	private static ArrayList computeFeatureSubtree(
		IFeature top,
		IFeature feature,
		ArrayList features,
		boolean tolerateMissingChildren)
		throws CoreException {
		return computeFeatureSubtree(
			top,
			feature,
			features,
			tolerateMissingChildren,
			null);
	}

	/*
	 * Compute the nested feature subtree starting at the specified base feature
	 */
	private static ArrayList computeFeatureSubtree(
		IFeature top,
		IFeature feature,
		ArrayList features,
		boolean tolerateMissingChildren,
		ArrayList configuredFeatures)
		throws CoreException {

		// check arguments
		if (features == null)
			features = new ArrayList();
		if (top == null)
			return features;
		if (feature == null)
			feature = top;

		// check for <includes> cycle
		if (features.contains(feature)) {
			IStatus status = createStatus(top, UpdateUtils.getString(KEY_CYCLE));
			throw new CoreException(status);
		}

		// return specified base feature and all its children
		features.add(feature);
		IIncludedFeatureReference[] children =
			feature.getIncludedFeatureReferences();
		for (int i = 0; i < children.length; i++) {
			try {
				IFeature child;
				if (configuredFeatures == null)
					child = children[i].getFeature(null);
				else
					child = getBestMatch(children[i], configuredFeatures);
				features =
					computeFeatureSubtree(
						top,
						child,
						features,
						tolerateMissingChildren);
			} catch (CoreException e) {
				if (!children[i].isOptional() && !tolerateMissingChildren)
					throw e;
			}
		}
		return features;
	}
	/*
	 * This method fixes the defect 34241. Included feature reference
	 * of the feature from the remote server always returns 
	 * a perfect match. However, the actual install behaviour is
	 * different if that feature already exists (as disabled) 
	 * while a better one is enabled. This typically happens
	 * through branch updates or patches.
	 * 
	 * To avoid this problem, we need to check if a better feature
	 * that still matches the reference is enabled in the current
	 * configuration. If it is, it will be used instead of the
	 * 'perfect' match. If not, we should default to the old
	 * behaviour.
	 */

	private static IFeature getBestMatch(
		IIncludedFeatureReference ref,
		ArrayList configuredFeatures)
		throws CoreException {
		int match = ref.getMatch();
		ISite site = ref.getSite();
		IConfiguredSite csite = site.getCurrentConfiguredSite();
		// If the feature is from the remote server and
		// it can handle better features, see if you can
		// resolve locally.
		if (csite == null && match != IUpdateConstants.RULE_PERFECT) {
			// there is a chance that there is a better match
			// in the platform
			VersionedIdentifier vid = ref.getVersionedIdentifier();
			PluginVersionIdentifier version = vid.getVersion();

			for (int i = 0; i < configuredFeatures.size(); i++) {
				IFeature feature = (IFeature) configuredFeatures.get(i);
				VersionedIdentifier fvid = feature.getVersionedIdentifier();
				if (fvid.getIdentifier().equals(vid.getIdentifier())) {
					// Feature found in local configuration.
					// Ignore if the same version.
					// Use it if better
					PluginVersionIdentifier fversion = fvid.getVersion();
					if (fversion.isGreaterThan(version)) {
						boolean matches = false;
						switch (match) {
							case IImport.RULE_COMPATIBLE :
								matches =
									fvid.getVersion().isCompatibleWith(
										vid.getVersion());
								break;
							case IImport.RULE_EQUIVALENT :
								matches =
									fvid.getVersion().isEquivalentTo(
										vid.getVersion());
								break;
							case IImport.RULE_GREATER_OR_EQUAL :
								matches =
									fvid.getVersion().isGreaterOrEqualTo(
										vid.getVersion());
								break;
						}
						if (matches)
							return feature;
					}
				}
			}
		}
		// fallback - just get the feature from the reference.
		return ref.getFeature(null);
	}

	private static void checkLicense(IFeature feature, ArrayList status) {
		IURLEntry licenseEntry = feature.getLicense();
		if (licenseEntry != null) {
			String license = licenseEntry.getAnnotation();
			if (license != null && license.trim().length() > 0)
				return;
		}
		status.add(createStatus(feature, UpdateUtils.getString(KEY_NO_LICENSE)));
	}

	/*
	 * Compute a list of features that will be configured after the operation
	 */
	private static ArrayList computeFeaturesAfterOperation(
		ArrayList features,
		IFeature add,
		IFeature remove)
		throws CoreException {

		ArrayList addTree =
			computeFeatureSubtree(
				add,
				null,
				null,
				false,
		/* do not tolerate missing children */
		features);
		ArrayList removeTree =
			computeFeatureSubtree(
				remove,
				null,
				null,
				true /* tolerate missing children */
		);
		if (remove != null) {
			// Patches to features are removed together with
			// those features. Include them in the list.
			contributePatchesFor(removeTree, features, removeTree);
		}

		if (remove != null)
			features.removeAll(removeTree);

		if (add != null)
			features.addAll(addTree);

		return features;
	}

	private static void contributePatchesFor(
		ArrayList removeTree,
		ArrayList features,
		ArrayList result)
		throws CoreException {

		for (int i = 0; i < removeTree.size(); i++) {
			IFeature feature = (IFeature) removeTree.get(i);
			contributePatchesFor(feature, features, result);
		}
	}

	private static void contributePatchesFor(
		IFeature feature,
		ArrayList features,
		ArrayList result)
		throws CoreException {
		for (int i = 0; i < features.size(); i++) {
			IFeature candidate = (IFeature) features.get(i);
			if (UpdateUtils.isPatch(feature, candidate)) {
				ArrayList removeTree =
					computeFeatureSubtree(candidate, null, null, true);
				result.addAll(removeTree);
			}
		}
	}

	/*
	 * Compute a list of features that will be configured after performing the revert
	 */
	private static ArrayList computeFeaturesAfterRevert(IInstallConfiguration config)
		throws CoreException {

		ArrayList list = new ArrayList();
		IConfiguredSite[] csites = config.getConfiguredSites();
		for (int i = 0; i < csites.length; i++) {
			IConfiguredSite csite = csites[i];
			IFeatureReference[] features = csite.getConfiguredFeatures();
			for (int j = 0; j < features.length; j++) {
				list.add(features[j].getFeature(null));
			}
		}
		return list;
	}

	/*
	 * Compute a list of features that will be configured after applying the
	 * specified delta
	 */
	private static ArrayList computeFeaturesAfterDelta(
		ISessionDelta delta,
		IFeatureReference[] deltaRefs)
		throws CoreException {

		if (delta == null || deltaRefs == null)
			deltaRefs = new IFeatureReference[0];
		else if (deltaRefs == null)
			deltaRefs = delta.getFeatureReferences();

		ArrayList features = new ArrayList(); // cumulative results list
		ILocalSite localSite = SiteManager.getLocalSite();
		IInstallConfiguration config = localSite.getCurrentConfiguration();
		IConfiguredSite[] csites = config.getConfiguredSites();

		// compute changes for each site
		for (int i = 0; i < csites.length; i++) {
			IConfiguredSite csite = csites[i];
			ArrayList siteFeatures = new ArrayList();

			// collect currently configured features on site
			IFeatureReference[] crefs = csite.getConfiguredFeatures();
			for (int j = 0; crefs != null && j < crefs.length; j++) {
				IFeatureReference cref = crefs[j];
				IFeature cfeature = cref.getFeature(null);
				siteFeatures.add(cfeature);
			}

			// add deltas for the site			
			for (int j = 0; j < deltaRefs.length; j++) {
				ISite deltaSite = deltaRefs[j].getSite();
				if (deltaSite.equals(csite.getSite())) {
					IFeature dfeature = deltaRefs[j].getFeature(null);
					if (!siteFeatures.contains(dfeature)) // don't add dups
						siteFeatures.add(dfeature);
				}
			}

			// reduce the list if needed	
			IFeature[] array =
				(IFeature[]) siteFeatures.toArray(
					new IFeature[siteFeatures.size()]);
			ArrayList removeTree = new ArrayList();
			for (int j = 0; j < array.length; j++) {
				VersionedIdentifier id1 = array[j].getVersionedIdentifier();
				for (int k = 0; k < array.length; k++) {
					if (j == k)
						continue;
					VersionedIdentifier id2 = array[k].getVersionedIdentifier();
					if (id1.getIdentifier().equals(id2.getIdentifier())) {
						if (id2.getVersion().isGreaterThan(id1.getVersion())) {
							removeTree.add(array[j]);
							siteFeatures.remove(array[j]);
							break;
						}
					}
				}
			}
			// Compute patches that will need to be removed together with 
			// the removed features
			ArrayList patchesTree = new ArrayList();
			contributePatchesFor(removeTree, siteFeatures, patchesTree);
			siteFeatures.removeAll(patchesTree);

			// accumulate site results
			features.addAll(siteFeatures);
		}

		return features;
	}

	/*
	 * Compute a list of plugin entries for the specified features.
	 */
	private static ArrayList computePluginsForFeatures(ArrayList features)
		throws CoreException {
		if (features == null)
			return new ArrayList();

		HashMap plugins = new HashMap();
		for (int i = 0; i < features.size(); i++) {
			IFeature feature = (IFeature) features.get(i);
			IPluginEntry[] entries = feature.getPluginEntries();
			for (int j = 0; j < entries.length; j++) {
				IPluginEntry entry = entries[j];
				plugins.put(entry.getVersionedIdentifier(), entry);
			}
		}
		ArrayList result = new ArrayList();
		result.addAll(plugins.values());
		return result;
	}

	private static boolean isPatch(IFeature feature) {
		IImport[] imports = feature.getImports();
		for (int i = 0; i < imports.length; i++) {
			IImport iimport = imports[i];
			if (iimport.isPatch()) {
				return true;
			}
		}
		return false;
	}

	/*
	 * 
	 */
	private static void checkUnique(
		IFeature feature,
		ArrayList features,
		ArrayList status)
		throws CoreException {
		if (features == null)
			return;
		IIncludedFeatureReference[] irefs =
			feature.getIncludedFeatureReferences();
		for (int i = 0; i < irefs.length; i++) {
			IIncludedFeatureReference iref = irefs[i];
			IFeature ifeature = iref.getFeature(null);
			boolean patch = isPatch(ifeature);
			VersionedIdentifier vid = ifeature.getVersionedIdentifier();
			String id = vid.getIdentifier();
			PluginVersionIdentifier version = vid.getVersion();
			boolean found = false;
			for (int j = 0; j < features.size(); j++) {
				IFeature candidate = (IFeature) features.get(j);
				VersionedIdentifier cvid = candidate.getVersionedIdentifier();
				String cid = cvid.getIdentifier();
				PluginVersionIdentifier cversion = cvid.getVersion();
				if (cid.equals(id)) {
					// The same identifier - this one will
					// be unconfigured. Check if it is lower,
					// otherwise flag.
					found = true;
					// Ignore equal - will be filtered in the download
					if (version.equals(cversion))
						continue;
					// Flag only the case when the installed one is
					// newer than the one that will be installed.
					if (!version.isGreaterThan(cversion)) {
						// Don't allow this.
						String msg =
							UpdateUtils.getFormattedMessage(
								KEY_PATCH_REGRESSION,
								new String[] {
									ifeature.getLabel(),
									version.toString()});
						status.add(createStatus(feature, msg));

					}
				}
			}
			if (!found) {
				// All the features carried in a patch must
				// already be present, unless this feature
				// is a patch itself

				// 30849: optional feature does not
				// need to be present.
				if (!patch && iref.isOptional() == false) {
					String msg =
						UpdateUtils.getFormattedMessage(
							KEY_PATCH_MISSING_TARGET,
							new String[] {
								ifeature.getLabel(),
								version.toString()});
					status.add(createStatus(feature, msg));
				}
			}
			if (patch)
				checkUnique(ifeature, features, status);
		}
	}

	/*
	 * validate constraints
	 */
	private static void checkConstraints(ArrayList features, ArrayList status)
		throws CoreException {
		if (features == null)
			return;

		ArrayList plugins = computePluginsForFeatures(features);

		checkEnvironment(features, status);
		checkPlatformFeature(features, plugins, status);
		checkPrimaryFeature(features, status);
		checkPrereqs(features, plugins, status);
	}

	/*
	 * Verify all features are either portable, or match the current environment
	 */
	private static void checkEnvironment(
		ArrayList features,
		ArrayList status) {

		String os = BootLoader.getOS();
		String ws = BootLoader.getWS();
		String arch = BootLoader.getOSArch();

		for (int i = 0; i < features.size(); i++) {
			IFeature feature = (IFeature) features.get(i);
			ArrayList fos = createList(feature.getOS());
			ArrayList fws = createList(feature.getWS());
			ArrayList farch = createList(feature.getOSArch());

			if (fos.size() > 0) {
				if (!fos.contains(os)) {
					status.add(
						createStatus(feature, UpdateUtils.getString(KEY_OS)));
					continue;
				}
			}

			if (fws.size() > 0) {
				if (!fws.contains(ws)) {
					status.add(
						createStatus(feature, UpdateUtils.getString(KEY_WS)));
					continue;
				}
			}

			if (farch.size() > 0) {
				if (!farch.contains(arch)) {
					status.add(
						createStatus(feature, UpdateUtils.getString(KEY_ARCH)));
					continue;
				}
			}
		}
	}

	/*
	 * Verify we end up with a version of platform configured
	 */
	private static void checkPlatformFeature(
		ArrayList features,
		ArrayList plugins,
		ArrayList status) {

		String[] bootstrapPlugins =
			BootLoader
				.getCurrentPlatformConfiguration()
				.getBootstrapPluginIdentifiers();

		for (int i = 0; i < bootstrapPlugins.length; i++) {
			boolean found = false;
			for (int j = 0; j < plugins.size(); j++) {
				IPluginEntry plugin = (IPluginEntry) plugins.get(j);
				if (bootstrapPlugins[i]
					.equals(plugin.getVersionedIdentifier().getIdentifier())) {
					found = true;
					break;
				}
			}
			if (!found) {
				status.add(
					createStatus(null, UpdateUtils.getString(KEY_PLATFORM)));
				return;
			}
		}
	}

	/*
	 * Verify we end up with a version of primary feature configured
	 */
	private static void checkPrimaryFeature(
		ArrayList features,
		ArrayList status) {

		String featureId =
			BootLoader
				.getCurrentPlatformConfiguration()
				.getPrimaryFeatureIdentifier();

		for (int i = 0; i < features.size(); i++) {
			IFeature feature = (IFeature) features.get(i);
			if (featureId
				.equals(feature.getVersionedIdentifier().getIdentifier()))
				return;
		}

		status.add(createStatus(null, UpdateUtils.getString(KEY_PRIMARY)));
	}

	/*
	 * Verify we do not break prereqs
	 */
	private static void checkPrereqs(
		ArrayList features,
		ArrayList plugins,
		ArrayList status) {

		for (int i = 0; i < features.size(); i++) {
			IFeature feature = (IFeature) features.get(i);
			IImport[] imports = feature.getImports();

			for (int j = 0; j < imports.length; j++) {
				IImport iimport = imports[j];
				// for each import determine plugin or feature, version, match we need
				VersionedIdentifier iid = iimport.getVersionedIdentifier();
				String id = iid.getIdentifier();
				PluginVersionIdentifier version = iid.getVersion();
				boolean featurePrereq =
					iimport.getKind() == IImport.KIND_FEATURE;
				boolean ignoreVersion =
					version.getMajorComponent() == 0
						&& version.getMinorComponent() == 0
						&& version.getServiceComponent() == 0;
				int rule = iimport.getRule();
				if (rule == IImport.RULE_NONE)
					rule = IImport.RULE_COMPATIBLE;

				boolean found = false;

				ArrayList candidates;

				if (featurePrereq)
					candidates = features;
				else
					candidates = plugins;
				for (int k = 0; k < candidates.size(); k++) {
					VersionedIdentifier cid;
					if (featurePrereq) {
						// the candidate is a feature
						IFeature candidate = (IFeature) candidates.get(k);
						// skip self
						if (feature.equals(candidate))
							continue;
						cid = candidate.getVersionedIdentifier();
					} else {
						// the candidate is a plug-in
						IPluginEntry plugin = (IPluginEntry) candidates.get(k);
						cid = plugin.getVersionedIdentifier();
					}
					PluginVersionIdentifier cversion = cid.getVersion();
					if (id.equals(cid.getIdentifier())) {
						// have a candidate
						if (ignoreVersion)
							found = true;
						else if (
							rule == IImport.RULE_PERFECT
								&& cversion.isPerfect(version))
							found = true;
						else if (
							rule == IImport.RULE_EQUIVALENT
								&& cversion.isEquivalentTo(version))
							found = true;
						else if (
							rule == IImport.RULE_COMPATIBLE
								&& cversion.isCompatibleWith(version))
							found = true;
						else if (
							rule == IImport.RULE_GREATER_OR_EQUAL
								&& cversion.isGreaterOrEqualTo(version))
							found = true;
					}
					if (found)
						break;
				}

				if (!found) {
					// report status
					String target =
						featurePrereq
							? UpdateUtils.getString(KEY_PREREQ_FEATURE)
							: UpdateUtils.getString(KEY_PREREQ_PLUGIN);
					String msg =
						UpdateUtils.getFormattedMessage(
							KEY_PREREQ,
							new String[] { target, id });

					if (!ignoreVersion) {
						if (rule == IImport.RULE_PERFECT)
							msg =
								UpdateUtils.getFormattedMessage(
									KEY_PREREQ_PERFECT,
									new String[] {
										target,
										id,
										version.toString()});
						else if (rule == IImport.RULE_EQUIVALENT)
							msg =
								UpdateUtils.getFormattedMessage(
									KEY_PREREQ_EQUIVALENT,
									new String[] {
										target,
										id,
										version.toString()});
						else if (rule == IImport.RULE_COMPATIBLE)
							msg =
								UpdateUtils.getFormattedMessage(
									KEY_PREREQ_COMPATIBLE,
									new String[] {
										target,
										id,
										version.toString()});
						else if (rule == IImport.RULE_GREATER_OR_EQUAL)
							msg =
								UpdateUtils.getFormattedMessage(
									KEY_PREREQ_GREATER,
									new String[] {
										target,
										id,
										version.toString()});
					}
					status.add(createStatus(feature, msg));
				}
			}
		}
	}

	/*
	 * Verify we end up with valid nested features after revert
	 */
	private static void checkRevertConstraints(
		ArrayList features,
		ArrayList status) {

		for (int i = 0; i < features.size(); i++) {
			IFeature feature = (IFeature) features.get(i);
			try {
				computeFeatureSubtree(
					feature,
					null,
					null,
					false /* do not tolerate missing children */
				);
			} catch (CoreException e) {
				status.add(e.getStatus());
			}
		}
	}

	/*
	 * Verify that a parent of an optional child is configured
	 * before we allow the child to be configured as well
	 */

	private static void checkOptionalChildConfiguring(
		IFeature feature,
		ArrayList status)
		throws CoreException {
		ILocalSite localSite = SiteManager.getLocalSite();
		IInstallConfiguration config = localSite.getCurrentConfiguration();
		IConfiguredSite[] csites = config.getConfiguredSites();

		boolean included = false;
		for (int i = 0; i < csites.length; i++) {
			IConfiguredSite csite = csites[i];
			ISiteFeatureReference[] crefs =
				csite.getSite().getFeatureReferences();
			for (int j = 0; j < crefs.length; j++) {
				IFeatureReference cref = crefs[j];
				IFeature cfeature = null;
				try {
					cfeature = cref.getFeature(null);
				} catch (CoreException e) {
					//FIXME: cannot ask 'isOptional' here
					// Ignore missing optional feature.
					/* if (cref.isOptional())
						continue;
					else */
					throw e;
				}
				if (isParent(cfeature, feature, true)) {
					// Included in at least one feature as optional
					included = true;
					if (csite.isConfigured(cfeature)) {
						// At least one feature parent
						// is enabled - it is OK to
						// configure optional child.
						return;
					}
				}
			}
		}
		if (included) {
			// feature is included as optional but
			// no parent is currently configured.
			String msg = UpdateUtils.getString(KEY_OPTIONAL_CHILD);
			status.add(createStatus(feature, msg));
		} else {
			//feature is root - can be configured
		}
	}

	private static boolean isParent(
		IFeature candidate,
		IFeature feature,
		boolean optionalOnly)
		throws CoreException {
		IIncludedFeatureReference[] refs =
			candidate.getIncludedFeatureReferences();
		for (int i = 0; i < refs.length; i++) {
			IIncludedFeatureReference child = refs[i];
			VersionedIdentifier fvid = feature.getVersionedIdentifier();
			VersionedIdentifier cvid = child.getVersionedIdentifier();

			if (fvid.getIdentifier().equals(cvid.getIdentifier()) == false)
				continue;
			// same ID
			PluginVersionIdentifier fversion = fvid.getVersion();
			PluginVersionIdentifier cversion = cvid.getVersion();

			int match = child.getMatch();
			boolean matched = false;

			switch (match) {
				case IUpdateConstants.RULE_EQUIVALENT :
					if (fversion.isEquivalentTo(cversion))
						matched = true;
					break;
				case IUpdateConstants.RULE_COMPATIBLE :
					if (fversion.isCompatibleWith(cversion))
						matched = true;
					break;
				case IUpdateConstants.RULE_GREATER_OR_EQUAL :
					if (fversion.isGreaterOrEqualTo(cversion))
						matched = true;
					break;
				default :
					if (fversion.equals(cversion))
						matched = true;

			}
			if (matched) {
				// included and matched; return true if optionality is not 
				// important or it is and the inclusion is optional
				return optionalOnly == false || child.isOptional();
			}
		}
		return false;
	}

	private static boolean checkTimeline(
		IInstallConfiguration config,
		ArrayList status) {
		try {
			ILocalSite lsite = SiteManager.getLocalSite();
			IInstallConfiguration cconfig = lsite.getCurrentConfiguration();
			if (cconfig.getTimeline() != config.getTimeline()) {
				// Not the same timeline - cannot revert
				String msg =
					UpdateUtils.getFormattedMessage(
						KEY_WRONG_TIMELINE,
						config.getLabel());
				status.add(createStatus(null, msg));
				return false;
			}
		} catch (CoreException e) {
			status.add(e.getStatus());
		}
		return true;
	}

	private static IStatus createMultiStatus(
		String rootKey,
		ArrayList children) {
		IStatus[] carray =
			(IStatus[]) children.toArray(new IStatus[children.size()]);
		String message = UpdateUtils.getString(rootKey);
		return new MultiStatus(
			UpdateCore.getPlugin().getDescriptor().getUniqueIdentifier(),
			IStatus.ERROR,
			carray,
			message,
			null);
	}

	private static IStatus createStatus(IFeature feature, String message) {

		String fullMessage;
		if (feature == null)
			fullMessage = message;
		else {
			PluginVersionIdentifier version =
				feature.getVersionedIdentifier().getVersion();
			fullMessage =
				UpdateUtils.getFormattedMessage(
					KEY_CHILD_MESSAGE,
					new String[] {
						feature.getLabel(),
						version.toString(),
						message });
		}

		return new Status(
			IStatus.ERROR,
			UpdateCore.getPlugin().getDescriptor().getUniqueIdentifier(),
			IStatus.OK,
			fullMessage,
			null);
	}

	private static ArrayList createList(String commaSeparatedList) {
		ArrayList list = new ArrayList();
		if (commaSeparatedList != null) {
			StringTokenizer t =
				new StringTokenizer(commaSeparatedList.trim(), ",");
			while (t.hasMoreTokens()) {
				String token = t.nextToken().trim();
				if (!token.equals(""))
					list.add(token);
			}
		}
		return list;
	}
}