bali 2.1.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/CHANGELOG.md +6 -0
- data/README.md +7 -6
- data/lib/bali/dsl/map_rules_dsl.rb +9 -5
- data/lib/bali/dsl/rules_for_dsl.rb +126 -104
- data/lib/bali/foundations/all_foundations.rb +6 -0
- data/lib/bali/foundations/exceptions/authorization_error.rb +22 -3
- data/lib/bali/foundations/judger/judge.rb +329 -0
- data/lib/bali/foundations/judger/negative_judge.rb +40 -0
- data/lib/bali/foundations/judger/positive_judge.rb +41 -0
- data/lib/bali/foundations/role_extractor.rb +61 -0
- data/lib/bali/foundations/rule/rule_class.rb +3 -2
- data/lib/bali/foundations/rule/rule_group.rb +3 -0
- data/lib/bali/objector.rb +58 -359
- data/lib/bali/version.rb +1 -1
- metadata +6 -2
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            module Bali::Judger
         | 
| 2 | 
            +
              class NegativeJudge < Judge
         | 
| 3 | 
            +
                def initialize
         | 
| 4 | 
            +
                  super(false)
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def auth_level
         | 
| 8 | 
            +
                  :cannot
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def reverse_auth_level
         | 
| 12 | 
            +
                  :can
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def zeus_return_value
         | 
| 16 | 
            +
                  BALI_FALSE
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def plant_return_value
         | 
| 20 | 
            +
                  BALI_TRUE
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def default_positive_return_value
         | 
| 24 | 
            +
                  BALI_TRUE
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def default_negative_fuzy_return_value
         | 
| 28 | 
            +
                  BALI_FUZY_TRUE
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                # cannot? by default return true when
         | 
| 32 | 
            +
                def natural_value
         | 
| 33 | 
            +
                  BALI_TRUE
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
                
         | 
| 36 | 
            +
                def need_to_check_for_intervention?
         | 
| 37 | 
            +
                  rule_group && rule_group.plant?
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            module Bali::Judger
         | 
| 2 | 
            +
              class PositiveJudge < Judge
         | 
| 3 | 
            +
                def initialize
         | 
| 4 | 
            +
                  super(false)
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def auth_level
         | 
| 8 | 
            +
                  :can
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def reverse_auth_level
         | 
| 12 | 
            +
                  :cannot
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def zeus_return_value
         | 
| 16 | 
            +
                  BALI_TRUE
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def plant_return_value
         | 
| 20 | 
            +
                  BALI_FALSE
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def default_positive_return_value
         | 
| 24 | 
            +
                  BALI_TRUE
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def default_negative_fuzy_return_value
         | 
| 28 | 
            +
                  BALI_FUZY_FALSE
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                # value that is natural to be returned by the jury
         | 
| 32 | 
            +
                # can? by default return false
         | 
| 33 | 
            +
                def natural_value
         | 
| 34 | 
            +
                  BALI_FALSE
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def need_to_check_for_intervention?
         | 
| 38 | 
            +
                  rule_group && rule_group.zeus?
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end # positive judger
         | 
| 41 | 
            +
            end # module judger
         | 
| @@ -0,0 +1,61 @@ | |
| 1 | 
            +
            class Bali::RoleExtractor
         | 
| 2 | 
            +
              attr_reader :arg
         | 
| 3 | 
            +
              
         | 
| 4 | 
            +
              # argument can be anything, as long as role extractor know how to extract
         | 
| 5 | 
            +
              def initialize(arg)
         | 
| 6 | 
            +
                @arg = arg
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def get_roles(object = @arg)
         | 
| 10 | 
            +
                case object
         | 
| 11 | 
            +
                when String; get_role_string(object)
         | 
| 12 | 
            +
                when Symbol; get_role_symbol(object)
         | 
| 13 | 
            +
                when NilClass; get_role_nil(object)
         | 
| 14 | 
            +
                when Array; get_role_array(object)
         | 
| 15 | 
            +
                else
         | 
| 16 | 
            +
                  get_role_object(object)
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              private
         | 
| 21 | 
            +
                def get_role_string(object)
         | 
| 22 | 
            +
                  [object]
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def get_role_symbol(object)
         | 
| 26 | 
            +
                  [object]
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def get_role_nil(object)
         | 
| 30 | 
            +
                  [object]
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def get_role_array(object)
         | 
| 34 | 
            +
                  object
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                # this case, _subtarget_roles is an object but not a symbol or a string
         | 
| 38 | 
            +
                # let's try to deduct subtarget's roles
         | 
| 39 | 
            +
                def get_role_object(object)
         | 
| 40 | 
            +
                  object_class = object.class.to_s
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  # variable to hold deducted role of the passed object
         | 
| 43 | 
            +
                  deducted_roles = nil
         | 
