/*******************************************************************************
 * 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
 *     Mickael Istria (Red Hat Inc.) - [263316] regexp for file association
 *******************************************************************************/
package org.eclipse.core.internal.content;

import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.*;
import org.eclipse.core.runtime.content.IContentTypeManager.ISelectionPolicy;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.osgi.util.NLS;

public final class ContentTypeCatalog {
	private static final IContentType[] NO_CONTENT_TYPES = new IContentType[0];

	/**
	 * All fields are guarded by lock on "this"
	 */
	private final Map<ContentType, ContentType[]> allChildren = new HashMap<>();
	private final Map<String, IContentType> contentTypes = new HashMap<>();
	private final Map<String, Set<ContentType>> fileExtensions = new HashMap<>();
	private final Map<String, Set<ContentType>> fileNames = new HashMap<>();
	private final Map<String, Pattern> compiledRegexps = new HashMap<>();
	private final Map<Pattern, String> initialPatternForRegexp = new HashMap<>();
	private final Map<Pattern, Set<ContentType>> fileRegexps = new HashMap<>();
	private int generation;
	private ContentTypeManager manager;

	/**
	 * A sorting policy where the more generic content type wins. Lexicographical comparison is done
	 * as a last resort when all other criteria fail.
	 */
	private final Comparator<IContentType> policyConstantGeneralIsBetter = new Comparator<IContentType>() {
		@Override
		public int compare(IContentType o1, IContentType o2) {
			ContentType type1 = (ContentType) o1;
			ContentType type2 = (ContentType) o2;
			// first criteria: depth - the lower, the better
			int depthCriteria = type1.getDepth() - type2.getDepth();
			if (depthCriteria != 0)
				return depthCriteria;
			// second criteria: priority - the higher, the better
			int priorityCriteria = type1.getPriority() - type2.getPriority();
			if (priorityCriteria != 0)
				return -priorityCriteria;
			// they have same depth and priority - choose one arbitrarily (stability is important)
			return type1.getId().compareTo(type2.getId());
		}
	};

	/**
	 * A sorting policy where the more specific content type wins. Lexicographical comparison is done
	 * as a last resort when all other criteria fail.
	 */
	private Comparator<IContentType> policyConstantSpecificIsBetter = new Comparator<IContentType>() {
		@Override
		public int compare(IContentType o1, IContentType o2) {
			ContentType type1 = (ContentType) o1;
			ContentType type2 = (ContentType) o2;
			// first criteria: depth - the higher, the better
			int depthCriteria = type1.getDepth() - type2.getDepth();
			if (depthCriteria != 0)
				return -depthCriteria;
			// second criteria: priority - the higher, the better
			int priorityCriteria = type1.getPriority() - type2.getPriority();
			if (priorityCriteria != 0)
				return -priorityCriteria;
			// they have same depth and priority - choose one arbitrarily (stability is important)
			return type1.getId().compareTo(type2.getId());
		}
	};

	/**
	 * A sorting policy where the more general content type wins.
	 */
	private Comparator<IContentType> policyGeneralIsBetter = new Comparator<IContentType>() {
		@Override
		public int compare(IContentType o1, IContentType o2) {
			ContentType type1 = (ContentType) o1;
			ContentType type2 = (ContentType) o2;
			// first criteria: depth - the lower, the better
			int depthCriteria = type1.getDepth() - type2.getDepth();
			if (depthCriteria != 0)
				return depthCriteria;
			// second criteria: priority - the higher, the better
			int priorityCriteria = type1.getPriority() - type2.getPriority();
			if (priorityCriteria != 0)
				return -priorityCriteria;
			return 0;
		}
	};

	/**
	 * A sorting policy where content types are sorted by id.
	 */
	private Comparator<IContentType> policyLexicographical = new Comparator<IContentType>() {
		@Override
		public int compare(IContentType o1, IContentType o2) {
			ContentType type1 = (ContentType) o1;
			ContentType type2 = (ContentType) o2;
			return type1.getId().compareTo(type2.getId());
		}
	};
	/**
	 * A sorting policy where the more specific content type wins.
	 */
	private Comparator<IContentType> policySpecificIsBetter = new Comparator<IContentType>() {
		@Override
		public int compare(IContentType o1, IContentType o2) {
			ContentType type1 = (ContentType) o1;
			ContentType type2 = (ContentType) o2;
			// first criteria: depth - the higher, the better
			int depthCriteria = type1.getDepth() - type2.getDepth();
			if (depthCriteria != 0)
				return -depthCriteria;
			// second criteria: priority - the higher, the better
			int priorityCriteria = type1.getPriority() - type2.getPriority();
			if (priorityCriteria != 0)
				return -priorityCriteria;
			return 0;
		}
	};

