protected function decorateSubreportsDataSource(): void
	{
		$builder = $this->getContainerBuilder();

		$subreports = $builder->findByTag(self::TAG_CACHE);
		foreach ($subreports as $service => $tag) {
			$serviceDef = $builder->getDefinition($service);

			// Validate datasource class
			if (!is_subclass_of((string) $serviceDef->getType(), DataSource::class)) {
				throw new AssertionException(sprintf(
					'Please use tag "%s" only on datasource (object %s found in %s).',
					self::TAG_CACHE,
					$serviceDef->getType(),
					$service
				));
			}

			// If cache.key is not provided, pick subreport name (fullname)
			if (!isset($tag['key'])) $tag['key'] = $serviceDef->getTag(self::TAG_SUBREPORT_DATASOURCE);

			// Validate cache scheme
			$this->validateConfig($this->scheme['tags'][self::TAG_CACHE], $tag, sprintf('%s', self::TAG_CACHE));

			// Wrap factory to cache
			$wrappedDef = $builder->addDefinition(sprintf('%s_cached', $service), $serviceDef);

			// Remove definition
			$builder->removeDefinition($service);

			// Add cached defition of datasource with wrapped original datasource
			$builder->addDefinition($service)
				->setFactory(CachedDataSource::class, [1 => $wrappedDef])
				->addSetup('setKey', [$tag['key']])
				->addSetup('setExpiration', [$tag['expiration']])
				->addTag(self::TAG_SUBREPORT_DATASOURCE, $wrappedDef->getTag(self::TAG_SUBREPORT_DATASOURCE));

			// Append cache tags to subreport introspection
			$subreportDef = $builder->getDefinition($wrappedDef->getTag(self::TAG_SUBREPORT_DATASOURCE));
			$introspection = $subreportDef->getTag(self::TAG_INTROSPECTION);
			$introspection['cache'] = ['datasource' => $tag];
			$subreportDef->addTag(self::TAG_INTROSPECTION, $introspection);
		}
	}