/*******************************************************************************
 * Copyright (c) 2004, 2010 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.osgi.internal.module;

import java.util.*;
import java.util.Map.Entry;
import org.eclipse.osgi.service.resolver.*;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.Capability;

/*
 * A companion to BundleDescription from the state used while resolving.
 */
public class ResolverBundle extends VersionSupplier implements Comparable<ResolverBundle>, BundleRevision {
	public static final int UNRESOLVED = 0;
	public static final int RESOLVING = 1;
	public static final int RESOLVED = 2;

	private final Long bundleID;
	private BundleConstraint host;
	private ResolverImport[] imports;
	private ResolverExport[] exports;
	private BundleConstraint[] requires;
	private GenericCapability[] genericCapabilities;
	private GenericConstraint[] genericReqiures;
	// Fragment support
	private ArrayList<ResolverBundle> fragments;
	private HashMap<Long, List<ResolverExport>> fragmentExports;
	private HashMap<Long, List<ResolverImport>> fragmentImports;
	private HashMap<Long, List<BundleConstraint>> fragmentRequires;
	private HashMap<Long, List<GenericCapability>> fragmentGenericCapabilities;
	private HashMap<Long, List<GenericConstraint>> fragmentGenericRequires;
	// Flag specifying whether this bundle is resolvable
	private boolean resolvable = true;
	// Internal resolver state for this bundle
	private int state = UNRESOLVED;
	private boolean uninstalled = false;
	private final ResolverImpl resolver;
	private boolean newFragmentExports;
	private boolean newFragmentCapabilities;
	private List<ResolverBundle> refs;

	ResolverBundle(BundleDescription bundle, ResolverImpl resolver) {
		super(bundle);
		this.bundleID = new Long(bundle.getBundleId());
		this.resolver = resolver;
		initialize(bundle.isResolved());
	}

	void initialize(boolean useSelectedExports) {
		if (getBundleDescription().isSingleton())
			refs = new ArrayList<ResolverBundle>();
		if (getBundleDescription().getHost() != null) {
			host = new BundleConstraint(this, getBundleDescription().getHost());
			exports = new ResolverExport[0];
			imports = new ResolverImport[0];
			requires = new BundleConstraint[0];
			genericReqiures = new GenericConstraint[0];
			genericCapabilities = new GenericCapability[0];
			return;
		}

		ImportPackageSpecification[] actualImports = getBundleDescription().getImportPackages();
		// Reorder imports so that optionals are at the end so that we wire statics before optionals
		List<ResolverImport> importList = new ArrayList<ResolverImport>(actualImports.length);
		for (int i = actualImports.length - 1; i >= 0; i--)
			if (ImportPackageSpecification.RESOLUTION_OPTIONAL.equals(actualImports[i].getDirective(Constants.RESOLUTION_DIRECTIVE)))
				importList.add(new ResolverImport(this, actualImports[i]));
			else
				importList.add(0, new ResolverImport(this, actualImports[i]));
		imports = importList.toArray(new ResolverImport[importList.size()]);

		ExportPackageDescription[] actualExports = useSelectedExports ? getBundleDescription().getSelectedExports() : getBundleDescription().getExportPackages();
		exports = new ResolverExport[actualExports.length];
		for (int i = 0; i < actualExports.length; i++)
			exports[i] = new ResolverExport(this, actualExports[i]);

		BundleSpecification[] actualRequires = getBundleDescription().getRequiredBundles();
		requires = new BundleConstraint[actualRequires.length];
		for (int i = 0; i < requires.length; i++)
			requires[i] = new BundleConstraint(this, actualRequires[i]);

		GenericSpecification[] actualGenericRequires = getBundleDescription().getGenericRequires();
		genericReqiures = new GenericConstraint[actualGenericRequires.length];
		for (int i = 0; i < genericReqiures.length; i++)
			genericReqiures[i] = new GenericConstraint(this, actualGenericRequires[i]);

		GenericDescription[] actualCapabilities = useSelectedExports ? getBundleDescription().getSelectedGenericCapabilities() : getBundleDescription().getGenericCapabilities();
		genericCapabilities = new GenericCapability[actualCapabilities.length];
		for (int i = 0; i < genericCapabilities.length; i++)
			genericCapabilities[i] = new GenericCapability(this, actualCapabilities[i]);

		fragments = null;
		fragmentExports = null;
		fragmentImports = null;
		fragmentRequires = null;
		fragmentGenericCapabilities = null;
		fragmentGenericRequires = null;
	}

