1919package static
2020
2121import (
22+ "container/heap"
2223 "context"
2324 "fmt"
25+ "strconv"
2426 "strings"
2527 "sync"
2628
@@ -37,6 +39,8 @@ func init() {
3739 registry .Register ("static" , New )
3840}
3941
42+ const defaultPriority = 0
43+
4044type mimeTypeConfig struct {
4145 MimeType string `mapstructure:"mime_type"`
4246 Extension string `mapstructure:"extension"`
@@ -45,9 +49,7 @@ type mimeTypeConfig struct {
4549 Icon string `mapstructure:"icon"`
4650 DefaultApp string `mapstructure:"default_app"`
4751 AllowCreation bool `mapstructure:"allow_creation"`
48- // apps keeps the Providers able to open this mime type.
49- // the list will always keep the default AppProvider at the head
50- apps []* registrypb.ProviderInfo
52+ apps providerHeap
5153}
5254
5355type config struct {
@@ -122,7 +124,7 @@ func New(m map[string]interface{}) (app.Registry, error) {
122124func unregisterProvider (p * registrypb.ProviderInfo , mime * mimeTypeConfig ) {
123125 if index , in := getIndex (mime .apps , p ); in {
124126 // remove the provider from the list
125- mime . apps = append ( mime .apps [: index ], mime . apps [ index + 1 :] ... )
127+ heap . Remove ( & mime .apps , index )
126128 }
127129}
128130
@@ -131,11 +133,21 @@ func registerProvider(p *registrypb.ProviderInfo, mime *mimeTypeConfig) {
131133 // so we will remove it
132134 unregisterProvider (p , mime )
133135
134- if providerIsDefaultForMimeType (p , mime ) {
135- mime .apps = prependProvider (p , mime .apps )
136- } else {
137- mime .apps = append (mime .apps , p )
136+ heap .Push (& mime .apps , providerWithPriority {
137+ provider : p ,
138+ priority : getPriority (p ),
139+ })
140+ }
141+
142+ func getPriority (p * registrypb.ProviderInfo ) uint64 {
143+ if p .Opaque != nil && len (p .Opaque .Map ) != 0 {
144+ if priority , ok := p .Opaque .Map ["priority" ]; ok {
145+ if pr , err := strconv .ParseUint (string (priority .GetValue ()), 10 , 64 ); err == nil {
146+ return pr
147+ }
148+ }
138149 }
150+ return defaultPriority
139151}
140152
141153func (m * manager ) FindProviders (ctx context.Context , mimeType string ) ([]* registrypb.ProviderInfo , error ) {
@@ -160,15 +172,11 @@ func (m *manager) FindProviders(ctx context.Context, mimeType string) ([]*regist
160172 mimeMatch := mimeInterface .(* mimeTypeConfig )
161173 var providers = make ([]* registrypb.ProviderInfo , 0 , len (mimeMatch .apps ))
162174 for _ , p := range mimeMatch .apps {
163- providers = append (providers , m .providers [p .Address ])
175+ providers = append (providers , m .providers [p .provider . Address ])
164176 }
165177 return providers , nil
166178}
167179
168- func providerIsDefaultForMimeType (p * registrypb.ProviderInfo , mime * mimeTypeConfig ) bool {
169- return p .Address == mime .DefaultApp || p .Name == mime .DefaultApp
170- }
171-
172180func (m * manager ) AddProvider (ctx context.Context , p * registrypb.ProviderInfo ) error {
173181 m .Lock ()
174182 defer m .Unlock ()
@@ -232,7 +240,7 @@ func (m *manager) ListSupportedMimeTypes(ctx context.Context) ([]*registrypb.Mim
232240 Name : mime .Name ,
233241 Description : mime .Description ,
234242 Icon : mime .Icon ,
235- AppProviders : mime .apps ,
243+ AppProviders : mime .apps . getOrderedProviderByPriority () ,
236244 AllowCreation : mime .AllowCreation ,
237245 DefaultApplication : mime .DefaultApp ,
238246 })
@@ -242,17 +250,17 @@ func (m *manager) ListSupportedMimeTypes(ctx context.Context) ([]*registrypb.Mim
242250 return res , nil
243251}
244252
245- // prepend an AppProvider obj to the list
246- func prependProvider ( n * registrypb.ProviderInfo , lst [] * registrypb. ProviderInfo ) [] * registrypb. ProviderInfo {
247- lst = append ( lst , & registrypb. ProviderInfo {})
248- copy ( lst [ 1 :], lst )
249- lst [ 0 ] = n
250- return lst
253+ func ( h providerHeap ) getOrderedProviderByPriority () [] * registrypb. ProviderInfo {
254+ providers := make ([] * registrypb.ProviderInfo , 0 , h . Len ())
255+ for _ , pp := range h {
256+ providers = append ( providers , pp . provider )
257+ }
258+ return providers
251259}
252260
253- func getIndex (lst [] * registrypb. ProviderInfo , s * registrypb.ProviderInfo ) (int , bool ) {
254- for i , e := range lst {
255- if equalsProviderInfo (e , s ) {
261+ func getIndex (h providerHeap , s * registrypb.ProviderInfo ) (int , bool ) {
262+ for i , e := range h {
263+ if equalsProviderInfo (e . provider , s ) {
256264 return i , true
257265 }
258266 }
@@ -268,15 +276,7 @@ func (m *manager) SetDefaultProviderForMimeType(ctx context.Context, mimeType st
268276 mime := mimeInterface .(* mimeTypeConfig )
269277 mime .DefaultApp = p .Address
270278
271- if index , in := getIndex (mime .apps , p ); in {
272- // the element is in the list, we will remove it
273- // TODO (gdelmont): not the best way to remove an element from a slice
274- // but maybe we want to keep the order?
275- mime .apps = append (mime .apps [:index ], mime .apps [index + 1 :]... )
276- }
277- // prepend it to the front of the list
278- mime .apps = prependProvider (p , mime .apps )
279-
279+ registerProvider (p , mime )
280280 } else {
281281 // the mime type should be already registered as config in the AppRegistry
282282 // we will create a new entry fot the mimetype, but leaving a warning for
@@ -288,9 +288,17 @@ func (m *manager) SetDefaultProviderForMimeType(ctx context.Context, mimeType st
288288}
289289
290290func dummyMimeType (m string , apps []* registrypb.ProviderInfo ) * mimeTypeConfig {
291+ appsHeap := providerHeap {}
292+ for _ , p := range apps {
293+ heap .Push (& appsHeap , providerWithPriority {
294+ provider : p ,
295+ priority : getPriority (p ),
296+ })
297+ }
298+
291299 return & mimeTypeConfig {
292300 MimeType : m ,
293- apps : apps ,
301+ apps : appsHeap ,
294302 //Extension: "", // there is no meaningful general extension, so omit it
295303 //Name: "", // there is no meaningful general name, so omit it
296304 //Description: "", // there is no meaningful general description, so omit it
@@ -337,3 +345,33 @@ func providersEquals(l1, l2 []*registrypb.ProviderInfo) bool {
337345 }
338346 return true
339347}
348+
349+ type providerWithPriority struct {
350+ provider * registrypb.ProviderInfo
351+ priority uint64
352+ }
353+
354+ type providerHeap []providerWithPriority
355+
356+ func (h providerHeap ) Len () int {
357+ return len (h )
358+ }
359+
360+ func (h providerHeap ) Less (i , j int ) bool {
361+ return h [i ].priority > h [j ].priority
362+ }
363+
364+ func (h providerHeap ) Swap (i , j int ) {
365+ h [i ], h [j ] = h [j ], h [i ]
366+ }
367+
368+ func (h * providerHeap ) Push (x interface {}) {
369+ * h = append (* h , x .(providerWithPriority ))
370+ }
371+
372+ func (h * providerHeap ) Pop () interface {} {
373+ last := len (* h ) - 1
374+ x := (* h )[last ]
375+ * h = (* h )[:last ]
376+ return x
377+ }
0 commit comments