TaskManager.cs :  » Web-Frameworks » Ingenious-MVC » Ingenious » Mvc » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Web Frameworks » Ingenious MVC 
Ingenious MVC » Ingenious » Mvc » TaskManager.cs
#region License

/**
 * Ingenious MVC : An MVC framework for .NET 2.0
 * Copyright (C) 2006, JDP Group
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * Authors: - Kent Boogaart (kentcb@internode.on.net)
 */

#endregion

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Threading;
using Ingenious.Mvc.Configuration;
using Ingenious.Mvc.Factories;
using Ingenious.Mvc.Util;

namespace Ingenious.Mvc{
  /// <include file='TaskManager.doc.xml' path='/doc/member[@name="T:TaskManager"]/*'/>
  [Serializable]
  public sealed class TaskManager
  {
    private ConfigurationInfo _configuration;
    private Task _activeTask;
    private IDictionary<Id<Task>, TaskInfo> _taskCache;
    private IDictionary<Id<IViewManager>, IViewManager> _viewManagerCache;
    [NonSerialized]
    private ReaderWriterLock _taskCacheLock;
    [NonSerialized]
    private ReaderWriterLock _viewManagerCacheLock;

    private static readonly TaskManager _instance = new TaskManager();
    private static readonly Log _log = Log.CreateForType(typeof(TaskManager));

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="P:ConfigurationInfo"]/*'/>
    public ConfigurationInfo ConfigurationInfo
    {
      get
      {
        return _configuration;
      }
      set
      {
        _configuration = value;
      }
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="P:Tasks"]/*'/>
    public IList<Task> Tasks
    {
      get
      {
        IList<Task> retVal = new List<Task>();
        _taskCacheLock.AcquireReaderLock(Timeout.Infinite);

        try
        {
          foreach (TaskInfo taskInfo in _taskCache.Values)
          {
            retVal.Add(taskInfo.Task);
          }
        }
        finally
        {
          _taskCacheLock.ReleaseReaderLock();
        }

        return retVal;
      }
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="P:ActiveTask"]/*'/>
    public Task ActiveTask
    {
      get
      {
        return _activeTask;
      }
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="P:Instance"]/*'/>
    public static TaskManager Instance
    {
      get
      {
        return _instance;
      }
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="E:TaskStarting"]/*'/>
    [field: NonSerialized]
    public event EventHandler<TaskEventArgs> TaskStarting;

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="E:TaskStarted"]/*'/>
    [field: NonSerialized]
    public event EventHandler<TaskEventArgs> TaskStarted;

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="E:TaskEnding"]/*'/>
    [field: NonSerialized]
    public event EventHandler<TaskEndingEventArgs> TaskEnding;

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="E:TaskEnded"]/*'/>
    [field: NonSerialized]
    public event EventHandler<TaskEventArgs> TaskEnded;

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="M:.ctor()"]/*'/>
    public TaskManager()
    {
      _viewManagerCache = new Dictionary<Id<IViewManager>, IViewManager>();
      _viewManagerCacheLock = new ReaderWriterLock();
      _taskCache = new Dictionary<Id<Task>, TaskInfo>();
      _taskCacheLock = new ReaderWriterLock();
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="M:StartTask(Ingenious.Mvc.Id`1)"]/*'/>
    public Task StartTask(Id<INavigator> navigatorId)
    {
      return StartTask(navigatorId, null, null);
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="M:StartTask(Ingenious.Mvc.Id`1,System.Object)"]/*'/>
    public Task StartTask(Id<INavigator> navigatorId, object data)
    {
      return StartTask(navigatorId, data, null);
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="M:StartTask(Ingenious.Mvc.Id`1,System.Object,System.Object)"]/*'/>
    public Task StartTask(Id<INavigator> navigatorId, object data, object viewData)
    {
      ArgumentHelper.AssertNotEmpty(navigatorId, "navigatorId");
      _log.Information("Starting task for navigator with ID '{0}'.", navigatorId);
      ConfigurationInfo configurationInfo = ConfigurationInfo;
      //make sure we have some configuration to work with
      ExceptionHelper.ThrowIf(configurationInfo == null, "StartTask.noConfiguration");
      //try and get an Navigator instance from the configuration
      Debug.Assert(configurationInfo.NavigatorInfos != null);
      NavigatorInfo navigatorInfo = configurationInfo.NavigatorInfos[navigatorId];
      //make sure we have the navigator info and the view manager info
      ExceptionHelper.ThrowIf(navigatorInfo == null, "StartTask.navigatorNotFound", navigatorId);
      ExceptionHelper.ThrowIf(navigatorInfo.ViewManagerInfo == null, "StartTask.viewManagerNotSpecified", navigatorId);
      Debug.Assert(configurationInfo.ViewManagerFactory != null);
      //get the view manager from the cache
      IViewManager viewManager = GetViewManager(navigatorInfo.ViewManagerInfo, configurationInfo, navigatorInfo.Id);
      //try and get an INavigator instance from the configured navigator factory
      Debug.Assert(configurationInfo.NavigatorFactory != null);
      //create the task details
      Task task = _configuration.TaskFactory.Create(ActiveTask, GetNewTaskId(), this, data);
      //create the INavigator instance
      INavigator navigator = configurationInfo.NavigatorFactory.Create(navigatorInfo, task, viewManager);
      //make sure the navigator was created and it specifies a starting view
      ExceptionHelper.ThrowIf(navigator == null, "StartTask.navigatorFactoryFailed", navigatorId);
      ExceptionHelper.ThrowIf(navigator.StartingViewId.IsEmpty, "StartTask.startingViewNotSpecified", navigatorId);

      AddTaskToCache(task, navigator, viewManager);

      _log.Verbose("Navigating to starting view with ID '{0}'.", navigator.StartingViewId);
      //navigate to the first view in the navigator
      navigator.NavigateTo(navigator.StartingViewId, viewData);
      //attach to the task to bubble up events
      AttachToTask(task);
      //ask the task to start
      task.Start();

      return task;
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="M:GetViewManager(Ingenious.Mvc.Id`1)"]/*'/>
    public IViewManager GetViewManager(Id<IViewManager> viewManagerId)
    {
      ArgumentHelper.AssertNotEmpty(viewManagerId, "viewManagerId");
      _viewManagerCacheLock.AcquireReaderLock(Timeout.Infinite);

      try
      {
        if (_viewManagerCache.ContainsKey(viewManagerId))
        {
          return _viewManagerCache[viewManagerId];
        }
      }
      finally
      {
        _viewManagerCacheLock.ReleaseReaderLock();
      }

      return null;
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="M:GetViewManagerForTask(Ingenious.Mvc.Task)"]/*'/>
    public IViewManager GetViewManagerForTask(Task task)
    {
      ArgumentHelper.AssertNotNull(task, "task");
      _taskCacheLock.AcquireReaderLock(Timeout.Infinite);

      try
      {
        ExceptionHelper.ThrowIf(!_taskCache.ContainsKey(task.Id), "GetViewManagerForTask.taskNotFound", task.Id);
        return _taskCache[task.Id].ViewManager;
      }
      finally
      {
        _taskCacheLock.ReleaseReaderLock();
      }
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="M:GetControllerForTask(Ingenious.Mvc.Task,Ingenious.Mvc.Configuration.ControllerInfo,Ingenious.Mvc.IControllerFactory)"]/*'/>
    public IController GetControllerForTask(Task task, ControllerInfo controllerInfo, IControllerFactory controllerFactory)
    {
      ArgumentHelper.AssertNotNull(task, "task");
      ArgumentHelper.AssertNotNull(controllerFactory, "controllerFactory");
      _taskCacheLock.AcquireReaderLock(Timeout.Infinite);

      try
      {
        ExceptionHelper.ThrowIf(!_taskCache.ContainsKey(task.Id), "GetControllerForTask.taskNotFound", task.Id);
        TaskInfo taskInfo = _taskCache[task.Id];
        //found the task information - now look for controller with required ID
        IController retVal = null;
        
        if (controllerInfo != null)
        {
          taskInfo.Controllers.TryGetValue(controllerInfo.Id, out retVal);
        }

        if ((retVal == null) && (controllerInfo != null))
        {
          //need to write to cache (probably) so get writer lock
          LockCookie lockCookie = _taskCacheLock.UpgradeToWriterLock(Timeout.Infinite);

          try
          {
            //other threads may have written to the cache before we obtained the writer lock so re-check the cache
            taskInfo.Controllers.TryGetValue(controllerInfo.Id, out retVal);

            if (retVal == null)
            {
              retVal = controllerFactory.Create(controllerInfo, task, taskInfo.Navigator);
              //add the created controller to the cache
              taskInfo.Controllers[controllerInfo.Id] = retVal;
            }
          }
          finally
          {
            //finished writing so release
            _taskCacheLock.DowngradeFromWriterLock(ref lockCookie);
          }
        }

        return retVal;
      }
      finally
      {
        _taskCacheLock.ReleaseReaderLock();
      }
    }

    /// <include file='TaskManager.doc.xml' path='/doc/member[@name="M:GetNavigatorForTask(Ingenious.Mvc.Task)"]/*'/>
    public INavigator GetNavigatorForTask(Task task)
    {
      ArgumentHelper.AssertNotNull(task, "task");
      _taskCacheLock.AcquireReaderLock(Timeout.Infinite);

      try
      {
        ExceptionHelper.ThrowIf(!_taskCache.ContainsKey(task.Id), "GetNavigatorForTask.taskNotFound", task.Id);
        return _taskCache[task.Id].Navigator;
      }
      finally
      {
        _taskCacheLock.ReleaseReaderLock();
      }
    }

    private IViewManager GetViewManager(ViewManagerInfo viewManagerInfo, ConfigurationInfo configurationInfo, Id<INavigator> navigatorId)
    {
      _viewManagerCacheLock.AcquireReaderLock(Timeout.Infinite);

      try
      {
        IViewManager retVal;
        _viewManagerCache.TryGetValue(viewManagerInfo.Id, out retVal);

        if (retVal == null)
        {
          //need to write to cache (probably) so get writer lock
          LockCookie lockCookie = _viewManagerCacheLock.UpgradeToWriterLock(Timeout.Infinite);

          try
          {
            //other threads may have written to the cache before we obtained the writer lock so re-check the cache
            _viewManagerCache.TryGetValue(viewManagerInfo.Id, out retVal);

            if (retVal == null)
            {
              retVal = configurationInfo.ViewManagerFactory.Create(viewManagerInfo, this);
              ExceptionHelper.ThrowIf(retVal == null, "GetViewManager.viewManagerFactoryFailed", navigatorId);
              retVal.ViewActivated += new EventHandler<ViewEventArgs>(retVal_ViewActivated);
              //store in cache for next time
              _viewManagerCache[viewManagerInfo.Id] = retVal;
            }
          }
          finally
          {
            //finished writing so release
            _viewManagerCacheLock.DowngradeFromWriterLock(ref lockCookie);
          }
        }

        Debug.Assert(retVal != null);
        return retVal;
      }
      finally
      {
        _viewManagerCacheLock.ReleaseReaderLock();
      }
    }

    private static string GetNewTaskId()
    {
      return Guid.NewGuid().ToString();
    }

    private void AddTaskToCache(Task task, INavigator navigator, IViewManager viewManager)
    {
      Debug.Assert(task != null);
      Debug.Assert(navigator != null);
      Debug.Assert(navigator.Task.Id == task.Id);
      Debug.Assert(viewManager != null);
      _taskCacheLock.AcquireWriterLock(Timeout.Infinite);

      try
      {
        ExceptionHelper.ThrowIf(_taskCache.ContainsKey(task.Id), "AddTaskToCache.taskAlreadyAdded", navigator.Task.Id, navigator.Id);
        //ensure we bubble up events
        AttachToTask(task);
        _taskCache[task.Id] = new TaskInfo(task, navigator, viewManager);
        _log.Verbose("Added task with ID '{0}' to task cache.", task.Id);
      }
      finally
      {
        _taskCacheLock.ReleaseWriterLock();
      }
    }

    private void RemoveTask(Task task)
    {
      Debug.Assert(task != null);
      Debug.Assert(task.State == TaskState.Ended);
      _taskCacheLock.AcquireWriterLock(Timeout.Infinite);

      try
      {
        //ensure we no longer bubble up events for this task
        DetachFromTask(task);
        //remove the task from the cache
        _taskCache.Remove(task.Id);
        _log.Verbose("Removed task with ID '{0}' from task cache.", task.Id);
      }
      finally
      {
        _taskCacheLock.ReleaseWriterLock();
      }
    }

    private void AttachToTask(Task task)
    {
      task.Starting += task_Starting;
      task.Started += task_Started;
      task.Ending += task_Ending;
      task.Ended += task_Ended;
    }

    private void DetachFromTask(Task task)
    {
      task.Starting -= task_Starting;
      task.Started -= task_Started;
      task.Ending -= task_Ending;
      task.Ended -= task_Ended;
    }

    private void OnTaskStarting(TaskEventArgs e)
    {
      EventHelper.Raise(TaskStarting, this, e);
    }

    private void OnTaskStarted(TaskEventArgs e)
    {
      EventHelper.Raise(TaskStarted, this, e);
    }

    private void OnTaskEnding(TaskEndingEventArgs e)
    {
      EventHelper.Raise(TaskEnding, this, e);
    }

    private void OnTaskEnded(TaskEventArgs e)
    {
      EventHelper.Raise(TaskEnded, this, e);
    }

    private void task_Starting(object sender, TaskEventArgs e)
    {
      OnTaskStarting(e);
    }

    private void task_Started(object sender, TaskEventArgs e)
    {
      OnTaskStarted(e);
    }

    private void task_Ending(object sender, TaskEndingEventArgs e)
    {
      OnTaskEnding(e);
    }

    private void task_Ended(object sender, TaskEventArgs e)
    {
      RemoveTask(e.Task);
      OnTaskEnded(e);
    }

    private void retVal_ViewActivated(object sender, ViewEventArgs e)
    {
      _activeTask = e.View.Task;
    }

    [OnDeserialized]
    private void OnDeserialized(StreamingContext context)
    {
      //recreate locks
      _viewManagerCacheLock = new ReaderWriterLock();
      _taskCacheLock = new ReaderWriterLock();
    }

    [Serializable]
    private sealed class TaskInfo
    {
      private Task _task;
      private INavigator _navigator;
      private IViewManager _viewManager;
      private IDictionary<Id<IController>, IController> _controllers;

      public Task Task
      {
        get
        {
          return _task;
        }
      }

      public INavigator Navigator
      {
        get
        {
          return _navigator;
        }
      }

      public IViewManager ViewManager
      {
        get
        {
          return _viewManager;
        }
      }

      public IDictionary<Id<IController>, IController> Controllers
      {
        get
        {
          return _controllers;
        }
      }

      public TaskInfo(Task task, INavigator navigator, IViewManager viewManager)
      {
        _task = task;
        _navigator = navigator;
        _viewManager = viewManager;
        _controllers = new Dictionary<Id<IController>, IController>();
      }
    }
  }
}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.