protected void removeFile(@NonNull Collection<ResourceType> types, @NonNull ResourceFile file) {
    ensureInitialized();

    for (ResourceType type : types) {
      removeFile(type, file);
    }
  }
  /**
   * Removes a {@link ResourceFolder} associated with the specified {@link IAbstractFolder}.
   *
   * @param type The type of the folder
   * @param removedFolder the IAbstractFolder object.
   * @param context the scanning context
   * @return the {@link ResourceFolder} that was removed, or null if no matches were found.
   */
  @Nullable
  public ResourceFolder removeFolder(
      @NonNull ResourceFolderType type,
      @NonNull IAbstractFolder removedFolder,
      @Nullable ScanningContext context) {
    ensureInitialized();

    // get the list of folders for the resource type.
    List<ResourceFolder> list = mFolderMap.get(type);

    if (list != null) {
      int count = list.size();
      for (int i = 0; i < count; i++) {
        ResourceFolder resFolder = list.get(i);
        IAbstractFolder folder = resFolder.getFolder();
        if (removedFolder.equals(folder)) {
          // we found the matching ResourceFolder. we need to remove it.
          list.remove(i);

          // remove its content
          resFolder.dispose(context);

          return resFolder;
        }
      }
    }

    return null;
  }
  /**
   * Returns the list of source files for a given resource. Optionally, if a {@link
   * FolderConfiguration} is given, then only the best match for this config is returned.
   *
   * @param type the type of the resource.
   * @param name the name of the resource.
   * @param referenceConfig an optional config for which only the best match will be returned.
   * @return a list of files generating this resource or null if it was not found.
   */
  @Nullable
  public List<ResourceFile> getSourceFiles(
      @NonNull ResourceType type,
      @NonNull String name,
      @Nullable FolderConfiguration referenceConfig) {
    ensureInitialized();

    Collection<ResourceItem> items = getResourceItemsOfType(type);

    for (ResourceItem item : items) {
      if (name.equals(item.getName())) {
        if (referenceConfig != null) {
          Configurable match = referenceConfig.findMatchingConfigurable(item.getSourceFileList());

          if (match instanceof ResourceFile) {
            return Collections.singletonList((ResourceFile) match);
          }

          return null;
        }
        return item.getSourceFileList();
      }
    }

    return null;
  }
  /**
   * Returns the resources values matching a given {@link FolderConfiguration}.
   *
   * @param referenceConfig the configuration that each value must match.
   * @return a map with guaranteed to contain an entry for each {@link ResourceType}
   */
  @NonNull
  public Map<ResourceType, Map<String, ResourceValue>> getConfiguredResources(
      @NonNull FolderConfiguration referenceConfig) {
    ensureInitialized();

    return doGetConfiguredResources(referenceConfig);
  }
  /**
   * Returns the {@link ResourceFile} matching the given name, {@link ResourceType} and
   * configuration.
   *
   * <p>This only works with files generating one resource named after the file (for instance,
   * layouts, bitmap based drawable, xml, anims).
   *
   * @param name the resource name or file name
   * @param type the folder type search for
   * @param config the folder configuration to match for
   * @return the matching file or <code>null</code> if no match was found.
   */
  @Nullable
  public ResourceFile getMatchingFile(
      @NonNull String name, @NonNull ResourceType type, @NonNull FolderConfiguration config) {
    ensureInitialized();

    String resourceName = name;
    int dot = resourceName.indexOf('.');
    if (dot != -1) {
      resourceName = resourceName.substring(0, dot);
    }

    Map<String, ResourceItem> items = mResourceMap.get(type);
    if (items != null) {
      ResourceItem item = items.get(resourceName);
      if (item != null) {
        List<ResourceFile> files = item.getSourceFileList();
        if (files != null) {
          if (files.size() > 1) {
            ResourceValue value = item.getResourceValue(type, config, isFrameworkRepository());
            if (value != null) {
              String v = value.getValue();
              if (v != null) {
                ResourceUrl url = ResourceUrl.parse(v);
                if (url != null) {
                  return getMatchingFile(url.name, url.type, config);
                } else {
                  // Looks like the resource value is pointing to a file
                  // It's most likely one of the source files for this
                  // resource item, so check those first
                  for (ResourceFile f : files) {
                    if (v.equals(f.getFile().getOsLocation())) {
                      // Found the file
                      return f;
                    }
                  }

                  // No; look up the resource file from the full path
                  File file = new File(v);
                  if (file.exists()) {
                    ResourceFile f = findResourceFile(file);
                    if (f != null) {
                      return f;
                    }
                  }
                }
              }
            }
          } else if (files.size() == 1) {
            // Single file: see if it matches
            ResourceFile matchingFile = files.get(0);
            if (matchingFile.getFolder().getConfiguration().isMatchFor(config)) {
              return matchingFile;
            }
          }
        }
      }
    }

    return null;
  }
  /**
   * Returns true if this resource repository contains a resource of the given name.
   *
   * @param url the resource URL
   * @return true if the resource is known
   */
  public boolean hasResourceItem(@NonNull String url) {
    // Handle theme references
    if (url.startsWith(PREFIX_THEME_REF)) {
      String remainder = url.substring(PREFIX_THEME_REF.length());
      if (url.startsWith(ATTR_REF_PREFIX)) {
        url = PREFIX_RESOURCE_REF + url.substring(PREFIX_THEME_REF.length());
        return hasResourceItem(url);
      }
      int colon = url.indexOf(':');
      if (colon != -1) {
        // Convert from ?android:progressBarStyleBig to ?android:attr/progressBarStyleBig
        if (remainder.indexOf('/', colon) == -1) {
          remainder =
              remainder.substring(0, colon) + RESOURCE_CLZ_ATTR + '/' + remainder.substring(colon);
        }
        url = PREFIX_RESOURCE_REF + remainder;
        return hasResourceItem(url);
      } else {
        int slash = url.indexOf('/');
        if (slash == -1) {
          url = PREFIX_RESOURCE_REF + RESOURCE_CLZ_ATTR + '/' + remainder;
          return hasResourceItem(url);
        }
      }
    }

    if (!url.startsWith(PREFIX_RESOURCE_REF)) {
      return false;
    }

    assert url.startsWith("@") || url.startsWith("?") : url;

    ensureInitialized();

    int typeEnd = url.indexOf('/', 1);
    if (typeEnd != -1) {
      int nameBegin = typeEnd + 1;

      // Skip @ and @+
      int typeBegin = url.startsWith("@+") ? 2 : 1; // $NON-NLS-1$

      int colon = url.lastIndexOf(':', typeEnd);
      if (colon != -1) {
        typeBegin = colon + 1;
      }
      String typeName = url.substring(typeBegin, typeEnd);
      ResourceType type = ResourceType.getEnum(typeName);
      if (type != null) {
        String name = url.substring(nameBegin);
        return hasResourceItem(type, name);
      }
    }

    return false;
  }
  /**
   * Returns the resources values matching a given {@link FolderConfiguration} for the current
   * project.
   *
   * @param referenceConfig the configuration that each value must match.
   * @return a map with guaranteed to contain an entry for each {@link ResourceType}
   */
  @NonNull
  protected final Map<ResourceType, Map<String, ResourceValue>> doGetConfiguredResources(
      @NonNull FolderConfiguration referenceConfig) {
    ensureInitialized();

    Map<ResourceType, Map<String, ResourceValue>> map =
        new EnumMap<ResourceType, Map<String, ResourceValue>>(ResourceType.class);

    for (ResourceType key : ResourceType.values()) {
      // get the local results and put them in the map
      map.put(key, getConfiguredResource(key, referenceConfig));
    }

    return map;
  }
  /**
   * Returns true if this resource repository contains a resource of the given name.
   *
   * @param type the type of resource to look up
   * @param name the name of the resource
   * @return true if the resource is known
   */
  public boolean hasResourceItem(@NonNull ResourceType type, @NonNull String name) {
    ensureInitialized();

    Map<String, ResourceItem> map = mResourceMap.get(type);

    if (map != null) {

      ResourceItem resourceItem = map.get(name);
      if (resourceItem != null) {
        return true;
      }
    }

    return false;
  }
  /**
   * Returns the {@link ResourceFolder} associated with a {@link IAbstractFolder}.
   *
   * @param folder The {@link IAbstractFolder} object.
   * @return the {@link ResourceFolder} or null if it was not found.
   */
  @Nullable
  public ResourceFolder getResourceFolder(@NonNull IAbstractFolder folder) {
    ensureInitialized();

    Collection<List<ResourceFolder>> values = mFolderMap.values();

    for (List<ResourceFolder> list : values) {
      for (ResourceFolder resFolder : list) {
        IAbstractFolder wrapper = resFolder.getFolder();
        if (wrapper.equals(folder)) {
          return resFolder;
        }
      }
    }

    return null;
  }