| 44 | 
            +
                  role_extracted = false
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  Bali::TRANSLATED_SUBTARGET_ROLES.each do |current_subtarget_class, roles_field_name|
         | 
| 47 | 
            +
                    if object_class == current_subtarget_class
         | 
| 48 | 
            +
                      deducted_roles = object.send(roles_field_name)
         | 
| 49 | 
            +
                      deducted_roles = get_roles(deducted_roles)
         | 
| 50 | 
            +
                      role_extracted = true
         | 
| 51 | 
            +
                      break
         | 
| 52 | 
            +
                    end # if matching class
         | 
| 53 | 
            +
                  end # each TRANSLATED_SUBTARGET_ROLES
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  unless role_extracted
         | 
| 56 | 
            +
                    raise Bali::AuthorizationError, "Bali does not know how to process roles: #{object}"
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  deducted_roles
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
            end
         | 
| @@ -27,9 +27,10 @@ class Bali::RuleClass | |
| 27 27 | 
             
                if rule_group.is_a?(Bali::RuleGroup)
         | 
| 28 28 | 
             
                  target_user = rule_group.subtarget
         | 
| 29 29 | 
             
                  if target_user == "__*__" || target_user == :"__*__"
         | 
| 30 | 
            -
                     | 
| 30 | 
            +
                    self.others_rule_group = rule_group
         | 
| 31 | 
            +
                  else
         | 
| 32 | 
            +
                    self.rule_groups[rule_group.subtarget] = rule_group
         | 
| 31 33 | 
             
                  end
         | 
| 32 | 
            -
                  self.rule_groups[rule_group.subtarget] = rule_group
         | 
| 33 34 | 
             
                else
         | 
| 34 35 | 
             
                  raise Bali::DslError, "Rule group must be an instance of Bali::RuleGroup, got: #{rule_group.class.name}"
         | 
| 35 36 | 
             
                end
         | 
| @@ -33,6 +33,9 @@ class Bali::RuleGroup | |
| 33 33 | 
             
                self.cants = {}
         | 
| 34 34 |  | 
| 35 35 | 
             
                # by default, rule group is neither zeus nor plant
         | 
| 36 | 
            +
                # it is neutral.
         | 
| 37 | 
            +
                # meaning, it is neither allowed to do everything, nor it is 
         | 
| 38 | 
            +
                # prohibited to do anything. neutral.
         | 
| 36 39 | 
             
                self.zeus = false
         | 
| 37 40 | 
             
                self.plant = false
         | 
| 38 41 | 
             
              end
         | 
    
        data/lib/bali/objector.rb
    CHANGED
    
    | @@ -40,392 +40,82 @@ module Bali::Objector | |
| 40 40 | 
             
              end
         | 
| 41 41 | 
             
            end
         | 
| 42 42 |  | 
| 43 | 
            +
            # to allow class-level objection
         | 
| 43 44 | 
             
            module Bali::Objector::Statics
         | 
| 44 | 
            -
              #  | 
| 45 | 
            -
               | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
              #   cannot :view
         | 
| 49 | 
            -
              # end
         | 
| 50 | 
            -
              # others do
         | 
| 51 | 
            -
              #   can :view
         | 
| 52 | 
            -
              #   can :index
         | 
| 53 | 
            -
              # end
         | 
| 54 | 
            -
              #
         | 
| 55 | 
            -
              # In the example above, objecting cannot view on finance will result in STRONG_FALSE, but
         | 
| 56 | 
            -
              # objecting can index on finance will result in FUZY_TRUE.
         | 
| 57 | 
            -
              #
         | 
| 58 | 
            -
              # Eventually, all FUZY value will be normal TRUE or FALSE if no definite counterpart 
         | 
| 59 | 
            -
              # is found/defined
         | 
| 60 | 
            -
              BALI_FUZY_FALSE = -2
         | 
| 61 | 
            -
              BALI_FUZY_TRUE = 2
         | 
| 62 | 
            -
              BALI_FALSE = -1
         | 
| 63 | 
            -
              BALI_TRUE = 1
         | 
| 64 | 
            -
             | 
| 65 | 
            -
              # translate response for value above to traditional true/false
         | 
| 66 | 
            -
              def bali_translate_response(bali_bool_value)
         | 
| 67 | 
            -
                raise Bali::Error, "Expect bali value to be an integer" unless bali_bool_value.is_a?(Integer)
         | 
| 68 | 
            -
                if bali_bool_value < 0
         | 
| 69 | 
            -
                  return false
         | 
| 70 | 
            -
                elsif bali_bool_value > 0
         | 
| 71 | 
            -
                  return true
         | 
| 72 | 
            -
                else 
         | 
| 73 | 
            -
                  raise Bali::Error, "Bali bool value can either be negative or positive integer"
         | 
