Beispiel #1
0
def localize_domain_model_from_descriptor_class(domain_model, descriptor_cls):
    """Localize the domain model for configuration information in the 
    descriptor i.e. any extended/derived attributes.
    
    For any model/descriptor this should be called only once!
    """
    type_key = naming.polymorphic_identity(domain_model)
    # localize models from descriptors only once!
    assert type_key not in localize_domain_model_from_descriptor_class.DONE, \
        "May not re-localize [%s] domain model from descriptor" % (type_key)
    localize_domain_model_from_descriptor_class.DONE.append(type_key)
    
    #!+GET_ARCHETYPE
    #!+archetype_key = naming.polymorphic_identity(domain_model.__bases__[0]) multiple inheritance...
    archetype_key = naming._type_key_from_descriptor_class_name(
            descriptor_cls.__bases__[0].__name__)
    
    for field in descriptor_cls.fields:
        
        # extended
        if field.extended is not None:
            add_extended_property_to_model(domain_model, 
                field.name, field.extended, archetype_key)
        
        # derived
        if field.derived is not None:
            add_derived_property_to_model(domain_model, 
                field.name, field.derived)
    
    # !+if domain_model.extended_properties: ?
    # !+instrument_extended_properties, archetype_key => table...
    instrument_extended_properties(domain_model, archetype_key)
    mapper_add_relation_vertical_properties(domain_model)
    # !+AUDIT_EXTENDED_ATTRIBUTES as audit class was created prior to 
    # extended attributes being updated on domain type, need to push onto 
    # it any extended attrs that were read from model's descriptor
    if interfaces.IFeatureAudit.implementedBy(domain_model):
        # either defined manually or created dynamically in feature_audit()
        audit_kls = getattr(MODEL_MODULE, "%sAudit" % (domain_model.__name__))
        # propagate any extended attributes on head kls also to its audit_kls
        import bungeni.models.domain
        audit_table_name = bungeni.models.domain.get_audit_table_name(domain_model)
        instrument_extended_properties(
            audit_kls, audit_table_name, from_class=domain_model)
    
    # containers
    from bungeni.capi import capi
    for name, target_type_key, rel_attr in descriptor_cls.info_containers:
        try:
            tti = capi.get_type_info(target_type_key)
        except KeyError:
            # target type not enabled
            log.warn("Ignoring %r container property %r to disabled type: %s.%s", 
                type_key, name, target_type_key, rel_attr)
            continue
        
        container_qualname = "bungeni.models.domain.%s" % (
            naming.container_class_name(target_type_key))
        add_container_property_to_model(domain_model, 
            name, container_qualname, rel_attr)
Beispiel #2
0
def generate_container_class(ti):
    """Generate a zope3 container class for a domain model.
    """
    type_key = naming.polymorphic_identity(ti.domain_model)
    container_name = naming.container_class_name(type_key)
    container_iname = naming.container_interface_name(type_key)
    base_interfaces = (IAlchemistContainer,
                       )  # !+achetype.container_interface?

    # logging variables
    msg = (ti.domain_model.__name__, CONTAINER_MODULE.__name__, container_name)

    # container class - if we already have one, exit
    if getattr(CONTAINER_MODULE, container_name, None):
        log.info(
            "generate_container_class [model=%s] found container %s.%s, skipping",
            *msg)
        ti.container_class = getattr(CONTAINER_MODULE, container_name)
        return

    container_class = type(
        container_name, (AlchemistContainer, ),
        dict(_class=ti.domain_model, __module__=CONTAINER_MODULE.__name__))
    # set on CONTAINER_MODULE, register on type_info
    setattr(CONTAINER_MODULE, container_name, container_class)
    ti.container_class = container_class
    log.info("generate_container_class [model=%s] generated container %s.%s",
             *msg)

    # container interface - if we already have one, skip creation
    # !+ should always be newly created?
    container_iface = getattr(INTERFACE_MODULE, container_iname, None)
    msg = (ti.domain_model.__name__, CONTAINER_MODULE.__name__,
           container_iname)
    if container_iface is not None:
        assert issubclass(container_iface, IAlchemistContainer)
        log.info(
            "generate_container_class [model=%s] skipping container interface %s.%s for",
            *msg)
    else:
        container_iface = interface.interface.InterfaceClass(
            container_iname,
            bases=base_interfaces,
            __module__=INTERFACE_MODULE.__name__)
        # set on INTERFACE_MODULE, register on type_info
        setattr(INTERFACE_MODULE, container_iname, container_iface)
        ti.container_interface = container_iface
        log.info(
            "generate_container_class [model=%s] generated container interface %s.%s",
            *msg)

    # setup security
    for n, d in container_iface.namesAndDescriptions(all=True):
        protectName(container_class, n, "zope.Public")
    # apply implementedBy
    if not container_iface.implementedBy(container_class):
        interface.classImplements(container_class, container_iface)