	ResolverExport getExport(String name) {
		ResolverExport[] allExports = getExports(name);
		return allExports.length == 0 ? null : allExports[0];
	}

	ResolverExport[] getExports(String name) {
		List<ResolverExport> results = new ArrayList<ResolverExport>(1); // rare to have more than one
		// it is faster to ask the VersionHashMap for this package name and then compare the exporter to this
		List<ResolverExport> resolverExports = resolver.getResolverExports().get(name);
		for (ResolverExport export : resolverExports)
			if (export.getExporter() == this)
				results.add(export);
		return results.toArray(new ResolverExport[results.size()]);
	}

	void clearWires() {
		ResolverImport[] allImports = getImportPackages();
		for (int i = 0; i < allImports.length; i++)
			allImports[i].clearPossibleSuppliers();

		if (host != null)
			host.clearPossibleSuppliers();

		BundleConstraint[] allRequires = getRequires();
		for (int i = 0; i < allRequires.length; i++)
			allRequires[i].clearPossibleSuppliers();

		GenericConstraint[] allGenericRequires = getGenericRequires();
		for (int i = 0; i < allGenericRequires.length; i++)
			allGenericRequires[i].clearPossibleSuppliers();

		ResolverExport[] allExports = getExportPackages();
		for (int i = 0; i < allExports.length; i++)
			allExports[i].setSubstitute(null);
	}

	boolean isResolved() {
		return getState() == ResolverBundle.RESOLVED;
	}

	boolean isFragment() {
		return host != null;
	}

	int getState() {
		return state;
	}

	void setState(int state) {
		this.state = state;
	}

	private <T> List<T> getAll(T[] hostEntries, Map<Long, List<T>> fragmentMap) {
		List<T> result = new ArrayList<T>(hostEntries.length);
		for (T entry : hostEntries)
			result.add(entry);
		for (ResolverBundle fragment : fragments) {
			List<T> fragEntries = fragmentMap.get(fragment.bundleID);
			if (fragEntries != null)
				result.addAll(fragEntries);
		}
		return result;
	}

	ResolverImport[] getImportPackages() {
		if (isFragment() || fragments == null || fragments.size() == 0)
			return imports;
		List<ResolverImport> result = getAll(imports, fragmentImports);
		return result.toArray(new ResolverImport[result.size()]);
	}

	ResolverExport[] getExportPackages() {
		if (isFragment() || fragments == null || fragments.size() == 0)
			return exports;
		List<ResolverExport> result = getAll(exports, fragmentExports);
		return result.toArray(new ResolverExport[result.size()]);
	}

	ResolverExport[] getSelectedExports() {
		return getExports(true);
	}

	ResolverExport[] getSubstitutedExports() {
		return getExports(false);
	}

	private ResolverExport[] getExports(boolean selected) {
		ResolverExport[] results = getExportPackages();
		int removedExports = 0;
		for (int i = 0; i < results.length; i++)
			if (selected ? results[i].getSubstitute() != null : results[i].getSubstitute() == null)
				removedExports++;
		if (removedExports == 0)
			return results;
		ResolverExport[] selectedExports = new ResolverExport[results.length - removedExports];
		int index = 0;
		for (int i = 0; i < results.length; i++) {
			if (selected ? results[i].getSubstitute() != null : results[i].getSubstitute() == null)
				continue;
			selectedExports[index] = results[i];
			index++;
		}
		return selectedExports;
	}

