コード例 #1
0
ファイル: generic.py プロジェクト: swergas/assembl
 def special_quad_patterns(cls, alias_maker, discussion_id):
     discussion_alias = alias_maker.get_reln_alias(cls.discussion)
     return [
         QuadMapPatternS(
             None, FOAF.homepage,
             PatternIriClass(
                 QUADNAMES.post_external_link_iri,
                 # TODO: Use discussion.get_base_url.
                 # This should be computed outside the DB.
                 get_global_base_url() + '/%s/posts/local:Content/%d', None,
                 ('slug', Unicode, False), ('id', Integer, False)).apply(
                 discussion_alias.slug, cls.id),
             name=QUADNAMES.post_external_link_map)
     ]
コード例 #2
0
ファイル: idea.py プロジェクト: rmoorman/assembl
 def special_quad_patterns(cls, alias_maker, discussion_id):
     discussion_alias = alias_maker.get_reln_alias(cls.discussion)
     return [
         QuadMapPatternS(
             None, RDF.type,
             IriClass(VirtRDF.QNAME_ID).apply(Idea.rdf_type),
             name=QUADNAMES.class_Idea_class),
         QuadMapPatternS(
             None, FOAF.homepage,
             PatternIriClass(
                 QUADNAMES.idea_external_link_iri,
                 # TODO: Use discussion.get_base_url.
                 # This should be computed outside the DB.
                 get_global_base_url() + '/%s/idea/local:Idea/%d', None,
                 ('slug', Unicode, False), ('id', Integer, False)).apply(
                 discussion_alias.slug, cls.id),
             name=QUADNAMES.idea_external_link_map)
     ]
コード例 #3
0
class Base(object):
    def __init__(self, **kw):
        for k, v in kw.iteritems():
            setattr(self, k, v)


class A(Base):
    __tablename__ = "test_a"
    id = Column(Integer, primary_key=True)
    name = Column(
        String, info={'rdf': QuadMapPattern(None, TST.name, None)})


inspect(A).local_table.info = {
    "rdf_iri": PatternIriClass(
        TST.ta_iri, 'http://example.com/test#tA/%d', None,
        ('id', Integer, False)),
    "rdf_patterns": [QuadMapPattern(None, RDF.type, TST.tA)]
}


