/**
  * Looks up a (possibly cached) {@link ResourceVisibilityLookup} for the given {@link
  * AndroidLibrary}
  *
  * @param library the library
  * @return the corresponding {@link ResourceVisibilityLookup}
  */
 @NonNull
 public ResourceVisibilityLookup get(@NonNull AndroidLibrary library) {
   ResourceVisibilityLookup visibility = mInstances.get(library);
   if (visibility == null) {
     visibility = new LibraryResourceVisibility(library);
     if (visibility.isEmpty()) {
       visibility = NONE;
     }
     List<? extends AndroidLibrary> dependsOn = library.getLibraryDependencies();
     if (!dependsOn.isEmpty()) {
       List<ResourceVisibilityLookup> list =
           Lists.newArrayListWithExpectedSize(dependsOn.size() + 1);
       list.add(visibility);
       for (AndroidLibrary d : dependsOn) {
         ResourceVisibilityLookup v = get(d);
         if (!v.isEmpty()) {
           list.add(v);
         }
       }
       if (list.size() > 1) {
         visibility = new MultipleLibraryResourceVisibility(list);
       }
     }
     mInstances.put(library, visibility);
   }
   return visibility;
 }
    /**
     * Returns a map from name to resource types for all resources known to this library. This is
     * used to make sure that when the {@link #isPrivate(ResourceType, String)} query method is
     * called, it can tell the difference between a resource implicitly private by not being
     * declared as public and a resource unknown to this library (e.g. defined by a different
     * library or the user's own project resources.)
     *
     * @return a map from name to resource type for all resources in this library
     */
    @Nullable
    private Multimap<String, ResourceType> computeAllMap() {
      // getSymbolFile() is not defined in AndroidLibrary, only in the subclass LibraryBundle
      File symbolFile = new File(mLibrary.getPublicResources().getParentFile(), FN_RESOURCE_TEXT);
      if (!symbolFile.exists()) {
        return null;
      }

      try {
        List<String> lines = Files.readLines(symbolFile, Charsets.UTF_8);
        Multimap<String, ResourceType> result = ArrayListMultimap.create(lines.size(), 2);

        ResourceType previousType = null;
        String previousTypeString = "";
        int lineIndex = 1;
        final int count = lines.size();
        for (; lineIndex <= count; lineIndex++) {
          String line = lines.get(lineIndex - 1);

          if (line.startsWith("int ")) { // not int[] definitions for styleables
            // format is "int <type> <class> <name> <value>"
            int typeStart = 4;
            int typeEnd = line.indexOf(' ', typeStart);

            // Items are sorted by type, so we can avoid looping over types in
            // ResourceType.getEnum() for each line by sharing type in each section
            String typeString = line.substring(typeStart, typeEnd);
            ResourceType type;
            if (typeString.equals(previousTypeString)) {
              type = previousType;
            } else {
              type = ResourceType.getEnum(typeString);
              previousTypeString = typeString;
              previousType = type;
            }
            if (type == null) { // some newly introduced type
              continue;
            }

            int nameStart = typeEnd + 1;
            int nameEnd = line.indexOf(' ', nameStart);
            String name = line.substring(nameStart, nameEnd);
            result.put(name, type);
          }
        }
        return result;
      } catch (IOException ignore) {
      }
      return null;
    }
    /**
     * Returns a map from name to applicable resource types where the presence of the type+name
     * combination means that the corresponding resource is explicitly public.
     *
     * <p>If the result is null, there is no {@code public.txt} definition for this library, so all
     * resources should be taken to be public.
     *
     * @return a map from name to resource type for public resources in this library
     */
    @Nullable
    private Multimap<String, ResourceType> computeVisibilityMap() {
      File publicResources = mLibrary.getPublicResources();
      if (!publicResources.exists()) {
        return null;
      }

      try {
        List<String> lines = Files.readLines(publicResources, Charsets.UTF_8);
        Multimap<String, ResourceType> result = ArrayListMultimap.create(lines.size(), 2);
        for (String line : lines) {
          // These files are written by code in MergedResourceWriter#postWriteAction
          // Format for each line: <type><space><name>\n
          // Therefore, we don't expect/allow variations in the format (we don't
          // worry about extra spaces needing to be trimmed etc)
          int index = line.indexOf(' ');
          if (index == -1 || line.isEmpty()) {
            continue;
          }

          String typeString = line.substring(0, index);
          ResourceType type = ResourceType.getEnum(typeString);
          if (type == null) {
            // This could in theory happen if in the future a new ResourceType is
            // introduced, and a newer version of the Gradle build system writes the
            // name of this type into the public.txt file, and an older version of
            // the IDE then attempts to read it. Just skip these symbols.
            continue;
          }
          String name = line.substring(index + 1);
          result.put(name, type);
        }
        return result;
      } catch (IOException ignore) {
      }
      return null;
    }