	BundleConstraint getHost() {
		return host;
	}

	GenericCapability[] getGenericCapabilities() {
		if (isFragment() || fragments == null || fragments.size() == 0)
			return genericCapabilities;
		List<GenericCapability> result = getAll(genericCapabilities, fragmentGenericCapabilities);
		return result.toArray(new GenericCapability[result.size()]);
	}

	BundleConstraint[] getRequires() {
		if (isFragment() || fragments == null || fragments.size() == 0)
			return requires;
		List<BundleConstraint> result = getAll(requires, fragmentRequires);
		return result.toArray(new BundleConstraint[result.size()]);
	}

	GenericConstraint[] getGenericRequires() {
		if (isFragment() || fragments == null || fragments.size() == 0)
			return genericReqiures;
		List<GenericConstraint> result = getAll(genericReqiures, fragmentGenericRequires);
		return result.toArray(new GenericConstraint[result.size()]);
	}

	BundleConstraint getRequire(String name) {
		BundleConstraint[] allRequires = getRequires();
		for (int i = 0; i < allRequires.length; i++)
			if (allRequires[i].getVersionConstraint().getName().equals(name))
				return allRequires[i];
		return null;
	}

	public BundleDescription getBundleDescription() {
		return (BundleDescription) getBaseDescription();
	}

	public ResolverBundle getResolverBundle() {
		return this;
	}

	ResolverImport getImport(String name) {
		ResolverImport[] allImports = getImportPackages();
		for (int i = 0; i < allImports.length; i++) {
			if (allImports[i].getName().equals(name)) {
				return allImports[i];
			}
		}
		return null;
	}

	public String toString() {
		return "[" + getBundleDescription() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
	}

	private void initFragments() {
		if (fragments == null)
			fragments = new ArrayList<ResolverBundle>(1);
		if (fragmentExports == null)
			fragmentExports = new HashMap<Long, List<ResolverExport>>(1);
		if (fragmentImports == null)
			fragmentImports = new HashMap<Long, List<ResolverImport>>(1);
		if (fragmentRequires == null)
			fragmentRequires = new HashMap<Long, List<BundleConstraint>>(1);
		if (fragmentGenericCapabilities == null)
			fragmentGenericCapabilities = new HashMap<Long, List<GenericCapability>>(1);
		if (fragmentGenericRequires == null)
			fragmentGenericRequires = new HashMap<Long, List<GenericConstraint>>(1);
	}

	private boolean isImported(String packageName) {
		ResolverImport[] allImports = getImportPackages();
		for (int i = 0; i < allImports.length; i++)
			if (packageName.equals(allImports[i].getName()))
				return true;

		return false;
	}

	private boolean isRequired(String bundleName) {
		return getRequire(bundleName) != null;
	}

