module Eco module API class UseCases class UseCaseChain < UseCase MAX_CHAINS = 70 @@num_chains = 0 @types = [:import, :filter, :transform, :sync, :export] def initialize(name = nil, type: nil, root:, usecase: nil, &block) if usecase raise "Expected Eco::API::UseCases::UseCase. Given #{usecase.class}" if !usecase.is_a?(Eco::API::UseCases::UseCase) type = usecase.type name = usecase.name block = usecase.callback unless block end super(name, type: type, root: root, &block) @chains = [] @resolved_chains = nil end def root=(value) raise "You cannot change root Eco::API::UseCases once the chains have been resolved" if @resolved_chains super(value) end def use(preserve_chains: false, recursive: false) UseCase.new(@name, type: @type, root: @root, &@case).tap do |newcase| if preserve_chains chain_use = {preserve_chains: recursive, recursive: recursive} @chains = @chains.map do |usecase| if usecase.respond_to? :call Proc.new do |usegroup| usecase = usecase.call(usegroup) usecase.use(chain_use).chain_to(newcase) usecase end elsif usecase.is_a?(UseCase) usecase.use(chain_use).chain_to(newcase) usecase end end end end end # @see Eco::API::UseCases::UseCase#launch def launch(io: nil, **kargs) super(io: io, **kargs).tap do |uio| next if resolved_chains.empty? resolved_chains.each do |usecase| uio = usecase.launch(io: uio.chain(usecase: usecase)) end end end def chain(usecase = nil) @@num_chains += 1 raise "Reached maximum number of chained use cases (#{MAX_CHAINS}). Looks like a recursive cyclic chain 'use'" if @@num_chains >= MAX_CHAINS raise "A UseCase can only be chained with another UseCase" if usecase && !usecase.is_a?(UseCase) raise "Missuse. Please use either parameter or block but not both" if block_given? && usecase usecase = block_given?? Proc.new : usecase @chains.push(usecase) self end protected def chain_to(usecase) raise "A UseCase can only be chained with another UseCase" if usecase && !usecase.is_a?(UseCase) usecase.chain(self) end def resolved_chains(use_group = nil) return @resolved_chains if @resolved_chains raise "Only Eco::API::UseCases object can contain resolved chains. Given: #{use_group.class} " if use_group && !use_group.is_a?(Eco::API::UseCases) use_group = use_group || @root @resolved_chains = @chains.map do |usecase| usecase = usecase.call(use_group) if usecase.respond_to?(:call) raise "A UseCase can only be chained with another UseCase" if usecase && !usecase.is_a?(UseCase) usecase.resolved_chains(use_group) if usecase.respond_to?(:resolved_chains) usecase end end end end end end