Esempio n. 10
0
  /**
   * Returns a list of {@link ResourceItem} matching a given {@link ResourceType}.
   *
   * @param type the type of the resource items to return
   * @return a non null collection of resource items
   */
  @NonNull
  public Collection<ResourceItem> getResourceItemsOfType(@NonNull ResourceType type) {
    ensureInitialized();

    Map<String, ResourceItem> map = mResourceMap.get(type);

    if (map == null) {
      return Collections.emptyList();
    }

    Collection<ResourceItem> roList = mReadOnlyListMap.get(map);
    if (roList == null) {
      roList = Collections.unmodifiableCollection(map.values());
      mReadOnlyListMap.put(map, roList);
    }

    return roList;
  }
Esempio n. 11
0
  /** Returns the sorted list of languages used in the resources. */
  @NonNull
  public SortedSet<String> getLanguages() {
    ensureInitialized();

    SortedSet<String> set = new TreeSet<String>();

    Collection<List<ResourceFolder>> folderList = mFolderMap.values();
    for (List<ResourceFolder> folderSubList : folderList) {
      for (ResourceFolder folder : folderSubList) {
        FolderConfiguration config = folder.getConfiguration();
        LocaleQualifier locale = config.getLocaleQualifier();
        if (locale != null) {
          set.add(locale.getLanguage());
        }
      }
    }

    return set;
  }