	void attachFragment(ResolverBundle fragment, boolean dynamicAttach) {
		if (isFragment())
			return; // cannot attach to fragments;
		if (!getBundleDescription().attachFragments() || (isResolved() && !getBundleDescription().dynamicFragments()))
			return; // host is restricting attachment
		if (fragment.getHost().getNumPossibleSuppliers() > 0 && !((HostSpecification) fragment.getHost().getVersionConstraint()).isMultiHost())
			return; // fragment is restricting attachment

		ImportPackageSpecification[] newImports = fragment.getBundleDescription().getImportPackages();
		BundleSpecification[] newRequires = fragment.getBundleDescription().getRequiredBundles();
		ExportPackageDescription[] newExports = fragment.getBundleDescription().getExportPackages();
		GenericDescription[] newGenericCapabilities = fragment.getBundleDescription().getGenericCapabilities();
		GenericSpecification[] newGenericRequires = fragment.getBundleDescription().getGenericRequires();

		// if this is not during initialization then check if constraints conflict
		if (dynamicAttach && constraintsConflict(fragment.getBundleDescription(), newImports, newRequires, newGenericRequires))
			return; // do not allow fragments with conflicting constraints
		if (isResolved() && newExports.length > 0)
			fragment.setNewFragmentExports(true);
		if (isResolved() && newGenericCapabilities.length > 0)
			fragment.setNewFragmentCapabilities(true);

		initFragments();
		// need to make sure there is not already another version of this fragment 
		// already attached to this host
		for (Iterator<ResolverBundle> iFragments = fragments.iterator(); iFragments.hasNext();) {
			ResolverBundle existingFragment = iFragments.next();
			String bsn = existingFragment.getName();
			if (bsn != null && bsn.equals(fragment.getName()))
				return;
		}
		if (fragments.contains(fragment))
			return;
		fragments.add(fragment);
		fragment.getHost().addPossibleSupplier(this);

		if (newImports.length > 0) {
			ArrayList<ResolverImport> hostImports = new ArrayList<ResolverImport>(newImports.length);
			for (int i = 0; i < newImports.length; i++)
				if (!isImported(newImports[i].getName()))
					hostImports.add(new ResolverImport(this, newImports[i]));
			fragmentImports.put(fragment.bundleID, hostImports);
		}

		if (newRequires.length > 0) {
			ArrayList<BundleConstraint> hostRequires = new ArrayList<BundleConstraint>(newRequires.length);
			for (int i = 0; i < newRequires.length; i++)
				if (!isRequired(newRequires[i].getName()))
					hostRequires.add(new BundleConstraint(this, newRequires[i]));
			fragmentRequires.put(fragment.bundleID, hostRequires);
		}

		if (newGenericRequires.length > 0) {
			ArrayList<GenericConstraint> hostGenericRequires = new ArrayList<GenericConstraint>(newGenericRequires.length);
			for (int i = 0; i < newGenericRequires.length; i++)
				hostGenericRequires.add(new GenericConstraint(this, newGenericRequires[i]));
			fragmentGenericRequires.put(fragment.bundleID, hostGenericRequires);
		}

		ArrayList<ResolverExport> hostExports = new ArrayList<ResolverExport>(newExports.length);
		if (newExports.length > 0 && dynamicAttach) {
			StateObjectFactory factory = resolver.getState().getFactory();
			for (int i = 0; i < newExports.length; i++) {
				ResolverExport currentExports[] = getExports(newExports[i].getName());
				boolean foundEquivalent = false;
				for (int j = 0; j < currentExports.length && !foundEquivalent; j++) {
					if (equivalentExports(currentExports[j], newExports[i]))
						foundEquivalent = true;
				}
				if (!foundEquivalent) {
					ExportPackageDescription hostExport = factory.createExportPackageDescription(newExports[i].getName(), newExports[i].getVersion(), newExports[i].getDirectives(), newExports[i].getAttributes(), true, getBundleDescription());
					hostExports.add(new ResolverExport(this, hostExport));
				}
			}
			fragmentExports.put(fragment.bundleID, hostExports);
		}

		List<GenericCapability> hostCapabilities = new ArrayList<GenericCapability>(newGenericCapabilities.length);
		if (newGenericCapabilities.length > 0 && dynamicAttach) {
			StateObjectFactory factory = resolver.getState().getFactory();
			for (GenericDescription capability : newGenericCapabilities) {
				Dictionary<String, Object> origAttrs = capability.getAttributes();
				Map<String, Object> attrs = new HashMap<String, Object>();
				if (origAttrs != null) {
					for (Enumeration<String> keys = origAttrs.keys(); keys.hasMoreElements();) {
						String key = keys.nextElement();
						attrs.put(key, origAttrs.get(key));
					}
				}
				GenericDescription hostCapabililty = factory.createGenericDescription(capability.getType(), attrs, null, getBundleDescription());
				hostCapabilities.add(new GenericCapability(this, hostCapabililty));
			}
			fragmentGenericCapabilities.put(fragment.bundleID, hostCapabilities);
		}
		if (dynamicAttach) {
			resolver.getResolverExports().put(hostExports.toArray(new ResolverExport[hostExports.size()]));
			resolver.addGenerics(hostCapabilities.toArray(new GenericCapability[hostCapabilities.size()]));
		}
	}

