Skip to content

Commit

Permalink
Add basic channel/context support to example (#42)
Browse files Browse the repository at this point in the history
* Add basic channel/context support to example
* dotnet Pack invidual lib projects rather than whole solution including example
  • Loading branch information
bingenito authored Mar 6, 2023
1 parent eba2487 commit 02fbf43
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 15 deletions.
9 changes: 7 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,13 @@ jobs:
- name: Test
run: dotnet test src/fdc3-dotnet.sln --no-build --verbosity normal --collect:"XPlat Code Coverage" --configuration Release

- name: Pack
run: dotnet pack src/fdc3-dotnet.sln --no-build --configuration Release --output packages
- name: Pack Fdc3
run:
dotnet pack src/Fdc3/MorganStanley.Fdc3.csproj --no-build --configuration Release --output packages

- name: Pack Fdc3.Json
run:
dotnet pack src/Fdc3.Json/MorganStanley.Fdc3.Json.csproj --no-build --configuration Release --output packages

- name: Upload
uses: actions/upload-artifact@v3
Expand Down
63 changes: 63 additions & 0 deletions src/Examples/WpfFdc3/Fdc3/Channel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Morgan Stanley makes this available to you under the Apache License,
* Version 2.0 (the "License"). You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership. Unless required by applicable law or agreed
* to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/

using MorganStanley.Fdc3;
using MorganStanley.Fdc3.Context;
using Prism.Events;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace WpfFdc3.Fdc3
{
public class Channel : IChannel
{
private readonly IEventAggregator _eventAggregator;
private readonly Dictionary<string, IContext> _lastContexts = new Dictionary<string, IContext>();
private IContext? _lastContext;

public Channel(string id, string type)
{
this.Id = id;
this.Type = type;
_eventAggregator = new EventAggregator();
}

public string Id { get; }

public string Type { get; }

public IDisplayMetadata? DisplayMetadata => throw new System.NotImplementedException();

public Task<IListener> AddContextListener<T>(string? contextType, ContextHandler<T> handler) where T : IContext
{
return Task.Run<IListener>(() => {
return new Listener<T>(_eventAggregator, contextType, handler);
});
}

public Task Broadcast(IContext context)
{
return Task.Run(() =>
{
_lastContexts[context.Type] = _lastContext = context;
_eventAggregator.GetEvent<ContextEvent>().Publish(context);
});
}

public Task<IContext?> GetCurrentContext(string? contextType)
{
return Task.Run<IContext?>(() => (contextType != null) ? _lastContexts[contextType] : _lastContext);
}
}
}
23 changes: 23 additions & 0 deletions src/Examples/WpfFdc3/Fdc3/ContextEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Morgan Stanley makes this available to you under the Apache License,
* Version 2.0 (the "License"). You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership. Unless required by applicable law or agreed
* to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/

using MorganStanley.Fdc3.Context;
using Prism.Events;

namespace WpfFdc3.Fdc3
{
internal class ContextEvent : PubSubEvent<IContext>
{
}
}
49 changes: 42 additions & 7 deletions src/Examples/WpfFdc3/Fdc3/DesktopAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,24 @@
using MorganStanley.Fdc3.Context;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WpfFdc3.Fdc3
{
internal class DesktopAgent : IDesktopAgent
{
private readonly List<IChannel> _channels = new List<IChannel>();
private IChannel? _currentChannel;

public DesktopAgent()
{
_channels.Add(new Channel("global", "app"));
}

public Task<IListener> AddContextListener<T>(string? contextType, ContextHandler<T> handler) where T : IContext
{
throw new NotImplementedException();
return _currentChannel?.AddContextListener<T>(contextType, handler);
}

public Task<IListener> AddIntentListener<T>(string intent, IntentHandler<T> handler) where T : IContext
Expand All @@ -34,7 +43,12 @@ public Task<IListener> AddIntentListener<T>(string intent, IntentHandler<T> hand

public Task Broadcast(IContext context)
{
throw new NotImplementedException();
if (_currentChannel != null)
{
return Task.Run(() => _currentChannel.Broadcast(context));
}

throw new Exception("Not joined to a channel");
}

public Task<IPrivateChannel> CreatePrivateChannel()
Expand Down Expand Up @@ -64,7 +78,7 @@ public Task<IAppMetadata> GetAppMetadata(IAppIdentifier app)

public Task<IChannel?> GetCurrentChannel()
{
throw new NotImplementedException();
return Task.Run<IChannel?>(() => _currentChannel);
}


Expand All @@ -80,22 +94,43 @@ public Task<IImplementationMetadata> GetInfo()

public Task<IChannel> GetOrCreateChannel(string channelId)
{
throw new NotImplementedException();
return Task.Run<IChannel>(() =>
{
IChannel channel = _channels.First<IChannel>(channel => channel.Id == channelId);
if (channel == null)
{
channel = new Channel(channelId, "app");
_channels.Add(channel);
}

return channel;
});
}

public Task<IEnumerable<IChannel>> GetUserChannels()
{
throw new NotImplementedException();
return Task.Run<IEnumerable<IChannel>>(() => _channels );
}

public Task JoinUserChannel(string channelId)
{
throw new NotImplementedException();
return Task.Run(() =>
{
IChannel channel = _channels.First<IChannel>(channel => channel.Id == channelId);
if (channel != null)
{
_currentChannel = channel;
}
else
{
throw new Exception(ChannelError.NoChannelFound);
}
});
}

public Task LeaveCurrentChannel()
{
throw new NotImplementedException();
return Task.Run(() => _currentChannel = null);
}

public Task<IAppIdentifier> Open(IAppIdentifier app, IContext? context = null)
Expand Down
45 changes: 45 additions & 0 deletions src/Examples/WpfFdc3/Fdc3/Listener.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Morgan Stanley makes this available to you under the Apache License,
* Version 2.0 (the "License"). You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership. Unless required by applicable law or agreed
* to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/

using MorganStanley.Fdc3;
using MorganStanley.Fdc3.Context;
using Prism.Events;

namespace WpfFdc3.Fdc3
{
internal class Listener<T> : IListener where T : IContext
{
private IEventAggregator _eventAggregator;
private System.Action<IContext> _callback;

internal Listener(IEventAggregator eventAggregator, string? contextType, ContextHandler<T> handler)
{
_eventAggregator = eventAggregator;
_callback = context =>
{
if (contextType == context.Type)
{
handler((T)context, null);
}
};

_eventAggregator.GetEvent<ContextEvent>().Subscribe(_callback);
}

public void Unsubscribe()
{
_eventAggregator.GetEvent<ContextEvent>().Unsubscribe(_callback);
}
}
}
102 changes: 98 additions & 4 deletions src/Examples/WpfFdc3/ViewModels/WorkbenchViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,115 @@
*/

using MorganStanley.Fdc3;
using MorganStanley.Fdc3.Context;
using MorganStanley.Fdc3.Json.Serialization;
using Newtonsoft.Json;
using Prism.Commands;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Input;

namespace WpfFdc3.ViewModels
{
public class WorkbenchViewModel
public class WorkbenchViewModel : INotifyPropertyChanged
{
private readonly IDesktopAgent DesktopAgent;
private readonly IDesktopAgent _desktopAgent;
private IListener? _listener;
private ICommand? _joinChannelCommand;
private ICommand? _addContextListenerCommand;
private ICommand? _broadcastContextCommand;
private Fdc3JsonSerializerSettings SerializerSettings = new Fdc3JsonSerializerSettings() { Formatting = Formatting.Indented };

public WorkbenchViewModel(IDesktopAgent desktopAgent)
{
this.DesktopAgent = desktopAgent;
_desktopAgent = desktopAgent;
}

public IImplementationMetadata? ImplementionMetadata
{
get { return this.DesktopAgent?.GetInfo()?.Result; }
get { return _desktopAgent?.GetInfo()?.Result; }
}

public IEnumerable<IChannel>? AvailableChannels
{
get { return _desktopAgent?.GetUserChannels()?.Result; }
}

public IChannel? SelectedChannel { get; set; }

public ICommand JoinChannelCommand
{
get
{
return _joinChannelCommand ?? (_joinChannelCommand = new DelegateCommand(() =>
{
if (this.SelectedChannel != null)
{
_desktopAgent.JoinUserChannel(this.SelectedChannel.Id);
}
}));
}
}

public IEnumerable<IContext> AvailableContexts
{
get
{
return new IContext[]
{
new Contact(new ContactID() {Email="[email protected]"}, "Jane Doe"),
new Instrument(new InstrumentID() {Ticker = "MSFT", RIC="MSFT.OQ", ISIN="US5949181045"}),
new Position(200000, new Instrument(new InstrumentID() {Ticker = "AAPL"}))
};
}
}

public IContext? SelectedContextListener { get; set; }

public string? LastContextMessage { get; private set; }

public ICommand AddContextListenerCommand
{
get
{
return _addContextListenerCommand ?? (_addContextListenerCommand = new DelegateCommand(async () =>
{
if (this.SelectedContextListener != null)
{
_listener?.Unsubscribe();

_listener = await _desktopAgent.AddContextListener<IContext>(this.SelectedContextListener.Type, (context, contextMetadata) =>
{
this.LastContextMessage = JsonConvert.SerializeObject(context, this.SerializerSettings);
this.OnPropertyChanged("LastContextMessage");
});
}
}));
}
}

public IContext? SelectedContext { get; set; }


public ICommand BroadcastContextCommand
{
get
{
return _broadcastContextCommand ?? (_broadcastContextCommand = new DelegateCommand(() =>
{
if (this.SelectedContext != null)
{
_desktopAgent.Broadcast(this.SelectedContext);
}
}));
}
}

protected void OnPropertyChanged(string property)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}

public event PropertyChangedEventHandler? PropertyChanged;
}
}
Loading

0 comments on commit 02fbf43

Please sign in to comment.