/******************************************************************************* * Copyright 2013 Geoscience Australia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package au.gov.ga.earthsci.intent; import org.eclipse.core.runtime.content.IContentType; /** * Contains helper methods for dealing with {@link IContentType}s. * * @author Michael de Hoog (michael.dehoog@ga.gov.au) */ public class ContentTypeHelper { /** * Search the list of content types for the closest type that is a kind of * the given content type. Closest means the smallest distance between the * given content type and a content type in it's ancestry. * * @see #ancestryDistance(IContentType, IContentType) * * @param contentType * Content type who's ancestry to search for a content type in * the collection * @param contentTypes * Collection of content types to search * @return Closest content type from <code>contentTypes</code> that the * <code>contentType</code> is a kind of */ public static IContentType closestMatching(IContentType contentType, Iterable<IContentType> contentTypes) { if (contentType == null || contentTypes == null) { return null; } int minDistance = Integer.MAX_VALUE; IContentType closest = null; for (IContentType test : contentTypes) { int distance = ancestryDistance(contentType, test); if (distance >= 0 && distance < minDistance) { minDistance = distance; closest = test; } } return closest; } /** * Search the list of content types for the closest type that is a kind of * the given content type, and return the ancestry distance to that type. * Closest means the smallest distance between the given content type and a * content type in it's ancestry. * <p/> * Returns -1 if no matching content type could be found. * * @see #ancestryDistance(IContentType, IContentType) * * @param contentType * Content type who's ancestry to search for a content type in * the collection * @param contentTypes * Collection of content types to search * @return Ancestry distance to the closest content type from * <code>contentTypes</code> that the <code>contentType</code> is a * kind of, or -1 if no matching content type could be found */ public static int distanceToClosestMatching(IContentType contentType, Iterable<IContentType> contentTypes) { if (contentType == null || contentTypes == null) { return -1; } int minDistance = Integer.MAX_VALUE; for (IContentType test : contentTypes) { int distance = ancestryDistance(contentType, test); if (distance >= 0 && distance < minDistance) { minDistance = distance; } } return minDistance == Integer.MAX_VALUE ? -1 : minDistance; } /** * Calculate the distance between the child content type and the parent, * searching the child's ancestry. * <p/> * For example: * <ul> * <li>Returns 0 if child == parent</li> * <li>Returns 1 if child's base type == parent</li> * <li>etc...</li> * </ul> * * Returns -1 if the parent doesn't exist in the child's ancestry. * * @param child * @param parent * @return The distance between the child and the parent in the child's * ancestry, or -1 if the parent could not be found */ public static int ancestryDistance(IContentType child, IContentType parent) { return ancestryDistance(child, parent, 0); } private static int ancestryDistance(IContentType child, IContentType parent, int position) { if (child == null || parent == null) { return -1; } if (child.equals(parent)) { return position; } return ancestryDistance(child.getBaseType(), parent, position++); } }