/*******************************************************************************
 * Copyright (c) 2004, 2017 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.core.internal.registry;

import java.lang.ref.SoftReference;
import java.util.*;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.spi.RegistryContributor;

/**
 * This class manage all the object from the registry but does not deal with their dependencies.
 * It serves the objects which are either directly obtained from memory or read from a cache.
 * It also returns handles for objects.
 */
public class RegistryObjectManager implements IObjectManager {
	//Constants used to get the objects and their handles
	static public final byte CONFIGURATION_ELEMENT = 1;
	static public final byte EXTENSION = 2;
	static public final byte EXTENSION_POINT = 3;
	static public final byte THIRDLEVEL_CONFIGURATION_ELEMENT = 4;

	static final int CACHE_INITIAL_SIZE = 512; //This value has been picked because it is the minimal size required to startup an RCP app. (FYI, eclipse requires 3 growths).
	static final float DEFAULT_LOADFACTOR = 0.75f; //This is the default factor used in reference map.

	static final int[] EMPTY_INT_ARRAY = new int[0];
	static final String[] EMPTY_STRING_ARRAY = new String[0];

	static final ExtensionHandle[] EMPTY_EXTENSIONS_ARRAY = new ExtensionHandle[0];

	static int UNKNOWN = -1;

	// key: extensionPointName, value: object id
	private HashtableOfStringAndInt extensionPoints; //This is loaded on startup. Then entries can be added when loading a new plugin from the xml.
	// key: object id, value: an object
	private ReferenceMap cache; //Entries are added by getter. The structure is not thread safe.
	//key: int, value: int
	private OffsetTable fileOffsets = null; //This is read once on startup when loading from the cache. Entries are never added here. They are only removed to prevent "removed" objects to be reloaded.

	private int nextId = 1; //This is only used to get the next number available.

	//Those two data structures are only used when the addition or the removal of a plugin occurs.
	//They are used to keep track on a contributor basis of the extension being added or removed
	private final KeyedHashSet newContributions; //represents the contributers added during this session.
	private Object formerContributions; //represents the contributers encountered in previous sessions. This is loaded lazily.

	private HashMap<String, RegistryContributor> contributors; // key: contributor ID; value: contributor name
	private HashMap<String, RegistryContributor> removedContributors; // key: contributor ID; value: contributor name
	private KeyedHashSet namespacesIndex; // registry elements (extension & extensionpoints) indexed by namespaces

	// Map key: extensionPointFullyQualifiedName, value int[] of orphan extensions.
	// The orphan access does not need to be synchronized because the it is protected by the lock in extension registry.
	private Object orphanExtensions;

	private final KeyedHashSet heldObjects = new KeyedHashSet(); //strong reference to the objects that must be hold on to

	//Indicate if objects have been removed or added from the table. This only needs to be set in a couple of places (addNamespace and removeNamespace)
	private boolean isDirty = false;

	private boolean fromCache = false;

	private final ExtensionRegistry registry;

	// TODO this option is not used
	// OSGI system properties.  Copied from EclipseStarter
	public static final String PROP_NO_REGISTRY_FLUSHING = "eclipse.noRegistryFlushing"; //$NON-NLS-1$

	public RegistryObjectManager(ExtensionRegistry registry) {
		extensionPoints = new HashtableOfStringAndInt();
		if ("true".equalsIgnoreCase(RegistryProperties.getProperty(PROP_NO_REGISTRY_FLUSHING))) { //$NON-NLS-1$
			cache = new ReferenceMap(ReferenceMap.HARD, CACHE_INITIAL_SIZE, DEFAULT_LOADFACTOR);
		} else {
			cache = new ReferenceMap(ReferenceMap.SOFT, CACHE_INITIAL_SIZE, DEFAULT_LOADFACTOR);
		}
		newContributions = new KeyedHashSet();

		this.registry = registry;
	}

	/**
	 * Initialize the object manager. Return true if the initialization succeeded, false otherwise
	 */
	synchronized boolean init(long timeStamp) {
		TableReader reader = registry.getTableReader();
		Object[] results = reader.loadTables(timeStamp);
		if (results == null) {
			return false;
		}
		fileOffsets = (OffsetTable) results[0];
		extensionPoints = (HashtableOfStringAndInt) results[1];
		nextId = ((Integer) results[2]).intValue();
		fromCache = true;

		if (!registry.useLazyCacheLoading()) {
			//TODO Here we could grow all the tables to the right size (ReferenceMap)
			reader.setHoldObjects(true);
			markOrphansHasDirty(getOrphans());
			fromCache = reader.readAllCache(this);
			formerContributions = getFormerContributions();
		}
		return fromCache;
	}