Beispiel #3
0
def localize_domain_model_from_descriptor_class(domain_model, descriptor_cls):
    """Localize the domain model for configuration information in the 
    descriptor i.e. any extended/derived attributes.
    
    For any model/descriptor this should be called only once!
    """
    type_key = naming.polymorphic_identity(domain_model)
    # localize models from descriptors only once!
    assert type_key not in localize_domain_model_from_descriptor_class.DONE, \
        "May not re-localize [%s] domain model from descriptor" % (type_key)
    localize_domain_model_from_descriptor_class.DONE.append(type_key)
    log.info("localize_domain_model_from_descriptor_class: (%s, %s)",
             domain_model.__name__, descriptor_cls.__name__)

    # ensure cls has own dedicated "extended_properties" list property
    # i.e. a "extended_properties" key in own cls.__dict__,
    # and that it is initialized with current (possibly inherited) values
    domain_model.extended_properties = domain_model.extended_properties[:]

    for field in descriptor_cls.fields:

        # extended
        if field.extended is not None:
            add_extended_property_to_model(domain_model, field.name,
                                           field.extended)

        # derived
        if field.derived is not None:
            add_derived_property_to_model(domain_model, field.name,
                                          field.derived)

    # !+if domain_model.extended_properties: ?
    instrument_extended_properties(domain_model)
    mapper_add_relation_vertical_properties(domain_model)
    # !+AUDIT_EXTENDED_ATTRIBUTES as audit class was created prior to
    # extended attributes being updated on domain type, need to push onto
    # it any extended attrs that were read from model's descriptor
    if IFeatureAudit.implementedBy(domain_model):
        # either defined manually or created dynamically in feature_audit()
        audit_kls = getattr(MODEL_MODULE, "%sAudit" % (domain_model.__name__))
        # ensure cls has own dedicated "extended_properties" list property
        audit_kls.extended_properties = domain_model.extended_properties[:]
        # propagate any extended attributes on head kls also to its audit_kls
        instrument_extended_properties(audit_kls)

    # containers
    for ic in descriptor_cls.info_containers:
        container_qualname = "bungeni.models.domain.%s" % (
            naming.container_class_name(ic.target_type_key))
        add_container_property_to_model(domain_model, ic.container_attr_name,
                                        container_qualname, ic.rel_attr_name,
                                        ic.indirect_key)
def generate_container_class(ti):
    """Generate a zope3 container class for a domain model.
    """
    type_key = naming.polymorphic_identity(ti.domain_model)
    container_name = naming.container_class_name(type_key)
    container_iname = naming.container_interface_name(type_key)
    base_interfaces = (IAlchemistContainer,)
    
    # logging variables
    msg = (ti.domain_model.__name__, CONTAINER_MODULE.__name__, container_name)
    
    # container class - if we already have one, exit                
    if getattr(CONTAINER_MODULE, container_name, None):
        log.info("generate_container_class [model=%s] found container %s.%s, skipping" % msg)
        ti.container_class = getattr(CONTAINER_MODULE, container_name)
        return
    
    container_class = type(container_name,
        (AlchemistContainer,),
        dict(_class=ti.domain_model, 
            __module__=CONTAINER_MODULE.__name__)
    )
    # set on CONTAINER_MODULE, register on type_info
    setattr(CONTAINER_MODULE, container_name, container_class)
    ti.container_class = container_class
    log.info("generate_container_class [model=%s] generated container %s.%s" % msg)
    
    # container interface - if we already have one, skip creation 
    # !+ should always be newly created?
    container_iface = getattr(INTERFACE_MODULE, container_iname, None)
    msg = (ti.domain_model.__name__, CONTAINER_MODULE.__name__, container_iname)
    if container_iface is not None:
        assert issubclass(container_iface, IAlchemistContainer)
        log.info("generate_container_class [model=%s] skipping container interface %s.%s for" % msg)
    else:
        container_iface = interface.interface.InterfaceClass(
            container_iname,
            bases=base_interfaces,
            __module__=INTERFACE_MODULE.__name__
        )
        # set on INTERFACE_MODULE, register on type_info
        setattr(INTERFACE_MODULE, container_iname, container_iface)
        ti.container_interface = container_iface
        log.info("generate_container_class [model=%s] generated container interface %s.%s" % msg)
    
    # setup security
    for n, d in container_iface.namesAndDescriptions(all=True):
        protectName(container_class, n, "zope.Public")
    # apply implementedBy
    if not container_iface.implementedBy(container_class):
        interface.classImplements(container_class, container_iface)