	private boolean equivalentExports(ResolverExport existingExport, ExportPackageDescription newDescription) {
		ExportPackageDescription existingDescription = existingExport.getExportPackageDescription();
		if (!existingDescription.getName().equals(newDescription.getName()))
			return false;
		if (!existingDescription.getVersion().equals(newDescription.getVersion()))
			return false;
		if (!equivalentMaps(existingDescription.getAttributes(), newDescription.getAttributes(), true))
			return false;
		if (!equivalentMaps(existingDescription.getDirectives(), newDescription.getDirectives(), true))
			return false;
		return true;
	}

	public static boolean equivalentMaps(Map<String, Object> existingDirectives, Map<String, Object> newDirectives, boolean exactMatch) {
		if (existingDirectives == null && newDirectives == null)
			return true;
		if (existingDirectives == null ? newDirectives != null : newDirectives == null)
			return false;
		if (exactMatch && existingDirectives.size() != newDirectives.size())
			return false;
		for (Iterator<Entry<String, Object>> entries = existingDirectives.entrySet().iterator(); entries.hasNext();) {
			Entry<String, Object> entry = entries.next();
			Object newValue = newDirectives.get(entry.getKey());
			if (newValue == null || entry.getValue().getClass() != newValue.getClass())
				return false;
			if (newValue instanceof String[]) {
				if (!Arrays.equals((Object[]) entry.getValue(), (Object[]) newValue))
					return false;
			} else if (!entry.getValue().equals(newValue)) {
				return false;
			}
		}
		return true;
	}

	boolean constraintsConflict(BundleDescription fragment, ImportPackageSpecification[] newImports, BundleSpecification[] newRequires, GenericSpecification[] newGenericRequires) {
		// this method iterates over all additional constraints from a fragment
		// if the host is resolved then the fragment is not allowed to add new constraints;
		// if the host is resolved and it already has a constraint of the same name then ensure the supplier satisfies the fragment's constraint
		boolean result = false;
		for (int i = 0; i < newImports.length; i++) {
			ResolverImport hostImport = getImport(newImports[i].getName());
			ResolverExport resolvedExport = (ResolverExport) (hostImport == null ? null : hostImport.getSelectedSupplier());
			if ((resolvedExport == null && isResolved()) || (resolvedExport != null && !newImports[i].isSatisfiedBy(resolvedExport.getExportPackageDescription()))) {
				result = true;
				resolver.getState().addResolverError(fragment, ResolverError.FRAGMENT_CONFLICT, newImports[i].toString(), newImports[i]);
			}
		}
		for (int i = 0; i < newRequires.length; i++) {
			BundleConstraint hostRequire = getRequire(newRequires[i].getName());
			ResolverBundle resolvedRequire = (ResolverBundle) (hostRequire == null ? null : hostRequire.getSelectedSupplier());
			if ((resolvedRequire == null && isResolved()) || (resolvedRequire != null && !newRequires[i].isSatisfiedBy(resolvedRequire.getBundleDescription()))) {
				result = true;
				resolver.getState().addResolverError(fragment, ResolverError.FRAGMENT_CONFLICT, newRequires[i].toString(), newRequires[i]);
			}
		}
		// generic constraints cannot conflict; 
		// only check that a fragment does not add generics constraints to an already resolved host
		if (isResolved() && newGenericRequires != null && newGenericRequires.length > 0)
			result = true;
		return result;
	}

	private void setNewFragmentExports(boolean newFragmentExports) {
		this.newFragmentExports = newFragmentExports;
	}

	boolean isNewFragmentExports() {
		return newFragmentExports;
	}

	private void setNewFragmentCapabilities(boolean newFragmentCapabilities) {
		this.newFragmentCapabilities = newFragmentCapabilities;
	}

	boolean isNewFragmentCapabilities() {
		return newFragmentCapabilities;
	}