	synchronized void addContribution(Contribution contribution) {
		isDirty = true;
		Object Id = contribution.getKey();

		KeyedElement existingContribution = getFormerContributions().getByKey(Id);
		if (existingContribution != null) { // move it from former to new contributions
			removeContribution(Id);
			newContributions.add(existingContribution);
		} else
			existingContribution = newContributions.getByKey(Id);

		if (existingContribution != null) // merge
			((Contribution) existingContribution).mergeContribution(contribution);
		else
			newContributions.add(contribution);

		updateNamespaceIndex(contribution, true);
	}

	// TODO make ExtensionPoint, Extension provide namespace in a same way (move it to the RegistryObject?)
	// See if all the registryObjects have the same namespace. If not, return null.
	// Also can return null if empty array is passed in or objects are of an unexpected type
	private String findCommonNamespaceIdentifier(RegistryObject[] registryObjects) {
		String namespaceName = null;
		for (int i = 0; i < registryObjects.length; i++) {
			RegistryObject currentObject = registryObjects[i];
			String tmp = null;
			if (currentObject instanceof ExtensionPoint)
				tmp = ((ExtensionPoint) currentObject).getNamespace();
			else if (currentObject instanceof Extension)
				tmp = ((Extension) currentObject).getNamespaceIdentifier();

			if (namespaceName == null) {
				namespaceName = tmp;
				continue;
			}
			if (!namespaceName.equals(tmp)) {
				return null;
			}
		}
		return namespaceName;
	}

	synchronized void removeExtensionPointFromNamespaceIndex(int extensionPoint, String namespaceName) {
		RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
		indexElement.updateExtensionPoint(extensionPoint, false);
	}

	synchronized void removeExtensionFromNamespaceIndex(int extensions, String namespaceName) {
		RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
		indexElement.updateExtension(extensions, false);
	}

	// Called from a synchronized method
	private void updateNamespaceIndex(Contribution contribution, boolean added) {
		// if all extension points are from the same namespace combine them in one block and add them all together
		int[] contribExtensionPoints = contribution.getExtensionPoints();
		RegistryObject[] extensionPointObjects = getObjects(contribExtensionPoints, EXTENSION_POINT);
		String commonExptsNamespace = null;
		if (contribExtensionPoints.length > 1)
			commonExptsNamespace = findCommonNamespaceIdentifier(extensionPointObjects);
		if (commonExptsNamespace != null) {
			RegistryIndexElement indexElement = getNamespaceIndex(commonExptsNamespace);
			indexElement.updateExtensionPoints(contribExtensionPoints, added);
		} else {
			for (int i = 0; i < contribExtensionPoints.length; i++) {
				String namespaceName = ((ExtensionPoint) extensionPointObjects[i]).getNamespace();
				RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
				indexElement.updateExtensionPoint(contribExtensionPoints[i], added);
			}
		}

		// if all extensions are from the same namespace combine them in one block and add them all together
		int[] contrExtensions = contribution.getExtensions();
		RegistryObject[] extensionObjects = getObjects(contrExtensions, EXTENSION);
		String commonExtNamespace = null;
		if (contrExtensions.length > 1)
			commonExtNamespace = findCommonNamespaceIdentifier(extensionObjects);
		if (commonExtNamespace != null) {
			RegistryIndexElement indexElement = getNamespaceIndex(commonExtNamespace);
			indexElement.updateExtensions(contrExtensions, added);
		} else {
			for (int i = 0; i < contrExtensions.length; i++) {
				String namespaceName = ((Extension) extensionObjects[i]).getNamespaceIdentifier();
				RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
				indexElement.updateExtension(contrExtensions[i], added);
			}
		}
	}

	synchronized int[] getExtensionPointsFrom(String id) {
		KeyedElement tmp = newContributions.getByKey(id);
		if (tmp == null)
			tmp = getFormerContributions().getByKey(id);
		if (tmp == null)
			return EMPTY_INT_ARRAY;
		return ((Contribution) tmp).getExtensionPoints();
	}

	synchronized boolean hasContribution(String id) {
		Object result = newContributions.getByKey(id);
		if (result == null)
			result = getFormerContributions().getByKey(id);
		return result != null;
	}

