/* (non-Javadoc)
   * @see org.jasig.portal.io.xml.IEntityImportService#importEntity(javax.xml.transform.Source)
   */
  protected final void importData(final Source source, PortalDataKey portalDataKey) {
    // Get a StAX reader for the source to determine info about the data to import
    final BufferedXMLEventReader bufferedXmlEventReader = createSourceXmlEventReader(source);

    // If no PortalDataKey was passed build it from the source
    if (portalDataKey == null) {
      final StartElement rootElement = StaxUtils.getRootElement(bufferedXmlEventReader);
      portalDataKey = new PortalDataKey(rootElement);
      bufferedXmlEventReader.reset();
    }

    final String systemId = source.getSystemId();

    // Post Process the PortalDataKey to see if more complex import operations are needed
    final IPortalDataType portalDataType = this.dataKeyTypes.get(portalDataKey);
    if (portalDataType == null) {
      throw new RuntimeException(
          "No IPortalDataType configured for "
              + portalDataKey
              + ", the resource will be ignored: "
              + getPartialSystemId(systemId));
    }
    final Set<PortalDataKey> postProcessedPortalDataKeys =
        portalDataType.postProcessPortalDataKey(systemId, portalDataKey, bufferedXmlEventReader);
    bufferedXmlEventReader.reset();

    // If only a single result from post processing import
    if (postProcessedPortalDataKeys.size() == 1) {
      this.importOrUpgradeData(
          systemId,
          DataAccessUtils.singleResult(postProcessedPortalDataKeys),
          bufferedXmlEventReader);
    }
    // If multiple results from post processing ordering is needed
    else {
      // Iterate over the data key order list to run the imports in the correct order
      for (final PortalDataKey orderedPortalDataKey : this.dataKeyImportOrder) {
        if (postProcessedPortalDataKeys.contains(orderedPortalDataKey)) {
          // Reset the to start of the XML document for each import/upgrade call
          bufferedXmlEventReader.reset();
          this.importOrUpgradeData(systemId, orderedPortalDataKey, bufferedXmlEventReader);
        }
      }
    }
  }
  @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;
  }