This function allows you to map subclasses of L{ClassAlias} to classes
    listed in C{args}.

    When an object is read/written from/to the AMF stream, a paired L{ClassAlias}
    instance is created (or reused), based on the Python class of that object.
    L{ClassAlias} provides important metadata for the class and can also control
    how the equivalent Python object is created, how the attributes are applied
    etc.

    Use this function if you need to do something non-standard.

    @since: 0.4
    @see:
     - L{pyamf.adapters._google_appengine_ext_db.DataStoreClassAlias} for a
       good example.
     - L{unregister_alias_type}
    @raise RuntimeError: alias is already registered
    @raise TypeError: Value supplied to C{klass} is not a class
    @raise ValueError:
     - New aliases must subclass L{pyamf.ClassAlias}
     - At least one type must be supplied

def register_alias_type(klass, *args):
    """
    This function allows you to map subclasses of L{ClassAlias} to classes
    listed in C{args}.

    When an object is read/written from/to the AMF stream, a paired L{ClassAlias}
    instance is created (or reused), based on the Python class of that object.
    L{ClassAlias} provides important metadata for the class and can also control
    how the equivalent Python object is created, how the attributes are applied
    etc.

    Use this function if you need to do something non-standard.

    @since: 0.4
    @see:
     - L{pyamf.adapters._google_appengine_ext_db.DataStoreClassAlias} for a
       good example.
     - L{unregister_alias_type}
    @raise RuntimeError: alias is already registered
    @raise TypeError: Value supplied to C{klass} is not a class
    @raise ValueError:
     - New aliases must subclass L{pyamf.ClassAlias}
     - At least one type must be supplied
    """
    def check_type_registered(arg):
        for k, v in ALIAS_TYPES.iteritems():
            for kl in v:
                if arg is kl:
                    raise RuntimeError('%r is already registered under %r' % (
                        arg, k))

    if not isinstance(klass, python.class_types):
        raise TypeError('klass must be class')

    if not issubclass(klass, ClassAlias):
        raise ValueError('New aliases must subclass pyamf.ClassAlias')

    if len(args) == 0:
        raise ValueError('At least one type must be supplied')

    if len(args) == 1 and hasattr(args[0], '__call__'):
        c = args[0]

        check_type_registered(c)
    else:
        for arg in args:
            if not isinstance(arg, python.class_types):
                raise TypeError('%r must be class' % (arg,))

            check_type_registered(arg)

    ALIAS_TYPES[klass] = args

    for k, v in CLASS_CACHE.copy().iteritems():
        new_alias = util.get_class_alias(v.klass)

        if new_alias is klass:
            meta = util.get_class_meta(v.klass)
            meta['alias'] = v.alias

            alias_klass = klass(v.klass, **meta)

            CLASS_CACHE[k] = alias_klass
            CLASS_CACHE[v.klass] = alias_klass