	private KeyedHashSet getFormerContributions() {
		KeyedHashSet result;
		if (fromCache == false)
			return new KeyedHashSet(0);

		if (formerContributions == null || (result = ((KeyedHashSet) ((formerContributions instanceof SoftReference) ? ((SoftReference<?>) formerContributions).get() : formerContributions))) == null) {
			result = registry.getTableReader().loadContributions();
			formerContributions = new SoftReference<>(result);
		}
		return result;
	}

	synchronized public void add(RegistryObject registryObject, boolean hold) {
		if (registryObject.getObjectId() == UNKNOWN) {
			int id = nextId++;
			registryObject.setObjectId(id);
		}
		cache.put(registryObject.getObjectId(), registryObject);
		if (hold)
			hold(registryObject);
	}

	private void remove(RegistryObject registryObject, boolean release) {
		cache.remove(registryObject.getObjectId());
		if (release)
			release(registryObject);
	}

	synchronized void remove(int id, boolean release) {
		RegistryObject toRemove = (RegistryObject) cache.get(id);
		if (fileOffsets != null)
			fileOffsets.removeKey(id);
		if (toRemove != null)
			remove(toRemove, release);
	}

	private void hold(RegistryObject toHold) {
		heldObjects.add(toHold);
	}

	private void release(RegistryObject toRelease) {
		heldObjects.remove(toRelease);
	}

	@Override
	public synchronized Object getObject(int id, byte type) {
		return basicGetObject(id, type);
	}

	private Object basicGetObject(int id, byte type) {
		Object result = cache.get(id);
		if (result != null)
			return result;
		if (fromCache)
			result = load(id, type);
		if (result == null)
			throw new InvalidRegistryObjectException();
		cache.put(id, result);
		return result;
	}

	// The current impementation of this method assumes that we don't cache dynamic
	// extension. In this case all extensions not yet loaded (i.e. not in the memory cache)
	// are "not dynamic" and we actually check memory objects to see if they are dynamic.
	//
	// If we decide to allow caching of dynamic objects, the implementation
	// of this method would have to retrieved the object from disk and check
	// its "dynamic" status. The problem is that id alone is not enough to get the object
	// from the disk; object type is needed as well.
	public boolean shouldPersist(int id) {
		Object result = cache.get(id);
		if (result != null)
			return ((RegistryObject) result).shouldPersist();
		return true;
	}

	@Override
	public synchronized RegistryObject[] getObjects(int[] values, byte type) {
		if (values.length == 0) {
			switch (type) {
				case EXTENSION_POINT :
					return ExtensionPoint.EMPTY_ARRAY;
				case EXTENSION :
					return Extension.EMPTY_ARRAY;
				case CONFIGURATION_ELEMENT :
				case THIRDLEVEL_CONFIGURATION_ELEMENT :
					return ConfigurationElement.EMPTY_ARRAY;
			}
		}

		RegistryObject[] results = null;
		switch (type) {
			case EXTENSION_POINT :
				results = new ExtensionPoint[values.length];
				break;
			case EXTENSION :
				results = new Extension[values.length];
				break;
			case CONFIGURATION_ELEMENT :
			case THIRDLEVEL_CONFIGURATION_ELEMENT :
				results = new ConfigurationElement[values.length];
				break;
		}
		for (int i = 0; i < values.length; i++) {
			results[i] = (RegistryObject) basicGetObject(values[i], type);
		}
		return results;
	}

	synchronized ExtensionPoint getExtensionPointObject(String xptUniqueId) {
		int id;
		if ((id = extensionPoints.get(xptUniqueId)) == HashtableOfStringAndInt.MISSING_ELEMENT)
			return null;
		return (ExtensionPoint) getObject(id, EXTENSION_POINT);
	}

	@Override
	public Handle getHandle(int id, byte type) {
		switch (type) {
			case EXTENSION_POINT :
				return new ExtensionPointHandle(this, id);

			case EXTENSION :
				return new ExtensionHandle(this, id);

			case CONFIGURATION_ELEMENT :
				return new ConfigurationElementHandle(this, id);

			case THIRDLEVEL_CONFIGURATION_ELEMENT :
			default : //avoid compiler error, type should always be known
				return new ThirdLevelConfigurationElementHandle(this, id);
		}
	}