| 74 | 
            -
                end
         | 
| 45 | 
            +
              # get the proper roles for the subtarget, for any type of subtarget
         | 
| 46 | 
            +
              def bali_translate_subtarget_roles(arg)
         | 
| 47 | 
            +
                role_extractor = Bali::RoleExtractor.new(arg)
         | 
| 48 | 
            +
                role_extractor.get_roles
         | 
| 75 49 | 
             
              end
         | 
| 76 50 |  | 
| 77 | 
            -
              # will return array
         | 
| 78 | 
            -
              def bali_translate_subtarget_roles(_subtarget_roles)
         | 
| 79 | 
            -
                if _subtarget_roles.is_a?(String) || _subtarget_roles.is_a?(Symbol) || _subtarget_roles.is_a?(NilClass)
         | 
| 80 | 
            -
                  return [_subtarget_roles]
         | 
| 81 | 
            -
                elsif _subtarget_roles.is_a?(Array)
         | 
| 82 | 
            -
                  return _subtarget_roles
         | 
| 83 | 
            -
                else
         | 
| 84 | 
            -
                  # this case, _subtarget_roles is an object but not a symbol or a string
         | 
| 85 | 
            -
                  # let's try to deduct subtarget's roles
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                  _subtarget = _subtarget_roles
         | 
| 88 | 
            -
                  _subtarget_class = _subtarget.class.to_s
         | 
| 89 | 
            -
             | 
| 90 | 
            -
                  # variable to hold deducted role of the passed object
         | 
| 91 | 
            -
                  deducted_roles = nil
         | 
| 92 | 
            -
             | 
| 93 | 
            -
                  Bali::TRANSLATED_SUBTARGET_ROLES.each do |subtarget_class, roles_field_name|
         | 
| 94 | 
            -
                    if _subtarget_class == subtarget_class
         | 
| 95 | 
            -
                      deducted_roles = _subtarget.send(roles_field_name)
         | 
| 96 | 
            -
                      if deducted_roles.is_a?(String) || deducted_roles.is_a?(Symbol) || deducted_roles.is_a?(NilClass)
         | 
| 97 | 
            -
                        deducted_roles = [deducted_roles]
         | 
| 98 | 
            -
                        break
         | 
| 99 | 
            -
                      elsif deducted_roles.is_a?(Array)
         | 
| 100 | 
            -
                        break
         | 
| 101 | 
            -
                      end
         | 
| 102 | 
            -
                    end # if matching class
         | 
| 103 | 
            -
                  end # each TRANSLATED_SUBTARGET_ROLES
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                  if deducted_roles.nil?
         | 
| 106 | 
            -
                    raise Bali::AuthorizationError, "Bali does not know how to process roles: #{_subtarget_roles}"
         | 
| 107 | 
            -
                  end
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                  return deducted_roles
         | 
| 110 | 
            -
                end # if
         | 
| 111 | 
            -
              end
         | 
| 112 | 
            -
             | 
| 113 | 
            -
              ### options passable to bali_can? and bali_cannot? are:
         | 
| 114 | 
            -
              ### cross_action: if set to true wouldn't call its counterpart so as to prevent
         | 
| 115 | 
            -
              ###   overflowing stack
         | 
| 116 | 
            -
              ### original_subtarget: the original passed to can? and cannot? before
         | 
| 117 | 
            -
              ###   processed by bali_translate_subtarget_roles
         | 
| 118 | 
            -
             | 
| 119 | 
            -
              def bali_can?(subtarget, operation, record = self, options = {})
         | 
| 120 | 
            -
                # if performed on a class-level, don't call its class or it will return
         | 
| 121 | 
            -
                # Class. That's not what is expected.
         | 
| 122 | 
            -
                if self.is_a?(Class)
         | 
| 123 | 
            -
                  klass = self
         | 
| 124 | 
            -
                else
         | 
| 125 | 
            -
                  klass = self.class
         | 
| 126 | 
            -
                end
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                rule_group = Bali::Integrators::Rule.rule_group_for(klass, subtarget)
         | 
| 129 | 
            -
                other_rule_group = Bali::Integrators::Rule.rule_group_for(klass, "__*__") 
         | 
| 130 | 
            -
             | 
| 131 | 
            -
                rule = nil 
         | 
| 132 | 
            -
             | 
| 133 | 
            -
                # default of can? is false whenever RuleClass for that class is undefined
         | 
| 134 | 
            -
                # or RuleGroup for that subtarget is not defined
         | 
| 135 | 
            -
                if rule_group.nil?
         | 
| 136 | 
            -
                  # no more chance for checking
         | 
| 137 | 
            -
                  return BALI_FALSE if other_rule_group.nil?
         | 
| 138 | 
            -
                else
         | 
