CreateWorkspace activity
My CreateWorkspace activity has several properties: the Groove identity in which the workspace will be created; the name of the new workspace; the path to find the workspace template; and (for other activities to consume) the actual workspace which was created. So my activity class code looks like this:
namespace GrooveActivitiesLibrary
{
[ToolboxBitmapAttribute(typeof(CreateWorkspace), "Resources.GrooveLogo.png")]
public partial class CreateWorkspace : Activity
{
// Properties definition
public static DependencyProperty GrooveIdentityProperty = DependencyProperty.Register("GrooveIdentity", typeof(GrvIdentity), typeof(GrooveActivitiesLibrary.CreateWorkspace));
public static DependencyProperty WorkspaceNameProperty = DependencyProperty.Register("WorkspaceName", typeof(string), typeof(GrooveActivitiesLibrary.CreateWorkspace));
public static DependencyProperty TemplatePathProperty = DependencyProperty.Register("TemplatePath", typeof(System.String), typeof(GrooveActivitiesLibrary.CreateWorkspace));
public static DependencyProperty GrooveSpaceProperty = DependencyProperty.Register("GrooveSpace", typeof(GrvSpace), typeof(GrooveActivitiesLibrary.CreateWorkspace));
public CreateWorkspace()
{
InitializeComponent();
}
#region Public Properties
// ... to follow ...
#endregion
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
{
// ... to follow ...
}
}
}
The GrvIdentity and GrvSpace classes are small types wrapping over the Groove Web Services proxy code generated by Visual Studio. Originally I built these wrappers to just override .ToString() so I could put Groove objects into WinForms controls:
public class GrvIdentity
{
// GrooveAccounts.Identity2 is the Groove "identity" structure
// in the GrooveAccounts web service...
public GrooveAccounts.Identity2 identity;
public GrvIdentity(GrooveAccounts.Identity2 i)
{
identity = i;
}
public override string ToString()
{
return identity.Name;
}
public GrvSpaces Spaces
{
get
{
return new GrvSpaces(this);
}
}
}
but since that was such a success, now they've expanded a little. The GrvSpaces class wraps the GrooveSpaces web service:
public class GrvSpaces
{
public GrvIdentity identity;
public GrvSpaces(GrvIdentity i)
{
identity = i;
}
private GrooveSpaces.GrooveSpaces GetService()
{
return GetService(null);
}
private GrooveSpaces.GrooveSpaces GetService(string uri)
{
GrooveSpaces.GrooveSpaces svc = new GrooveSpaces.GrooveSpaces();
svc.GrooveRequestHeaderValue = new GrooveSpaces.GrooveRequestHeader();
svc.GrooveRequestHeaderValue.GrooveRequestKey = GWSUtil.GrooveLocalRequestKey;
svc.GrooveRequestHeaderValue.GrooveIdentityURL = identity.identity.URI;
if (uri == null)
{
// The Spaces property on the Identity is a URI
// which is the web services target for us to retrieve the identity's workspaces list.
// Set up a call to the Spaces web service to read.
string spacesServiceURI = identity.identity.Spaces;
svc.Url = GWSUtil.GrooveURL + spacesServiceURI;
}
else
{
svc.Url = GWSUtil.GrooveURL + uri;
}
return svc;
}
public IEnumerable<GrvSpace> Read()
{
GrooveSpaces.GrooveSpaces svc = GetService();
// Read the identity's workspaces.
GrooveSpaces.Space[] spaces = svc.Read("");
foreach (GrooveSpaces.Space space in spaces)
{
yield return new GrvSpace(space);
}
}
public GrvSpace ReadSpace(string workspaceURI)
{
GrooveSpaces.GrooveSpaces svc = GetService(workspaceURI);
GrooveSpaces.Space space = svc.ReadSpace();
return new GrvSpace(space);
}
public GrvSpace Create(string workspaceName, string templatePath)
{
GrooveSpaces.GrooveSpaces svc = GetService();
string workspaceURI = svc.CreateFromGSAByRef(templatePath, workspaceName, "");
return ReadSpace(workspaceURI);
}
}
and the GrvSpace class is another trivial wrapper like the Identity wrapper above:
public class GrvSpace
{
public GrooveSpaces.Space space;
public GrvSpace(GrooveSpaces.Space s)
{
space = s;
}
public override string ToString()
{
return space.Name;
}
}
So although this is beginning to look like too much code for a blog entry, it's really only a handful of small classes.
Back to the CreateWorkspace activity: properties are defined in the standard way, thus:
// Input: GrooveIdentity property
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
[ValidationOptionAttribute(ValidationOption.Required)]
[BrowsableAttribute(true)]
public GrvIdentity GrooveIdentity
{
get
{
return ((GrvIdentity)(base.GetValue(GrooveActivitiesLibrary.CreateWorkspace.GrooveIdentityProperty)));
}
set
{
base.SetValue(GrooveActivitiesLibrary.CreateWorkspace.GrooveIdentityProperty, value);
}
}
and finally, the Execute method, which actually creates a workpace, becomes really really simple (which was the point all along).
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
{
Console.WriteLine("in CreateWorkspace::Execute");
GrvSpaces spacesService = new GrvSpaces(this.GrooveIdentity);
GrvSpace space = spacesService.Create(this.WorkspaceName, this.TemplatePath);
Console.WriteLine("Created workspace " + this.WorkspaceName);
// Set the space property
this.GrooveSpace = space;
// We're done!
Console.WriteLine("CreateWorkspace done");
return ActivityExecutionStatus.Closed;
}
In the workflow designer, this appears as an activity block, and has some properties we can connect to other objects in the workflow's scope.
