class ViewModel::AccessControl::Tree::Node

def editable_check(traversal_env)

def editable_check(traversal_env)
  view                = traversal_env.view
  deserialize_context = traversal_env.deserialize_context
  validate_root!(view, deserialize_context)
  if deserialize_context.root?
    save_root_editability!(traversal_env)
    super
  else
    root_editability = fetch_descendent_editability(deserialize_context.nearest_root_viewmodel)
    root_editability.merge { super }
  end
end

def inherited(subclass)

def inherited(subclass)
  super
  subclass.initialize_as_node
end

def initialize(tree_access_control)

def initialize(tree_access_control)
  super()
  @tree_access_control = tree_access_control
end

def initialize_as_node

def initialize_as_node
  @root = false
  @root_children_editable_ifs      = []
  @root_children_editable_unlesses = []
  @root_children_visible_ifs       = []
  @root_children_visible_unlesses  = []
end

def inspect_checks

def inspect_checks
  checks = super
  if root?
    checks << "root_children_visible_if: #{root_children_visible_ifs.map(&:reason)}"            if root_children_visible_ifs.present?
    checks << "root_children_visible_unless: #{root_children_visible_unlesses.map(&:reason)}"   if root_children_visible_unlesses.present?
    checks << "root_children_editable_if: #{root_children_editable_ifs.map(&:reason)}"          if root_children_editable_ifs.present?
    checks << "root_children_editable_unless: #{root_children_editable_unlesses.map(&:reason)}" if root_children_editable_unlesses.present?
  end
  checks
end

def root?

def root?
  @root
end

def root_children_editable_if!(reason, &block)

def root_children_editable_if!(reason, &block)
  @root = true
  root_children_editable_ifs << new_permission_check(reason, &block)
end

def root_children_editable_unless!(reason, &block)

def root_children_editable_unless!(reason, &block)
  @root = true
  root_children_editable_unlesses << new_permission_check(reason, &block)
end

def root_children_visible_if!(reason, &block)

def root_children_visible_if!(reason, &block)
  @root = true
  root_children_visible_ifs << new_permission_check(reason, &block)
end

def root_children_visible_unless!(reason, &block)

def root_children_visible_unless!(reason, &block)
  @root = true
  root_children_visible_unlesses << new_permission_check(reason, &block)
end

def save_root_editability!(traversal_env)

def save_root_editability!(traversal_env)
  result = check_delegates(traversal_env,
                           self.class.each_check(:root_children_editable_ifs,      ->(a) { a < Node }),
                           self.class.each_check(:root_children_editable_unlesses, ->(a) { a < Node }))
  store_descendent_editability(traversal_env.view, result)
end

def save_root_visibility!(traversal_env)

def save_root_visibility!(traversal_env)
  result = check_delegates(traversal_env,
                           self.class.each_check(:root_children_visible_ifs,      ->(a) { a < Node }),
                           self.class.each_check(:root_children_visible_unlesses, ->(a) { a < Node }))
  store_descendent_visibility(traversal_env.view, result)
end

def validate_root!(view, context)

def validate_root!(view, context)
  if self.class.requires_root? && !context.root?
    raise RuntimeError.new("AccessControl instance for #{view.class.view_name} node requires root context but was visited in owned context.")
  end
end

def visible_check(traversal_env)

def visible_check(traversal_env)
  view    = traversal_env.view
  context = traversal_env.context
  validate_root!(view, context)
  if context.root?
    save_root_visibility!(traversal_env)
    super
  else
    root_visibility = fetch_descendent_visibility(context.nearest_root_viewmodel)
    root_visibility.merge { super }
  end
end