| 139 | 
            -
                  # get the specific rule from its own describe block
         | 
| 140 | 
            -
                  rule = rule_group.get_rule(:can, operation)
         | 
| 141 | 
            -
                end
         | 
| 142 | 
            -
             | 
| 143 | 
            -
                # retrieve rule from others group
         | 
| 144 | 
            -
                otherly_rule = other_rule_group.get_rule(:can, operation)
         | 
| 145 | 
            -
             | 
| 146 | 
            -
                # godly subtarget is allowed to do as he wishes
         | 
| 147 | 
            -
                # so long that the rule is not specificly defined
         | 
| 148 | 
            -
                # or overwritten by subsequent rule
         | 
| 149 | 
            -
                if rule_group && rule_group.zeus?
         | 
| 150 | 
            -
                  if rule.nil?
         | 
| 151 | 
            -
                    _options = options.dup
         | 
| 152 | 
            -
                    _options[:cross_check] = true
         | 
| 153 | 
            -
                    _options[:original_subtarget] = original_subtarget if _options[:original_subtarget].nil?
         | 
| 154 | 
            -
             | 
| 155 | 
            -
                    check_val = self.bali_cannot?(subtarget, operation, record, _options)
         | 
| 156 | 
            -
             | 
| 157 | 
            -
                    # check further whether cant is defined to overwrite this can_all
         | 
| 158 | 
            -
                    if check_val == BALI_TRUE 
         | 
| 159 | 
            -
                      return BALI_FALSE
         | 
| 160 | 
            -
                    else
         | 
| 161 | 
            -
                      return BALI_TRUE
         | 
| 162 | 
            -
                    end
         | 
| 163 | 
            -
                  end
         | 
| 164 | 
            -
                end
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                # do after crosscheck
         | 
| 167 | 
            -
                # plan subtarget is not allowed unless spesificly defined
         | 
| 168 | 
            -
                return BALI_FALSE if rule_group && rule_group.plant? && rule.nil? && otherly_rule.nil?
         | 
| 169 | 
            -
             | 
| 170 | 
            -
                if rule.nil?
         | 
| 171 | 
            -
                  # default if can? for undefined rule is false, after related clause
         | 
| 172 | 
            -
                  # cannot be found in cannot?
         | 
| 173 | 
            -
             | 
| 174 | 
            -
                  unless options[:cross_check] 
         | 
| 175 | 
            -
                    options[:cross_check] = true
         | 
| 176 | 
            -
                    cross_check_value = self.bali_cannot?(subtarget, operation, record, options)
         | 
| 177 | 
            -
                  end
         | 
| 178 | 
            -
             | 
| 179 | 
            -
                  # either if rule from others block is defined, and the result so far is fuzy
         | 
| 180 | 
            -
                  # or, otherly rule is defined, and it is still a cross check
         | 
| 181 | 
            -
                  # plus, the result is not a definite BALI_TRUE/BALI_FALSE
         | 
| 182 | 
            -
                  #
         | 
| 183 | 
            -
                  # rationalisation:
         | 
| 184 | 
            -
                  # 1. Definite answer such as BALI_TRUE and BALI_FALSE is to be prioritised over
         | 
| 185 | 
            -
                  #    FUZY answer, because definite answer is not gathered from others block where
         | 
| 186 | 
            -
                  #    FUZY answer is. Therefore, it is an intended result
         | 
| 187 | 
            -
                  # 2. If the answer is FUZY, otherly_rule only be considered if the result 
         | 
| 188 | 
            -
                  #    is either FUZY TRUE or FUZY FALSE, or
         | 
| 189 | 
            -
                  # 3. Or, when already in cross check mode, we cannot retrieve cross_check_value
         | 
| 190 | 
            -
                  #    what we can is instead, if otherly rule is available, just to try the odd 
         | 
| 191 | 
            -
                  if (otherly_rule && cross_check_value && !(cross_check_value == BALI_TRUE || cross_check_value == BALI_FALSE)) ||
         | 
| 192 | 
            -
                      (otherly_rule && (cross_check_value == BALI_FUZY_FALSE || cross_check_value == BALI_FUZY_TRUE)) ||
         | 
| 193 | 
            -
                      (otherly_rule && options[:cross_check] && cross_check_value.nil?)
         | 
| 194 | 
            -
                    # give chance to check at the others block
         | 
| 195 | 
            -
                    rule = otherly_rule
         | 
| 196 | 
            -
                  else
         | 
| 197 | 
            -
                    # either the return is not fuzy, or otherly rule is undefined
         | 
| 198 | 
            -
                    if cross_check_value == BALI_TRUE
         | 
| 199 | 
            -
                      return BALI_FALSE
         | 
| 200 | 
            -
                    elsif cross_check_value == BALI_FALSE
         | 
