Quickly setup attributes validation by one-time, based on `sqlalchemy.orm.validates`.

    Don't like `sqlalchemy.orm.validates`, you don't need create many model method,
    as long as pass formatted validate rule.
    (Cause of SQLAlchemy's validate mechanism, you need assignment this funciton's return value
    to a model property.)

    For simplicity, complex_validates don't support `include_removes` and `include_backrefs` parameters
    that in `sqlalchemy.orm.validates`.

    And we don't recommend you use this function multiple times in one model.
    Because this will bring many problems, like:
    1. Multiple complex_validates's execute order was decide by it's model property name, and by reversed order.
       eg. predicates in `validator1 = complex_validates(...)`
       will be executed **AFTER** predicates in `validator2 = complex_validates(...)`
    2. If you try to validate the same attribute in two (or more) complex_validates, only one of complex_validates
       will be execute. (May be this is a bug of SQLAlchemy?)
    `complex_validates` was currently based on `sqlalchemy.orm.validates`, so it is difficult to solve these problems.
    May be we can try to use `AttributeEvents` directly in further, to provide more reliable function.

    Rule Format
    -----------

    {
        column_name: predicate                          # basic format
        (column_name2, column_name3): predicate         # you can specify multiple column_names to given predicates
        column_name4: (predicate, predicate2)           # you can specify multiple predicates to given column_names
        column_name5: [(predicate, arg1, ... argN)]     # and you can specify what arguments should pass to predicate
                                                        # when it doing validate
        (column_name6, column_name7): [(predicate, arg1, ... argN), predicate2]   # another example
    }

    Notice: If you want pass arguments to predicate, you must wrap whole command by another list or tuple.
            Otherwise, we will determine the argument as another predicate.
            So, this is wrong: { column_name: (predicate, arg) }
            this is right: { column_name: [(predicate, arg)] }

    Predicate
    ---------

    There's some `predefined_predicates`, you can just reference its name in validate rule.

        {column_name: ['trans_upper']}

    Or you can pass your own predicate function to the rule, like this:

        def custom_predicate(value):
            return value_is_legal       # return True or False for valid or invalid value

        {column_name: [custom_predicate]}

    If you want change the value when doing validate, return an `dict(value=new_value)` instead of boolean

        {column_name: lambda value: dict(value = value * 2)}   # And you see, we can use lambda as a predicate.

    And the predicate can receive extra arguments, that passes in rule:

        def multiple(value, target_multiple):
            return dict(value= value * target_multiple)

        {column_name: (multiple, 10)}

    Complete Example
    ----------------

    class People(db.Model):
        name = Column(String(100))
        age = Column(Integer)
        IQ = Column(Integer)
        has_lover = Column(Boolean)

        validator = complex_validates({
            'name': [('min_length', 1), ('max_length', 100)],
            ('age', 'IQ'): [('min', 0)],
            'has_lover': lambda value: return !value    # hate you!
        })

def complex_validates(validate_rule):
    """Quickly setup attributes validation by one-time, based on `sqlalchemy.orm.validates`.

    Don't like `sqlalchemy.orm.validates`, you don't need create many model method,
    as long as pass formatted validate rule.
    (Cause of SQLAlchemy's validate mechanism, you need assignment this funciton's return value
    to a model property.)

    For simplicity, complex_validates don't support `include_removes` and `include_backrefs` parameters
    that in `sqlalchemy.orm.validates`.

    And we don't recommend you use this function multiple times in one model.
    Because this will bring many problems, like:
    1. Multiple complex_validates's execute order was decide by it's model property name, and by reversed order.
       eg. predicates in `validator1 = complex_validates(...)`
       will be executed **AFTER** predicates in `validator2 = complex_validates(...)`
    2. If you try to validate the same attribute in two (or more) complex_validates, only one of complex_validates
       will be execute. (May be this is a bug of SQLAlchemy?)
    `complex_validates` was currently based on `sqlalchemy.orm.validates`, so it is difficult to solve these problems.
    May be we can try to use `AttributeEvents` directly in further, to provide more reliable function.

    Rule Format
    -----------

    {
        column_name: predicate                          # basic format
        (column_name2, column_name3): predicate         # you can specify multiple column_names to given predicates
        column_name4: (predicate, predicate2)           # you can specify multiple predicates to given column_names
        column_name5: [(predicate, arg1, ... argN)]     # and you can specify what arguments should pass to predicate
                                                        # when it doing validate
        (column_name6, column_name7): [(predicate, arg1, ... argN), predicate2]   # another example
    }

    Notice: If you want pass arguments to predicate, you must wrap whole command by another list or tuple.
            Otherwise, we will determine the argument as another predicate.
            So, this is wrong: { column_name: (predicate, arg) }
            this is right: { column_name: [(predicate, arg)] }

    Predicate
    ---------

    There's some `predefined_predicates`, you can just reference its name in validate rule.

        {column_name: ['trans_upper']}

    Or you can pass your own predicate function to the rule, like this:

        def custom_predicate(value):
            return value_is_legal       # return True or False for valid or invalid value

        {column_name: [custom_predicate]}

    If you want change the value when doing validate, return an `dict(value=new_value)` instead of boolean

        {column_name: lambda value: dict(value = value * 2)}   # And you see, we can use lambda as a predicate.

    And the predicate can receive extra arguments, that passes in rule:

        def multiple(value, target_multiple):
            return dict(value= value * target_multiple)

        {column_name: (multiple, 10)}

    Complete Example
    ----------------

    class People(db.Model):
        name = Column(String(100))
        age = Column(Integer)
        IQ = Column(Integer)
        has_lover = Column(Boolean)

        validator = complex_validates({
            'name': [('min_length', 1), ('max_length', 100)],
            ('age', 'IQ'): [('min', 0)],
            'has_lover': lambda value: return !value    # hate you!
        })"""

    ref_dict = {
        # column_name: (
        #   (predicate, arg1, ... argN),
        #   ...
        # )
    }

    for column_names, predicate_refs in validate_rule.items():
        for column_name in _to_tuple(column_names):
            ref_dict[column_name] = \
                ref_dict.get(column_name, tuple()) + _normalize_predicate_refs(predicate_refs)

    return validates(*ref_dict.keys())(
        lambda self, name, value: _validate_handler(name, value, ref_dict[name]))