Beispiel #5
0
def localize_domain_model_from_descriptor_class(domain_model, descriptor_cls):
    """Localize the domain model for configuration information in the 
    descriptor i.e. any extended/derived attributes.
    
    For any model/descriptor this should be called only once!
    """
    type_key = naming.polymorphic_identity(domain_model)
    # localize models from descriptors only once!
    assert type_key not in localize_domain_model_from_descriptor_class.DONE, \
        "May not re-localize [%s] domain model from descriptor" % (type_key)
    localize_domain_model_from_descriptor_class.DONE.append(type_key)
    log.info("localize_domain_model_from_descriptor_class: (%s, %s)", 
            domain_model.__name__, descriptor_cls.__name__)
    
    # ensure cls has own dedicated "extended_properties" list property 
    # i.e. a "extended_properties" key in own cls.__dict__, 
    # and that it is initialized with current (possibly inherited) values
    domain_model.extended_properties = domain_model.extended_properties[:]
    
    for field in descriptor_cls.fields:
        
        # extended
        if field.extended is not None:
            add_extended_property_to_model(domain_model, field.name, field.extended)
        
        # derived
        if field.derived is not None:
            add_derived_property_to_model(domain_model, 
                field.name, field.derived)
    
    # !+if domain_model.extended_properties: ?
    instrument_extended_properties(domain_model)
    mapper_add_relation_vertical_properties(domain_model)
    # !+AUDIT_EXTENDED_ATTRIBUTES as audit class was created prior to 
    # extended attributes being updated on domain type, need to push onto 
    # it any extended attrs that were read from model's descriptor
    if IFeatureAudit.implementedBy(domain_model):
        # either defined manually or created dynamically in feature_audit()
        audit_kls = getattr(MODEL_MODULE, "%sAudit" % (domain_model.__name__))
        # ensure cls has own dedicated "extended_properties" list property 
        audit_kls.extended_properties = domain_model.extended_properties[:]
        # propagate any extended attributes on head kls also to its audit_kls
        instrument_extended_properties(audit_kls)
    
    # containers
    for ic in descriptor_cls.info_containers:
        container_qualname = "bungeni.models.domain.%s" % (
            naming.container_class_name(ic.target_type_key))
        add_container_property_to_model(domain_model, ic.container_attr_name, 
            container_qualname, ic.rel_attr_name, ic.indirect_key)
Beispiel #6
0
def feature_event(kls, feature):
    """Decorator for domain types to support "event" feature.
    For Doc types (other than Event itself).
    """
    # !+ feature "descriptor/processing/validation", move elsewhere?
    # parameter "types":
    # - may "allow" multiple event types
    # - if none specified, "event" is assumed as the default.
    feature.params["types"] = feature.params.get("types", "event").split()
    
    # domain.Event itself may NOT support events
    assert not interfaces.IEvent.implementedBy(kls)
    interface.classImplements(kls, interfaces.IFeatureEvent)
    
    # container property per enabled event type
    for event_type_key in feature.params["types"]:
        if capi.has_type_info(event_type_key):
            container_property_name = naming.plural(event_type_key)
            container_class_name = naming.container_class_name(event_type_key)
            add_container_property_to_model(kls, container_property_name,
                "bungeni.models.domain.%s" % (container_class_name), "head_id")
        else:
            log.warn('IGNORING feature "event" ref to disabled type %r', event_type_key)
