1 /** 2 Copyright: 2018 Mark Fisher 3 4 License: 5 Permission is hereby granted, free of charge, to any person obtaining a copy of 6 this software and associated documentation files (the "Software"), to deal in 7 the Software without restriction, including without limitation the rights to 8 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 of the Software, and to permit persons to whom the Software is furnished to do 10 so, subject to the following conditions: 11 12 The above copyright notice and this permission notice shall be included in all 13 copies or substantial portions of the Software. 14 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 SOFTWARE. 22 **/ 23 module dxx.app.platform; 24 25 private import std.exception; 26 private import std.typecons; 27 private import std.variant; 28 29 private import aermicioi.aedi; 30 31 //import hunt.cache; 32 33 private import dxx.util; 34 private import dxx.app; 35 36 private import dxx.app.component; 37 private import dxx.app.resource; 38 private import dxx.app.document; 39 private import dxx.app.workbench; 40 private import dxx.app.extension; 41 private import dxx.app.resource.impl.wsmanager; 42 43 44 //interface DocumentResourceAdaptor { 45 //DocumentType getDocType(FileResource); 46 //} 47 48 /++ 49 Methods exposed by the platform, accessible via the injector. 50 ++/ 51 interface PlatformComponents { 52 URIResolver getURIResolver(); 53 ResourceValidator getResourceValidator(); 54 ResourceContentProvider getResourceContentProvider(); 55 //DocumentResourceAdaptor getDocumentResourceAdaptor(); 56 57 public WorkflowRunner getWorkflowRunner(); 58 public PluginLoader getPluginLoader(); 59 public ExtensionsManager getExtensionsManager(); 60 //public Cache getLocalCache(); 61 } 62 63 struct PlatformJobEvent { 64 enum Status { 65 Setup,Process,Terminate 66 }; 67 Status status; 68 shared(PlatformJob) job; 69 } 70 /++ 71 This represents the state of the framework for an application. 72 The platform handles the resource workspace, loading of plugins and is 73 also a job manager. 74 ++/ 75 class DXXPlatform : SyncNotificationSource 76 { 77 static class ThreadLocal : 78 URIResolver, 79 ResourceValidator, 80 ResourceContentProvider 81 //DocumentResourceAdaptor 82 { 83 static WorkflowRunner workflowRunner; 84 //Cache localCache; 85 86 Resource resolveURI(string uri,ResourceSet owner) { 87 return null; 88 } 89 bool isValid(ResourceSet set) { 90 return true; 91 } 92 bool isValidResource(Resource res) { 93 return true; 94 } 95 void* getContent(Resource) { 96 return null; 97 } 98 override ubyte[] getContent(Resource) { 99 return []; 100 } 101 override void putContent(ubyte[],Resource) { 102 } 103 DocumentType getDocType(FileResource) { 104 return null; 105 } 106 107 WorkflowRunner getWorkflowRunner() { 108 if(workflowRunner is null) { 109 workflowRunner = new WorkflowRunner; 110 } 111 return workflowRunner; 112 } 113 /*Cache getLocalCache() { 114 if(localCache is null) { 115 localCache = CacheFectory.create(); 116 } 117 return localCache; 118 }*/ 119 } 120 static ThreadLocal _local; 121 122 static auto getLocals() { 123 if(_local is null) { 124 _local = new ThreadLocal; 125 } 126 return _local; 127 } 128 129 static __gshared DXXPlatform INSTANCE; 130 131 static 132 auto getInstance() { 133 static bool instantiated = false; 134 if(!instantiated) { 135 synchronized(DXXPlatform.classinfo) { 136 if(!INSTANCE) { 137 INSTANCE=new DXXPlatform; 138 } 139 } 140 instantiated = true; 141 } 142 return INSTANCE; 143 } 144 145 static Workspace getDefaultWorkspace() { 146 return resolveInjector!(Workspace)("app.workspace"); 147 } 148 /* static Workbench getDefaultWorkbench() { 149 return resolveInjector!(Workbench)("app.workbench"); 150 } */ 151 152 ExtensionsManager extensionsManager; 153 154 private this() { 155 extensionsManager = new _ExtensionsManager; 156 } 157 158 _PluginLoader[string] plugins; 159 160 class _PluginLoader : PluginLoader { 161 override void load(string path) { 162 super.load(path); 163 plugins[desc.id] = this; 164 } 165 } 166 PluginLoader newPluginLoader() { 167 return new _PluginLoader(); 168 } 169 170 static nothrow 171 void sendJobEvent( 172 PlatformJobEvent.Status status) 173 (shared(PlatformJob) j) 174 { 175 try { 176 PlatformJobEvent event = PlatformJobEvent(status,j); 177 auto p = cast(shared(DXXPlatform))getInstance; 178 p.send!PlatformJobEvent(&event); 179 } catch(Exception e) { 180 MsgLog.warning(e.message); 181 } 182 } 183 static void executeJob(shared(Job) job) { 184 //auto j = cast(shared(Job))job; 185 job.execute; 186 } 187 188 static void clearLocalCache() { 189 //destroy(getLocals.localCache); 190 } 191 } 192 193 /++ 194 Job that sends events to the DXXPlatform listeners. 195 ++/ 196 interface PlatformJob : Job { 197 T getProperty(T)(string id); 198 void setProperty(T)(T t,string id); 199 } 200 201 abstract class PlatformJobBase : JobBase,PlatformJob { 202 shared(Workbench) workbench; 203 Variant[string] _props; 204 205 this(Workbench w = resolveInjector!(Workbench)("app.workbench")) shared { 206 //super(); 207 workbench = cast(shared(Workbench))w; 208 } 209 this() shared { 210 //super(); 211 } 212 213 override 214 void setup() shared { 215 DXXPlatform.sendJobEvent!(PlatformJobEvent.Status.Setup)(this); 216 } 217 override 218 void terminate() shared { 219 DXXPlatform.sendJobEvent!(PlatformJobEvent.Status.Terminate)(this); 220 } 221 222 override 223 void process() shared { 224 DXXPlatform.sendJobEvent!(PlatformJobEvent.Status.Process)(this); 225 processPlatformJob(); 226 } 227 228 abstract 229 void processPlatformJob() shared; 230 231 //override 232 T getProperty(T)(string id) { 233 return _props[id].get!T; 234 } 235 //override 236 void setProperty(T)(T t,string id) { 237 _props[id] = Variant(t); 238 } 239 } 240 241 struct PluginDef { 242 public string name; 243 public string pluginVersion; 244 public string path; 245 //public string[string] properties; 246 } 247 248 struct PlatformParam { 249 PluginDef[] plugins; 250 } 251 252 alias DXXParam = Tuple!( 253 PlatformParam,"dxx" 254 ); 255 256 /++ 257 Default runtime module that exposes components for use by the injector. 258 259 260 So, for example, to access a PluginLoader: 261 ` 262 PluginLoader loader = resolveInjector!PluginLoader; 263 ` 264 ++/ 265 @component 266 class PlatformRuntime(Param...) : 267 RuntimeComponents!(Param,PlatformParam), 268 PlatformComponents { 269 270 @component 271 override URIResolver getURIResolver() { 272 return DXXPlatform.getLocals(); 273 } 274 275 @component 276 override ResourceValidator getResourceValidator() { 277 return DXXPlatform.getLocals; 278 } 279 280 @component 281 override ResourceContentProvider getResourceContentProvider() { 282 return DXXPlatform.getLocals; 283 } 284 285 //@component 286 //override DocumentResourceAdaptor getDocumentResourceAdaptor() { 287 // return Platform.getInstance(); 288 //} 289 290 @component 291 override PluginLoader getPluginLoader() { 292 return DXXPlatform.getInstance.newPluginLoader; 293 } 294 295 @component 296 public ExtensionsManager getExtensionsManager() { 297 return DXXPlatform.getInstance.extensionsManager; 298 } 299 300 @component 301 public WorkflowRunner getWorkflowRunner() { 302 return DXXPlatform.getLocals.getWorkflowRunner; 303 } 304 /*@component 305 override Cache getLocalCache() { 306 return DXXPlatform.getLocals.getLocalCache; 307 }*/ 308 309 void registerPlatformDependencies(InjectionContainer injector) { 310 WorkspaceManager w = new WorkspaceManager; 311 Workspace ws = w.workspace; 312 injector.register!(Workspace)(ws,"app.workspace"); 313 } 314 315 override void registerAppDependencies(InjectionContainer injector) { 316 super.registerAppDependencies(injector); 317 registerPlatformDependencies(injector); 318 } 319 version(unittest) { 320 alias UTParam = Tuple!( 321 string,"name", 322 uing,"age" 323 ); 324 mixin registerComponent!(PlatformRuntime!UTParam); 325 } 326 } 327 unittest { 328 WorkflowRunner runner = resolveInjector!WorkflowRunner; 329 assert(runner !is null); 330 PluginLoader loader = resolveInjector!PluginLoader; 331 assert(loader !is null); 332 }