/*
* Copyright 2014 the original author or authors.
*
* 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 org.gradle.model.internal.type;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import groovy.lang.GroovyObject;
import org.gradle.model.ModelMap;
import org.gradle.model.ModelSet;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Queue;
import java.util.Set;
public abstract class ModelTypes {
public static <I> ModelType<ModelMap<I>> modelMap(Class<I> type) {
return modelMap(ModelType.of(type));
}
public static <I> ModelType<ModelMap<I>> modelMap(ModelType<I> type) {
return new ModelType.Builder<ModelMap<I>>() {
}.where(
new ModelType.Parameter<I>() {
}, type
).build();
}
public static <I> ModelType<ModelSet<I>> modelSet(ModelType<I> type) {
return new ModelType.Builder<ModelSet<I>>() {
}.where(
new ModelType.Parameter<I>() {
}, type
).build();
}
public static <I> ModelType<List<I>> list(ModelType<I> type) {
return new ModelType.Builder<List<I>>() {
}.where(
new ModelType.Parameter<I>() {
}, type
).build();
}
public static <I> ModelType<Set<I>> set(ModelType<I> type) {
return new ModelType.Builder<Set<I>>() {
}.where(
new ModelType.Parameter<I>() {
}, type
).build();
}
public static <T> Ordering<ModelType<? extends T>> displayOrder() {
return new Ordering<ModelType<? extends T>>() {
@Override
public int compare(ModelType<? extends T> left, ModelType<? extends T> right) {
return left.getDisplayName().compareTo(right.getDisplayName());
}
};
}
/**
* Returns the sorted, unique display names of the given types.
*/
public static Iterable<String> getDisplayNames(Iterable<? extends ModelType<?>> types) {
ImmutableSortedSet.Builder<String> builder = ImmutableSortedSet.naturalOrder();
for (ModelType<?> type : types) {
builder.add(type.getDisplayName());
}
return builder.build();
}
/**
* Collect all types that make up the type hierarchy of the given types.
*/
public static Set<ModelType<?>> collectHierarchy(Iterable<? extends ModelType<?>> types) {
Queue<ModelType<?>> queue = new ArrayDeque<ModelType<?>>(Iterables.size(types) * 2);
Iterables.addAll(queue, types);
Set<ModelType<?>> seenTypes = Sets.newLinkedHashSet();
ModelType<?> type;
while ((type = queue.poll()) != null) {
// Do not process Object's or GroovyObject's methods
Class<?> rawClass = type.getRawClass();
if (rawClass.equals(Object.class) || rawClass.equals(GroovyObject.class)) {
continue;
}
// Do not reprocess
if (!seenTypes.add(type)) {
continue;
}
Class<?> superclass = rawClass.getSuperclass();
if (superclass != null) {
ModelType<?> superType = ModelType.of(superclass);
if (!seenTypes.contains(superType)) {
queue.add(superType);
}
}
for (Class<?> iface : rawClass.getInterfaces()) {
ModelType<?> ifaceType = ModelType.of(iface);
if (!seenTypes.contains(ifaceType)) {
queue.add(ifaceType);
}
}
}
return seenTypes;
}
}