package org.netbeans.gradle.project.extensions; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.jtrim.utils.ExceptionHelper; import org.netbeans.gradle.model.api.GradleProjectInfoQuery2; import org.netbeans.gradle.model.util.CollectionUtils; import org.netbeans.gradle.project.api.entry.GradleProjectExtensionDef; import org.netbeans.gradle.project.api.modelquery.GradleModelDef; import org.netbeans.gradle.project.api.modelquery.GradleModelDefQuery1; import org.netbeans.gradle.project.api.modelquery.GradleModelDefQuery2; import org.netbeans.gradle.project.api.modelquery.GradleTarget; public final class ModelNeeds { private static final Logger LOGGER = Logger.getLogger(ModelNeeds.class.getName()); private final GradleModelDefQuery1 query1; private final GradleModelDefQuery2 query2; public ModelNeeds(GradleProjectExtensionDef<?> extensionDef) { ExceptionHelper.checkNotNullArgument(extensionDef, "extensionDef"); this.query1 = createQuery1(extensionDef); this.query2 = createQuery2(extensionDef); } public GradleModelDefQuery1 getQuery1() { return query1; } public GradleModelDefQuery2 getQuery2() { return query2; } private static GradleModelDefQuery1 createQuery1( Collection<? extends GradleModelDefQuery1> extensionQueries) { final List<GradleModelDefQuery1> queries = CollectionUtils.copyNullSafeList(extensionQueries); int size = queries.size(); if (size == 0) { return NoModels1.INSTANCE; } if (queries.size() == 1) { return queries.iterator().next(); } return new GradleModelDefQuery1() { @Override public Collection<Class<?>> getToolingModels(GradleTarget gradleTarget) { List<Class<?>> result = new ArrayList<>(); for (GradleModelDefQuery1 query: queries) { Collection<Class<?>> models = safelyReturn(query.getToolingModels(gradleTarget), query); result.addAll(models); } return result; } }; } private static GradleModelDefQuery1 createQuery1(final GradleProjectExtensionDef<?> extensionDef) { return createQuery1(extensionDef.getLookup().lookupAll(GradleModelDefQuery1.class)); } private static GradleModelDefQuery2 query1AsQuery2(final GradleModelDefQuery1 query1) { return new GradleModelDefQuery2() { @Override public GradleModelDef getModelDef(GradleTarget gradleTarget) { Collection<Class<?>> toolinModels = query1.getToolingModels(gradleTarget); if (toolinModels.isEmpty()) { return GradleModelDef.EMPTY; } return GradleModelDef.create( toolinModels, Collections.<GradleProjectInfoQuery2<?>>emptyList()); } }; } private static GradleModelDefQuery2 createQuery2( Collection<? extends GradleModelDefQuery2> extensionQueries) { final List<GradleModelDefQuery2> queries = CollectionUtils.copyNullSafeList(extensionQueries); int size = queries.size(); if (size == 0) { return NoModels2.INSTANCE; } if (size == 1) { return queries.iterator().next(); } return new GradleModelDefQuery2() { @Override public GradleModelDef getModelDef(GradleTarget gradleTarget) { List<GradleProjectInfoQuery2<?>> projectInfoQueries = new ArrayList<>(); List<Class<?>> toolingModels = new ArrayList<>(); for (GradleModelDefQuery2 query: queries) { GradleModelDef modelDef = safelyReturn(query.getModelDef(gradleTarget), query); projectInfoQueries.addAll(modelDef.getProjectInfoQueries2()); toolingModels.addAll(modelDef.getToolingModels()); } return GradleModelDef.create(toolingModels, projectInfoQueries); } }; } private static GradleModelDefQuery2 createQuery2(final GradleProjectExtensionDef<?> extension) { Collection<? extends GradleModelDefQuery2> queries2 = extension.getLookup().lookupAll(GradleModelDefQuery2.class); if (!queries2.isEmpty()) { return createQuery2(queries2); } return query1AsQuery2(createQuery1(extension)); } private static <T> Collection<T> safelyReturn(Collection<T> result, Object query) { if (result == null) { LOGGER.log(Level.WARNING, "GradleModelDefQuery1.getToolingModels returned null for a query {0}", query.getClass().getName()); return Collections.emptyList(); } else { return result; } } private static GradleModelDef safelyReturn(GradleModelDef result, Object query) { if (result == null) { LOGGER.log(Level.WARNING, "GradleModelDefQuery2.getModelDef returned null for a query {0}", query.getClass().getName()); return GradleModelDef.EMPTY; } else { return result; } } private enum NoModels1 implements GradleModelDefQuery1 { INSTANCE; @Override public Collection<Class<?>> getToolingModels(GradleTarget gradleTarget) { return Collections.emptyList(); } } private enum NoModels2 implements GradleModelDefQuery2 { INSTANCE; @Override public GradleModelDef getModelDef(GradleTarget gradleTarget) { return GradleModelDef.EMPTY; } } }