	@Override
	public Handle[] getHandles(int[] ids, byte type) {
		Handle[] results = null;
		int nbrId = ids.length;
		switch (type) {
			case EXTENSION_POINT :
				if (nbrId == 0)
					return ExtensionPointHandle.EMPTY_ARRAY;
				results = new ExtensionPointHandle[nbrId];
				for (int i = 0; i < nbrId; i++) {
					results[i] = new ExtensionPointHandle(this, ids[i]);
				}
				break;

			case EXTENSION :
				if (nbrId == 0)
					return ExtensionHandle.EMPTY_ARRAY;
				results = new ExtensionHandle[nbrId];
				for (int i = 0; i < nbrId; i++) {
					results[i] = new ExtensionHandle(this, ids[i]);
				}
				break;

			case CONFIGURATION_ELEMENT :
				if (nbrId == 0)
					return ConfigurationElementHandle.EMPTY_ARRAY;
				results = new ConfigurationElementHandle[nbrId];
				for (int i = 0; i < nbrId; i++) {
					results[i] = new ConfigurationElementHandle(this, ids[i]);
				}
				break;

			case THIRDLEVEL_CONFIGURATION_ELEMENT :
				if (nbrId == 0)
					return ConfigurationElementHandle.EMPTY_ARRAY;
				results = new ThirdLevelConfigurationElementHandle[nbrId];
				for (int i = 0; i < nbrId; i++) {
					results[i] = new ThirdLevelConfigurationElementHandle(this, ids[i]);
				}
				break;
		}
		return results;
	}

	synchronized ExtensionPointHandle[] getExtensionPointsHandles() {
		return (ExtensionPointHandle[]) getHandles(extensionPoints.getValues(), EXTENSION_POINT);
	}

	synchronized ExtensionPointHandle getExtensionPointHandle(String xptUniqueId) {
		int id = extensionPoints.get(xptUniqueId);
		if (id == HashtableOfStringAndInt.MISSING_ELEMENT)
			return null;
		return (ExtensionPointHandle) getHandle(id, EXTENSION_POINT);
	}

	private Object load(int id, byte type) {
		TableReader reader = registry.getTableReader();
		if (fileOffsets == null)
			return null;
		int offset = fileOffsets.get(id);
		if (offset == Integer.MIN_VALUE)
			return null;
		switch (type) {
			case CONFIGURATION_ELEMENT :
				return reader.loadConfigurationElement(offset);

			case THIRDLEVEL_CONFIGURATION_ELEMENT :
				return reader.loadThirdLevelConfigurationElements(offset, this);

			case EXTENSION :
				return reader.loadExtension(offset);

			case EXTENSION_POINT :
			default : //avoid compile errors. type must always be known
				return reader.loadExtensionPointTree(offset, this);
		}
	}

	synchronized int[] getExtensionsFrom(String contributorId) {
		KeyedElement tmp = newContributions.getByKey(contributorId);
		if (tmp == null)
			tmp = getFormerContributions().getByKey(contributorId);
		if (tmp == null)
			return EMPTY_INT_ARRAY;
		return ((Contribution) tmp).getExtensions();
	}

	synchronized boolean addExtensionPoint(ExtensionPoint currentExtPoint, boolean hold) {
		String uniqueId = currentExtPoint.getUniqueIdentifier();
		if (extensionPoints.get(uniqueId) != HashtableOfStringAndInt.MISSING_ELEMENT)
			return false;
		add(currentExtPoint, hold);
		extensionPoints.put(uniqueId, currentExtPoint.getObjectId());
		return true;
	}

	synchronized void removeExtensionPoint(String extensionPointId) {
		int pointId = extensionPoints.removeKey(extensionPointId);
		if (pointId == HashtableOfStringAndInt.MISSING_ELEMENT)
			return;
		remove(pointId, true);
	}

	public boolean isDirty() {
		return isDirty;
	}

	public void markDirty() {
		isDirty = true;
	}

	synchronized void removeContribution(Object contributorId) {
		boolean removed = newContributions.removeByKey(contributorId);
		if (removed == false) {
			removed = getFormerContributions().removeByKey(contributorId);
			if (removed)
				formerContributions = getFormerContributions(); //This forces the removed namespace to stay around, so we do not forget about removed namespaces
		}

		if (removed) {
			isDirty = true;
			return;
		}

	}