Beispiel #7
0
    def setUp(self):

        # register translations
        #import zope.i18n.zcml
        #zope.i18n.zcml.registerTranslations(getConfigContext(),
        #    capi.get_path_for("translations", "bungeni"))
        # !+ZCML_PYTHON(mr, apr-2011) above registerTranslations() in python
        # does not work, as subsequent utility lookup fails. We workaround it
        # by executing the following parametrized bit of ZCML:
        from zope.configuration import xmlconfig
        xmlconfig.string("""
            <configure xmlns="http://namespaces.zope.org/zope"
                xmlns:i18n="http://namespaces.zope.org/i18n">
                <include package="zope.i18n" file="meta.zcml" />
                <i18n:registerTranslations directory="%s" />
            </configure>
            """ % (capi.get_path_for("translations", "bungeni")))

        sm = site.LocalSiteManager(self.context)
        self.context.setSiteManager(sm)

        from bungeni.core import language
        from bungeni.ui import z3evoque
        z3evoque.set_get_gettext()
        z3evoque.setup_evoque()
        z3evoque.domain.set_on_globals("devmode",
                                       common.has_feature("devmode"))
        z3evoque.domain.set_on_globals("absoluteURL", url.absoluteURL)
        z3evoque.domain.set_on_globals("get_section_name",
                                       url.get_section_name)
        z3evoque.domain.set_on_globals("get_base_direction",
                                       language.get_base_direction)
        z3evoque.domain.set_on_globals("is_rtl", language.is_rtl)

        # !+ where is the view name for the app root (slash) set?

        # CONVENTION: the action of each site top-section is made to point
        # directly the primary sub-section (the INDEX) that it contains.
        # EXCEPTION: the "/", when logged in, is redirected to "/workspace/pi"

        self.context["bungeni"] = AkomaNtosoSection(
            title=_(u"Bungeni"),
            description=_(u"Current parliamentary activity"),
            default_name="bung",  # !+NAMING(mr, jul-2011) bung?!?
        )

        # top-level sections
        workspace = self.context["workspace"] = WorkspaceSection(
            title=_("section_workspace", default=u"Workspace"),
            description=_(u"Current parliamentary activity"),
            default_name="my-documents",
        )
        alsoProvides(workspace, interfaces.ISearchableSection)

        workspace["my-documents"] = WorkspaceSection(
            title=_("section_workspace_documents", default=u"my documents"),
            description=_(u"my documents workspace section"),
            default_name="inbox",
            marker=interfaces.IWorkspaceDocuments,
        )

        for tab in capi.workspace_tabs:
            workspace["my-documents"][tab] = WorkspaceContainer(
                tab_type=tab,
                title=_("section_workspace_%s" % tab, default=tab),
                marker=interfaces.IWorkspaceTab)

        ws_uc = workspace["under-consideration"] = WorkspaceSection(
            title=_(u"under consideration"),
            description=_(u"documents under consideration"),
            default_name="documents",
            marker=interfaces.IWorkspaceUnderConsideration)
        ws_uc["documents"] = WorkspaceUnderConsiderationContainer(
            name="documents",
            title=_(u"under consideration"),
            description=_(u"documents under consideration"),
            marker=interfaces.IWorkspaceTrackedDocuments)
        ws_uc["tracked-documents"] = WorkspaceTrackedDocumentsContainer(
            name="tracked documents",
            title=_(u"tracked documents"),
            description=_(u"tracked documents"))

        ws_sched = workspace["scheduling"] = Section(
            title=_("section_scheduling", default=u"Scheduling"),
            description=_(u"Workspace Scheduling"),
            default_name="index",
            marker=interfaces.IWorkspaceScheduling)
        ws_sched["committees"] = QueryContent(
            container_getter(get_chamber_for_context, "committees"),
            title=_("section_scheduling_committees", default=u"Committees"),
            #!+marker=interfaces.ICommitteeAddContext,
            description=_(u"Committee schedules"))
        ws_sched["documents"] = WorkspaceSchedulableContainer(
            name=_(u"schedulable items"),
            title=_(u"schedulable items"),
            description=_(u"documents available for scheduling"))
        ws_sched["sittings"] = QueryContent(
            container_getter(get_chamber_for_context, "sittings"),
            title=_("section_scheduling_sittings", default=u"Sittings"),
            description=_(u"Plenary Sittings"))
        ws_sched["sessions"] = QueryContent(
            container_getter(get_chamber_for_context, "sessions"),
            title=_("section_scheduling_sessions", default=u"Sessions"),
            description=_(u"Plenary Sessions"))
        ws_sched["venues"] = QueryContent(container_getter(
            get_chamber_for_context, "venues"),
                                          title=_("section_scheduling_venues",
                                                  default=u"Venues"),
                                          description=_(u"Venues"))
        ws_sched["agendaitems"] = QueryContent(
            container_getter(get_chamber_for_context, "agendaitems"),
            title=_("section_scheduling_agenda_items",
                    default=u"Agenda items"),
            #marker=interfaces.IAgendaItemAddContext,
            description=_(u"Manage agenda items"))
        ws_sched["publications"] = QueryContent(
            container_getter(get_chamber_for_context, "publications"),
            title=_("section_scheduling_publications",
                    default=u"Publications"),
            description=_(u"Publications"))

        workspace["groups"] = WorkspaceSection(
            title=_("section_groups", default=u"Groups"),
            description=_(u"Bungeni Groups"),
            default_name="my-groups",
            marker=interfaces.IWorkspaceGroups)
        workspace["groups"]["my-groups"] = WorkspaceGroupsContainer(
            name="my-groups",
            title=_(u"My Groups"),
            description=_(u"Groups that the user is a member of"))

        #!+TIMING
        #!+AUTO CONTAINERS SCHEDULING(mb, April-2012)
        # type_info missing container name
        for type_key, ti in capi.iter_type_info():
            if model_interfaces.IScheduleContent.implementedBy(
                    ti.domain_model):
                container_property_name = naming.plural(type_key)
                container_class_name = naming.container_class_name(type_key)
                if not ws_sched.has_key(container_property_name):
                    ws_sched[container_property_name] = \
                        getattr(domain, container_class_name)()
                    to_locatable_container(ti.domain_model,
                                           ws_sched[container_property_name])

        ##########
        # Admin User Interface
        # Administration section

        #!+SECURITY(miano. nov-2010) Admin section now uses AdminSection
        # container that is identical to Section, only difference is that
        # traversing though it requires zope.ManageSite permission as defined
        # in core/configure.zcml

        admin = self.context["admin"] = AdminSection(
            title=_(u"Administration"),
            description=_(u"Manage bungeni settings"),
            default_name="admin-index",
            marker=model_interfaces.IBungeniAdmin)

        content = admin["content"] = Section(
            title=_(u"Content"),
            description=_(u"browse bungeni content"),
            marker=model_interfaces.IBungeniAdmin,
            default_name="browse-admin")
        alsoProvides(content, interfaces.ISearchableSection)

        admin["email-settings"] = Section(
            title=_(u"email settings"),
            description=_(u"manage email settings"),
            marker=model_interfaces.IBungeniAdmin,
            default_name="email-settings")

        admin["search-settings"] = Section(
            title=_(u"search settings"),
            description=_(u"manage bungeni email settings"),
            marker=model_interfaces.IBungeniAdmin,
            default_name="search-settings")

        admin["registry-settings"] = Section(
            title=_(u"registry settings"),
            description=_(u"manage registry settings"),
            marker=model_interfaces.IBungeniAdmin,
            default_name="registry-settings")

        admin["serialization-manager"] = Section(
            title=_(u"serialization manager"),
            description=_(u"batch serialization of content"),
            marker=model_interfaces.IBungeniAdmin,
            default_name="serialization-manager")

        content[u"parliaments"] = domain.ParliamentContainer()
        to_locatable_container(domain.Parliament, content[u"parliaments"])
        content[u"governments"] = domain.GovernmentContainer()
        to_locatable_container(domain.Government, content[u"governments"])
        content[u"joint-committees"] = domain.JointCommitteeContainer()
        to_locatable_container(domain.JointCommittee,
                               content["joint-committees"])
        content[u"users"] = domain.UserContainer()
        to_locatable_container(domain.User, content[u"users"])

        api = self.context[u"api"] = APISection(
            title=_(u"Bungeni API"),
            description=_(u"Bungeni REST API"),
            default_name="index",
        )

        api[u"workspace"] = copy.deepcopy(workspace)

        api[u"users"] = copy.deepcopy(content[u"users"])

        self.context["oauth"] = OAuthSection(
            title=_(u"Bungeni OAuth API"),
            description=_(u"Bungeni OAuth API"),
            default_name="index",
        )
        admin[u"applications"] = domain.OAuthApplicationContainer()
        to_locatable_container(domain.OAuthApplication, admin[u"applications"])