Esempio n. 12
0
  /**
   * Processes a folder and adds it to the list of existing folders.
   *
   * @param folder the folder to process
   * @return the ResourceFolder created from this folder, or null if the process failed.
   */
  @Nullable
  public ResourceFolder processFolder(@NonNull IAbstractFolder folder) {
    ensureInitialized();

    // split the name of the folder in segments.
    String[] folderSegments = folder.getName().split(SdkConstants.RES_QUALIFIER_SEP);

    // get the enum for the resource type.
    ResourceFolderType type = ResourceFolderType.getTypeByName(folderSegments[0]);

    if (type != null) {
      // get the folder configuration.
      FolderConfiguration config = FolderConfiguration.getConfig(folderSegments);

      if (config != null) {
        return add(type, config, folder);
      }
    }

    return null;
  }
Esempio n. 13
0
  @NonNull
  public List<ResourceType> getAvailableResourceTypes() {
    ensureInitialized();

    List<ResourceType> list = new ArrayList<ResourceType>();

    // For each key, we check if there's a single ResourceType match.
    // If not, we look for the actual content to give us the resource type.

    for (ResourceFolderType folderType : mFolderMap.keySet()) {
      List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(folderType);
      if (types.size() == 1) {
        // before we add it we check if it's not already present, since a ResourceType
        // could be created from multiple folders, even for the folders that only create
        // one type of resource (drawable for instance, can be created from drawable/ and
        // values/)
        if (list.contains(types.get(0)) == false) {
          list.add(types.get(0));
        }
      } else {
        // there isn't a single resource type out of this folder, so we look for all
        // content.
        List<ResourceFolder> folders = mFolderMap.get(folderType);
        if (folders != null) {
          for (ResourceFolder folder : folders) {
            Collection<ResourceType> folderContent = folder.getResourceTypes();

            // then we add them, but only if they aren't already in the list.
            for (ResourceType folderResType : folderContent) {
              if (list.contains(folderResType) == false) {
                list.add(folderResType);
              }
            }
          }
        }
      }
    }

    return list;
  }