	@SuppressWarnings("unchecked")
	private Map<String, int[]> getOrphans() {
		Object result;
		if (orphanExtensions == null && !fromCache) {
			result = new HashMap<>();
			orphanExtensions = result;
		} else if (orphanExtensions == null || (result = ((orphanExtensions instanceof SoftReference) ? ((SoftReference<?>) orphanExtensions).get() : orphanExtensions)) == null) {
			result = registry.getTableReader().loadOrphans();
			orphanExtensions = new SoftReference<>(result);
		}
		return (HashMap<String, int[]>) result;
	}

	void addOrphans(String extensionPoint, int[] extensions) {
		Map<String, int[]> orphans = getOrphans();
		int[] existingOrphanExtensions = orphans.get(extensionPoint);

		if (existingOrphanExtensions != null) {
			// just add
			int[] newOrphanExtensions = new int[existingOrphanExtensions.length + extensions.length];
			System.arraycopy(existingOrphanExtensions, 0, newOrphanExtensions, 0, existingOrphanExtensions.length);
			System.arraycopy(extensions, 0, newOrphanExtensions, existingOrphanExtensions.length, extensions.length);
			orphans.put(extensionPoint, newOrphanExtensions);
		} else {
			// otherwise this is the first one
			orphans.put(extensionPoint, extensions);
		}
		markOrphansHasDirty(orphans);
	}

	void markOrphansHasDirty(Map<String, int[]> orphans) {
		orphanExtensions = orphans;
	}

	void addOrphan(String extensionPoint, int extension) {
		Map<String, int[]> orphans = getOrphans();
		int[] existingOrphanExtensions = orphans.get(extensionPoint);

		if (existingOrphanExtensions != null) {
			// just add
			int[] newOrphanExtensions = new int[existingOrphanExtensions.length + 1];
			System.arraycopy(existingOrphanExtensions, 0, newOrphanExtensions, 0, existingOrphanExtensions.length);
			newOrphanExtensions[existingOrphanExtensions.length] = extension;
			orphans.put(extensionPoint, newOrphanExtensions);
		} else {
			// otherwise this is the first one
			orphans.put(extensionPoint, new int[] {extension});
		}
		markOrphansHasDirty(orphans);
	}

	int[] removeOrphans(String extensionPoint) {
		Map<String, int[]> orphans = getOrphans();
		int[] existingOrphanExtensions = orphans.remove(extensionPoint);
		if (existingOrphanExtensions != null) {
			markOrphansHasDirty(orphans);
		}
		return existingOrphanExtensions;
	}

	void removeOrphan(String extensionPoint, int extension) {
		Map<String, int[]> orphans = getOrphans();
		int[] existingOrphanExtensions = orphans.get(extensionPoint);

		if (existingOrphanExtensions == null)
			return;

		markOrphansHasDirty(orphans);
		int newSize = existingOrphanExtensions.length - 1;
		if (newSize == 0) {
			orphans.remove(extensionPoint);
			return;
		}

		int[] newOrphanExtensions = new int[existingOrphanExtensions.length - 1];
		for (int i = 0, j = 0; i < existingOrphanExtensions.length; i++)
			if (extension != existingOrphanExtensions[i])
				newOrphanExtensions[j++] = existingOrphanExtensions[i];

		orphans.put(extensionPoint, newOrphanExtensions);
		return;
	}

	//This method is only used by the writer to reach in
	Map<String, int[]> getOrphanExtensions() {
		return getOrphans();
	}

	//	This method is only used by the writer to reach in
	int getNextId() {
		return nextId;
	}

	//	This method is only used by the writer to reach in
	HashtableOfStringAndInt getExtensionPoints() {
		return extensionPoints;
	}

	//	This method is only used by the writer to reach in
	KeyedHashSet[] getContributions() {
		return new KeyedHashSet[] {newContributions, getFormerContributions()};
	}

	// This method is used internally and by the writer to reach in. Notice that it doesn't
	// return contributors marked as removed.
	HashMap<String, RegistryContributor> getContributors() {
		if (contributors == null) {
			if (fromCache == false)
				contributors = new HashMap<>();
			else
				contributors = registry.getTableReader().loadContributors();
		}
		return contributors;
	}

	synchronized IContributor[] getContributorsSync() {
		Collection<RegistryContributor> contributorValues = getContributors().values();
		return contributorValues.toArray(new IContributor[contributorValues.size()]);
	}

	synchronized RegistryContributor getContributor(String id) {
		RegistryContributor contributor = getContributors().get(id);
		if (contributor != null)
			return contributor;
		// check if we have it among removed contributors - potentially
		// notification of removals might be processed after the contributor
		// marked as removed:
		if (removedContributors != null)
			return removedContributors.get(id);
		return null;
	}