Beispiel #8
0
    def setUp(self):
        
        # register translations
        #import zope.i18n.zcml
        #zope.i18n.zcml.registerTranslations(getConfigContext(),
        #    capi.get_path_for("translations", "bungeni"))
        # !+ZCML_PYTHON(mr, apr-2011) above registerTranslations() in python 
        # does not work, as subsequent utility lookup fails. We workaround it 
        # by executing the following parametrized bit of ZCML:
        from zope.configuration import xmlconfig
        xmlconfig.string("""
            <configure xmlns="http://namespaces.zope.org/zope"
                xmlns:i18n="http://namespaces.zope.org/i18n">
                <include package="zope.i18n" file="meta.zcml" />
                <i18n:registerTranslations directory="%s" />
            </configure>
            """ % (capi.get_path_for("translations", "bungeni")))
        
        sm = site.LocalSiteManager(self.context)
        self.context.setSiteManager(sm)
        
        from bungeni.core import language
        from bungeni.ui import z3evoque
        z3evoque.set_get_gettext()
        z3evoque.setup_evoque()
        z3evoque.domain.set_on_globals("devmode", common.has_feature("devmode"))
        z3evoque.domain.set_on_globals("absoluteURL", url.absoluteURL)
        z3evoque.domain.set_on_globals("get_section_name", url.get_section_name)
        z3evoque.domain.set_on_globals("get_base_direction", 
            language.get_base_direction)
        z3evoque.domain.set_on_globals("is_rtl", language.is_rtl)          
        
        # !+ where is the view name for the app root (slash) set?
        
        # CONVENTION: the action of each site top-section is made to point 
        # directly the primary sub-section (the INDEX) that it contains.
        # EXCEPTION: the "/", when logged in, is redirected to "/workspace/pi"
        
        self.context["bungeni"] = AkomaNtosoSection(
            title=_(u"Bungeni"),
            description=_(u"Current parliamentary activity"),
            default_name="bung", # !+NAMING(mr, jul-2011) bung?!?
        )
        
        # top-level sections
        workspace = self.context["workspace"] = WorkspaceSection(
            title=_("section_workspace", default=u"Workspace"),
            description=_(u"Current parliamentary activity"),
            default_name="my-documents",
        )
        alsoProvides(workspace, interfaces.ISearchableSection)
        
        workspace["my-documents"] = WorkspaceSection(
            title=_("section_workspace_documents", default=u"my documents"),
            description=_(u"my documents workspace section"),
            default_name="inbox",
            marker=interfaces.IWorkspaceDocuments,
        )
        
        for tab in capi.workspace_tabs:
            workspace["my-documents"][tab] = WorkspaceContainer(
                tab_type=tab,
                title=_("section_workspace_%s" % tab, default=tab),
                marker=interfaces.IWorkspaceTab
            )

        ws_uc = workspace["under-consideration"] = WorkspaceSection(
            title=_(u"under consideration"),
            description=_(u"documents under consideration"),
            default_name="documents",
            marker=interfaces.IWorkspaceUnderConsideration)
        ws_uc["documents"] = WorkspaceUnderConsiderationContainer(
            name="documents",
            title=_(u"under consideration"),
            description=_(u"documents under consideration"),
            marker=interfaces.IWorkspaceTrackedDocuments)
        ws_uc["tracked-documents"] = WorkspaceTrackedDocumentsContainer(
            name="tracked documents",
            title=_(u"tracked documents"),
            description=_(u"tracked documents"))
        
        ws_sched = workspace["scheduling"] = Section(
            title=_("section_scheduling", default=u"Scheduling"),
            description=_(u"Workspace Scheduling"),
            default_name="index",
            marker=interfaces.IWorkspaceScheduling)
        ws_sched["committees"] = QueryContent(
            container_getter(get_chamber_for_context, "committees"),
            title=_("section_scheduling_committees", default=u"Committees"),
            #!+marker=interfaces.ICommitteeAddContext,
            description=_(u"Committee schedules"))
        ws_sched["documents"] = WorkspaceSchedulableContainer(
            name=_(u"schedulable items"),
            title=_(u"schedulable items"),
            description=_(u"documents available for scheduling"))
        ws_sched["sittings"] = QueryContent(
            container_getter(get_chamber_for_context, "sittings"),
            title=_("section_scheduling_sittings", default=u"Sittings"),
            description=_(u"Plenary Sittings"))
        ws_sched["sessions"] = QueryContent(
            container_getter(get_chamber_for_context, "sessions"),
            title=_("section_scheduling_sessions", default=u"Sessions"),
            description=_(u"Plenary Sessions"))
        ws_sched["venues"] = QueryContent(
            container_getter(get_chamber_for_context, "venues"),
            title=_("section_scheduling_venues", default=u"Venues"),
            description=_(u"Venues"))
        ws_sched["agendaitems"] = QueryContent(
            container_getter(get_chamber_for_context, "agendaitems"),
            title=_("section_scheduling_agenda_items", 
                default=u"Agenda items"),
            #marker=interfaces.IAgendaItemAddContext,
            description=_(u"Manage agenda items"))
        ws_sched["publications"] = QueryContent(
            container_getter(get_chamber_for_context, "publications"),
            title=_("section_scheduling_publications", 
                default=u"Publications"),
            description=_(u"Publications"))
        
        workspace["groups"] = WorkspaceSection(
            title=_("section_groups", default=u"Groups"),
            description=_(u"Bungeni Groups"),
            default_name="my-groups",
            marker=interfaces.IWorkspaceGroups)
        workspace["groups"]["my-groups"] = WorkspaceGroupsContainer(
            name="my-groups",
            title=_(u"My Groups"),
            description=_(u"Groups that the user is a member of"))
        
        #!+TIMING
        #!+AUTO CONTAINERS SCHEDULING(mb, April-2012)
        # type_info missing container name
        for type_key, ti in capi.iter_type_info():
            if model_interfaces.IScheduleContent.implementedBy(ti.domain_model):
                container_property_name = naming.plural(type_key)
                container_class_name = naming.container_class_name(type_key)
                if not ws_sched.has_key(container_property_name):
                    ws_sched[container_property_name] = \
                        getattr(domain, container_class_name)()
                    to_locatable_container(
                        ti.domain_model, ws_sched[container_property_name])
        
        
        ##########
        # Admin User Interface
        # Administration section
        
        #!+SECURITY(miano. nov-2010) Admin section now uses AdminSection
        # container that is identical to Section, only difference is that
        # traversing though it requires zope.ManageSite permission as defined
        # in core/configure.zcml
        
        admin = self.context["admin"] = AdminSection(
            title=_(u"Administration"),
            description=_(u"Manage bungeni settings"),
            default_name="admin-index",
            marker=model_interfaces.IBungeniAdmin)
        
        content = admin["content"] = Section(
            title=_(u"Content"),
            description=_(u"browse bungeni content"),
            marker=model_interfaces.IBungeniAdmin,
            default_name="browse-admin")
        alsoProvides(content, interfaces.ISearchableSection)
        
        admin["email-settings"] = Section(
            title=_(u"email settings"),
            description=_(u"manage email settings"),
            marker=model_interfaces.IBungeniAdmin,
            default_name="email-settings")
        
        admin["search-settings"] = Section(
            title=_(u"search settings"),
            description=_(u"manage bungeni email settings"),
            marker=model_interfaces.IBungeniAdmin,
            default_name="search-settings")
        
        admin["registry-settings"] = Section(
            title=_(u"registry settings"),
            description=_(u"manage registry settings"),
            marker=model_interfaces.IBungeniAdmin,
            default_name="registry-settings")
        
        admin["serialization-manager"] = Section(
            title=_(u"serialization manager"),
            description=_(u"batch serialization of content"),
            marker=model_interfaces.IBungeniAdmin,
            default_name="serialization-manager")
        
        content[u"parliaments"] = domain.ParliamentContainer()
        to_locatable_container(domain.Parliament, content[u"parliaments"])
        content[u"governments"] = domain.GovernmentContainer()
        to_locatable_container(domain.Government, content[u"governments"])
        content[u"joint-committees"] = domain.JointCommitteeContainer()
        to_locatable_container(domain.JointCommittee,
            content["joint-committees"])
        content[u"users"] = domain.UserContainer()
        to_locatable_container(domain.User, content[u"users"])

        api = self.context[u"api"] = APISection(
            title=_(u"Bungeni API"),
            description=_(u"Bungeni REST API"),
            default_name="index",
        )

        api[u"workspace"] = copy.deepcopy(workspace)

        api[u"users"] = copy.deepcopy(content[u"users"])

        self.context["oauth"] = OAuthSection(
            title=_(u"Bungeni OAuth API"),
            description=_(u"Bungeni OAuth API"),
            default_name="index",
        )
        admin[u"applications"] = domain.OAuthApplicationContainer()
        to_locatable_container(domain.OAuthApplication, admin[u"applications"])