Esempio n. 14
0
  /**
   * Returns whether the repository has resources of a given {@link ResourceType}.
   *
   * @param type the type of resource to check.
   * @return true if the repository contains resources of the given type, false otherwise.
   */
  public boolean hasResourcesOfType(@NonNull ResourceType type) {
    ensureInitialized();

    Map<String, ResourceItem> items = mResourceMap.get(type);
    return (items != null && !items.isEmpty());
  }
Esempio n. 15
0
 /** Loads the resources. */
 public void loadResources() {
   clear();
   ensureInitialized();
 }
Esempio n. 16
0
  /**
   * Returns a list of {@link ResourceFolder} for a specific {@link ResourceFolderType}.
   *
   * @param type The {@link ResourceFolderType}
   */
  @Nullable
  public List<ResourceFolder> getFolders(@NonNull ResourceFolderType type) {
    ensureInitialized();

    return mFolderMap.get(type);
  }
Esempio n. 17
0
  /**
   * Returns a {@link ResourceItem} matching the given {@link ResourceType} and name. If none exist,
   * it creates one.
   *
   * @param type the resource type
   * @param name the name of the resource.
   * @return A resource item matching the type and name.
   */
  @NonNull
  public ResourceItem getResourceItem(@NonNull ResourceType type, @NonNull String name) {
    ensureInitialized();

    // looking for an existing ResourceItem with this type and name
    ResourceItem item = findDeclaredResourceItem(type, name);

    // create one if there isn't one already, or if the existing one is inlined, since
    // clearly we need a non inlined one (the inline one is removed too)
    if (item == null || item.isDeclaredInline()) {
      ResourceItem oldItem = item != null && item.isDeclaredInline() ? item : null;

      item = createResourceItem(name);

      Map<String, ResourceItem> map = mResourceMap.get(type);

      if (map == null) {
        if (isFrameworkRepository()) {
          // Pick initial size for the maps. Also change the load factor to 1.0
          // to avoid rehashing the whole table when we (as expected) get near
          // the known rough size of each resource type map.
          int size;
          switch (type) {
              // Based on counts in API 16. Going back to API 10, the counts
              // are roughly 25-50% smaller (e.g. compared to the top 5 types below
              // the fractions are 1107 vs 1734, 831 vs 1508, 895 vs 1255,
              // 733 vs 1064 and 171 vs 783.
            case PUBLIC:
              size = 1734;
              break;
            case DRAWABLE:
              size = 1508;
              break;
            case STRING:
              size = 1255;
              break;
            case ATTR:
              size = 1064;
              break;
            case STYLE:
              size = 783;
              break;
            case ID:
              size = 347;
              break;
            case DECLARE_STYLEABLE:
              size = 210;
              break;
            case LAYOUT:
              size = 187;
              break;
            case COLOR:
              size = 120;
              break;
            case ANIM:
              size = 95;
              break;
            case DIMEN:
              size = 81;
              break;
            case BOOL:
              size = 54;
              break;
            case INTEGER:
              size = 52;
              break;
            case ARRAY:
              size = 51;
              break;
            case PLURALS:
              size = 20;
              break;
            case XML:
              size = 14;
              break;
            case INTERPOLATOR:
              size = 13;
              break;
            case ANIMATOR:
              size = 8;
              break;
            case RAW:
              size = 4;
              break;
            case MENU:
              size = 2;
              break;
            case MIPMAP:
              size = 2;
              break;
            case FRACTION:
              size = 1;
              break;
            default:
              size = 2;
          }
          map = new HashMap<String, ResourceItem>(size, 1.0f);
        } else {
          map = new HashMap<String, ResourceItem>();
        }
        mResourceMap.put(type, map);
      }

      map.put(item.getName(), item);

      if (oldItem != null) {
        map.remove(oldItem.getName());
      }
    }

    return item;
  }