	// only adds a contributor if it is not already present in the table
	synchronized void addContributor(RegistryContributor newContributor) {
		String key = newContributor.getActualId();
		if (!getContributors().containsKey(key)) {
			isDirty = true;
			if (removedContributors != null)
				removedContributors.remove(key);
			getContributors().put(key, newContributor);
		}
	}

	synchronized void removeContributor(String id) {
		isDirty = true;
		RegistryContributor removed = getContributors().remove(id);
		if (removed != null) {
			if (removedContributors == null)
				removedContributors = new HashMap<>();
			removedContributors.put(id, removed);
		}
	}

	KeyedHashSet getNamespacesIndex() {
		if (namespacesIndex == null) {
			if (fromCache == false)
				namespacesIndex = new KeyedHashSet(0);
			else
				namespacesIndex = registry.getTableReader().loadNamespaces();
		}
		return namespacesIndex;
	}

	// Find or create required index element
	private RegistryIndexElement getNamespaceIndex(String namespaceName) {
		RegistryIndexElement indexElement = (RegistryIndexElement) getNamespacesIndex().getByKey(namespaceName);
		if (indexElement == null) {
			indexElement = new RegistryIndexElement(namespaceName);
			namespacesIndex.add(indexElement);
		}
		return indexElement;
	}

	/**
	 * Collect all the objects that are removed by this operation and store
	 * them in a IObjectManager so that they can be accessed from the appropriate
	 * deltas but not from the registry.
	 */
	synchronized Map<Integer, RegistryObject> getAssociatedObjects(String contributionId) {
		//Collect all the objects associated with this contribution
		int[] xpts = getExtensionPointsFrom(contributionId);
		int[] exts = getExtensionsFrom(contributionId);
		Map<Integer, RegistryObject> actualObjects = new HashMap<>(xpts.length + exts.length);
		for (int i = 0; i < exts.length; i++) {
			Extension tmp = (Extension) basicGetObject(exts[i], RegistryObjectManager.EXTENSION);
			actualObjects.put(new Integer(exts[i]), tmp);
			collectChildren(tmp, 0, actualObjects);
		}
		for (int i = 0; i < xpts.length; i++) {
			ExtensionPoint xpt = (ExtensionPoint) basicGetObject(xpts[i], RegistryObjectManager.EXTENSION_POINT);
			actualObjects.put(new Integer(xpts[i]), xpt);
		}

		return actualObjects;
	}

	/**
	 * Adds elements to be removed along with the registry object.
	 */
	synchronized void addAssociatedObjects(Map<Integer, RegistryObject> map, RegistryObject registryObject) {
		collectChildren(registryObject, 0, map);
	}

	/**
	 * Add to the set of the objects all extensions and extension points that
	 * could be navigated to from the objects in the set.
	 */
	synchronized void addNavigableObjects(Map<Integer, RegistryObject> associatedObjects) {
		Map<Integer, RegistryObject> result = new HashMap<>();
		for (Iterator<RegistryObject> iter = associatedObjects.values().iterator(); iter.hasNext();) {
			RegistryObject object = iter.next();
			if (object instanceof Extension) {
				// add extension point
				ExtensionPoint extPoint = getExtensionPointObject(((Extension) object).getExtensionPointIdentifier());
				if (extPoint == null) // already removed?
					continue;

				Integer extPointIndex = new Integer(extPoint.getKeyHashCode());
				if (!associatedObjects.containsKey(extPointIndex))
					result.put(new Integer(extPoint.getKeyHashCode()), extPoint);

				// add all extensions for the extension point
				int[] extensions = extPoint.getRawChildren();
				for (int j = 0; j < extensions.length; j++) {
					Extension tmp = (Extension) basicGetObject(extensions[j], RegistryObjectManager.EXTENSION);
					if (tmp == null) // already removed
						continue;
					Integer extensionIndex = new Integer(extensions[j]);
					if (!associatedObjects.containsKey(extensionIndex)) {
						result.put(extensionIndex, tmp);
						collectChildren(tmp, 0, result);
					}
				}
			} else if (object instanceof ExtensionPoint) {
				// by now extensions of this extension point have been marked as orphans
				Map<String, int[]> orphans = getOrphans();
				String name = ((ExtensionPoint) object).getUniqueIdentifier();
				int[] extensions = orphans.get(name);
				if (extensions != null) {
					for (int j = 0; j < extensions.length; j++) {
						Extension tmp = (Extension) basicGetObject(extensions[j], RegistryObjectManager.EXTENSION);
						if (tmp == null) // already removed
							continue;
						Integer extensionIndex = new Integer(extensions[j]);
						if (!associatedObjects.containsKey(extensionIndex)) {
							result.put(extensionIndex, tmp);
							collectChildren(tmp, 0, result);
						}
					}
				}
			}
		}
		associatedObjects.putAll(result);
	}