| 201 | 
            -
                      return BALI_TRUE
         | 
| 202 | 
            -
                    end
         | 
| 203 | 
            -
                  end
         | 
| 204 | 
            -
                end
         | 
| 205 | 
            -
             | 
| 206 | 
            -
                if rule
         | 
| 207 | 
            -
                  if rule.has_decider?
         | 
| 208 | 
            -
                    # must test first
         | 
| 209 | 
            -
                    decider = rule.decider
         | 
| 210 | 
            -
                    original_subtarget = options.fetch(:original_subtarget)
         | 
| 211 | 
            -
                    case decider.arity
         | 
| 212 | 
            -
                    when 0
         | 
| 213 | 
            -
                      if rule.decider_type == :if
         | 
| 214 | 
            -
                        return decider.() ? BALI_TRUE : BALI_FALSE
         | 
| 215 | 
            -
                      elsif rule.decider_type == :unless
         | 
| 216 | 
            -
                        unless decider.()
         | 
| 217 | 
            -
                          return BALI_TRUE
         | 
| 218 | 
            -
                        else
         | 
| 219 | 
            -
                          return BALI_FALSE
         | 
| 220 | 
            -
                        end
         | 
| 221 | 
            -
                      end
         | 
| 222 | 
            -
                    when 1
         | 
| 223 | 
            -
                      if rule.decider_type == :if
         | 
| 224 | 
            -
                        return decider.(record) ? BALI_TRUE : BALI_FALSE
         | 
| 225 | 
            -
                      elsif rule.decider_type == :unless
         | 
| 226 | 
            -
                        unless decider.(record)
         | 
| 227 | 
            -
                          return BALI_TRUE
         | 
| 228 | 
            -
                        else
         | 
| 229 | 
            -
                          return BALI_FALSE
         | 
| 230 | 
            -
                        end
         | 
| 231 | 
            -
                      end
         | 
| 232 | 
            -
                    when 2
         | 
| 233 | 
            -
                      if rule.decider_type == :if
         | 
| 234 | 
            -
                        return decider.(record, original_subtarget) ? BALI_TRUE : BALI_FALSE
         | 
| 235 | 
            -
                      elsif rule.decider_type == :unless
         | 
| 236 | 
            -
                        unless decider.(record, original_subtarget)
         | 
| 237 | 
            -
                          return BALI_TRUE
         | 
| 238 | 
            -
                        else
         | 
| 239 | 
            -
                          return BALI_FALSE
         | 
| 240 | 
            -
                        end
         | 
| 241 | 
            -
                      end
         | 
| 242 | 
            -
                    end
         | 
| 243 | 
            -
                  else
         | 
| 244 | 
            -
                    # rule is properly defined
         | 
| 245 | 
            -
                    return BALI_TRUE
         | 
| 246 | 
            -
                  end
         | 
| 247 | 
            -
                end
         | 
| 248 | 
            -
             | 
| 249 | 
            -
                # return fuzy if otherly rule defines contrary to this (can)
         | 
| 250 | 
            -
                if other_rule_group.get_rule(:cannot, operation)
         | 
| 251 | 
            -
                  return BALI_FUZY_FALSE
         | 
| 252 | 
            -
                else
         | 
| 253 | 
            -
                  return BALI_FALSE
         | 
| 254 | 
            -
                end
         | 
| 255 | 
            -
              end
         | 
| 256 | 
            -
             | 
| 257 | 
            -
              def bali_cannot?(subtarget, operation, record = self, options = {})
         | 
| 258 | 
            -
                if self.is_a?(Class)
         | 
| 259 | 
            -
                  klass = self
         | 
| 260 | 
            -
                else
         | 
| 261 | 
            -
                  klass = self.class
         | 
| 262 | 
            -
                end
         | 
| 263 | 
            -
             | 
| 264 | 
            -
                rule_group = Bali::Integrators::Rule.rule_group_for(klass, subtarget)
         | 
| 265 | 
            -
                other_rule_group = Bali::Integrators::Rule.rule_group_for(klass, "__*__")
         | 
| 266 | 
            -
             | 
| 267 | 
            -
                rule = nil
         | 
| 268 | 
            -
             | 
| 269 | 
            -
                # default of cannot? is true whenever RuleClass for that class is undefined
         | 
| 270 | 
            -
                # or RuleGroup for that subtarget is not defined
         | 
| 271 | 
            -
                if rule_group.nil?
         | 
| 272 | 
            -
                  return BALI_TRUE if other_rule_group.nil?
         | 
| 273 | 
            -
                else
         | 
| 274 | 
            -
                  # get the specific rule from its own describe block
         | 
| 275 | 
            -
                  rule = rule_group.get_rule(:cannot, operation)
         | 
| 276 | 
            -
                end
         | 
| 277 | 
            -
             | 