	void detachFragment(ResolverBundle fragment, ResolverConstraint reason) {
		if (isFragment())
			return;
		initFragments();

		// must save off old imports and requires before we remove the fragment;
		// this will be used to merge the constraints of the same name from the remaining fragments 
		ResolverImport[] oldImports = getImportPackages();
		BundleConstraint[] oldRequires = getRequires();
		if (!fragments.remove(fragment))
			return;

		fragment.setNewFragmentExports(false);
		fragment.setNewFragmentCapabilities(false);
		fragment.getHost().removePossibleSupplier(this);
		fragmentImports.remove(fragment.bundleID);
		fragmentRequires.remove(fragment.bundleID);
		List<ResolverExport> removedExports = fragmentExports.remove(fragment.bundleID);
		fragmentGenericRequires.remove(fragment.bundleID);
		List<GenericCapability> removedCapabilities = fragmentGenericCapabilities.remove(fragment.bundleID);
		if (reason != null) {
			// the fragment is being detached because one of its imports or requires cannot be resolved;
			// we need to check the remaining fragment constraints to make sure they do not have
			// the same unresolved constraint.
			for (ResolverBundle remainingFrag : fragments) {
				List<ResolverImport> additionalImports = new ArrayList<ResolverImport>(0);
				List<BundleConstraint> additionalRequires = new ArrayList<BundleConstraint>(0);
				if (hasUnresolvedConstraint(reason, fragment, remainingFrag, oldImports, oldRequires, additionalImports, additionalRequires))
					continue;
				// merge back the additional imports or requires which the detached fragment has in common with the remaining fragment
				if (additionalImports.size() > 0) {
					List<ResolverImport> remainingImports = fragmentImports.get(remainingFrag.bundleID);
					if (remainingImports == null)
						fragmentImports.put(remainingFrag.bundleID, additionalImports);
					else
						remainingImports.addAll(additionalImports);
				}
				if (additionalRequires.size() > 0) {
					List<BundleConstraint> remainingRequires = fragmentRequires.get(remainingFrag.bundleID);
					if (remainingRequires == null)
						fragmentRequires.put(remainingFrag.bundleID, additionalRequires);
					else
						remainingRequires.addAll(additionalRequires);
				}
			}
		}
		ResolverExport[] results = removedExports == null ? new ResolverExport[0] : removedExports.toArray(new ResolverExport[removedExports.size()]);
		for (int i = 0; i < results.length; i++)
			// TODO this is a hack; need to figure out how to indicate that a fragment export is no longer attached
			results[i].setSubstitute(results[i]);
		resolver.getResolverExports().remove(results);
		if (removedCapabilities != null)
			resolver.removeGenerics(removedCapabilities.toArray(new GenericCapability[removedCapabilities.size()]));
	}

	private boolean hasUnresolvedConstraint(ResolverConstraint reason, ResolverBundle detachedFragment, ResolverBundle remainingFragment, ResolverImport[] oldImports, BundleConstraint[] oldRequires, List<ResolverImport> additionalImports, List<BundleConstraint> additionalRequires) {
		ImportPackageSpecification[] remainingFragImports = remainingFragment.getBundleDescription().getImportPackages();
		BundleSpecification[] remainingFragRequires = remainingFragment.getBundleDescription().getRequiredBundles();
		VersionConstraint[] constraints;
		if (reason instanceof ResolverImport)
			constraints = remainingFragImports;
		else
			constraints = remainingFragRequires;
		for (int i = 0; i < constraints.length; i++)
			if (reason.getName().equals(constraints[i].getName())) {
				detachFragment(remainingFragment, null);
				return true;
			}
		for (int i = 0; i < oldImports.length; i++) {
			if (oldImports[i].getVersionConstraint().getBundle() != detachedFragment.getBundleDescription())
				continue; // the constraint is not from the detached fragment
			for (int j = 0; j < remainingFragImports.length; j++) {
				if (oldImports[i].getName().equals(remainingFragImports[j].getName())) {
					// same constraint, must reuse the constraint object but swap out the fragment info
					additionalImports.add(oldImports[i]);
					oldImports[i].setVersionConstraint(remainingFragImports[j]);
					break;
				}
			}
		}
		for (int i = 0; i < oldRequires.length; i++) {
			if (oldRequires[i].getVersionConstraint().getBundle() != detachedFragment.getBundleDescription())
				continue; // the constraint is not from the detached fragment
			for (int j = 0; j < remainingFragRequires.length; j++) {
				if (oldRequires[i].getName().equals(remainingFragRequires[j].getName())) {
					// same constraint, must reuse the constraint object but swap out the fragment info
					additionalRequires.add(oldRequires[i]);
					oldRequires[i].setVersionConstraint(remainingFragRequires[j]);
					break;
				}
			}
		}
		return false;
	}

