diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 64c94a1..77571b6 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -38,6 +38,10 @@ jobs:
run:
dotnet pack src/Fdc3.NewtonsoftJson/MorganStanley.Fdc3.NewtonsoftJson.csproj --no-build --configuration Release --output packages
+ - name: Pack Fdc3.AppDirectory
+ run:
+ dotnet pack src/Fdc3.AppDirectory/MorganStanley.Fdc3.AppDirectory.csproj --no-build --configuration Release --output packages
+
- name: Upload
uses: actions/upload-artifact@v3
with:
diff --git a/src/Fdc3.AppDirectory/AppChannel.cs b/src/Fdc3.AppDirectory/AppChannel.cs
new file mode 100644
index 0000000..4167884
--- /dev/null
+++ b/src/Fdc3.AppDirectory/AppChannel.cs
@@ -0,0 +1,57 @@
+/*
+ * 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 System;
+using System.Collections.Generic;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// Describes the application's use of App Channels.
+ /// This metadata is not currently used by the desktop agent, but is provided
+ /// to help find apps that will interoperate with this app and to document API
+ /// interactions for use by other app developers.
+ ///
+ public class AppChannel
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name
+ /// Exception if name is null
+ public AppChannel(string name)
+ {
+ Name = name ?? throw new ArgumentNullException(nameof(name));
+ }
+ ///
+ /// The name of the App Channel.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// A description of how the channel is used.
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// Context type names that are broadcast by the application on the channel.
+ ///
+ public IEnumerable? Broadcasts { get; set; }
+
+ ///
+ /// Context type names that the application listens for on the channel.
+ ///
+ public IEnumerable? ListensFor { get; set; }
+ }
+}
diff --git a/src/Fdc3.AppDirectory/AppDetails/CitrixAppDetails.cs b/src/Fdc3.AppDirectory/AppDetails/CitrixAppDetails.cs
new file mode 100644
index 0000000..952c160
--- /dev/null
+++ b/src/Fdc3.AppDirectory/AppDetails/CitrixAppDetails.cs
@@ -0,0 +1,46 @@
+/*
+ * 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 System;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// App virtualized via Citrix.
+ ///
+ public class CitrixAppDetails
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The alias
+ /// The arguments
+ /// Exception if the alias is null
+ public CitrixAppDetails(string alias, string? arguments)
+ {
+ Alias = alias ?? throw new ArgumentNullException(nameof(alias));
+ Arguments = arguments;
+ }
+
+ ///
+ /// The Citrix alias / name of the virtual app (passed to the Citrix SelfService qlaunch parameter).
+ ///
+ public string Alias { get; set; }
+
+ ///
+ /// Arguments that must be passed on the command line to launch the app in the expected configuration.
+ ///
+ public string? Arguments { get; set; }
+ }
+}
diff --git a/src/Fdc3.AppDirectory/AppDetails/NativeAppDetails.cs b/src/Fdc3.AppDirectory/AppDetails/NativeAppDetails.cs
new file mode 100644
index 0000000..2fadf2c
--- /dev/null
+++ b/src/Fdc3.AppDirectory/AppDetails/NativeAppDetails.cs
@@ -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 System;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// Native application pre-installed on a device and launch via a filesystem path.
+ ///
+ public class NativeAppDetails
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The path
+ /// The arguments
+ /// Exception if the path is null
+ public NativeAppDetails(string path, string? arguments)
+ {
+ Path = path ?? throw new ArgumentNullException(nameof(path));
+ Arguments = arguments;
+ }
+ ///
+ /// The path on disk from which the application is launched.
+ ///
+ public string Path { get; set; }
+
+ ///
+ /// Arguments that must be passed on the command line to launch the app in the expected configuration.
+ ///
+ public string? Arguments { get; set; }
+ }
+}
diff --git a/src/Fdc3.AppDirectory/AppDetails/OnlineNativeAppDetails.cs b/src/Fdc3.AppDirectory/AppDetails/OnlineNativeAppDetails.cs
new file mode 100644
index 0000000..d1b3a01
--- /dev/null
+++ b/src/Fdc3.AppDirectory/AppDetails/OnlineNativeAppDetails.cs
@@ -0,0 +1,38 @@
+/*
+ * 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 System;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// Native app that have an online launcher, e.g. online ClickOnce app deployments.
+ ///
+ public class OnlineNativeAppDetails
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The url
+ /// Exception if the url is null
+ public OnlineNativeAppDetails(string url)
+ {
+ Url = url ?? throw new ArgumentNullException(nameof(url));
+ }
+ ///
+ /// Application URL.
+ ///
+ public string Url { get; set; }
+ }
+}
diff --git a/src/Fdc3.AppDirectory/AppDetails/WebAppDetails.cs b/src/Fdc3.AppDirectory/AppDetails/WebAppDetails.cs
new file mode 100644
index 0000000..75e47b5
--- /dev/null
+++ b/src/Fdc3.AppDirectory/AppDetails/WebAppDetails.cs
@@ -0,0 +1,40 @@
+/*
+ * 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 System;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// Web application launched via a URL.
+ ///
+ public class WebAppDetails
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The url
+ /// Exception if the url is null
+ public WebAppDetails(string url)
+ {
+ Url = url ?? throw new ArgumentNullException(nameof(url));
+ }
+
+ ///
+ ///
+ /// Application start URL.
+ ///
+ public string Url { get; set; }
+ }
+}
diff --git a/src/Fdc3.AppDirectory/AppType.cs b/src/Fdc3.AppDirectory/AppType.cs
new file mode 100644
index 0000000..695c911
--- /dev/null
+++ b/src/Fdc3.AppDirectory/AppType.cs
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// FDC3 application types
+ ///
+ public enum AppType
+ {
+ Other,
+ Web,
+ Native,
+ Citrix,
+ OnlineNative
+ }
+}
diff --git a/src/Fdc3.AppDirectory/Fdc3App.cs b/src/Fdc3.AppDirectory/Fdc3App.cs
new file mode 100644
index 0000000..a63897f
--- /dev/null
+++ b/src/Fdc3.AppDirectory/Fdc3App.cs
@@ -0,0 +1,194 @@
+/*
+ * 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 System;
+using System.Collections.Generic;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// Defines an application retrieved from an FDC3 App Directory, which can then be launched.
+ /// Launching typically means running for a user on a desktop. The details around 'launching' including
+ /// who or what might do it, and how the launch action is initiated are discussed elsewhere in the FDC3
+ /// App Directory spec.
+ ///
+ public class Fdc3App
+ {
+ public Fdc3App(string appId, string name, AppType type, object details)
+ {
+ AppId = appId ?? throw new ArgumentNullException(nameof(appId));
+ Name = name ?? throw new ArgumentNullException( nameof(name));
+ Type = type;
+ Details = details ?? throw new ArgumentNullException(nameof(details));
+ }
+ ///
+ /// The unique application identifier located within a specific application directory instance.
+ ///
+ public string AppId { get; set; }
+
+ ///
+ /// The name of the application. The name should be unique within an FDC3 App Directory instance.
+ /// The exception to the uniqueness constraint is that an App Directory can hold definitions
+ /// for multiple versions of the same app. The same appName could occur in other directories.
+ /// We are not currently specifying app name conventions in the document.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// The technology type that is used to launch and run the application.
+ /// Each application type implies a particular set of launch details. The supported types include:
+ ///
+ /// -
+ /// web: Web applications launched via a URL
+ ///
+ /// -
+ /// native: Native applications pre-installed on a device and launch via a filesystem path
+ ///
+ /// -
+ /// citrix: Apps virtualized via Citrix
+ ///
+ /// -
+ /// onlineNative: Native apps that have an online launcher, e.g.online ClickOnce app deployments.
+ ///
+ /// -
+ /// other: Used to represent apps that do not conform to or cannot be launched via the other types,
+ /// and are likely to be defined solely by a hostManifest.
+ ///
+ ///
+ /// FDC3 Desktop Agents MUST support at least the web application type and MAY support any or all of the other types.
+ ///
+ public AppType Type { get; set; }
+
+ ///
+ /// The type specific launch details of the application. These details are intended to be vendor-agnostic
+ /// and MAY be duplicated or overridden by details provided in the hostManifests object for a specific host.
+ ///
+ public object Details { get; set; }
+
+ ///
+ /// Version of the application. This allows multiple app versions to be defined using the same app name.
+ /// This can be a triplet but can also include things like 1.2.5 (BETA)
+ ///
+ public string? Version { get; set; }
+
+ ///
+ /// Optional title for the application, if missing use appName, typically used in a launcher UI.
+ ///
+ public string? Title { get; set; }
+
+ ///
+ /// Optional tooltip description e.g. for a launcher
+ ///
+ public string? ToolTip { get; set; }
+
+ ///
+ /// Description of the application. This will typically be a 1-2 paragraph style blurb about the application.
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// An array of string categories that describe the application.These are meant as a hint to catalogs or stores
+ /// listing FDC3-enabled apps and it is expected that these will make a best effort to find appropriate categories (or category)
+ /// under which to list the app.AppD record authors are encouraged to use lower-case and, where possible,
+ /// to select categories from the following list: allocations, analytics, charts, chat,communication,
+ /// compliance, crm, developer tools, events, execution management, file sharing, market data, news
+ /// networking, office apps, order management, other, portfolio management, presentation, pricing
+ /// productivity, research, risk, screen sharing, security, spreadsheet, trade cost analysis
+ /// trading system, training, travel, video, visualization, weather
+ ///
+ public IEnumerable? Categories { get; set; }
+
+ ///
+ /// A language tag that specifies the primary language of both the application and its AppD entry, as defined by IETF RFC 5646.
+ ///
+ public string? Lang { get; set; }
+
+ ///
+ /// Holds Icons used for the application, a Launcher may be able to use multiple Icon sizes or there may be a 'button' Icon
+ ///
+ public IEnumerable? Icons { get; set; }
+
+ ///
+ /// Array of images to show the user when they are looking at app description. Each image can have an optional description/tooltip
+ ///
+ public IEnumerable? Screenshots { get; set; }
+
+ ///
+ /// Optional e-mail to receive queries about the application
+ ///
+ public string? ContactEmail { get; set; }
+
+ ///
+ /// Optional e-mail to receive support requests for the application
+ ///
+ public string? SupportEmail { get; set; }
+
+ ///
+ /// Optional URL that provides more information about the application
+ ///
+ public string? MoreInfo { get; set; }
+
+ ///
+ /// The name of the company that owns the application. The publisher has control over their namespace/app/signature.
+ ///
+ public string? Publisher { get; set; }
+
+ ///
+ /// An optional set of name value pairs that can be used to deliver custom data from an App Directory to a launcher.
+ ///
+ public Dictionary? CustomConfig { get; set; }
+
+ ///
+ ///
+ ///
+ public Dictionary? HostManifests { get; set; }
+
+ ///
+ ///
+ ///
+ public Interop? Interop { get; set; }
+
+ ///
+ /// Provides localized alternatives to any field of the AppD record, which may also refer to an alternative
+ /// version of the application that is also localized (e.g. by providing customConfig or an alternative URL).
+ /// The keys to this object should be language tags as defined by IETF RFC 5646, e.g. en, en-GB or fr-FR.
+ ///
+ public Dictionary? LocalizedVersions { get; set; }
+ }
+
+ ///
+ /// Represents an FDC3 application with specific details of type .
+ ///
+ /// The type of application details.
+ public class Fdc3App : Fdc3App where TDetails : class
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The application ID.
+ /// The application name.
+ /// The application type.
+ /// The application details of type .
+ public Fdc3App(string appId, string name, AppType type, TDetails details) : base(appId, name, type, details)
+ {
+ }
+
+ ///
+ public new TDetails Details
+ {
+ get => base.Details as TDetails ?? throw new InvalidCastException($"Cannot cast base.Details to {typeof(TDetails)}");
+ set => base.Details = value;
+ }
+ }
+}
diff --git a/src/Fdc3.AppDirectory/IAppDirectory.cs b/src/Fdc3.AppDirectory/IAppDirectory.cs
new file mode 100644
index 0000000..b0f8e06
--- /dev/null
+++ b/src/Fdc3.AppDirectory/IAppDirectory.cs
@@ -0,0 +1,38 @@
+/*
+ * 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 System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// Interface definition for the AppDirectory.
+ ///
+ public interface IAppDirectory
+ {
+ ///
+ /// Returns a list of all applications from the AppDirectory.
+ ///
+ /// List of applications.
+ Task> GetApps();
+
+ ///
+ /// Returns an application by appId from the AppDirectory.
+ ///
+ /// Application identifier
+ /// The application
+ Task GetApp(string appId);
+ }
+}
diff --git a/src/Fdc3.AppDirectory/IntentMetadata.cs b/src/Fdc3.AppDirectory/IntentMetadata.cs
new file mode 100644
index 0000000..6618726
--- /dev/null
+++ b/src/Fdc3.AppDirectory/IntentMetadata.cs
@@ -0,0 +1,69 @@
+/*
+ * 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 System;
+using System.Collections.Generic;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// Implementation of
+ ///
+ public class IntentMetadata : IIntentMetadata
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name
+ /// The displayName
+ /// The contexts
+ /// Exception contexts is null
+ public IntentMetadata(string name, string displayName, IEnumerable contexts)
+ {
+ Name = name;
+ DisplayName = displayName;
+ Contexts = contexts ?? throw new ArgumentNullException(nameof(contexts));
+ }
+
+ ///
+ /// Definition of an intent that an app listens for
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// An optional display name for the intent that may be used in UI instead of the name.
+ ///
+ public string DisplayName { get; set; }
+
+ ///
+ /// A comma separated list of the types of contexts the intent offered by the application
+ /// can process, where the first part of the context type is the namespace e.g."fdc3.contact,
+ /// org.symphony.contact"
+ ///
+ public IEnumerable Contexts { get; set; }
+
+ ///
+ /// An optional type for output returned by the application, if any, when resolving this intent.
+ /// May indicate a context type by type name (e.g. "fdc3.instrument"), a channel (e.g. "channel")
+ /// or a combination that indicates a channel that returns a particular
+ /// context type (e.g. "channel").
+ ///
+ public string? ResultType { get; set; }
+
+ ///
+ /// Custom configuration for the intent that may be required for a particular desktop agent.
+ ///
+ public object? CustomConfig { get; set; }
+ }
+}
diff --git a/src/Fdc3.AppDirectory/Intents.cs b/src/Fdc3.AppDirectory/Intents.cs
new file mode 100644
index 0000000..48d2f59
--- /dev/null
+++ b/src/Fdc3.AppDirectory/Intents.cs
@@ -0,0 +1,43 @@
+/*
+ * 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 System.Collections.Generic;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// Describes the app's interactions with intents.
+ ///
+ public class Intents
+ {
+ ///
+ /// A mapping of Intents names that an app listens for via fdc3.addIntentListener() to their configuration.
+ /// Used to support intent resolution by desktop agents.Replaces the intents element used in appD records
+ /// prior to FDC3 2.0.
+ ///
+ public Dictionary? ListensFor { get; set; }
+
+ ///
+ /// A mapping of Intent names that an app raises (via fdc3.raiseIntent)
+ /// to an array of context type names that it may be raised with.
+ /// Use the intent name "any" to represent use of the
+ /// fdc3.raiseIntentForContext and fdc3.findIntentForContext functions,
+ /// which allow the user to select from intents available for a specified context type.
+ /// This metadata is not currently used by the desktop agent, but is provided to
+ /// help find apps that will interoperate with this app and to document API
+ /// interactions for use by other app developers.
+ ///
+ public Dictionary>? Raises { get; set; }
+ }
+}
diff --git a/src/Fdc3.AppDirectory/Interop.cs b/src/Fdc3.AppDirectory/Interop.cs
new file mode 100644
index 0000000..c4163b6
--- /dev/null
+++ b/src/Fdc3.AppDirectory/Interop.cs
@@ -0,0 +1,51 @@
+/*
+ * 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 System.Collections.Generic;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// Metadata that describes how the application uses FDC3 APIs. This metadata serves multiple purposes:
+ ///
+ /// -
+ /// It supports intent resolution by a desktop agent, by declaring what intents an app listens for.
+ ///
+ /// -
+ /// It may be used, for example in an app catalog UI, to find apps that 'interoperate with' other apps.
+ ///
+ /// -
+ /// It provides a standard location to document how the app interacts with user channels, app channels,
+ /// and intents, for use by other app developers and desktop assemblers.
+ ///
+ ///
+ ///
+ public class Interop
+ {
+ ///
+ ///
+ ///
+ public Intents? Intents { get; set; }
+
+ ///
+ ///
+ ///
+ public UserChannels? UserChannels { get; set; }
+
+ ///
+ /// List of
+ ///
+ public IEnumerable? AppChannels { get; set; }
+ }
+}
diff --git a/src/Fdc3.AppDirectory/LocalizedVersion.cs b/src/Fdc3.AppDirectory/LocalizedVersion.cs
new file mode 100644
index 0000000..bc9f9d3
--- /dev/null
+++ b/src/Fdc3.AppDirectory/LocalizedVersion.cs
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ public class LocalizedVersion
+ {
+ public string? Title { get; set; }
+ public string? Description { get; set; }
+ }
+}
diff --git a/src/Fdc3.AppDirectory/MorganStanley.Fdc3.AppDirectory.csproj b/src/Fdc3.AppDirectory/MorganStanley.Fdc3.AppDirectory.csproj
new file mode 100644
index 0000000..dca2bd1
--- /dev/null
+++ b/src/Fdc3.AppDirectory/MorganStanley.Fdc3.AppDirectory.csproj
@@ -0,0 +1,45 @@
+
+
+
+ MorganStanley.Fdc3.AppDirectory
+ MorganStanley.Fdc3.AppDirectory
+ 2.0.0
+ alpha.5
+ .NET FDC3 Newtonsoft JSON
+ true
+ ..\keypair.snk
+ README.md
+ netstandard2.0
+ enable
+ 8.0
+ https://github.com/morganstanley/fdc3-dotnet
+ .NET Standard 2.0 declarations to implement FDC3 AppDirectory.
+ FDC3
+
+
+
+ true
+ 9999
+
+
+
+ True
+ 9999
+
+
+
+
+ True
+
+
+
+ True
+ \
+
+
+
+
+
+
+
+
diff --git a/src/Fdc3.AppDirectory/UserChannels.cs b/src/Fdc3.AppDirectory/UserChannels.cs
new file mode 100644
index 0000000..632635c
--- /dev/null
+++ b/src/Fdc3.AppDirectory/UserChannels.cs
@@ -0,0 +1,37 @@
+/*
+ * 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 System.Collections.Generic;
+
+namespace MorganStanley.Fdc3.AppDirectory
+{
+ ///
+ /// Describes the application's use of context types on User Channels.
+ /// This metadata is not currently used by the desktop agent, but is provided
+ /// to help find apps that will interoperate with this app and to document API
+ /// interactions for use by other app developers.
+ ///
+ public class UserChannels
+ {
+ ///
+ /// Context type names that are broadcast by the application.
+ ///
+ public IEnumerable? Broadcasts { get; set; }
+
+ ///
+ /// Context type names that the application listens for.
+ ///
+ public IEnumerable? ListensFor { get; set; }
+ }
+}
diff --git a/src/Fdc3.NewtonsoftJson/MorganStanley.Fdc3.NewtonsoftJson.csproj b/src/Fdc3.NewtonsoftJson/MorganStanley.Fdc3.NewtonsoftJson.csproj
index eecec0b..fdb28ed 100644
--- a/src/Fdc3.NewtonsoftJson/MorganStanley.Fdc3.NewtonsoftJson.csproj
+++ b/src/Fdc3.NewtonsoftJson/MorganStanley.Fdc3.NewtonsoftJson.csproj
@@ -43,6 +43,7 @@
+
diff --git a/src/Fdc3.NewtonsoftJson/Serialization/Fdc3AppConverter.cs b/src/Fdc3.NewtonsoftJson/Serialization/Fdc3AppConverter.cs
new file mode 100644
index 0000000..9d68f4b
--- /dev/null
+++ b/src/Fdc3.NewtonsoftJson/Serialization/Fdc3AppConverter.cs
@@ -0,0 +1,62 @@
+/*
+ * 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.AppDirectory;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+
+
+namespace MorganStanley.Fdc3.NewtonsoftJson.Serialization
+{
+ public class Fdc3AppConverter : JsonConverter
+ {
+ public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
+ {
+ var jsonObject = JObject.Load(reader);
+
+ if (Enum.TryParse(jsonObject["type"]?.ToString(), true, out AppType appType))
+ {
+ switch (appType)
+ {
+ case AppType.Web:
+ return serializer.Deserialize>(jsonObject.CreateReader());
+ case AppType.Citrix:
+ return serializer.Deserialize>(jsonObject.CreateReader());
+ case AppType.Native:
+ return serializer.Deserialize>(jsonObject.CreateReader());
+ case AppType.OnlineNative:
+ return serializer.Deserialize>(jsonObject.CreateReader());
+ case AppType.Other:
+ return serializer.Deserialize>(jsonObject.CreateReader());
+ }
+ }
+
+ throw new InvalidOperationException("Unknown AppType. Possible values are: web, native, citrix, onlineNative, other");
+ }
+
+ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(Fdc3App);
+ }
+
+ public override bool CanRead => true;
+ public override bool CanWrite => false;
+ }
+}
diff --git a/src/Fdc3.NewtonsoftJson/Serialization/Fdc3JsonSerializerSettings.cs b/src/Fdc3.NewtonsoftJson/Serialization/Fdc3JsonSerializerSettings.cs
index 7c9287a..7814a18 100644
--- a/src/Fdc3.NewtonsoftJson/Serialization/Fdc3JsonSerializerSettings.cs
+++ b/src/Fdc3.NewtonsoftJson/Serialization/Fdc3JsonSerializerSettings.cs
@@ -30,7 +30,7 @@ public Fdc3JsonSerializerSettings()
{
NamingStrategy = new Fdc3CamelCaseNamingStrategy()
};
- this.Converters = new JsonConverter[] { new StringEnumConverter(new CamelCaseNamingStrategy()), new RecipientJsonConverter() };
+ this.Converters = new JsonConverter[] { new StringEnumConverter(new CamelCaseNamingStrategy()), new RecipientJsonConverter(), new Fdc3AppConverter() };
}
}
}
\ No newline at end of file
diff --git a/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/DeserializationTest.cs b/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/DeserializationTest.cs
new file mode 100644
index 0000000..40131d3
--- /dev/null
+++ b/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/DeserializationTest.cs
@@ -0,0 +1,82 @@
+
+/*
+ * 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.NewtonsoftJson.Serialization;
+using Newtonsoft.Json;
+
+namespace MorganStanley.Fdc3.AppDirectory.Tests
+{
+ public class DeserializationTest
+ {
+ [Fact]
+ public void AppDAppDeserializationTest()
+ {
+ string jsonString = File.ReadAllText("TestJsons\\SampleAppForInterop.json");
+
+#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
+ Fdc3App app = JsonConvert.DeserializeObject(jsonString, new Fdc3JsonSerializerSettings());
+#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
+
+ Assert.Equal("my-application", app!.AppId);
+ Assert.Equal("my-application", app.Name);
+ Assert.Equal("My Application", app.Title);
+ Assert.Equal("An example application that uses FDC3 and fully describes itself in an AppD record.", app.Description);
+ Assert.Equal("1.0.0", app.Version);
+ Assert.Equal("My example application definition", app.ToolTip);
+ Assert.Equal("en-US", app.Lang);
+ Assert.Equal("fdc3@finos.org", app.ContactEmail);
+ Assert.Equal("fdc3-maintainers@finos.org", app.SupportEmail);
+ Assert.Equal("http://example.domain.com/", app.MoreInfo);
+ Assert.Equal("Example App, Inc.", app.Publisher);
+ Assert.Equal(AppType.Web, app.Type);
+ Assert.Equal(3, app.Categories!.Count()!);
+ Assert.Contains("market data", app.Categories!);
+ Assert.Contains("research", app.Categories!);
+ Assert.Contains("news", app.Categories!);
+ Assert.Single(app.Icons!);
+ Assert.Equal("http://example.domain.com/assets/my-app-icon.png", app.Icons!.First().Src);
+ Assert.Equal("256x256", app.Icons!.First().Size);
+ Assert.Equal("image/png", app.Icons!.First().Type);
+ Assert.Equal(2, app.Screenshots!.Count());
+ Assert.Equal("http://example.domain.com/assets/my-app-screenshot-1.png", app.Screenshots!.First().Src);
+ Assert.Equal("The first screenshot of my example app", app.Screenshots!.First().Label);
+ Assert.Equal("image/png", app.Screenshots!.First().Type);
+ Assert.Equal("800x600", app.Screenshots!.First().Size);
+ Assert.IsType(app.Details);
+ Assert.Equal("http://example.domain.com/app.html", ((WebAppDetails)app.Details).Url);
+ Assert.Contains("Finsemble", app.HostManifests!.Keys);
+ Assert.Contains("Glue42", app.HostManifests.Keys);
+ Assert.Contains("Web App Manifest", app.HostManifests.Keys);
+ Assert.Contains("ViewChart", app.Interop!.Intents!.ListensFor!.Keys);
+ Assert.Contains("myApp.GetPrice", app.Interop.Intents.ListensFor.Keys);
+ Assert.Contains("fdc3.instrument", app.Interop!.Intents!.ListensFor!["myApp.GetPrice"].Contexts!);
+ Assert.Equal("Get Price", app.Interop!.Intents!.ListensFor!["myApp.GetPrice"].DisplayName);
+ Assert.Equal("myApp.quote", app.Interop!.Intents!.ListensFor!["myApp.GetPrice"].ResultType);
+ Assert.Contains("ViewOrders", app.Interop.Intents.Raises!.Keys);
+ Assert.Contains("fdc3.instrument", app.Interop.Intents.Raises!["ViewOrders"]);
+ Assert.Contains("StartEmail", app.Interop.Intents.Raises.Keys);
+ Assert.Equal(2, app.Interop.UserChannels!.Broadcasts!.Count()!);
+ Assert.Equal(2, app.Interop.UserChannels!.ListensFor!.Count()!);
+ Assert.Contains("fdc3.instrument", app.Interop!.UserChannels!.Broadcasts!);
+ Assert.Contains("fdc3.organization", app.Interop!.UserChannels!.ListensFor!);
+ Assert.Single(app.Interop.AppChannels!);
+ Assert.Equal("myApp.quotes,", app.Interop!.AppChannels!.First().Name);
+ Assert.Contains("myApp.quote", app.Interop.AppChannels!.First().Broadcasts!);
+ Assert.Contains("fdc3.instrument", app.Interop.AppChannels!.First().ListensFor!);
+ Assert.Contains("fr-FR", app.LocalizedVersions!.Keys);
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/MorganStanley.Fdc3.AppDirectory.Tests.csproj b/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/MorganStanley.Fdc3.AppDirectory.Tests.csproj
new file mode 100644
index 0000000..724cacb
--- /dev/null
+++ b/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/MorganStanley.Fdc3.AppDirectory.Tests.csproj
@@ -0,0 +1,40 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+ false
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/TestJsons/SampleAppForInterop.json b/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/TestJsons/SampleAppForInterop.json
new file mode 100644
index 0000000..0fc814d
--- /dev/null
+++ b/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/TestJsons/SampleAppForInterop.json
@@ -0,0 +1,112 @@
+{
+ "appId": "my-application",
+ "name": "my-application",
+ "title": "My Application",
+ "description": "An example application that uses FDC3 and fully describes itself in an AppD record.",
+ "categories": [ "market data", "research", "news" ],
+ "version": "1.0.0",
+ "tooltip": "My example application definition",
+ "lang": "en-US",
+ "icons": [
+ {
+ "src": "http://example.domain.com/assets/my-app-icon.png",
+ "size": "256x256",
+ "type": "image/png"
+ }
+ ],
+ "screenshots": [
+ {
+ "src": "http://example.domain.com/assets/my-app-screenshot-1.png",
+ "label": "The first screenshot of my example app",
+ "type": "image/png",
+ "size": "800x600"
+ },
+ {
+ "src": "http://example.domain.com/assets/my-app-screenshot-2.png",
+ "label": "The second screenshot of my example app",
+ "type": "image/png",
+ "size": "800x600"
+ }
+ ],
+ "contactEmail": "fdc3@finos.org",
+ "supportEmail": "fdc3-maintainers@finos.org",
+ "moreInfo": "http://example.domain.com/",
+ "publisher": "Example App, Inc.",
+ "type": "web",
+ "details": { "url": "http://example.domain.com/app.html" },
+ "hostManifests": {
+ "Finsemble": {
+ "window": {
+ "left": 120,
+ "top": 120,
+ "width": 600,
+ "height": 800,
+ "options": { "minWidth": 75 }
+ },
+ "foreign": {
+ "components": {
+ "App Launcher": { "launchableByUser": true },
+ "Window Manager": {
+ "FSBLHeader": true,
+ "persistWindowState": true
+ }
+ }
+ },
+ "interop": { "autoConnect": true }
+ },
+ "Glue42": {
+ "type": "window",
+ "details": {
+ "height": 800,
+ "width": 600,
+ "left": 120,
+ "top": 120,
+ "mode": "tab",
+ "allowChannels": true,
+ "loader": {
+ "enabled": true,
+ "hideOnLoad": true
+ }
+ },
+ "customProperties": { "folder": "FDC3 Toolbox" }
+ },
+ "Web App Manifest": "http://example.domain.com/my-app.json"
+ },
+ "interop": {
+ "intents": {
+ "listensFor": {
+ "ViewChart": {
+ "displayName": "View Chart",
+ "contexts": [ "fdc3.instrument" ]
+ },
+ "myApp.GetPrice": {
+ "displayName": "Get Price",
+ "contexts": [ "fdc3.instrument" ],
+ "resultType": "myApp.quote"
+ }
+ },
+ "raises": {
+ "ViewOrders": [ "fdc3.instrument", "fdc3.organization" ],
+ "StartEmail": [ "fdc3.email" ]
+ }
+ },
+ "userChannels": {
+ "broadcasts": [ "fdc3.instrument", "fdc3.organization" ],
+ "listensFor": [ "fdc3.instrument", "fdc3.organization" ]
+ },
+ "appChannels": [
+ {
+ "name": "myApp.quotes,",
+ "description": "Used to share a stream of quotes for currently displayed instrument and may be used to change the currently displayed symbol,",
+ "broadcasts": [ "myApp.quote" ],
+ "listensFor": [ "fdc3.instrument" ]
+ }
+ ]
+ },
+ "localizedVersions": {
+ "fr-FR": {
+ "title": "Mon application,",
+ "description": "Un exemple d'application qui utilise FDC3 et se décrit entièrement dans un enregistrement AppD."
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/Usings.cs b/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/Usings.cs
new file mode 100644
index 0000000..89c3803
--- /dev/null
+++ b/src/Tests/MorganStanley.Fdc3.AppDirectory.Tests/Usings.cs
@@ -0,0 +1,14 @@
+/*
+ * 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.
+ */
+global using Xunit;
\ No newline at end of file
diff --git a/src/fdc3-dotnet.sln b/src/fdc3-dotnet.sln
index e2060a3..a0733e0 100644
--- a/src/fdc3-dotnet.sln
+++ b/src/fdc3-dotnet.sln
@@ -42,6 +42,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.Fdc3.Newtonso
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfFdc3", "Examples\WpfFdc3\WpfFdc3.csproj", "{06AD2640-C708-4C01-BF02-82D824CB09C1}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.Fdc3.AppDirectory", "Fdc3.AppDirectory\MorganStanley.Fdc3.AppDirectory.csproj", "{C741FC63-8954-473D-862A-F7F5AFE11E60}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.Fdc3.AppDirectory.Tests", "Tests\MorganStanley.Fdc3.AppDirectory.Tests\MorganStanley.Fdc3.AppDirectory.Tests.csproj", "{88BF9BA6-2934-4904-8952-DB733E4CBD48}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -68,6 +72,14 @@ Global
{06AD2640-C708-4C01-BF02-82D824CB09C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06AD2640-C708-4C01-BF02-82D824CB09C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06AD2640-C708-4C01-BF02-82D824CB09C1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C741FC63-8954-473D-862A-F7F5AFE11E60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C741FC63-8954-473D-862A-F7F5AFE11E60}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C741FC63-8954-473D-862A-F7F5AFE11E60}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C741FC63-8954-473D-862A-F7F5AFE11E60}.Release|Any CPU.Build.0 = Release|Any CPU
+ {88BF9BA6-2934-4904-8952-DB733E4CBD48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {88BF9BA6-2934-4904-8952-DB733E4CBD48}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {88BF9BA6-2934-4904-8952-DB733E4CBD48}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {88BF9BA6-2934-4904-8952-DB733E4CBD48}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -77,6 +89,7 @@ Global
{D932070B-937D-440F-9D79-B51C8F850E9E} = {97CAC97B-DB3A-4A45-9209-3BAD231B4837}
{A4FC0A7A-AD7D-4FDD-8143-46A63A65C96E} = {97CAC97B-DB3A-4A45-9209-3BAD231B4837}
{06AD2640-C708-4C01-BF02-82D824CB09C1} = {6C9A6509-FC32-4870-8AD3-9D0AE546A3D9}
+ {88BF9BA6-2934-4904-8952-DB733E4CBD48} = {97CAC97B-DB3A-4A45-9209-3BAD231B4837}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {356A9BB9-BD56-40C0-B1ED-06F7AF0C4BCA}