root/galaxy-central/lib/galaxy/model/item_attrs.py @ 2

リビジョン 2, 7.6 KB (コミッタ: hatakeyama, 14 年 前)

import galaxy-central

行番号 
1from sqlalchemy.sql.expression import func
2# Cannot import galaxy.model b/c it creates a circular import graph.
3import galaxy
4import logging
5log = logging.getLogger( __name__ )
6
7class RuntimeException( Exception ):
8    pass     
9
10class UsesItemRatings:
11    """
12        Mixin for getting and setting item ratings.
13       
14        Class makes two assumptions:
15        (1) item-rating association table is named <item_class>RatingAssocation
16        (2) item-rating association table has a column with a foreign key referencing
17        item table that contains the item's id.
18    """     
19    def get_ave_item_rating_data( self, db_session, item, webapp_model=None ):
20        """ Returns the average rating for an item."""
21        if webapp_model is None:
22            webapp_model = galaxy.model
23        item_rating_assoc_class = self._get_item_rating_assoc_class( item, webapp_model=webapp_model )
24        if not item_rating_assoc_class:
25            raise RuntimeException( "Item does not have ratings: %s" % item.__class__.__name__ )
26        item_id_filter = self._get_item_id_filter_str( item, item_rating_assoc_class )
27        ave_rating = db_session.query( func.avg( item_rating_assoc_class.rating ) ).filter( item_id_filter ).scalar()
28        # Convert ave_rating to float; note: if there are no item ratings, ave rating is None.
29        if ave_rating:
30            ave_rating = float( ave_rating )
31        else:
32            ave_rating = 0
33        num_ratings = int( db_session.query( func.count( item_rating_assoc_class.rating ) ).filter( item_id_filter ).scalar() )
34        return ( ave_rating, num_ratings )
35   
36    def rate_item( self, db_session, user, item, rating, webapp_model=None ):
37        """ Rate an item. Return type is <item_class>RatingAssociation. """
38        if webapp_model is None:
39            webapp_model = galaxy.model
40        item_rating = self.get_user_item_rating( db_session, user, item, webapp_model=webapp_model )
41        if not item_rating:
42            # User has not yet rated item; create rating.
43            item_rating_assoc_class = self._get_item_rating_assoc_class( item, webapp_model=webapp_model )
44            item_rating = item_rating_assoc_class()
45            item_rating.user = user
46            item_rating.set_item( item )
47            item_rating.rating = rating
48            db_session.add( item_rating )
49            db_session.flush()
50        elif item_rating.rating != rating:
51            # User has rated item; update rating.
52            item_rating.rating = rating
53            db_session.flush()
54        return item_rating
55       
56    def get_user_item_rating( self, db_session, user, item, webapp_model=None ):
57        """ Returns user's rating for an item. Return type is <item_class>RatingAssociation. """
58        if webapp_model is None:
59            webapp_model = galaxy.model
60        item_rating_assoc_class = self._get_item_rating_assoc_class( item, webapp_model=webapp_model )
61        if not item_rating_assoc_class:
62            raise RuntimeException( "Item does not have ratings: %s" % item.__class__.__name__ )
63       
64        # Query rating table by user and item id.
65        item_id_filter = self._get_item_id_filter_str( item, item_rating_assoc_class )
66        return db_session.query( item_rating_assoc_class ).filter_by( user=user ).filter( item_id_filter ).first()
67       
68    def _get_item_rating_assoc_class( self, item, webapp_model=None ):
69        """ Returns an item's item-rating association class. """
70        if webapp_model is None:
71            webapp_model = galaxy.model
72        item_rating_assoc_class = '%sRatingAssociation' % item.__class__.__name__
73        return getattr( webapp_model, item_rating_assoc_class, None )
74
75    def _get_item_id_filter_str( self, item, item_rating_assoc_class, webapp_model=None ):
76        # Get foreign key in item-rating association table that references item table.
77        if webapp_model is None:
78            webapp_model = galaxy.model
79        item_fk = None
80        for fk in item_rating_assoc_class.table.foreign_keys:
81            if fk.references( item.table ):
82                item_fk = fk
83                break
84               
85        if not item_fk:
86            raise RuntimeException( "Cannot find item id column in item-rating association table: %s, %s" % item_rating_assoc_class.__name__, item_rating_assoc_class.table.name )
87           
88        # TODO: can we provide a better filter than a raw string?
89        return "%s=%i" % ( item_fk.parent.name, item.id )
90
91class UsesAnnotations:
92    """ Mixin for getting and setting item annotations. """
93    def get_item_annotation_str( self, db_session, user, item ):
94        """ Returns a user's annotation string for an item. """
95        annotation_obj = self.get_item_annotation_obj( db_session, user, item )
96        if annotation_obj:
97            return annotation_obj.annotation
98        return None
99       
100    def get_item_annotation_obj( self, db_session, user, item ):
101        """ Returns a user's annotation object for an item. """
102        # Get annotation association class.
103        annotation_assoc_class = self._get_annotation_assoc_class( item )
104        if not annotation_assoc_class:
105            return None
106       
107        # Get annotation association object.
108        annotation_assoc = db_session.query( annotation_assoc_class ).filter_by( user=user )
109       
110        # TODO: use filtering like that in _get_item_id_filter_str()
111        if item.__class__ == galaxy.model.History:
112            annotation_assoc = annotation_assoc.filter_by( history=item )
113        elif item.__class__ == galaxy.model.HistoryDatasetAssociation:
114            annotation_assoc = annotation_assoc.filter_by( hda=item )
115        elif item.__class__ == galaxy.model.StoredWorkflow:
116            annotation_assoc = annotation_assoc.filter_by( stored_workflow=item )
117        elif item.__class__ == galaxy.model.WorkflowStep:
118            annotation_assoc = annotation_assoc.filter_by( workflow_step=item )
119        elif item.__class__ == galaxy.model.Page:
120            annotation_assoc = annotation_assoc.filter_by( page=item )
121        elif item.__class__ == galaxy.model.Visualization:
122            annotation_assoc = annotation_assoc.filter_by( visualization=item )
123        return annotation_assoc.first()
124       
125    def add_item_annotation( self, db_session, user, item, annotation ):
126        """ Add or update an item's annotation; a user can only have a single annotation for an item. """
127        # Get/create annotation association object.
128        annotation_assoc = self.get_item_annotation_obj( db_session, user, item )
129        if not annotation_assoc:
130            annotation_assoc_class = self._get_annotation_assoc_class( item )
131            if not annotation_assoc_class:
132                return None
133            annotation_assoc = annotation_assoc_class()
134            item.annotations.append( annotation_assoc )
135            annotation_assoc.user = user
136        # Set annotation.
137        annotation_assoc.annotation = annotation
138        return annotation_assoc
139       
140    def copy_item_annotation( self, db_session, source_user, source_item, target_user, target_item ):
141        """ Copy an annotation from a user/item source to a user/item target. """
142        if source_user and target_user:
143            annotation_str = self.get_item_annotation_str( db_session, source_user, source_item )
144            if annotation_str:
145                annotation = self.add_item_annotation( db_session, target_user, target_item, annotation_str )
146                return annotation
147        return None
148       
149    def _get_annotation_assoc_class( self, item ):
150        """ Returns an item's item-annotation association class. """
151        class_name = '%sAnnotationAssociation' % item.__class__.__name__
152        return getattr( galaxy.model, class_name, None )
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。