	void detachAllFragments() {
		if (fragments == null)
			return;
		ResolverBundle[] allFragments = fragments.toArray(new ResolverBundle[fragments.size()]);
		for (int i = 0; i < allFragments.length; i++)
			detachFragment(allFragments[i], null);
		fragments = null;
	}

	boolean isResolvable() {
		return resolvable;
	}

	void setResolvable(boolean resolvable) {
		this.resolvable = resolvable;
	}

	void addExport(ResolverExport re) {
		ResolverExport[] newExports = new ResolverExport[exports.length + 1];
		for (int i = 0; i < exports.length; i++)
			newExports[i] = exports[i];
		newExports[exports.length] = re;
		exports = newExports;
	}

	ResolverImpl getResolver() {
		return resolver;
	}

	void clearRefs() {
		if (refs != null)
			refs.clear();
	}

	void addRef(ResolverBundle ref) {
		if (((BundleDescription) getBaseDescription()).isResolved())
			return; // don't care when the bundle is already resolved
		if (refs != null && !refs.contains(ref))
			refs.add(ref);
	}

	int getRefs() {
		return refs == null ? 0 : refs.size();
	}

	ResolverBundle[] getFragments() {
		return fragments == null ? new ResolverBundle[0] : (ResolverBundle[]) fragments.toArray(new ResolverBundle[fragments.size()]);
	}

	/*
	 * This is used to sort bundles by BSN.  This is needed to fix bug 174930
	 * If both BSNs are null then 0 is returned
	 * If this BSN is null the 1 is returned
	 * If the other BSN is null then -1 is returned
	 * otherwise String.compareTo is used
	 */
	public int compareTo(ResolverBundle o) {
		String bsn = getName();
		String otherBsn = o.getName();
		if (bsn == null)
			return otherBsn == null ? 0 : 1;
		return otherBsn == null ? -1 : bsn.compareTo(otherBsn);
	}

	void setUninstalled() {
		uninstalled = true;
	}

	boolean isUninstalled() {
		return uninstalled;
	}

	public Bundle getBundle() {
		return getBundleDescription().getBundle();
	}

	public String getSymbolicName() {
		return getName();
	}

	public List<Capability> getDeclaredCapabilities(String namespace) {
		// This gives a view of the host and attached fragments.
		Capability[] capabilities = getGenericCapabilities();
		if (namespace == null)
			return new ArrayList<Capability>(Arrays.asList(capabilities));
		List<Capability> result = new ArrayList<Capability>();
		for (Capability capability : capabilities) {
			if (namespace.equals(capability.getNamespace()))
				result.add(capability);
		}
		return result;
	}

	public int getTypes() {
		return getBundleDescription().getTypes();
	}

	public String getNamespace() {
		return Capability.BUNDLE_CAPABILITY;
	}

	public Map<String, String> getDirectives() {
		return getBundleDescription().getDeclaredDirectives();
	}

	public Map<String, Object> getAttributes() {
		return getBundleDescription().getDeclaredAttributes();
	}

	public BundleRevision getProviderRevision() {
		return this;
	}
}
