/**
   * @param portalDataKey Optional PortalDataKey to use, useful for batch imports where
   *     post-processing of keys has already take place
   */
  protected final void importData(final Resource resource, final PortalDataKey portalDataKey) {
    final InputStream resourceStream;
    try {
      resourceStream = resource.getInputStream();
    } catch (IOException e) {
      throw new RuntimeException("Could not load InputStream for resource: " + resource, e);
    }

    try {
      final String resourceUri = ResourceUtils.getResourceUri(resource);
      this.importData(new StreamSource(resourceStream, resourceUri), portalDataKey);
    } finally {
      IOUtils.closeQuietly(resourceStream);
    }
  }
  @Override
  public Object apply(Resource input) {
    final InputStream fis;
    try {
      fis = input.getInputStream();
    } catch (IOException e) {
      if (this.options == null || this.options.isFailOnError()) {
        throw new RuntimeException("Failed to create InputStream for: " + input, e);
      }

      logger.warn("Failed to create InputStream, resource will be ignored: {}", input);
      return null;
    }

    final PortalDataKey portalDataKey;
    final BufferedXMLEventReader xmlEventReader;
    try {
      xmlEventReader =
          new BufferedXMLEventReader(this.xmlInputFactory.createXMLEventReader(fis), -1);

      final StartElement rootElement = StaxUtils.getRootElement(xmlEventReader);
      portalDataKey = new PortalDataKey(rootElement);
    } catch (Exception e) {
      if (this.options != null && !this.options.isIngoreNonDataFiles()) {
        throw new RuntimeException("Failed to parse: " + input, e);
      }

      logger.warn("Failed to parse resource, it will be ignored: {}", input);
      return null;
    } finally {
      IOUtils.closeQuietly(fis);
    }
    xmlEventReader.reset();

    final IPortalDataType portalDataType = this.dataKeyTypes.get(portalDataKey);
    if (portalDataType == null) {
      Iterator<PortalDataKey> iter = dataKeyTypes.keySet().iterator();
      StringBuffer potentialKeys = new StringBuffer();
      potentialKeys.append("---------------- Potential Keys To Match -------------------");
      while (iter.hasNext()) {
        PortalDataKey key = iter.next();
        potentialKeys.append(key + "\n");
      }
      logger.warn(
          "{}No IPortalDataType configured for {}, the resource will be ignored: {}",
          potentialKeys,
          portalDataKey,
          input);
      return null;
    }

    // Allow the PortalDataType to do any necessary post-processing of the input, needed as some
    // types require extra work
    final String resourceUri = ResourceUtils.getResourceUri(input);
    final Set<PortalDataKey> processedPortalDataKeys =
        portalDataType.postProcessPortalDataKey(resourceUri, portalDataKey, xmlEventReader);
    xmlEventReader.reset();

    for (final PortalDataKey processedPortalDataKey : processedPortalDataKeys) {
      // Add the PortalDataKey and File into the map
      Queue<Resource> queue = this.dataToImport.get(processedPortalDataKey);
      if (queue == null) {
        queue =
            ConcurrentMapUtils.putIfAbsent(
                this.dataToImport, processedPortalDataKey, new ConcurrentLinkedQueue<Resource>());
      }
      queue.offer(input);
      count.incrementAndGet();
    }

    return null;
  }