| 278 | 
            -
                otherly_rule = other_rule_group.get_rule(:cannot, operation)
         | 
| 279 | 
            -
                # plant subtarget is not allowed to do things unless specificly defined
         | 
| 280 | 
            -
                if rule_group && rule_group.plant?
         | 
| 281 | 
            -
                  if rule.nil?
         | 
| 282 | 
            -
                    _options = options.dup
         | 
| 283 | 
            -
                    _options[:cross_check] = true
         | 
| 284 | 
            -
                    _options[:original_subtarget] = original_subtarget if _options[:original_subtarget].nil?
         | 
| 285 | 
            -
                    
         | 
| 286 | 
            -
                    # check further whether defined in can?
         | 
| 287 | 
            -
                    check_val = self.bali_can?(subtarget, operation, record, _options)
         | 
| 288 | 
            -
             | 
| 289 | 
            -
                    if check_val == BALI_TRUE
         | 
| 290 | 
            -
                      return BALI_FALSE # well, it is defined in can, so it must overwrite this cant_all rule
         | 
| 291 | 
            -
                    else
         | 
| 292 | 
            -
                      # plant, and then rule is not defined for further inspection. stright
         | 
| 293 | 
            -
                      # is not allowed to do this thing
         | 
| 294 | 
            -
                      return BALI_TRUE
         | 
| 295 | 
            -
                    end
         | 
| 296 | 
            -
                  end
         | 
| 297 | 
            -
                end
         | 
| 298 | 
            -
             | 
| 299 | 
            -
                if rule.nil?
         | 
| 300 | 
            -
                  unless options[:cross_check]
         | 
| 301 | 
            -
                    options[:cross_check] = true
         | 
| 302 | 
            -
                    cross_check_value = self.bali_can?(subtarget, operation, record, options)
         | 
| 303 | 
            -
                  end
         | 
| 304 | 
            -
             | 
| 305 | 
            -
                  if (otherly_rule && cross_check_value && !(cross_check_value == BALI_TRUE || cross_check_value == BALI_FALSE)) ||
         | 
| 306 | 
            -
                      (otherly_rule && (cross_check_value == BALI_FUZY_FALSE || cross_check_value == BALI_FUZY_TRUE)) ||
         | 
| 307 | 
            -
                      (otherly_rule && options[:cross_check] && cross_check_value.nil?)
         | 
| 308 | 
            -
                    rule = otherly_rule
         | 
| 309 | 
            -
                  else
         | 
| 310 | 
            -
                    if cross_check_value == BALI_TRUE
         | 
| 311 | 
            -
                      # from can? because of cross check, then it should be false
         | 
| 312 | 
            -
                      return BALI_FALSE
         | 
| 313 | 
            -
                    elsif cross_check_value == BALI_FALSE
         | 
| 314 | 
            -
                      # from can? because of cross check returning false
         | 
| 315 | 
            -
                      # then it should be true, that is, cannot
         | 
| 316 | 
            -
                      return BALI_TRUE
         | 
| 317 | 
            -
                    end
         | 
| 318 | 
            -
                  end
         | 
| 319 | 
            -
                end
         | 
| 320 | 
            -
             | 
| 321 | 
            -
                # do after cross check
         | 
| 322 | 
            -
                # godly subtarget is not to be prohibited in his endeavours
         | 
| 323 | 
            -
                # so long that no specific rule about this operation is defined
         | 
| 324 | 
            -
                return BALI_FALSE if rule_group && rule_group.zeus? && rule.nil? && otherly_rule.nil?
         | 
| 325 | 
            -
             | 
| 326 | 
            -
                if rule
         | 
| 327 | 
            -
                  if rule.has_decider?
         | 
| 328 | 
            -
                    decider = rule.decider
         | 
| 329 | 
            -
                    original_subtarget = options.fetch(:original_subtarget)
         | 
| 330 | 
            -
                    case decider.arity
         | 
| 331 | 
            -
                    when 0
         | 
| 332 | 
            -
                      if rule.decider_type == :if
         | 
| 333 | 
            -
                        return decider.() ? BALI_TRUE : BALI_FALSE
         | 
| 334 | 
            -
                      elsif rule.decider_type == :unless
         | 
| 335 | 
            -
                        unless decider.()
         | 
| 336 | 
            -
                          return BALI_TRUE
         | 
| 337 | 
            -
                        else
         | 
| 338 | 
            -
                          return BALI_FALSE
         | 
| 339 | 
            -
                        end
         | 
| 340 | 
            -
                      end
         | 
| 341 | 
            -
                    when 1
         | 
| 342 | 
            -
                      if rule.decider_type == :if
         | 
| 343 | 
            -
                        return decider.(record) ? BALI_TRUE : BALI_FALSE
         | 
