# module Rad
#   class DependencyResolver    
#     class Dependency
#       attr_accessor :name, :block, :before, :after
#       
#       def initialize name, block
#         @name, @block = name, block
#         @before, @after = [], []
#       end
#       
#       def inspect
#         "#<#{name} #{before.inspect}, #{after.inspect}>"
#       end
#     end
#     
#     def dependencies; @dependencies ||= {} end
#       
#     # 
#     # Define dependency
#     #       
#     def run name, options = {}, &block
#       options = options.to_openobject
#       # raise "Invalid usage, you must specify :after or :before!" unless options.before? or options.after?
#       d = Dependency.new name, block
#       
#       if options.before?
#         add_dependency d, :before, options.before.must_be.present
#       elsif options.after?
#         add_dependency d, :after, options.after.must_be.present
#       else
#         add_dependency d, nil, nil
#       end
#     end
#     
#     
#     # 
#     # Call dependencies
#     # 
#     def call name, &block
#       return unless dep = dependencies[name]
#         
#       # before
#       callees = []
#       dep_lists = [dep.before]
#       while !dep_lists.empty?
#         dep_lists.each do |list|
#           callees << list
#         end
# 
#         dep_lists = next_level dep_lists, :before
#       end
#       call_all callees.reverse
#       
#       # call
#       dep.block.call if dep.block
#       
#       # after
#       dep_lists = [dep.after]
#       while !dep_lists.empty?
#         call_all dep_lists
#         
#         dep_lists = next_level dep_lists, :after
#       end
#     end  
#     
#     protected
#       def add_dependency dep, type, ref
#         raise "Dependency '#{dep.name}' already defined!" if dependencies.include? dep.name        
#         dependencies[dep.name] = dep
#         
#         # add back reference
#         if type
#           catch :found do          
#             dep_lists = [dependencies.values]
#             while !dep_lists.empty?
#               dep_lists.each do |list|
#                 list.each do |d|
#                   if d.name == ref
#                     d.send(type) << dep
#                     throw :found
#                   end
#                 end
#               end
#             
#               dep_lists = next_level dep_lists, type
#             end          
#             
#             raise "Dependency '#{ref}' referenced from '#{dep.name}' not found!"
#           end                    
#         end
#       end
#       
#       def next_level dep_lists, type
#         r = []
#         dep_lists.each do |list|          
#           list.each do |d|
#             r << d.send(type)
#           end
#         end
#         r
#       end
#       
#       def call_all list_of_lists
#         list_of_lists.each{|list| list.each{|d| d.block.call if d.block}}
#       end
#   end
# end