@Override
  public void addItem(@NonNull final ResourceItem item) throws ConsumerException {
    ResourceFile.FileType type = item.getSource().getType();

    if (type == ResourceFile.FileType.MULTI) {
      // this is a resource for the values files

      // just add the node to write to the map based on the qualifier.
      // We'll figure out later if the files needs to be written or (not)
      mValuesResMap.put(item.getSource().getQualifiers(), item);
    } else {
      // This is a single value file.
      // Only write it if the state is TOUCHED.
      if (item.isTouched()) {
        getExecutor()
            .execute(
                new Callable<Void>() {
                  @Override
                  public Void call() throws Exception {
                    ResourceFile resourceFile = item.getSource();
                    File file = resourceFile.getFile();

                    String filename = file.getName();
                    String folderName = item.getType().getName();
                    String qualifiers = resourceFile.getQualifiers();
                    if (!qualifiers.isEmpty()) {
                      folderName = folderName + RES_QUALIFIER_SEP + qualifiers;
                    }

                    File typeFolder = new File(getRootFolder(), folderName);
                    createDir(typeFolder);

                    File outFile = new File(typeFolder, filename);

                    if (mAaptRunner != null && filename.endsWith(DOT_PNG)) {
                      // run aapt in single crunch mode on the original file to write the
                      // destination file.
                      mAaptRunner.crunchPng(file, outFile);
                    } else if (filename.endsWith(DOT_XML)) {
                      copyXmlWithComment(file, outFile, createPathComment(file));
                    } else {
                      Files.copy(file, outFile);
                    }
                    return null;
                  }
                });
      }
    }
  }
  @Override
  protected void postWriteAction() throws ConsumerException {

    // now write the values files.
    for (String key : mValuesResMap.keySet()) {
      // the key is the qualifier.

      // check if we have to write the file due to deleted values.
      // also remove it from that list anyway (to detect empty qualifiers later).
      boolean mustWriteFile = mQualifierWithDeletedValues.remove(key);

      // get the list of items to write
      List<ResourceItem> items = mValuesResMap.get(key);

      // now check if we really have to write it
      if (!mustWriteFile) {
        for (ResourceItem item : items) {
          if (item.isTouched()) {
            mustWriteFile = true;
            break;
          }
        }
      }

      if (mustWriteFile) {
        String folderName =
            key.isEmpty()
                ? ResourceFolderType.VALUES.getName()
                : ResourceFolderType.VALUES.getName() + RES_QUALIFIER_SEP + key;

        try {
          File valuesFolder = new File(getRootFolder(), folderName);
          createDir(valuesFolder);
          File outFile = new File(valuesFolder, FN_VALUES_XML);

          DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
          factory.setNamespaceAware(true);
          factory.setValidating(false);
          factory.setIgnoringComments(true);
          DocumentBuilder builder;

          builder = factory.newDocumentBuilder();
          Document document = builder.newDocument();

          Node rootNode = document.createElement(TAG_RESOURCES);
          document.appendChild(rootNode);

          Collections.sort(items);

          ResourceFile currentFile = null;
          for (ResourceItem item : items) {
            ResourceFile source = item.getSource();
            if (source != currentFile) {
              currentFile = source;
              rootNode.appendChild(document.createTextNode("\n"));
              File file = source.getFile();
              rootNode.appendChild(document.createComment(createPathComment(file)));
              rootNode.appendChild(document.createTextNode("\n"));
            }
            Node adoptedNode = NodeUtils.adoptNode(document, item.getValue());
            rootNode.appendChild(adoptedNode);
          }

          String content;
          try {
            content = XmlPrettyPrinter.prettyPrint(document, true);
          } catch (Throwable t) {
            content = XmlUtils.toXml(document, false);
          }

          Files.write(content, outFile, Charsets.UTF_8);
        } catch (Throwable t) {
          throw new ConsumerException(t);
        }
      }
    }

    // now remove empty values files.
    for (String key : mQualifierWithDeletedValues) {
      String folderName =
          key != null && !key.isEmpty()
              ? ResourceFolderType.VALUES.getName() + RES_QUALIFIER_SEP + key
              : ResourceFolderType.VALUES.getName();

      removeOutFile(folderName, FN_VALUES_XML);
    }
  }