	private static IContentType[] concat(IContentType[][] types) {
		int size = 0;
		IContentType[] nonEmptyOne = NO_CONTENT_TYPES;
		for (IContentType[] array : types) {
			size += array.length;
			if (array.length > 0) {
				nonEmptyOne = array;
			}
		}
		if (nonEmptyOne.length == size) { // no other array has content
			return nonEmptyOne;
		}
		IContentType[] result = new IContentType[size];
		int currentIndex = 0;
		for (IContentType[] array : types) {
			System.arraycopy(array, 0, result, currentIndex, array.length);
			currentIndex += array.length;
		}
		return result;
	}

	public ContentTypeCatalog(ContentTypeManager manager, int generation) {
		this.manager = manager;
		this.generation = generation;
	}

	synchronized void addContentType(IContentType contentType) {
		contentTypes.put(contentType.getId(), contentType);
	}

	/**
	 * Applies a client-provided selection policy.
	 */
	private IContentType[] applyPolicy(final IContentTypeManager.ISelectionPolicy policy, final IContentType[] candidates, final boolean fileName, final boolean contents) {
		final IContentType[][] result = new IContentType[][] {candidates};
		SafeRunner.run(new ISafeRunnable() {
			@Override
			public void handleException(Throwable exception) {
				// already logged in SafeRunner#run()
				// default result is the original array
				// nothing to be done
			}

			@Override
			public void run() throws Exception {
				result[0] = policy.select(candidates, fileName, contents);
			}
		});
		return result[0];
	}

	private void associate(ContentType contentType) {
		String[] builtInFileNames = contentType.getFileSpecs(IContentType.IGNORE_USER_DEFINED | IContentType.FILE_NAME_SPEC);
		for (String builtInFileName : builtInFileNames)
			associate(contentType, builtInFileName, IContentType.FILE_NAME_SPEC);
		String[] builtInFileExtensions = contentType.getFileSpecs(IContentType.IGNORE_USER_DEFINED | IContentType.FILE_EXTENSION_SPEC);
		for (String builtInFileExtension : builtInFileExtensions)
			associate(contentType, builtInFileExtension, IContentType.FILE_EXTENSION_SPEC);
		String[] builtInFilePatterns = contentType
				.getFileSpecs(IContentType.IGNORE_USER_DEFINED | IContentType.FILE_PATTERN_SPEC);
		for (String builtInFilePattern : builtInFilePatterns) {
			associate(contentType, builtInFilePattern, IContentType.FILE_PATTERN_SPEC);
		}
	}

