'Extract mapped classes and relationships from the :class:`.MetaData` and
perform mappings.
:param engine: an :class:`.Engine` or :class:`.Connection` with which
to perform schema reflection, if specified.
If the :paramref:`.AutomapBase.prepare.reflect` argument is False, this
object is not used.
:param reflect: if True, the :meth:`.MetaData.reflect` method is called
on the :class:`.MetaData` associated with this :class:`.AutomapBase`.
The :class:`.Engine` passed via :paramref:`.AutomapBase.prepare.engine` will
be used to perform the reflection if present; else, the :class:`.MetaData`
should already be bound to some engine else the operation will fail.
:param classname_for_table: callable function which will be used to
produce new class names, given a table name.  Defaults to
:func:`.classname_for_table`.
:param name_for_scalar_relationship: callable function which will be used
to produce relationship names for scalar relationships.  Defaults to
:func:`.name_for_scalar_relationship`.
:param name_for_collection_relationship: callable function which will be used
to produce relationship names for collection-oriented relationships.  Defaults to
:func:`.name_for_collection_relationship`.
:param generate_relationship: callable function which will be used to
actually generate :func:`.relationship` and :func:`.backref` constructs.
Defaults to :func:`.generate_relationship`.
:param collection_class: the Python collection class that will be used
when a new :func:`.relationship` object is created that represents a
collection.  Defaults to ``list``.'

@classmethod
def prepare(cls, engine=None, reflect=False, classname_for_table=classname_for_table, collection_class=list, name_for_scalar_relationship=name_for_scalar_relationship, name_for_collection_relationship=name_for_collection_relationship, generate_relationship=generate_relationship):

    if reflect:
        cls.metadata.reflect(engine, extend_existing=True, autoload_replace=False)
    table_to_map_config = dict(((m.local_table, m) for m in _DeferredMapperConfig.classes_for_base(cls, sort=False)))
    many_to_many = []
    for table in cls.metadata.tables.values():
        (lcl_m2m, rem_m2m, m2m_const) = _is_many_to_many(cls, table)
        if (lcl_m2m is not None):
            many_to_many.append((lcl_m2m, rem_m2m, m2m_const, table))
        elif (not table.primary_key):
            continue
        elif (table not in table_to_map_config):
            mapped_cls = type(classname_for_table(cls, table.name, table), (cls,), {'__table__': table})
            map_config = _DeferredMapperConfig.config_for_cls(mapped_cls)
            cls.classes[map_config.cls.__name__] = mapped_cls
            table_to_map_config[table] = map_config
    for map_config in table_to_map_config.values():
        _relationships_for_fks(cls, map_config, table_to_map_config, collection_class, name_for_scalar_relationship, name_for_collection_relationship, generate_relationship)
    for (lcl_m2m, rem_m2m, m2m_const, table) in many_to_many:
        _m2m_relationship(cls, lcl_m2m, rem_m2m, m2m_const, table, table_to_map_config, collection_class, name_for_scalar_relationship, name_for_collection_relationship, generate_relationship)
    for map_config in _DeferredMapperConfig.classes_for_base(cls):
        map_config.map()
