1 /******************************************************************************* 2 3 Mixin for classes that support extensions. 4 5 Copyright: 6 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 7 All rights reserved. 8 9 License: 10 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 11 Alternatively, this file may be distributed under the terms of the Tango 12 3-Clause BSD License (see LICENSE_BSD.txt for details). 13 14 *******************************************************************************/ 15 16 module ocean.util.app.model.ExtensibleClassMixin; 17 18 /******************************************************************************* 19 20 Mixin for classes that support extensions. 21 22 It just provides a simple container for extensions (ordered in the order 23 provided by BaseExtension.order()) registering of extensions, and getting an 24 extension based on its type. 25 26 Typical usage: 27 28 --- 29 30 interface ISomeExtension : IExtension 31 { 32 void someMethod ( ); 33 } 34 35 class SomeExtensibleClass 36 { 37 mixin ExtensibleClassMixin!(ISomeExtension); 38 39 void something ( ) 40 { 41 foreach (ext; this.extensions) 42 { 43 ext.someMethod(); 44 } 45 } 46 } 47 48 --- 49 50 TODO: Assert that ExtensionClass is derived from IExtension 51 52 *******************************************************************************/ 53 54 template ExtensibleClassMixin ( ExtensionClass ) 55 { 56 57 /******************************************************************************* 58 59 Unfortunatelly template mixins needs to have all the symbols they use 60 available in the code making the mixing. For that reason, symbols 61 needed by this template are made public inside the template as the less 62 ugly solution. The class namespace will be polluted with the import 63 symbols but nothing else. The symbols imported are prepended with 64 mixin_ to make clear where they came from and to avoid accidental name 65 clashing. 66 67 *******************************************************************************/ 68 69 import ocean.core.Array : mixin_sort = sort; 70 71 72 /*************************************************************************** 73 74 List of extensions. Will be kept sorted by extension order when using 75 the registerExtension() method. 76 77 ***************************************************************************/ 78 79 ExtensionClass[] extensions; 80 81 82 /*************************************************************************** 83 84 Register a new extension, keeping extensions list sorted. 85 86 Extensions are considered unique by type, so is invalid to register 87 2 extensions with the exact same type. 88 89 Params: 90 ext = new extension to register 91 92 ***************************************************************************/ 93 94 public void registerExtension ( ExtensionClass ext ) 95 { 96 // TODO: Assert that we don't already have an extension of the same type 97 98 this.extensions ~= ext; 99 mixin_sort(this.extensions, 100 ( ExtensionClass e1, ExtensionClass e2 ) 101 { 102 return e1.order < e2.order; 103 }); 104 } 105 106 107 /*************************************************************************** 108 109 Get an extension based on its type. 110 111 Returns: 112 the instance of the extension of the type Ext, or null if not found 113 114 ***************************************************************************/ 115 116 public Ext getExtension ( Ext ) ( ) 117 { 118 // TODO: Assert that Ext is derived from ExtensionClass 119 foreach (e; this.extensions) 120 { 121 Ext ext = cast(Ext) e; 122 if ( ext !is null ) 123 { 124 return ext; 125 } 126 } 127 128 return null; 129 } 130 131 } 132