root/galaxy-central/lib/galaxy/datatypes/display_applications/application.py @ 2

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

import galaxy-central

行番号 
1#Contains objects for using external display applications
2from galaxy.util import parse_xml, string_as_bool
3from galaxy.util.odict import odict
4from galaxy.util.template import fill_template
5from galaxy.web import url_for
6from parameters import DisplayApplicationParameter, DEFAULT_DATASET_NAME
7from urllib import quote_plus
8from util import encode_dataset_user
9from copy import deepcopy
10
11#Any basic functions that we want to provide as a basic part of parameter dict should be added to this dict
12BASE_PARAMS = { 'qp': quote_plus, 'url_for':url_for } #url_for has route memory...
13
14class DisplayApplicationLink( object ):
15    @classmethod
16    def from_elem( cls, elem, display_application, other_values = None ):
17        rval = DisplayApplicationLink( display_application )
18        rval.id = elem.get( 'id', None )
19        assert rval.id, 'Link elements require a id.'
20        rval.name = elem.get( 'name', rval.id )
21        rval.url = elem.find( 'url' )
22        assert rval.url is not None, 'A url element must be provided for link elements.'
23        rval.other_values = other_values
24        rval.filters = elem.findall( 'filter' )
25        for param_elem in elem.findall( 'param' ):
26            param = DisplayApplicationParameter.from_elem( param_elem, rval )
27            assert param, 'Unable to load parameter from element: %s' % param_elem
28            rval.parameters[ param.name ] = param
29            rval.url_param_name_map[ param.url ] = param.name
30        return rval
31    def __init__( self, display_application ):
32        self.display_application = display_application
33        self.parameters = odict() #parameters are populated in order, allowing lower listed ones to have values of higher listed ones
34        self.url_param_name_map = {}
35        self.url = None
36        self.id = None
37        self.name = None
38    def get_display_url( self, data, trans ):
39        dataset_hash, user_hash = encode_dataset_user( trans, data, None )
40        return url_for( controller = '/dataset', action = "display_application", dataset_id = dataset_hash, user_id = user_hash, app_name = self.display_application.id, link_name = self.id, app_action = None )
41    def get_inital_values( self, data, trans ):
42        if self.other_values:
43            rval = odict( self.other_values )
44        else:
45            rval = odict()
46        rval.update( { 'BASE_URL': trans.request.base, 'APP': trans.app } ) #trans automatically appears as a response, need to add properties of trans that we want here
47        for key, value in  BASE_PARAMS.iteritems(): #add helper functions/variables
48            rval[ key ] = value
49        rval[ DEFAULT_DATASET_NAME ] = data #always have the display dataset name available
50        return rval
51    def build_parameter_dict( self, data, dataset_hash, user_hash, trans ):
52        other_values = self.get_inital_values( data, trans )
53        other_values[ 'DATASET_HASH' ] = dataset_hash
54        other_values[ 'USER_HASH' ] = user_hash
55        for name, param in self.parameters.iteritems():
56            assert name not in other_values, "The display parameter '%s' has been defined more than once." % name
57            if param.ready( other_values ):
58                other_values[ name ] = param.get_value( other_values, dataset_hash, user_hash, trans )#subsequent params can rely on this value
59            else:
60                other_values[ name ] = None
61                return False, other_values #need to stop here, next params may need this value
62        return True, other_values #we built other_values, lets provide it as well, or else we will likely regenerate it in the next step
63    def filter_by_dataset( self, data, trans ):
64        context = self.get_inital_values( data, trans )
65        for filter_elem in self.filters:
66            if fill_template( filter_elem.text, context = context ) != filter_elem.get( 'value', 'True' ):
67                return False
68        return True
69
70class DynamicDisplayApplicationBuilder( object ):
71    @classmethod
72    def __init__( self, elem, display_application ):
73        rval = []
74        filename = elem.get( 'from_file', None )
75        assert filename is not None, 'Filename and id attributes required for dynamic_links'
76        skip_startswith = elem.get( 'skip_startswith', None )
77        separator = elem.get( 'separator', '\t' )
78        id_col = int( elem.get( 'id', None ) )
79        name_col = int( elem.get( 'name', id_col ) )
80        dynamic_params = {}
81        max_col = max( id_col, name_col )
82        for dynamic_param in elem.findall( 'dynamic_param' ):
83            name = dynamic_param.get( 'name' )
84            value = int( dynamic_param.get( 'value' ) )
85            split = string_as_bool( dynamic_param.get( 'split', False ) )
86            param_separator =  dynamic_param.get( 'separator', ',' )
87            max_col = max( max_col, value )
88            dynamic_params[name] = { 'column': value, 'split': split, 'separator': param_separator }
89        for line in open( filename ):
90            if not skip_startswith or not line.startswith( skip_startswith ):
91                line = line.rstrip( '\n\r' )
92                fields = line.split( separator )
93                if len( fields ) >= max_col:
94                    new_elem = deepcopy( elem )
95                    new_elem.set( 'id', fields[id_col] )
96                    new_elem.set( 'name', fields[name_col] )
97                    dynamic_values = {}
98                    for key, attributes in dynamic_params.iteritems():
99                        value = fields[ attributes[ 'column' ] ]
100                        if attributes['split']:
101                            value = value.split( attributes['separator'] )
102                        dynamic_values[key] = value
103                    #now populate
104                    rval.append( DisplayApplicationLink.from_elem( new_elem, display_application, other_values = dynamic_values ) )
105        self.links = rval
106    def __iter__( self ):
107        return iter( self.links )
108
109class PopulatedDisplayApplicationLink( object ):
110    def __init__( self, display_application_link, data, dataset_hash, user_hash, trans ):
111        self.link = display_application_link
112        self.data = data
113        self.dataset_hash = dataset_hash
114        self.user_hash = user_hash
115        self.trans = trans
116        self.ready, self.parameters = self.link.build_parameter_dict( self.data, self.dataset_hash, self.user_hash, trans )
117    def display_ready( self ):
118        return self.ready
119    def get_param_value( self, name ):
120        value = None
121        if self.ready:
122            value = self.parameters.get( name, None )
123            assert value, 'Unknown parameter requested'
124        return value
125    def preparing_display( self ):
126        if not self.ready:
127            return self.link.parameters[ self.parameters.keys()[ -1 ] ].is_preparing( self.parameters )
128        return False
129    def prepare_display( self ):
130        if not self.ready and not self.preparing_display():
131            other_values = self.parameters
132            for name, param in self.link.parameters.iteritems():
133                if other_values.keys()[ -1 ] == name: #found last parameter to be populated
134                    value = param.prepare( other_values, self.dataset_hash, self.user_hash, self.trans )
135                    if value is None:
136                        return #we can go no further until we have a value for this parameter
137                    other_values[ name ] = value
138    def display_url( self ):
139        assert self.display_ready(), 'Display is not yet ready, cannot generate display link'
140        return fill_template( self.link.url.text, context = self.parameters )
141    def get_param_name_by_url( self, url ):
142        for name, parameter in self.link.parameters.iteritems():
143            if parameter.build_url( self.parameters ) == url:
144                return name
145        raise ValueError( "Unknown URL parameter name provided: %s" % url )
146
147class DisplayApplication( object ):
148    @classmethod
149    def from_file( cls, filename, datatypes_registry ):
150        return cls.from_elem( parse_xml( filename ).getroot(), datatypes_registry )
151    @classmethod
152    def from_elem( cls, elem, datatypes_registry ):
153        display_id = elem.get( 'id', None )
154        assert display_id, "ID tag is required for a Display Application"
155        name = elem.get( 'name', display_id )
156        version = elem.get( 'version', None )
157        rval = DisplayApplication( display_id, name, datatypes_registry, version )
158        for link_elem in elem.findall( 'link' ):
159            link = DisplayApplicationLink.from_elem( link_elem, rval )
160            if link:
161                rval.links[ link.id ] = link
162        for dynamic_links in elem.findall( 'dynamic_links' ):
163            for link in DynamicDisplayApplicationBuilder( dynamic_links, rval ):
164                rval.links[ link.id ] = link
165        return rval
166    def __init__( self, display_id, name, datatypes_registry, version = None ):
167        self.id = display_id
168        self.name = name
169        self.datatypes_registry = datatypes_registry
170        if version is None:
171            version = "1.0.0"
172        self.version = version
173        self.links = odict()
174    def get_link( self, link_name, data, dataset_hash, user_hash, trans ):
175        #returns a link object with data knowledge to generate links
176        return PopulatedDisplayApplicationLink( self.links[ link_name ], data, dataset_hash, user_hash, trans )
177    def filter_by_dataset( self, data, trans ):
178        filtered = DisplayApplication( self.id, self.name, self.datatypes_registry, version = self.version )
179        for link_name, link_value in self.links.iteritems():
180            if link_value.filter_by_dataset( data, trans ):
181                filtered.links[link_name] = link_value
182        return filtered
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。