/*******************************************************************************
 * Copyright (c) 2004, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * 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());
	}

}
