/* * Copyright (C) 2013 The Android Open Source Project * * 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 com.android.tools.idea.gradle.service; import com.android.tools.idea.gradle.AndroidProjectKeys; import com.android.tools.idea.gradle.GradleSyncState; import com.android.tools.idea.gradle.IdeaGradleProject; import com.android.tools.idea.gradle.facet.AndroidGradleFacet; import com.android.tools.idea.gradle.util.Facets; import com.google.common.collect.Maps; import com.intellij.facet.FacetManager; import com.intellij.facet.ModifiableFacetModel; import com.intellij.openapi.application.RunResult; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.Key; import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataService; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.Map; /** * Service that stores the "Gradle project paths" of an imported Android-Gradle project. */ public class GradleProjectDataService implements ProjectDataService<IdeaGradleProject, Void> { private static final Logger LOG = Logger.getInstance(GradleProjectDataService.class); @NotNull @Override public Key<IdeaGradleProject> getTargetDataKey() { return AndroidProjectKeys.IDE_GRADLE_PROJECT; } @Override public void importData(@NotNull Collection<DataNode<IdeaGradleProject>> toImport, @NotNull Project project, boolean synchronous) { if (!toImport.isEmpty()) { try { doImport(toImport, project); } catch (Throwable e) { LOG.error(String.format("Failed to set up modules in project '%1$s'", project.getName()), e); GradleSyncState.getInstance(project).syncFailed(e.getMessage()); } } } private static void doImport(final Collection<DataNode<IdeaGradleProject>> toImport, final Project project) throws Throwable { RunResult result = new WriteCommandAction.Simple(project) { @Override protected void run() throws Throwable { if (!project.isDisposed()) { ModuleManager moduleManager = ModuleManager.getInstance(project); Map<String, IdeaGradleProject> gradleProjectsByName = indexByModuleName(toImport); for (Module module : moduleManager.getModules()) { IdeaGradleProject gradleProject = gradleProjectsByName.get(module.getName()); if (gradleProject == null) { // This happens when there is an orphan IDEA module that does not map to a Gradle project. One way for this to happen is when // opening a project created in another machine, and Gradle import assigns a different name to a module. Then, user decides not // to delete the orphan module when Studio prompts to do so. Facets.removeAllFacetsOfType(module, AndroidGradleFacet.TYPE_ID); } else { customizeModule(module, gradleProject); } } } } }.execute(); Throwable error = result.getThrowable(); if (error != null) { throw error; } } @NotNull private static Map<String, IdeaGradleProject> indexByModuleName(@NotNull Collection<DataNode<IdeaGradleProject>> dataNodes) { Map<String, IdeaGradleProject> gradleProjectsByModuleName = Maps.newHashMap(); for (DataNode<IdeaGradleProject> d : dataNodes) { IdeaGradleProject gradleProject = d.getData(); gradleProjectsByModuleName.put(gradleProject.getModuleName(), gradleProject); } return gradleProjectsByModuleName; } private static void customizeModule(@NotNull Module module, @NotNull IdeaGradleProject gradleProject) { AndroidGradleFacet androidGradleFacet = setAndGetAndroidGradleFacet(module); androidGradleFacet.setGradleProject(gradleProject); } /** * Retrieves the Android-Gradle facet from the given module. If the given module does not have it, this method will create a new one. * * @param module the given module. * @return the Android-Gradle facet from the given module. */ @NotNull private static AndroidGradleFacet setAndGetAndroidGradleFacet(Module module) { AndroidGradleFacet facet = AndroidGradleFacet.getInstance(module); if (facet != null) { return facet; } // Module does not have Android-Gradle facet. Create one and add it. FacetManager facetManager = FacetManager.getInstance(module); ModifiableFacetModel model = facetManager.createModifiableModel(); try { facet = facetManager.createFacet(AndroidGradleFacet.getFacetType(), AndroidGradleFacet.NAME, null); model.addFacet(facet); } finally { model.commit(); } return facet; } @Override public void removeData(@NotNull Collection<? extends Void> toRemove, @NotNull Project project, boolean synchronous) { } }