	synchronized void removeObjects(Map<?, ?> associatedObjects) {
		//Remove the objects from the main object manager so they can no longer be accessed.
		Collection<?> allValues = associatedObjects.values();
		for (Iterator<?> iter = allValues.iterator(); iter.hasNext();) {
			RegistryObject toRemove = (RegistryObject) iter.next();
			remove((toRemove).getObjectId(), true);
			if (toRemove instanceof ExtensionPoint)
				removeExtensionPoint(((ExtensionPoint) toRemove).getUniqueIdentifier());
		}
	}

	IObjectManager createDelegatingObjectManager(Map<?, ?> object) {
		return new TemporaryObjectManager(object, this);
	}

	private void collectChildren(RegistryObject ce, int level, Map<Integer, RegistryObject> collector) {
		ConfigurationElement[] children = (ConfigurationElement[]) getObjects(ce.getRawChildren(), level == 0 || ce.noExtraData() ? RegistryObjectManager.CONFIGURATION_ELEMENT : RegistryObjectManager.THIRDLEVEL_CONFIGURATION_ELEMENT);
		for (int j = 0; j < children.length; j++) {
			collector.put(new Integer(children[j].getObjectId()), children[j]);
			collectChildren(children[j], level + 1, collector);
		}
	}

	@Override
	public void close() {
		//do nothing.
	}

	public ExtensionRegistry getRegistry() {
		return registry;
	}

	// Called from a synchronized method only
	private boolean unlinkChildFromContributions(KeyedElement[] contributions, int id) {
		for (int i = 0; i < contributions.length; i++) {
			Contribution candidate = (Contribution) contributions[i];
			if (candidate == null)
				continue;
			if (candidate.hasChild(id)) {
				candidate.unlinkChild(id);
				if (candidate.isEmpty())
					removeContribution(candidate.getContributorId());
				return true;
			}
		}
		return false;
	}

	synchronized boolean unlinkChildFromContributions(int id) {
		if (unlinkChildFromContributions(newContributions.elements, id))
			return true;
		return unlinkChildFromContributions(getFormerContributions().elements, id);
	}

	synchronized public ExtensionPointHandle[] getExtensionPointsFromNamespace(String namespaceName) {
		RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
		int[] namespaceExtensionPoints = indexElement.getExtensionPoints();
		return (ExtensionPointHandle[]) getHandles(namespaceExtensionPoints, EXTENSION_POINT);
	}

	// This method filters out extensions with no extension point
	synchronized public ExtensionHandle[] getExtensionsFromNamespace(String namespaceName) {
		RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
		int[] namespaceExtensions = indexElement.getExtensions();

		// filter extensions with no extension point (orphan extensions)
		List<Handle> tmp = new ArrayList<>();
		Extension[] exts = (Extension[]) getObjects(namespaceExtensions, EXTENSION);
		for (int i = 0; i < exts.length; i++) {
			if (getExtensionPointObject(exts[i].getExtensionPointIdentifier()) != null)
				tmp.add(getHandle(exts[i].getObjectId(), EXTENSION));
		}
		if (tmp.size() == 0)
			return EMPTY_EXTENSIONS_ARRAY;
		ExtensionHandle[] result = new ExtensionHandle[tmp.size()];
		return tmp.toArray(result);
	}

	public ExtensionHandle[] getExtensionsFromContributor(String contributorId) {
		int[] ids = getExtensionsFrom(contributorId); // never null
		return (ExtensionHandle[]) getHandles(ids, RegistryObjectManager.EXTENSION);
	}

	public ExtensionPointHandle[] getExtensionPointsFromContributor(String contributorId) {
		int[] ids = getExtensionPointsFrom(contributorId); // never null
		return (ExtensionPointHandle[]) getHandles(ids, RegistryObjectManager.EXTENSION_POINT);
	}
}