class B(Base):
    __tablename__ = "test_b"
    id = Column(Integer, primary_key=True)
    name = Column(String, info={'rdf': QuadMapPattern(None, TST.name, None)})
    type = Column(String(20))
    a_id = Column(Integer, ForeignKey(A.id), info={
        'rdf': QuadMapPattern(None, TST.alink)})
    a = relation(A)
    __mapper_args__ = {
        'polymorphic_identity': 'B',
コード例 #4
0
class Extract(IdeaContentPositiveLink):
    """
    An extracted part of a Content. A quotation to be referenced by an `Idea`.
    """
    __tablename__ = 'extract'
    rdf_class = CATALYST.Excerpt
    # Extract ID represents both the oa:Annotation and the oa:SpecificResource
    # TODO: This iri is not yet dereferencable.
    specific_resource_iri = PatternIriClass(
        QUADNAMES.oa_specific_resource_iri,
        get_global_base_url() + '/data/SpecificResource/%d', None,
        ('id', Integer, False))

    id = Column(Integer, ForeignKey(
            'idea_content_positive_link.id',
            ondelete='CASCADE', onupdate='CASCADE'
        ), primary_key=True, info= {
            'rdf': QuadMapPatternS(None, ASSEMBL.db_id)})

    graph_iri_class = PatternIriClass(
        QUADNAMES.ExcerptGraph_iri,
        get_global_base_url() + '/data/ExcerptGraph/%d',
        None,
        ('id', Integer, False))

    # TODO: body was misused to contain the extract fragment content,
    # which should belong in the TextFragmentIdentifier,
    # whereas it was meant to be a comment on the extract
    # if used from the Web annotator. I'll have to migrate it.
    body = Column(UnicodeText, nullable=False)
    # info={'rdf': QuadMapPatternS(None, OA.hasBody)})

    discussion_id = Column(Integer, ForeignKey(
        'discussion.id', ondelete="CASCADE", onupdate="CASCADE"),
        nullable=False, index=True,
        info={'rdf': QuadMapPatternS(None, CATALYST.relevantToConversation)})
    discussion = relationship(
        Discussion, backref=backref('extracts', cascade="all, delete-orphan"),
        info={'rdf': QuadMapPatternS(None, ASSEMBL.in_conversation)})

    important = Column('important', Boolean, server_default='0')

    def extract_graph_name(self):
        from pyramid.threadlocal import get_current_registry
        reg = get_current_registry()
        host = reg.settings['public_hostname']
        return URIRef('http://%s/data/ExcerptGraph/%d' % (host, self.id))

    def extract_graph_iri(self):
        return getattr(QUADNAMES, 'extract_%d_iri' % self.id)

    @classmethod
    def special_quad_patterns(cls, alias_maker, discussion_id):
        return [
            QuadMapPatternS(
                None, OA.hasBody,
                cls.graph_iri_class.apply(cls.id),
                name=QUADNAMES.oa_hasBody,
                conditions=((cls.idea_id != None),
                            (Idea.tombstone_date == None))),
            QuadMapPatternS(
                #Content.iri_class().apply(cls.content_id),
                cls.specific_resource_iri.apply(cls.id),
                # It would be better to use CATALYST.expressesIdea,
                # but Virtuoso hates the redundancy.
                ASSEMBL.resourceExpressesIdea,
                Idea.iri_class().apply(cls.idea_id),
                name=QUADNAMES.assembl_postExtractRelatedToIdea,
                conditions=((cls.idea_id != None),
                            (Idea.tombstone_date == None)
                   # and it's a post extract... treat webpages separately.
                )),
            QuadMapPatternS(
                None, OA.hasTarget, cls.specific_resource_iri.apply(cls.id),
                name=QUADNAMES.oa_hasTarget),
            QuadMapPatternS(
                cls.specific_resource_iri.apply(cls.id),
                RDF.type, OA.SpecificResource,
                name=QUADNAMES.oa_SpecificResource_type),
            QuadMapPatternS(
                cls.specific_resource_iri.apply(cls.id),
                ASSEMBL.in_conversation,
                Discussion.iri_class().apply(cls.discussion_id),
                name=QUADNAMES.oa_SpecificResource_in_conversation),
            QuadMapPatternS(
                cls.specific_resource_iri.apply(cls.id), OA.hasSource,
                Content.iri_class().apply(cls.content_id),
                name=QUADNAMES.oa_hasSource),
            # TODO: Paths
            # QuadMapPatternS(
            #     AgentProfile.iri_class().apply((cls.content_id, Post.creator_id)),
            #     DCTERMS.contributor,
            #     Idea.iri_class().apply(cls.idea_id),
            #     name=QUADNAMES.assembl_idea_contributor,
            #     conditions=(cls.idea_id != None,)),
            ]


    annotation_text = Column(UnicodeText)

    owner_id = Column(
        Integer,
        ForeignKey('agent_profile.id'),
        nullable=False,
    )

    owner = relationship(
        'AgentProfile', foreign_keys=[owner_id], backref='extracts_owned')

    extract_source = relationship(Content, backref="extracts")
    extract_ideas = relationship(Idea, backref="extracts")

    __mapper_args__ = {
        'polymorphic_identity': 'assembl:postExtractRelatedToIdea',
    }
    @property
    def target(self):
        retval = {
                '@type': self.content.external_typename()
                }
        if isinstance(self.content, Post):
            retval['@id'] = Post.uri_generic(self.content.id)
        elif self.content.type == 'webpage':
            retval['url'] = self.content.url
        return retval

    def __repr__(self):
        r = super(Extract, self).__repr__()
        body = self.body or ""
        return r[:-1] + body[:20].encode("ascii", "ignore") + ">"

    def get_target(self):
        return self.content

    def get_post(self):
        if isinstance(self.content, Post):
            return self.content

    def infer_text_fragment(self):
        return self._infer_text_fragment_inner(
            self.content.get_title(), self.content.get_body(),
            self.get_post().id)

    def _infer_text_fragment_inner(self, title, body, post_id):
        # dead code? If not needs to be refactored with langstrings
        body = IMAPMailbox.sanitize_html(body, [])
        quote = self.body.replace("\r", "")
        try:
            # for historical reasons
            quote = quopri.decodestring(quote)
        except:
            pass
        quote = IMAPMailbox.sanitize_html(quote, [])
        if quote != self.body:
            self.body = quote
        quote = quote.replace("\n", "")
        start = body.find(quote)
        lookin = 'message-body'
        if start < 0:
            xpath = "//div[@id='%s']/div[class='post_title']" % (post_id)
            start = title.find(quote)
            if start < 0:
                return None
            lookin = 'message-subject'
        xpath = "//div[@id='message-%s']//div[@class='%s']" % (
            Post.uri_generic(post_id), lookin)
        tfi = self.db.query(TextFragmentIdentifier).filter_by(
            extract=self).first()
        if not tfi:
            tfi = TextFragmentIdentifier(extract=self)
        tfi.xpath_start = tfi.xpath_end = xpath
        tfi.offset_start = start
        tfi.offset_end = start+len(quote)
        return tfi

    def send_to_changes(self, connection=None, operation=CrudOperation.UPDATE,
                        discussion_id=None, view_def="changes"):
        """invoke the modelWatcher on creation"""
        super(Extract, self).send_to_changes(
            connection, operation, discussion_id, view_def)
        watcher = get_model_watcher()
        if operation == CrudOperation.UPDATE:
            watcher.processExtractModified(self.id, 0)  # no versions yet.
        elif operation == CrudOperation.DELETE:
            watcher.processExtractDeleted(self.id)
        elif operation == CrudOperation.CREATE:
            watcher.processExtractCreated(self.id)

    def get_discussion_id(self):
        return self.discussion_id

    @classmethod
    def get_discussion_conditions(cls, discussion_id, alias_maker=None):
        return (cls.discussion_id == discussion_id,)

    @classmethod
    def base_conditions(cls, alias=None, alias_maker=None):
        # Allow idea-less extracts
        return ()

    @classmethod
    def restrict_to_owners(cls, query, user_id):
        "filter query according to object owners"
        return query.filter(cls.owner_id == user_id)

    crud_permissions = CrudPermissions(
            P_ADD_EXTRACT, P_READ, P_EDIT_EXTRACT, P_EDIT_EXTRACT,
            P_EDIT_MY_EXTRACT, P_EDIT_MY_EXTRACT)