| 344 | 
            -
                      elsif rule.decider_type == :unless
         | 
| 345 | 
            -
                        unless decider.(record)
         | 
| 346 | 
            -
                          return BALI_TRUE
         | 
| 347 | 
            -
                        else
         | 
| 348 | 
            -
                          return BALI_FALSE
         | 
| 349 | 
            -
                        end
         | 
| 350 | 
            -
                      end
         | 
| 351 | 
            -
                    when 2
         | 
| 352 | 
            -
                      if rule.decider_type == :if
         | 
| 353 | 
            -
                        return decider.(record, original_subtarget) ? BALI_TRUE : BALI_FALSE
         | 
| 354 | 
            -
                      elsif rule.decider_type == :unless
         | 
| 355 | 
            -
                        unless decider.(record, original_subtarget)
         | 
| 356 | 
            -
                          return BALI_TRUE
         | 
| 357 | 
            -
                        else
         | 
| 358 | 
            -
                          return BALI_FALSE
         | 
| 359 | 
            -
                        end
         | 
| 360 | 
            -
                      end
         | 
| 361 | 
            -
                    end
         | 
| 362 | 
            -
                  else
         | 
| 363 | 
            -
                    return BALI_TRUE # rule is properly defined
         | 
| 364 | 
            -
                  end # if rule has decider
         | 
| 365 | 
            -
                end # if rule is nil
         | 
| 366 | 
            -
             | 
| 367 | 
            -
                # return fuzy if otherly rule defines contrary to this cannot rule
         | 
| 368 | 
            -
                if other_rule_group.get_rule(:can, operation)
         | 
| 369 | 
            -
                  return BALI_FUZY_TRUE
         | 
| 370 | 
            -
                else
         | 
| 371 | 
            -
                  BALI_TRUE
         | 
| 372 | 
            -
                end
         | 
| 373 | 
            -
              end # bali cannot
         | 
| 374 | 
            -
             | 
| 375 51 | 
             
              def can?(subtarget_roles, operation, record = self, options = {})
         | 
| 376 52 | 
             
                subs = bali_translate_subtarget_roles(subtarget_roles)
         | 
| 377 53 | 
             
                # well, it is largely not used unless decider's is 2 arity
         | 
| 378 | 
            -
                 | 
| 54 | 
            +
                original_subtarget = options[:original_subtarget].nil? ? subtarget_roles : options[:original_subtarget]
         | 
| 379 55 |  | 
| 380 | 
            -
                 | 
| 56 | 
            +
                judgement_value = false
         | 
| 381 57 | 
             
                role = nil
         | 
| 58 | 
            +
                judger = nil
         | 
| 382 59 |  | 
| 383 60 | 
             
                subs.each do |subtarget|
         | 
| 384 | 
            -
                  next if  | 
| 61 | 
            +
                  next if judgement_value == true
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  judge = Bali::Judger::Judge.build(:can, {
         | 
| 64 | 
            +
                    subtarget: subtarget,
         | 
| 65 | 
            +
                    original_subtarget: original_subtarget,
         | 
| 66 | 
            +
                    operation: operation,
         | 
| 67 | 
            +
                    record: record
         | 
| 68 | 
            +
                  })
         | 
| 69 | 
            +
                  judgement_value = judge.judgement
         | 
| 70 | 
            +
             | 
| 385 71 | 
             
                  role = subtarget
         | 
| 386 | 
            -
                  can_value = bali_can?(role, operation, record, options)
         | 
| 387 72 | 
             
                end
         | 
| 388 73 |  | 
| 389 | 
            -
                if  | 
| 390 | 
            -
                  yield  | 
| 74 | 
            +
                if block_given? 
         | 
| 75 | 
            +
                  yield original_subtarget, role, judgement_value 
         | 
| 391 76 | 
             
                end
         | 
| 392 | 
            -
             | 
| 77 | 
            +
             | 
| 78 | 
            +
                judgement_value
         | 
| 393 79 | 
             
              rescue => e
         | 
| 394 | 
            -
                if e.is_a?(Bali::AuthorizationError)
         | 
| 80 | 
            +
                if e.is_a?(Bali::AuthorizationError) || e.is_a?(Bali::Error)
         | 
| 395 81 | 
             
                  raise e
         | 
| 396 82 | 
             
                else
         | 
| 397 | 
            -
                  raise Bali::ObjectionError, e.message
         | 
| 83 | 
            +
                  raise Bali::ObjectionError, e.message, e.backtrace
         | 
| 398 84 | 
             
                end
         | 
| 399 85 | 
             
              end
         | 
| 400 86 |  | 
| 401 | 
            -
              def cant?(subtarget_roles, operation, record = self, options = {})
         | 
| 402 | 
            -
                puts "Deprecation Warning: please use cannot? instead, cant? will be deprecated on major release 3.0"
         | 
