All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.android.util.AndroidDependenciesCache Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition android library. This is release number 1 of trunk branch 142.

The newest version!
package org.jetbrains.android.util;

import com.intellij.ProjectTopics;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.reference.SoftReference;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.annotations.NotNull;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author Eugene.Kudelevsky
 */
public class AndroidDependenciesCache {
  private static final Key> KEY = Key.create("ANDROID_DEPENDENCIES_CACHE");
  private final Module myModule;

  private final Ref>> myAllDependencies = Ref.create();
  private final Ref>> myAllLibraryDependencies = Ref.create();

  private AndroidDependenciesCache(@NotNull Module module) {
    myModule = module;

    module.getProject().getMessageBus().connect(module).subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
      @Override
      public void rootsChanged(ModuleRootEvent event) {
        dropCache();
      }
    });
  }

  private synchronized void dropCache() {
    myAllDependencies.set(null);
    myAllLibraryDependencies.set(null);
  }

  @NotNull
  public static AndroidDependenciesCache getInstance(@NotNull Module module) {
    AndroidDependenciesCache cache = SoftReference.dereference(module.getUserData(KEY));

    if (cache == null) {
      cache = new AndroidDependenciesCache(module);
      module.putUserData(KEY, new SoftReference(cache));
    }
    return cache;
  }

  @NotNull
  public synchronized List getAllAndroidDependencies(boolean androidLibrariesOnly) {
    return getAllAndroidDependencies(myModule, androidLibrariesOnly, getListRef(androidLibrariesOnly));
  }

  @NotNull
  private Ref>> getListRef(boolean androidLibrariesOnly) {
    return androidLibrariesOnly ? myAllLibraryDependencies : myAllDependencies;
  }

  @NotNull
  private static List getAllAndroidDependencies(@NotNull Module module,
                                                              boolean androidLibrariesOnly,
                                                              Ref>> listRef) {
    List> refs = listRef.get();

    if (refs == null) {
      final List facets = new ArrayList();
      collectAllAndroidDependencies(module, androidLibrariesOnly, facets, new HashSet());

      refs = ContainerUtil.map(ContainerUtil.reverse(facets), new Function>() {
        @Override
        public WeakReference fun(AndroidFacet facet) {
          return new WeakReference(facet);
        }
      });
      listRef.set(refs);
    }
    return dereference(refs);
  }

  @NotNull
  private static List dereference(@NotNull List> refs) {
    return ContainerUtil.mapNotNull(refs, new Function, AndroidFacet>() {
      @Override
      public AndroidFacet fun(WeakReference ref) {
        return ref.get();
      }
    });
  }

  private static void collectAllAndroidDependencies(Module module,
                                                    boolean androidLibrariesOnly,
                                                    List result,
                                                    Set visited) {
    final OrderEntry[] entries = ModuleRootManager.getInstance(module).getOrderEntries();
    // loop in the inverse order to resolve dependencies on the libraries, so that if a library
    // is required by two higher level libraries it can be inserted in the correct place

    for (int i = entries.length - 1; i >= 0; i--) {
      final OrderEntry orderEntry = entries[i];
      if (orderEntry instanceof ModuleOrderEntry) {
        final ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)orderEntry;

        if (moduleOrderEntry.getScope() == DependencyScope.COMPILE) {
          final Module depModule = moduleOrderEntry.getModule();

          if (depModule != null) {
            final AndroidFacet depFacet = AndroidFacet.getInstance(depModule);

            if (depFacet != null &&
                (!androidLibrariesOnly || depFacet.isLibraryProject()) &&
                visited.add(depFacet)) {
              final List> cachedDepDeps =
                getInstance(depModule).getListRef(androidLibrariesOnly).get();

              if (cachedDepDeps != null) {
                final List depDeps = dereference(cachedDepDeps);

                for (AndroidFacet depDepFacet : depDeps) {
                  if (visited.add(depDepFacet)) {
                    result.add(depDepFacet);
                  }
                }
              }
              else {
                collectAllAndroidDependencies(depModule, androidLibrariesOnly, result, visited);
              }
              result.add(depFacet);
            }
          }
        }
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy