/**
  * Create a new loading task. This task is meant to be executed concurrently. It will request the
  * required textures from the parent texture manager once the loading is progressed to this point.
  *
  * @param parserFactory the parser factory
  * @param atlasName the name of the atlas files
  * @param textureManager the parent texture manager
  * @param progressMonitor the monitor of the loading progress
  * @param taskExecutor the executor that takes care for executing further tasks.
  */
 public TextureAtlasListXmlLoadingTask(
     @Nonnull final XmlPullParserFactory parserFactory,
     @Nonnull final String atlasName,
     @Nonnull final AbstractTextureManager<T> textureManager,
     @Nonnull final ProgressMonitor progressMonitor,
     @Nullable final Executor taskExecutor) {
   this.parserFactory = parserFactory;
   this.atlasName = atlasName;
   this.textureManager = textureManager;
   this.progressMonitor = progressMonitor;
   this.taskExecutor = taskExecutor;
   done = false;
   progressMonitor.setProgress(0.f);
 }
  @Override
  public void run() {
    InputStream xmlStream = null;
    try {
      final XmlPullParser parser = parserFactory.newPullParser();

      final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      xmlStream = classLoader.getResourceAsStream(atlasName + "-atlas.xml");
      parser.setInput(xmlStream, "UTF-8");

      int currentEvent = parser.nextTag();
      int expectedAtlasCount = 0;
      @Nullable TextureAtlasFinalizeTask<T> currentTextureTask = null;
      while (currentEvent != XmlPullParser.END_DOCUMENT) {
        if (currentEvent == XmlPullParser.START_TAG) {
          final String tagName = parser.getName();
          switch (tagName) {
            case "atlasList":
              expectedAtlasCount = getExpectedAtlasCount(parser, expectedAtlasCount);
              if (expectedAtlasCount > 0) {
                progressMonitor.setWeight(expectedAtlasCount);
              }
              break;
            case "atlas":
              @Nullable final String currentAtlasName = getAtlasTextureName(parser);
              if (currentAtlasName != null) {
                final FutureTask<T> preLoadTask =
                    new FutureTask<>(
                        new TextureAtlasPreLoadTask<>(textureManager, currentAtlasName));
                if (taskExecutor == null) {
                  preLoadTask.run();
                } else {
                  taskExecutor.execute(preLoadTask);
                }

                final float progressToAdd =
                    (expectedAtlasCount == 0) ? 0.f : (1.f / expectedAtlasCount);
                currentTextureTask =
                    new TextureAtlasFinalizeTask<>(
                        preLoadTask,
                        currentAtlasName,
                        textureManager,
                        progressMonitor,
                        progressToAdd);
              }
              break;
            case "sprite":
              if (currentTextureTask != null) {
                transferSpriteData(parser, currentTextureTask);
              }
              break;
          }
        } else if (currentEvent == XmlPullParser.END_TAG) {
          final String tagName = parser.getName();
          if ("atlas".equals(tagName)) {
            if (currentTextureTask != null) {
              textureManager.addUpdateTask(currentTextureTask);
              textureManager.addLoadingTask(currentTextureTask);
              currentTextureTask = null;
            }
          } else if ("atlasList".equals(tagName)) {
            break;
          }
        }
        currentEvent = parser.nextTag();
      }
    } catch (@Nonnull final XmlPullParserException e) {
      LOGGER.error("Failed to load requested texture atlas: " + atlasName, e);
    } catch (@Nonnull final IOException e) {
      LOGGER.error("Reading error while loading texture atlas: " + atlasName, e);
    } finally {
      done = true;
      if (xmlStream != null) {
        try {
          xmlStream.close();
        } catch (@Nonnull final IOException ignored) {
        }
      }
    }
  }