| 403 | 
            -
                cannot?(subtarget_roles, operation, record, options)
         | 
| 404 | 
            -
              end
         | 
| 405 | 
            -
             | 
| 406 87 | 
             
              def cannot?(subtarget_roles, operation, record = self, options = {})
         | 
| 407 88 | 
             
                subs = bali_translate_subtarget_roles subtarget_roles
         | 
| 408 | 
            -
                 | 
| 89 | 
            +
                original_subtarget = options[:original_subtarget].nil? ? subtarget_roles : options[:original_subtarget]
         | 
| 409 90 |  | 
| 410 | 
            -
                 | 
| 91 | 
            +
                judgement_value = true
         | 
| 92 | 
            +
                role = nil
         | 
| 93 | 
            +
                judger = nil
         | 
| 411 94 |  | 
| 412 95 | 
             
                subs.each do |subtarget|
         | 
| 413 | 
            -
                  next if  | 
| 414 | 
            -
             | 
| 415 | 
            -
                   | 
| 416 | 
            -
                     | 
| 417 | 
            -
                     | 
| 418 | 
            -
             | 
| 419 | 
            -
                     | 
| 420 | 
            -
                   | 
| 96 | 
            +
                  next if judgement_value == false
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  judge = Bali::Judger::Judge.build(:cannot, {
         | 
| 99 | 
            +
                    subtarget: subtarget,
         | 
| 100 | 
            +
                    original_subtarget: original_subtarget,
         | 
| 101 | 
            +
                    operation: operation,
         | 
| 102 | 
            +
                    record: record
         | 
| 103 | 
            +
                  })
         | 
| 104 | 
            +
                  judgement_value = judge.judgement
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  role = subtarget
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                if block_given?
         | 
| 110 | 
            +
                  yield original_subtarget, role, judgement_value
         | 
| 421 111 | 
             
                end
         | 
| 422 112 |  | 
| 423 | 
            -
                 | 
| 113 | 
            +
                judgement_value
         | 
| 424 114 | 
             
              rescue => e
         | 
| 425 115 | 
             
                if e.is_a?(Bali::AuthorizationError)
         | 
| 426 116 | 
             
                  raise e
         | 
| 427 117 | 
             
                else
         | 
| 428 | 
            -
                  raise Bali::ObjectionError, e.message
         | 
| 118 | 
            +
                  raise Bali::ObjectionError, e.message, e.backtrace
         | 
| 429 119 | 
             
                end
         | 
| 430 120 | 
             
              end
         | 
| 431 121 |  | 
| @@ -444,8 +134,10 @@ module Bali::Objector::Statics | |
| 444 134 | 
             
                    end
         | 
| 445 135 |  | 
| 446 136 | 
             
                    raise auth_error
         | 
| 447 | 
            -
                   | 
| 448 | 
            -
             | 
| 137 | 
            +
                  else
         | 
| 138 | 
            +
                    return can_value
         | 
| 139 | 
            +
                  end # if cannot is false, means cannot
         | 
| 140 | 
            +
                end # can?
         | 
| 449 141 | 
             
              end
         | 
| 450 142 |  | 
| 451 143 | 
             
              def cant!(subtarget_roles, operation, record = self, options = {})
         | 
| @@ -453,6 +145,11 @@ module Bali::Objector::Statics | |
| 453 145 | 
             
                cannot!(subtarget_roles, operation, record, options)
         | 
| 454 146 | 
             
              end
         | 
| 455 147 |  | 
| 148 | 
            +
              def cant?(subtarget_roles, operation)
         | 
| 149 | 
            +
                puts "Deprecation Warning: please use cannot? instead, cant? will be deprecated on major release 3.0"
         | 
| 150 | 
            +
                cannot?(subtarget_roles, operation)
         | 
| 151 | 
            +
              end
         | 
| 152 | 
            +
             | 
| 456 153 | 
             
              def cannot!(subtarget_roles, operation, record = self, options = {})
         | 
| 457 154 | 
             
                cannot?(subtarget_roles, operation, record, options) do |original_subtarget, role, cant_value|
         | 
| 458 155 | 
             
                  if cant_value == false
         | 
| @@ -468,7 +165,9 @@ module Bali::Objector::Statics | |
| 468 165 | 
             
                    end
         | 
| 469 166 |  | 
| 470 167 | 
             
                    raise auth_error
         | 
| 471 | 
            -
                   | 
| 472 | 
            -
             | 
| 168 | 
            +
                  else
         | 
| 169 | 
            +
                    return cant_value
         | 
| 170 | 
            +
                  end # if cannot is false, means can
         | 
| 171 | 
            +
                end # cannot?
         | 
| 473 172 | 
             
              end
         | 
| 474 173 | 
             
            end
         |