	String toRegexp(String filePattern) {
		return filePattern.replace(".", "\\.").replace('?', '.').replace("*", ".*"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
	}

	synchronized void associate(ContentType contentType, String text, int type) {
		Map<String, Set<ContentType>> fileSpecMap = null;
		if ((type & IContentType.FILE_NAME_SPEC) != 0) {
			fileSpecMap = fileNames;
		} else if ((type & IContentType.FILE_EXTENSION_SPEC) != 0) {
			fileSpecMap = fileExtensions;
		}
		if (fileSpecMap != null) {
			String mappingKey = FileSpec.getMappingKeyFor(text);
			Set<ContentType> existing = fileSpecMap.get(mappingKey);
			if (existing == null)
				fileSpecMap.put(mappingKey, existing = new HashSet<>());
			existing.add(contentType);
		} else if ((type & IContentType.FILE_PATTERN_SPEC) != 0) {
			Pattern compiledPattern = compiledRegexps.get(text);
			if (compiledPattern == null) {
				compiledPattern = Pattern.compile(toRegexp(text));
				compiledRegexps.put(text, compiledPattern);
				initialPatternForRegexp.put(compiledPattern, text);
				fileRegexps.put(compiledPattern, new HashSet<>());
			}
			fileRegexps.get(compiledPattern).add(contentType);
		}
	}

	private int collectMatchingByContents(int valid, IContentType[] subset, List<ContentType> destination, ILazySource contents, Map<String, Object> properties) throws IOException {
		for (IContentType element : subset) {
			ContentType current = (ContentType) element;
			IContentDescriber describer = current.getDescriber();
			int status = IContentDescriber.INDETERMINATE;
			if (describer != null) {
				if (contents.isText() && !(describer instanceof ITextContentDescriber))
					// for text streams we skip content types that do not provide text-based content describers
					continue;
				status = describe(current, contents, null, properties);
				if (status == IContentDescriber.INVALID)
					continue;
			}
			if (status == IContentDescriber.VALID)
				destination.add(valid++, current);
			else
				destination.add(current);
		}
		return valid;
	}

	@SuppressWarnings("deprecation")
	int describe(ContentType type, ILazySource contents, ContentDescription description, Map<String, Object> properties) throws IOException {
		IContentDescriber describer = type.getDescriber();
		try {
			if (contents.isText()) {
				if (describer instanceof XMLRootElementContentDescriber2) {
					return ((XMLRootElementContentDescriber2) describer).describe((Reader) contents, description, properties);
				} else if (describer instanceof XMLRootElementContentDescriber) {
					return ((XMLRootElementContentDescriber) describer).describe((Reader) contents, description, properties);
				}
				return ((ITextContentDescriber) describer).describe((Reader) contents, description);
			} else {
				if (describer instanceof XMLRootElementContentDescriber2) {
					return ((XMLRootElementContentDescriber2) describer).describe((InputStream) contents, description, properties);
				} else if (describer instanceof XMLRootElementContentDescriber) {
					return ((XMLRootElementContentDescriber) describer).describe((InputStream) contents, description, properties);
				}
				return (describer).describe((InputStream) contents, description);
			}
		} catch (RuntimeException re) {
			// describer seems to be buggy. just disable it (logging the reason)
			type.invalidateDescriber(re);
		} catch (Error e) {
			// describer got some serious problem. disable it (logging the reason) and throw the error again
			type.invalidateDescriber(e);
			throw e;
		} catch (LowLevelIOException llioe) {
			// throw the actual exception
			throw llioe.getActualException();
		} catch (IOException ioe) {
			// bugs 67841/ 62443  - non-low level IOException should be "ignored"
			if (ContentTypeManager.DEBUGGING) {
				String message = NLS.bind(ContentMessages.content_errorReadingContents, type.getId());
				ContentType.log(message, ioe);
			}
			// we don't know what the describer would say if the exception didn't occur
			return IContentDescriber.INDETERMINATE;
		} finally {
			contents.rewind();
		}
		return IContentDescriber.INVALID;
	}

	synchronized void dissociate(ContentType contentType, String text, int type) {
		Map<String, Set<ContentType>> fileSpecMap = ((type & IContentType.FILE_NAME_SPEC) != 0) ? fileNames : fileExtensions;
		String mappingKey = FileSpec.getMappingKeyFor(text);
		Set<ContentType> existing = fileSpecMap.get(mappingKey);
		if (existing == null)
			return;
		existing.remove(contentType);
	}

	/**
	 * A content type will be valid if:
	 * <ol>
	 * <li>it does not designate a base type, or</li>
	 * <li>it designates a base type that exists and is valid</li>
	 * </ol>
	 * <p>And</p>:
	 * <ol>
	 * <li>it does not designate an alias type, or</li>
	 * <li>it designates an alias type that does not exist, or</li>
	 * <li>it designates an alias type that exists and is valid</li>
	 * </ol>
	 */
	private boolean ensureValid(ContentType type) {
		if (type.getValidation() != ContentType.STATUS_UNKNOWN)
			// already processed
			return type.isValid();
		// set this type temporarily as invalid to prevent cycles
		// all types in a cycle would remain as invalid
		type.setValidation(ContentType.STATUS_INVALID);
		if (type.isAlias())
			// it is an alias, leave as invalid
			return false;
		// check base type
		ContentType baseType = null;
		if (type.getBaseTypeId() != null) {
			baseType = (ContentType) contentTypes.get(type.getBaseTypeId());
			if (baseType == null)
				// invalid: specified base type is not known
				return false;
			// base type exists, ensure it is valid
			baseType = baseType.getAliasTarget(true);
			ensureValid(baseType);
			if (baseType.getValidation() != ContentType.STATUS_VALID)
				// invalid: base type was invalid
				return false;
		}
		// valid: all conditions satisfied
		type.setValidation(ContentType.STATUS_VALID);
		type.setBaseType(baseType);
		return true;
	}

	IContentType[] findContentTypesFor(ContentTypeMatcher matcher, InputStream contents, String fileName) throws IOException {
		final ILazySource buffer = ContentTypeManager.readBuffer(contents);
		IContentType[] selected = internalFindContentTypesFor(matcher, buffer, fileName, true);
		// give the policy a chance to change the results
		ISelectionPolicy policy = matcher.getPolicy();
		if (policy != null)
			selected = applyPolicy(policy, selected, fileName != null, true);
		return selected;
	}

	IContentType[] findContentTypesFor(ContentTypeMatcher matcher, final String fileName) {
		IContentType[] selected = concat(internalFindContentTypesFor(matcher, fileName, policyConstantGeneralIsBetter));
		// give the policy a chance to change the results
		ISelectionPolicy policy = matcher.getPolicy();
		if (policy != null)
			selected = applyPolicy(policy, selected, true, false);
		return selected;
	}

	synchronized public IContentType[] getAllContentTypes() {
		List<ContentType> result = new ArrayList<>(contentTypes.size());
		for (IContentType iContentType : contentTypes.values()) {
			ContentType type = (ContentType) iContentType;
			if (type.isValid() && !type.isAlias())
				result.add(type);
		}
		return result.toArray(new IContentType[result.size()]);
	}

	private ContentType[] getChildren(ContentType parent) {
		ContentType[] children = allChildren.get(parent);
		if (children != null)
			return children;
		List<ContentType> result = new ArrayList<>(5);
		for (IContentType iContentType : this.contentTypes.values()) {
			ContentType next = (ContentType) iContentType;
			if (next.getBaseType() == parent)
				result.add(next);
		}
		children = result.toArray(new ContentType[result.size()]);
		allChildren.put(parent, children);
		return children;
	}

	public ContentType getContentType(String contentTypeIdentifier) {
		ContentType type = internalGetContentType(contentTypeIdentifier);
		return (type != null && type.isValid() && !type.isAlias()) ? type : null;
	}

	private IContentDescription getDescriptionFor(ContentTypeMatcher matcher, ILazySource contents, String fileName, QualifiedName[] options) throws IOException {
		IContentType[] selected = internalFindContentTypesFor(matcher, contents, fileName, false);
		if (selected.length == 0)
			return null;
		// give the policy a chance to change the results
		ISelectionPolicy policy = matcher.getPolicy();
		if (policy != null) {
			selected = applyPolicy(policy, selected, fileName != null, true);
			if (selected.length == 0)
				return null;
		}
		return matcher.getSpecificDescription(((ContentType) selected[0]).internalGetDescriptionFor(contents, options));
	}

	public IContentDescription getDescriptionFor(ContentTypeMatcher matcher, InputStream contents, String fileName, QualifiedName[] options) throws IOException {
		return getDescriptionFor(matcher, ContentTypeManager.readBuffer(contents), fileName, options);
	}

	public IContentDescription getDescriptionFor(ContentTypeMatcher matcher, Reader contents, String fileName, QualifiedName[] options) throws IOException {
		return getDescriptionFor(matcher, ContentTypeManager.readBuffer(contents), fileName, options);
	}

	public int getGeneration() {
		return generation;
	}

	public ContentTypeManager getManager() {
		return manager;
	}

	private boolean internalAccept(ContentTypeVisitor visitor, ContentType root) {
		if (!root.isValid() || root.isAlias())
			return true;
		int result = visitor.visit(root);
		switch (result) {
				// stop traversing the tree
			case ContentTypeVisitor.STOP :
				return false;
				// stop traversing this subtree
			case ContentTypeVisitor.RETURN :
				return true;
		}
		ContentType[] children = getChildren(root);
		if (children == null)
			// this content type has no sub-types - keep traversing the tree
			return true;
		for (int i = 0; i < children.length; i++)
			if (!internalAccept(visitor, children[i]))
				// stop the traversal
				return false;
		return true;
	}

	private IContentType[] internalFindContentTypesFor(ILazySource buffer, IContentType[][] subset, Comparator<IContentType> validPolicy, Comparator<IContentType> indeterminatePolicy) throws IOException {
		Map<String, Object> properties = new HashMap<>();
		final List<ContentType> appropriate = new ArrayList<>(5);
		final int validFullName = collectMatchingByContents(0, subset[0], appropriate, buffer, properties);
		final int appropriateFullName = appropriate.size();
		final int validExtension = collectMatchingByContents(validFullName, subset[1], appropriate, buffer, properties) - validFullName;
		final int appropriateExtension = appropriate.size() - appropriateFullName;
		final int validPattern = collectMatchingByContents(validExtension, subset[2], appropriate, buffer, properties)
				- validExtension;
		final int appropriatePattern = appropriate.size() - appropriateFullName - appropriateExtension;
		IContentType[] result = appropriate.toArray(new IContentType[appropriate.size()]);
		if (validFullName > 1)
			Arrays.sort(result, 0, validFullName, validPolicy);
		if (validExtension > 1)
			Arrays.sort(result, validFullName, validFullName + validExtension, validPolicy);
		if (validPattern > 1) {
			Arrays.sort(result, validFullName + validExtension, validFullName + validExtension + validPattern,
					validPolicy);
		}
		if (appropriateFullName - validFullName > 1)
			Arrays.sort(result, validFullName + validExtension, appropriateFullName + validExtension, indeterminatePolicy);
		if (appropriateExtension - validExtension > 1)
			Arrays.sort(result, appropriateFullName + validExtension, appropriate.size() - validPattern,
					indeterminatePolicy);
		if (appropriatePattern - validPattern > 1) {
			Arrays.sort(result, appropriate.size() - validPattern, appropriate.size(), indeterminatePolicy);
		}
		return result;
	}

	private IContentType[] internalFindContentTypesFor(ContentTypeMatcher matcher, ILazySource buffer, String fileName, boolean forceValidation) throws IOException {
		final IContentType[][] subset;
		final Comparator<IContentType> validPolicy;
		Comparator<IContentType> indeterminatePolicy;
		if (fileName == null) {
			// we only have a single array, by need to provide a two-dimensional, 3-element
			// array
			subset = new IContentType[][] { getAllContentTypes(), NO_CONTENT_TYPES, NO_CONTENT_TYPES };
			indeterminatePolicy = policyConstantGeneralIsBetter;
			validPolicy = policyConstantSpecificIsBetter;
		} else {
			subset = internalFindContentTypesFor(matcher, fileName, policyLexicographical);
			indeterminatePolicy = policyGeneralIsBetter;
			validPolicy = policySpecificIsBetter;
		}
		int total = subset[0].length + subset[1].length + subset[2].length;
		if (total == 0)
			// don't do further work if subset is empty
			return NO_CONTENT_TYPES;
		if (!forceValidation && total == 1) {
			// do not do validation if not forced and only one was found (caller will validate later)
			IContentType[] found = subset[0].length == 1 ? subset[0] : (subset[1].length == 1 ? subset[1] : subset[2]);
			// bug 100032 - ignore binary content type if contents are text
			if (!buffer.isText())
				// binary buffer, caller can call the describer with no risk
				return found;
			// text buffer, need to check describer
			IContentDescriber describer = ((ContentType) found[0]).getDescriber();
			if (describer == null || describer instanceof ITextContentDescriber)
				// no describer or text describer, that is fine
				return found;
			// only eligible content type is binary and contents are text, ignore it
			return NO_CONTENT_TYPES;
		}
		return internalFindContentTypesFor(buffer, subset, validPolicy, indeterminatePolicy);
	}

	/**
	 * This is the implementation for file name based content type matching.
	 *
	 * @return all matching content types in the preferred order
	 * @see IContentTypeManager#findContentTypesFor(String)
	 */
	synchronized private IContentType[][] internalFindContentTypesFor(ContentTypeMatcher matcher, final String fileName, Comparator<IContentType> sortingPolicy) {
		IScopeContext context = matcher.getContext();
		IContentType[][] result = { NO_CONTENT_TYPES, NO_CONTENT_TYPES, NO_CONTENT_TYPES };

		Set<ContentType> existing = new HashSet<>();

		final Set<ContentType> allByFileName;
		if (context.equals(manager.getContext()))
			allByFileName = getDirectlyAssociated(fileName, IContentTypeSettings.FILE_NAME_SPEC);
		else {
			allByFileName = new HashSet<>(getDirectlyAssociated(fileName, IContentTypeSettings.FILE_NAME_SPEC | IContentType.IGNORE_USER_DEFINED));
			allByFileName.addAll(matcher.getDirectlyAssociated(this, fileName, IContentTypeSettings.FILE_NAME_SPEC));
		}
		Set<ContentType> selectedByName = selectMatchingByName(context, allByFileName, Collections.emptySet(), fileName,
				IContentType.FILE_NAME_SPEC);
		existing.addAll(selectedByName);
		result[0] = selectedByName.toArray(new IContentType[selectedByName.size()]);
		if (result[0].length > 1)
			Arrays.sort(result[0], sortingPolicy);

		final String fileExtension = ContentTypeManager.getFileExtension(fileName);
		if (fileExtension != null) {
			final Set<ContentType> allByFileExtension;
			if (context.equals(manager.getContext()))
				allByFileExtension = getDirectlyAssociated(fileExtension, IContentTypeSettings.FILE_EXTENSION_SPEC);
			else {
				allByFileExtension = new HashSet<>(getDirectlyAssociated(fileExtension, IContentTypeSettings.FILE_EXTENSION_SPEC | IContentType.IGNORE_USER_DEFINED));
				allByFileExtension.addAll(matcher.getDirectlyAssociated(this, fileExtension, IContentTypeSettings.FILE_EXTENSION_SPEC));
			}
			Set<ContentType> selectedByExtension = selectMatchingByName(context, allByFileExtension, selectedByName, fileExtension, IContentType.FILE_EXTENSION_SPEC);
			existing.addAll(selectedByExtension);
			if (!selectedByExtension.isEmpty())
				result[1] = selectedByExtension.toArray(new IContentType[selectedByExtension.size()]);
		}
		if (result[1].length > 1)
			Arrays.sort(result[1], sortingPolicy);

		final Set<ContentType> allByFilePattern;
		if (context.equals(manager.getContext()))
			allByFilePattern = getMatchingRegexpAssociated(fileName, IContentTypeSettings.FILE_PATTERN_SPEC);
		else {
			allByFilePattern = new HashSet<>(getMatchingRegexpAssociated(fileName,
					IContentTypeSettings.FILE_PATTERN_SPEC | IContentType.IGNORE_USER_DEFINED));
			allByFilePattern
					.addAll(matcher.getMatchingRegexpAssociated(this, fileName,
							IContentTypeSettings.FILE_PATTERN_SPEC));
		}
		existing.addAll(allByFilePattern);
		if (!allByFilePattern.isEmpty())
			result[2] = allByFilePattern.toArray(new IContentType[allByFilePattern.size()]);

		return result;
	}

	private Set<ContentType> getMatchingRegexpAssociated(String fileName, int typeMask) {
		if ((typeMask & IContentType.FILE_PATTERN_SPEC) == 0) {
			throw new IllegalArgumentException("This method requires FILE_PATTERN_SPEC."); //$NON-NLS-1$
		}
		Set<ContentType> res = new HashSet<>();
		for (Entry<Pattern, Set<ContentType>> spec : this.fileRegexps.entrySet()) {
			if (spec.getKey().matcher(fileName).matches()) {
				res.addAll(filterOnDefinitionSource(initialPatternForRegexp.get(spec.getKey()), typeMask,
						spec.getValue()));
			}
		}
		return res;
	}

	/**
	 * Returns content types directly associated with the given file spec.
	 *
	 * @param text a file name or extension
	 * @param typeMask a bit-wise or of the following flags:
	 * <ul>
	 * 		<li>IContentType.FILE_NAME, </li>
	 * 		<li>IContentType.FILE_EXTENSION, </li>
	 * 		<li>IContentType.IGNORE_PRE_DEFINED, </li>
	 * 		<li>IContentType.IGNORE_USER_DEFINED</li>
	 *	</ul>
	 * @return a set of content types
	 */
	private Set<ContentType> getDirectlyAssociated(String text, int typeMask) {
		if ((typeMask & IContentType.FILE_PATTERN_SPEC) != 0) {
			throw new IllegalArgumentException("This method don't allow FILE_REGEXP_SPEC."); //$NON-NLS-1$
		}
		Map<String, Set<ContentType>> associations = (typeMask & IContentTypeSettings.FILE_NAME_SPEC) != 0 ? fileNames : fileExtensions;
		Set<ContentType> result = associations.get(FileSpec.getMappingKeyFor(text));
		if ((typeMask & (IContentType.IGNORE_PRE_DEFINED | IContentType.IGNORE_USER_DEFINED)) != 0) {
			result = filterOnDefinitionSource(text, typeMask, result);
		}
		return result == null ? Collections.EMPTY_SET : result;
	}

	/**
	 * Filters a set of content-types on whether they have a mapping that matches
	 * provided criteria.
	 *
	 * @param text
	 *            file name, file extension or file regexp (depending on value of
	 *            {@code typeMask}.
	 * @param typeMask
	 *            the type mask. Spec type, and definition source (pre-defined or
	 *            user-defined) will be used
	 * @param contentTypes
	 *            content types to filter from (not modified during method
	 *            execution)
	 * @return set of filtered content-type
	 */
	private Set<ContentType> filterOnDefinitionSource(String text, int typeMask, Set<ContentType> contentTypes) {
		if ((typeMask & (IContentType.IGNORE_PRE_DEFINED | IContentType.IGNORE_USER_DEFINED)) == 0) {
			return contentTypes;
		}
		if (contentTypes != null && !contentTypes.isEmpty()) {
			// copy so we can modify
			contentTypes = new HashSet<>(contentTypes);
			// invert the last two bits so it is easier to compare
			typeMask ^= (IContentType.IGNORE_PRE_DEFINED | IContentType.IGNORE_USER_DEFINED);
			for (Iterator<ContentType> i = contentTypes.iterator(); i.hasNext();) {
				ContentType contentType = i.next();
				if (!contentType.hasFileSpec(text, typeMask, true))
					i.remove();
			}
		}
		return contentTypes;
	}

	synchronized ContentType internalGetContentType(String contentTypeIdentifier) {
		return (ContentType) contentTypes.get(contentTypeIdentifier);
	}

	private void makeAliases() {
		// process all content types marking aliases appropriately
		for (IContentType iContentType : contentTypes.values()) {
			ContentType type = (ContentType) iContentType;
			String targetId = type.getAliasTargetId();
			if (targetId == null)
				continue;
			ContentType target = internalGetContentType(targetId);
			if (target != null)
				type.setAliasTarget(target);
		}
	}

	/**
	 * Resolves inter-content type associations (inheritance and aliasing).
	 */
	synchronized protected void organize() {
		// build the aliasing
		makeAliases();
		// do the validation
		for (IContentType iContentType : contentTypes.values()) {
			ContentType type = (ContentType) iContentType;
			if (ensureValid(type))
				associate(type);
		}
		if (ContentTypeManager.DEBUGGING)
			for (IContentType iContentType : contentTypes.values()) {
				ContentType type = (ContentType) iContentType;
				if (!type.isValid())
					ContentMessages.message("Invalid: " + type); //$NON-NLS-1$
			}
	}

	/**
	 * Processes all content types in source, adding those matching the given file spec to the
	 * destination collection.
	 */
	private Set<ContentType> selectMatchingByName(final IScopeContext context, Collection<ContentType> source, final Collection<ContentType> existing, final String fileSpecText, final int fileSpecType) {
		if (source == null || source.isEmpty())
			return Collections.EMPTY_SET;
		final Set<ContentType> destination = new HashSet<>(5);
		// process all content types in the given collection
		for (ContentType root : source) {
			// From a given content type, check if it matches, and
			// include any children that match as well.
			internalAccept(new ContentTypeVisitor() {
				@Override
				public int visit(ContentType type) {
					if (type != root && type.hasBuiltInAssociations())
						// this content type has built-in associations - visit it later as root
						return RETURN;
					if (type == root && !type.hasFileSpec(context, fileSpecText, fileSpecType))
						// it is the root and does not match the file name - do not add it nor look into its children
						return RETURN;
					// either the content type is the root and matches the file name or
					// is a sub content type and does not have built-in files specs
					if (!existing.contains(type))
						destination.add(type);
					return CONTINUE;
				}
			}, root);
		}
		return destination;
	}

	void removeContentType(String contentTypeIdentifier) throws CoreException {
		ContentType contentType = getContentType(contentTypeIdentifier);
		if (contentType == null) {
			return;
		}
		if (!contentType.isUserDefined()) {
			throw new IllegalArgumentException("Content type must be user-defined."); //$NON-NLS-1$
		}
		contentTypes.remove(contentType.getId());
	}

}
