示例#1
0
        public bool CanConnectTo(
            GroupCompositionId importingGroup,
            GroupImportDefinition importDefinition,
            IDictionary <string, object> selectionCriteria,
            GroupCompositionId exportingGroup)
        {
            if (!m_Graph.Contains(importingGroup))
            {
                return(false);
            }

            if (!m_Graph.Contains(exportingGroup))
            {
                return(false);
            }

            if (m_Graph.IsConnected(importingGroup, importDefinition))
            {
                return(false);
            }

            var group = m_Graph.Group(exportingGroup);

            return(m_GroupImportEngine.Accepts(importDefinition, group.GroupExport) &&
                   m_GroupImportEngine.ExportPassesSelectionCriteria(group.GroupExport, selectionCriteria));
        }
 private static GroupDefinition CreateImportingGroup()
 {
     return(new GroupDefinition("b")
     {
         InternalConnections = Enumerable.Empty <PartImportToPartExportMap>(),
         Parts = new List <GroupPartDefinition>
         {
             new GroupPartDefinition(
                 TypeIdentity.CreateDefinition(typeof(string)),
                 0,
                 new Dictionary <ExportRegistrationId, SerializableExportDefinition>(),
                 new Dictionary <ImportRegistrationId, SerializableImportDefinition>
             {
                 {
                     new ImportRegistrationId(typeof(string), 0, "PartContract1"),
                     PropertyBasedImportDefinition.CreateDefinition(
                         "PartContract1",
                         TypeIdentity.CreateDefinition(typeof(int)),
                         ImportCardinality.ExactlyOne,
                         false,
                         CreationPolicy.Any,
                         typeof(ImportOnPropertyWithType).GetProperty("ImportingProperty"))
                 }
             },
                 new Dictionary <ScheduleActionRegistrationId, ScheduleActionDefinition>(),
                 new Dictionary <ScheduleConditionRegistrationId, ScheduleConditionDefinition>()),
             new GroupPartDefinition(
                 TypeIdentity.CreateDefinition(typeof(string)),
                 1,
                 new Dictionary <ExportRegistrationId, SerializableExportDefinition>(),
                 new Dictionary <ImportRegistrationId, SerializableImportDefinition>
             {
                 {
                     new ImportRegistrationId(typeof(string), 1, "PartContract2"),
                     PropertyBasedImportDefinition.CreateDefinition(
                         "PartContract2",
                         TypeIdentity.CreateDefinition(typeof(string)),
                         ImportCardinality.ExactlyOne,
                         false,
                         CreationPolicy.Any,
                         typeof(ImportOnPropertyWithEnumerable).GetProperty("ImportingProperty"))
                 }
             },
                 new Dictionary <ScheduleActionRegistrationId, ScheduleActionDefinition>(),
                 new Dictionary <ScheduleConditionRegistrationId, ScheduleConditionDefinition>()),
         },
         GroupImports = new List <GroupImportDefinition>
         {
             GroupImportDefinition.CreateDefinition(
                 "ContractName",
                 new GroupRegistrationId("b"),
                 null,
                 new List <ImportRegistrationId>
             {
                 new ImportRegistrationId(typeof(string), 0, "PartContract1"),
                 new ImportRegistrationId(typeof(string), 1, "PartContract2"),
             })
         },
     });
 }
示例#3
0
        public void ConnectWithUnknownExportingGroup()
        {
            using (var source = new CancellationTokenSource())
            {
                var commands = new Mock <ICompositionCommands>();
                {
                    commands.Setup(c => c.Add(It.IsAny <GroupCompositionId>(), It.IsAny <GroupDefinition>()))
                    .Returns(
                        Task.Factory.StartNew(
                            () => { },
                            source.Token,
                            TaskCreationOptions.None,
                            new CurrentThreadTaskScheduler()));
                }

                var connector         = new Mock <IConnectGroups>();
                var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null);
                var layer             = new ProxyCompositionLayer(commands.Object, connector.Object, systemDiagnostics);

                var exportingGroup = new GroupDefinition("Group1");
                var task           = layer.Add(exportingGroup);
                task.Wait();

                var importDefinition = GroupImportDefinition.CreateDefinition(
                    "a",
                    new GroupRegistrationId("b"),
                    null,
                    Enumerable.Empty <ImportRegistrationId>());
                Assert.Throws <UnknownPartGroupException>(() => layer.Connect(task.Result, importDefinition, new GroupCompositionId()));
            }
        }
示例#4
0
        public void Connect()
        {
            using (var source = new CancellationTokenSource())
            {
                var commands = new Mock <ICompositionCommands>();
                {
                    commands.Setup(c => c.Add(It.IsAny <GroupCompositionId>(), It.IsAny <GroupDefinition>()))
                    .Returns(
                        Task.Factory.StartNew(
                            () => { },
                            source.Token,
                            TaskCreationOptions.None,
                            new CurrentThreadTaskScheduler()));

                    commands.Setup(c => c.Connect(It.IsAny <GroupConnection>()))
                    .Returns(
                        Task.Factory.StartNew(
                            () => { },
                            source.Token,
                            TaskCreationOptions.None,
                            new CurrentThreadTaskScheduler()));
                }

                var connector = new Mock <IConnectGroups>();
                {
                    connector.Setup(
                        c => c.GenerateConnectionFor(
                            It.IsAny <GroupDefinition>(),
                            It.IsAny <GroupImportDefinition>(),
                            It.IsAny <GroupDefinition>()))
                    .Callback <GroupDefinition, GroupImportDefinition, GroupDefinition>(
                        (importingGroup, importDef, exportingGroup) => { })
                    .Returns(Enumerable.Empty <PartImportToPartExportMap>());
                }

                var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null);
                var layer             = new ProxyCompositionLayer(commands.Object, connector.Object, systemDiagnostics);

                var exportingDefinition = new GroupDefinition("Group1");
                var addTask             = layer.Add(exportingDefinition);
                var exportingId         = addTask.Result;

                var importingDefinition = new GroupDefinition("Group2");
                addTask = layer.Add(importingDefinition);
                var importingId = addTask.Result;

                var importDefinition = GroupImportDefinition.CreateDefinition(
                    "a",
                    new GroupRegistrationId("b"),
                    null,
                    Enumerable.Empty <ImportRegistrationId>());
                var connectTask = layer.Connect(importingId, importDefinition, exportingId);
                connectTask.Wait();

                Assert.IsTrue(layer.IsConnected(importingId, importDefinition));
                Assert.IsTrue(layer.IsConnected(importingId, importDefinition, exportingId));
                Assert.AreEqual(exportingId, layer.ConnectedTo(importingId, importDefinition));
            }
        }
示例#5
0
        public void ReloadFromDataset()
        {
            var importingId = new GroupCompositionId();
            var exportingId = new GroupCompositionId();

            var importingGroup = new GroupDefinition("Group1");
            var exportingGroup = new GroupDefinition("Group2");

            var importDefinition = GroupImportDefinition.CreateDefinition(
                "a",
                new GroupRegistrationId("b"),
                null,
                Enumerable.Empty <ImportRegistrationId>());

            var state = new GroupCompositionState(
                new List <Tuple <GroupCompositionId, GroupDefinition> >
            {
                new Tuple <GroupCompositionId, GroupDefinition>(importingId, importingGroup),
                new Tuple <GroupCompositionId, GroupDefinition>(exportingId, exportingGroup),
            },
                new List <Tuple <GroupCompositionId, GroupImportDefinition, GroupCompositionId> >
            {
                new Tuple <GroupCompositionId, GroupImportDefinition, GroupCompositionId>(importingId, importDefinition, exportingId)
            });

            using (var source = new CancellationTokenSource())
            {
                var commands = new Mock <ICompositionCommands>();
                {
                    commands.Setup(c => c.CurrentState())
                    .Returns(
                        Task <GroupCompositionState> .Factory.StartNew(
                            () => state,
                            source.Token,
                            TaskCreationOptions.None,
                            new CurrentThreadTaskScheduler()));
                }

                var connector         = new Mock <IConnectGroups>();
                var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null);
                var layer             = new ProxyCompositionLayer(commands.Object, connector.Object, systemDiagnostics);
                var task = layer.ReloadFromDataset();
                task.Wait();

                Assert.IsTrue(layer.Contains(importingId));
                Assert.AreEqual(importingGroup, layer.Group(importingId));

                Assert.IsTrue(layer.Contains(exportingId));
                Assert.AreEqual(exportingGroup, layer.Group(exportingId));

                Assert.IsTrue(layer.IsConnected(importingId, importDefinition));
                Assert.IsTrue(layer.IsConnected(importingId, importDefinition, exportingId));
                Assert.AreEqual(exportingId, layer.ConnectedTo(importingId, importDefinition));
            }
        }
示例#6
0
 /// <summary>
 /// Returns a collection containing all the groups which satisfy the given group import and match the given
 /// selection criteria.
 /// </summary>
 /// <param name="groupToLinkTo">The import definition which should be satisfied.</param>
 /// <param name="selectionCriteria">The collection containing all the selection filters.</param>
 /// <returns>
 /// A collection containing all the groups which satisfy the given group import and match the given
 /// selection criteria.
 /// </returns>
 public IEnumerable <GroupDescriptor> MatchingGroups(GroupImportDefinition groupToLinkTo, IDictionary <string, object> selectionCriteria)
 {
     return(m_GroupImportEngine.MatchingGroups(groupToLinkTo, selectionCriteria)
            .Select(
                g => new GroupDescriptor(
                    g,
                    OnGroupSelect,
                    OnGroupDeselect,
                    OnGroupConnect,
                    OnGroupDisconnect)));
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="CompositionLayerGroupEdge"/> class.
        /// </summary>
        /// <param name="importingGroup">The ID of the importing group.</param>
        /// <param name="importDefinition">The import definition.</param>
        /// <param name="exportingGroup">The ID of the exporting group.</param>
        public CompositionLayerGroupEdge(
            GroupCompositionId importingGroup,
            GroupImportDefinition importDefinition,
            GroupCompositionId exportingGroup)
            : base(exportingGroup, importingGroup)
        {
            {
                Debug.Assert(importDefinition != null, "The import definition should not be a null reference.");
            }

            m_Import = importDefinition;
        }
示例#8
0
        private Task OnGroupConnect(
            GroupCompositionId importingGroup,
            GroupImportDefinition importDefinition,
            GroupCompositionId exportingGroup,
            GroupExportDefinition exportDefinition)
        {
            if (!m_GroupImportEngine.Accepts(importDefinition, exportDefinition))
            {
                throw new CannotMapExportToImportException();
            }

            return(m_Graph.Connect(importingGroup, importDefinition, exportingGroup));
        }
示例#9
0
        public bool Accepts(GroupImportDefinition importDefinition, GroupExportDefinition exportDefinition)
        {
            if (importDefinition == null)
            {
                return(true);
            }

            if (!string.Equals(importDefinition.ContractName, exportDefinition.ContractName, StringComparison.OrdinalIgnoreCase))
            {
                return(false);
            }

            var importingGroup = m_Repository.Group(importDefinition.ContainingGroup);
            var exportingGroup = m_Repository.Group(exportDefinition.ContainingGroup);

            var isMatch = true;

            if (exportingGroup.Schedule != null)
            {
                isMatch = importDefinition.ScheduleInsertPosition != null;
            }

            if (isMatch)
            {
                var imports = importDefinition.ImportsToMatch.Select(i => importingGroup.Parts.PartImportById(i));
                var exports = exportDefinition.ProvidedExports.Select(e => exportingGroup.Parts.PartExportById(e));
                foreach (var import in imports)
                {
                    var foundMatch = false;
                    foreach (var export in exports)
                    {
                        if (m_PartImportEngine.Accepts(import, export))
                        {
                            foundMatch = true;
                        }
                    }

                    isMatch = isMatch && foundMatch;
                    if (!isMatch)
                    {
                        break;
                    }
                }
            }

            return(isMatch);
        }
示例#10
0
        public bool Accepts(GroupImportDefinition importDefinition, GroupExportDefinition exportDefinition)
        {
            if (importDefinition == null)
            {
                return true;
            }

            if (!string.Equals(importDefinition.ContractName, exportDefinition.ContractName, StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }

            var importingGroup = m_Repository.Group(importDefinition.ContainingGroup);
            var exportingGroup = m_Repository.Group(exportDefinition.ContainingGroup);

            var isMatch = true;
            if (exportingGroup.Schedule != null)
            {
                isMatch = importDefinition.ScheduleInsertPosition != null;
            }

            if (isMatch)
            {
                var imports = importDefinition.ImportsToMatch.Select(i => importingGroup.Parts.PartImportById(i));
                var exports = exportDefinition.ProvidedExports.Select(e => exportingGroup.Parts.PartExportById(e));
                foreach (var import in imports)
                {
                    var foundMatch = false;
                    foreach (var export in exports)
                    {
                        if (m_PartImportEngine.Accepts(import, export))
                        {
                            foundMatch = true;
                        }
                    }

                    isMatch = isMatch && foundMatch;
                    if (!isMatch)
                    {
                        break;
                    }
                }
            }

            return isMatch;
        }
示例#11
0
        public bool IsConnected(GroupCompositionId importingGroup, GroupImportDefinition importDefinition)
        {
            if ((importingGroup == null) || (importDefinition == null))
            {
                return(false);
            }

            if (!Contains(importingGroup))
            {
                return(false);
            }

            lock (m_Lock)
            {
                return(m_GroupConnections.InEdges(importingGroup).Any(e => e.Import.Equals(importDefinition)));
            }
        }
示例#12
0
        public void ConnectedToWithUnknownImportingGroup()
        {
            var commands          = new Mock <ICompositionCommands>();
            var connector         = new Mock <IConnectGroups>();
            var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null);
            var layer             = new ProxyCompositionLayer(commands.Object, connector.Object, systemDiagnostics);

            var importDefinition = GroupImportDefinition.CreateDefinition(
                "a",
                new GroupRegistrationId("b"),
                null,
                Enumerable.Empty <ImportRegistrationId>());

            Assert.IsNull(layer.ConnectedTo(null, importDefinition));
            Assert.IsNull(layer.ConnectedTo(new GroupCompositionId(), null));
            Assert.IsNull(layer.ConnectedTo(new GroupCompositionId(), importDefinition));
        }
示例#13
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GroupConnection"/> class.
        /// </summary>
        /// <param name="importingGroup">The ID of the group that provides the import.</param>
        /// <param name="exportingGroup">The ID of the group that provides the export.</param>
        /// <param name="import">The import definition that should be connected to.</param>
        /// <param name="partConnections">The collection that contains the mapping of the part imports to the part exports.</param>
        public GroupConnection(
            GroupCompositionId importingGroup,
            GroupCompositionId exportingGroup,
            GroupImportDefinition import,
            IEnumerable<PartImportToPartExportMap> partConnections)
        {
            {
                Lokad.Enforce.Argument(() => importingGroup);
                Lokad.Enforce.Argument(() => exportingGroup);
                Lokad.Enforce.Argument(() => import);
                Lokad.Enforce.Argument(() => partConnections);
            }

            m_ImportingGroup = importingGroup;
            m_ExportingGroup = exportingGroup;
            m_Import = import;
            m_PartConnections = partConnections;
        }
示例#14
0
        public void CanConnectToWithNonExistingExportGroup()
        {
            var importingId = new GroupCompositionId();
            var exportingId = new GroupCompositionId();

            var importEngine = new Mock <IConnectGroups>();
            var graph        = new Mock <ICompositionLayer>();
            {
                graph.Setup(g => g.Contains(It.IsAny <GroupCompositionId>()))
                .Returns <GroupCompositionId>(id => !id.Equals(exportingId));
            }

            var selector = new GroupSelector(importEngine.Object, graph.Object);

            Assert.IsFalse(
                selector.CanConnectTo(
                    importingId,
                    GroupImportDefinition.CreateDefinition("myContract", new GroupRegistrationId("a"), null, null),
                    exportingId));
        }
示例#15
0
        /// <summary>
        /// Creates the connection data that describes how the importing group and the exporting group should be connected.
        /// </summary>
        /// <param name="importingGroup">The ID of the group containing the import.</param>
        /// <param name="importDefinition">The import definition.</param>
        /// <param name="exportingGroup">The ID of the group containing the export.</param>
        /// <returns>A collection that describes how the parts of the importing and exporting group should be connected.</returns>
        public IEnumerable <PartImportToPartExportMap> GenerateConnectionFor(
            GroupDefinition importingGroup,
            GroupImportDefinition importDefinition,
            GroupDefinition exportingGroup)
        {
            if ((importingGroup == null) || (importDefinition == null) || (exportingGroup == null))
            {
                return(Enumerable.Empty <PartImportToPartExportMap>());
            }

            var importDefinitions = importDefinition
                                    .ImportsToMatch
                                    .Select(id => new Tuple <ImportRegistrationId, SerializableImportDefinition>(id, importingGroup.Parts.PartImportById(id)));
            var exportDefinitions = exportingGroup
                                    .GroupExport
                                    .ProvidedExports
                                    .Select(id => new Tuple <ExportRegistrationId, SerializableExportDefinition>(id, exportingGroup.Parts.PartExportById(id)))
                                    .ToList();

            var parts = new List <PartImportToPartExportMap>();

            foreach (var pair in importDefinitions)
            {
                var matchedExports = new List <Tuple <ExportRegistrationId, SerializableExportDefinition> >();
                foreach (var export in exportDefinitions)
                {
                    if (m_PartImportEngine.Accepts(pair.Item2, export.Item2))
                    {
                        matchedExports.Add(export);
                    }
                }

                parts.Add(new PartImportToPartExportMap(pair.Item1, matchedExports.Select(p => p.Item1).ToList()));
                foreach (var export in matchedExports)
                {
                    exportDefinitions.Remove(export);
                }
            }

            return(parts);
        }
        /// <summary>
        /// Registers a group with the currently stored data.
        /// </summary>
        /// <param name="name">The name of the newly created group.</param>
        /// <returns>The registration ID of the group.</returns>
        public GroupRegistrationId Register(string name)
        {
            var definition = new GroupDefinition(name);

            definition.Parts = m_Objects.SelectMany(p => p.Value).ToList();
            definition.InternalConnections = m_Connections.Select(
                p => new PartImportToPartExportMap(p.Key, (IEnumerable <ExportRegistrationId>)p.Value));

            if (m_Schedule != null)
            {
                definition.Schedule = ScheduleDefinition.CreateDefinition(
                    definition.Id,
                    m_Schedule,
                    m_Actions.ToDictionary(p => p.Value, p => p.Key),
                    m_Conditions.ToDictionary(p => p.Value, p => p.Key));
            }

            if (m_GroupExport != null)
            {
                definition.GroupExport = GroupExportDefinition.CreateDefinition(
                    m_GroupExport.ContractName,
                    definition.Id,
                    NonLinkedExports());
            }

            if (m_GroupImports.Count > 0)
            {
                definition.GroupImports = m_GroupImports.Select(
                    i => GroupImportDefinition.CreateDefinition(
                        i.Value.ContractName,
                        definition.Id,
                        i.Value.InsertPoint,
                        i.Value.ObjectImports))
                                          .ToList();
            }

            Clear();

            m_Repository.AddGroup(definition, m_FileInfo);
            return(definition.Id);
        }
示例#17
0
        public void MatchingGroupsWithGroupImport()
        {
            var groups = new List <GroupDefinition>
            {
                new GroupDefinition("Group1"),
                new GroupDefinition("Group2"),
                new GroupDefinition("Group3"),
            };
            var importEngine = new Mock <IConnectGroups>();
            {
                importEngine.Setup(i => i.MatchingGroups(It.IsAny <GroupImportDefinition>(), It.IsAny <IDictionary <string, object> >()))
                .Returns(new List <GroupDefinition> {
                    groups[0], groups[1]
                });
            }

            var selector       = new GroupSelector(importEngine.Object, new Mock <ICompositionLayer>().Object);
            var selectedGroups = selector.MatchingGroups(GroupImportDefinition.CreateDefinition("myContract", groups[0].Id, null, null));

            Assert.AreEqual(2, selectedGroups.Count());
        }
        public void Connect()
        {
            var lockKey     = new DatasetLockKey();
            var datasetLock = new Mock <ITrackDatasetLocks>();
            {
                datasetLock.Setup(d => d.LockForWriting())
                .Returns(lockKey)
                .Verifiable();
                datasetLock.Setup(d => d.RemoveWriteLock(It.IsAny <DatasetLockKey>()))
                .Callback <DatasetLockKey>(key => Assert.AreSame(lockKey, key))
                .Verifiable();
            }

            var originalConnection = new GroupConnection(
                new GroupCompositionId(),
                new GroupCompositionId(),
                GroupImportDefinition.CreateDefinition(
                    "a",
                    new GroupRegistrationId("a"),
                    null,
                    Enumerable.Empty <ImportRegistrationId>()),
                Enumerable.Empty <PartImportToPartExportMap>());
            var storage = new Mock <IStoreGroupsAndConnections>();
            {
                storage.Setup(s => s.Connect(It.IsAny <GroupConnection>()))
                .Callback <GroupConnection>(
                    id =>
                {
                    Assert.AreSame(originalConnection, id);
                });
            }

            var commands = new CompositionCommands(datasetLock.Object, storage.Object);
            var task     = commands.Connect(originalConnection);

            task.Wait();

            datasetLock.Verify(d => d.LockForWriting(), Times.Once());
            datasetLock.Verify(d => d.RemoveWriteLock(It.IsAny <DatasetLockKey>()), Times.Once());
        }
示例#19
0
        private void DisconnectParts(GroupCompositionId importingGroup, GroupImportDefinition importDefinition, GroupCompositionId exportingGroup)
        {
            var definitionId             = m_Groups[importingGroup];
            var importingGroupDefinition = m_Definitions[definitionId];
            var importingParts           = importDefinition
                                           .ImportsToMatch
                                           .Select(id => importingGroupDefinition.Parts.PartByImport(id))
                                           .Join(
                m_Parts,
                partDef => new PartCompositionId(importingGroup, partDef.Id),
                pair => pair.Key,
                (partDef, pair) => pair.Key);

            definitionId = m_Groups[exportingGroup];
            var exportingGroupDefinition = m_Definitions[definitionId];
            var exportingParts           = exportingGroupDefinition.GroupExport
                                           .ProvidedExports
                                           .Select(id => exportingGroupDefinition.Parts.PartByExport(id))
                                           .Join(
                m_Parts,
                partDef => new PartCompositionId(exportingGroup, partDef.Id),
                pair => pair.Key,
                (partDef, pair) => pair.Key);

            foreach (var importingPart in importingParts)
            {
                var matchedExports = m_PartConnections
                                     .InEdges(importingPart)
                                     .Where(edge => exportingParts.Contains(edge.Source))
                                     .Select(edge => new Tuple <ImportRegistrationId, PartCompositionId>(edge.ImportRegistration, edge.Source));

                foreach (var pair in matchedExports)
                {
                    DisconnectInstanceFromExport(importingPart, pair.Item1, pair.Item2);
                }

                m_PartConnections.RemoveInEdgeIf(importingPart, edge => exportingParts.Contains(edge.Source));
            }
        }
示例#20
0
        /// <summary>
        /// Returns the group information indicating which export the given import is connected to.
        /// </summary>
        /// <param name="importingGroup">The ID of the group owning the import.</param>
        /// <param name="importDefinition">The import.</param>
        /// <returns>The ID of the group the given import is connected to, if there is a connection; otherwise, <see langword="null" />.</returns>
        public GroupCompositionId ConnectedTo(
            GroupCompositionId importingGroup,
            GroupImportDefinition importDefinition)
        {
            if ((importingGroup == null) || (importDefinition == null))
            {
                return(null);
            }

            if (!Contains(importingGroup))
            {
                return(null);
            }

            lock (m_Lock)
            {
                return(m_GroupConnections.InEdges(importingGroup)
                       .Where(e => e.Import.Equals(importDefinition))
                       .Select(e => e.Source)
                       .FirstOrDefault());
            }
        }
示例#21
0
        /// <summary>
        /// Connects the given export to the given import.
        /// </summary>
        /// <param name="importingGroup">The ID of the group that owns the import.</param>
        /// <param name="importDefinition">The import.</param>
        /// <param name="exportingGroup">The ID of the group that owns the export.</param>
        /// <returns>A task which indicates when the connection has taken place.</returns>
        public Task Connect(
            GroupCompositionId importingGroup,
            GroupImportDefinition importDefinition,
            GroupCompositionId exportingGroup)
        {
            {
                Debug.Assert(importingGroup != null, "The ID of the importing group should not be a null reference.");
                Debug.Assert(importDefinition != null, "The import definition should not be a null reference.");
                Debug.Assert(exportingGroup != null, "The ID of the exporting group should not be a null reference.");
            }

            if (!Contains(importingGroup) || !Contains(exportingGroup))
            {
                throw new UnknownPartGroupException();
            }

            m_Diagnostics.Log(
                LevelToLog.Trace,
                HostConstants.LogPrefix,
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.ProxyCompositionLayer_LogMessage_ConnectingGroups_WithImportAndExport,
                    importingGroup,
                    exportingGroup));

            var parts      = m_Connector.GenerateConnectionFor(m_Groups[importingGroup], importDefinition, m_Groups[exportingGroup]);
            var state      = new GroupConnection(importingGroup, exportingGroup, importDefinition, parts);
            var remoteTask = m_Commands.Connect(state);

            return(remoteTask.ContinueWith(
                       t =>
            {
                lock (m_Lock)
                {
                    m_GroupConnections.AddEdge(new CompositionLayerGroupEdge(importingGroup, importDefinition, exportingGroup));
                }
            }));
        }
示例#22
0
        public void CanConnectToWithNonmatchingGroups()
        {
            var groups = new List <GroupDefinition>
            {
                new GroupDefinition("Group1"),
                new GroupDefinition("Group2"),
                new GroupDefinition("Group3"),
            };
            var importEngine = new Mock <IConnectGroups>();
            {
                importEngine.Setup(i => i.Accepts(It.IsAny <GroupImportDefinition>(), It.IsAny <GroupExportDefinition>()))
                .Returns(false);
                importEngine.Setup(i => i.ExportPassesSelectionCriteria(It.IsAny <GroupExportDefinition>(), It.IsAny <IDictionary <string, object> >()))
                .Returns(true);
            }

            var selector = new GroupSelector(importEngine.Object, new Mock <ICompositionLayer>().Object);

            Assert.IsFalse(
                selector.CanConnectTo(
                    new GroupCompositionId(),
                    GroupImportDefinition.CreateDefinition("myContract", groups[0].Id, null, null),
                    new GroupCompositionId()));
        }
示例#23
0
 /// <summary>
 /// Returns a collection containing all the groups which provide an export that can satisfy the given group import.
 /// </summary>
 /// <param name="groupToLinkTo">The import definition which should be satisfied.</param>
 /// <returns>A collection containing all the groups which satisfy the import condition.</returns>
 public IEnumerable<GroupDescriptor> MatchingGroups(GroupImportDefinition groupToLinkTo)
 {
     return MatchingGroups(groupToLinkTo, new Dictionary<string, object>());
 }
        public bool IsConnected(
            GroupCompositionId importingGroup,
            GroupImportDefinition importDefinition,
            GroupCompositionId exportingGroup)
        {
            if ((importingGroup == null) || (importDefinition == null) || (exportingGroup == null))
            {
                return false;
            }

            if (!Contains(importingGroup))
            {
                return false;
            }

            lock (m_Lock)
            {
                return m_GroupConnections.InEdges(importingGroup).Any(e => e.Import.Equals(importDefinition) && e.Source.Equals(exportingGroup));
            }
        }
        /// <summary>
        /// Returns the group information indicating which export the given import is connected to.
        /// </summary>
        /// <param name="importingGroup">The ID of the group owning the import.</param>
        /// <param name="importDefinition">The import.</param>
        /// <returns>The ID of the group the given import is connected to, if there is a connection; otherwise, <see langword="null" />.</returns>
        public GroupCompositionId ConnectedTo(
            GroupCompositionId importingGroup,
            GroupImportDefinition importDefinition)
        {
            if ((importingGroup == null) || (importDefinition == null))
            {
                return null;
            }

            if (!Contains(importingGroup))
            {
                return null;
            }

            lock (m_Lock)
            {
                return m_GroupConnections.InEdges(importingGroup)
                    .Where(e => e.Import.Equals(importDefinition))
                    .Select(e => e.Source)
                    .FirstOrDefault();
            }
        }
示例#26
0
        /// <summary>
        /// Creates the connection data that describes how the importing group and the exporting group should be connected.
        /// </summary>
        /// <param name="importingGroup">The ID of the group containing the import.</param>
        /// <param name="importDefinition">The import definition.</param>
        /// <param name="exportingGroup">The ID of the group containing the export.</param>
        /// <returns>A collection that describes how the parts of the importing and exporting group should be connected.</returns>
        public IEnumerable<PartImportToPartExportMap> GenerateConnectionFor(
            GroupDefinition importingGroup,
            GroupImportDefinition importDefinition,
            GroupDefinition exportingGroup)
        {
            if ((importingGroup == null) || (importDefinition == null) || (exportingGroup == null))
            {
                return Enumerable.Empty<PartImportToPartExportMap>();
            }

            var importDefinitions = importDefinition
                .ImportsToMatch
                .Select(id => new Tuple<ImportRegistrationId, SerializableImportDefinition>(id, importingGroup.Parts.PartImportById(id)));
            var exportDefinitions = exportingGroup
                .GroupExport
                .ProvidedExports
                .Select(id => new Tuple<ExportRegistrationId, SerializableExportDefinition>(id, exportingGroup.Parts.PartExportById(id)))
                .ToList();

            var parts = new List<PartImportToPartExportMap>();
            foreach (var pair in importDefinitions)
            {
                var matchedExports = new List<Tuple<ExportRegistrationId, SerializableExportDefinition>>();
                foreach (var export in exportDefinitions)
                {
                    if (m_PartImportEngine.Accepts(pair.Item2, export.Item2))
                    {
                        matchedExports.Add(export);
                    }
                }

                parts.Add(new PartImportToPartExportMap(pair.Item1, matchedExports.Select(p => p.Item1).ToList()));
                foreach (var export in matchedExports)
                {
                    exportDefinitions.Remove(export);
                }
            }

            return parts;
        }
示例#27
0
 /// <summary>
 /// Connects the export of the current group to the given import of another group.
 /// </summary>
 /// <param name="group">The ID of the group containing the import.</param>
 /// <param name="importToMatch">The import.</param>
 /// <returns>The task that will finish once the give connection has been made.</returns>
 public Task ConnectTo(GroupCompositionId group, GroupImportDefinition importToMatch)
 {
     return m_OnConnect(group, importToMatch, m_Id, m_Group.GroupExport);
 }
示例#28
0
 /// <summary>
 /// Connects the export of the current group to the given import of another group.
 /// </summary>
 /// <param name="group">The ID of the group containing the import.</param>
 /// <param name="importToMatch">The import.</param>
 /// <returns>The task that will finish once the give connection has been made.</returns>
 public Task ConnectTo(GroupCompositionId group, GroupImportDefinition importToMatch)
 {
     return(m_OnConnect(group, importToMatch, m_Id, m_Group.GroupExport));
 }
示例#29
0
 /// <summary>
 /// Returns a collection containing all the groups which provide an export that can satisfy the given group import.
 /// </summary>
 /// <param name="groupToLinkTo">The import definition which should be satisfied.</param>
 /// <returns>A collection containing all the groups which satisfy the import condition.</returns>
 public IEnumerable<GroupDefinition> MatchingGroups(GroupImportDefinition groupToLinkTo)
 {
     return MatchingGroups(groupToLinkTo, null);
 }
示例#30
0
 /// <summary>
 /// Returns a collection containing all the groups which provide an export that can satisfy the given group import.
 /// </summary>
 /// <param name="groupToLinkTo">The import definition which should be satisfied.</param>
 /// <returns>A collection containing all the groups which satisfy the import condition.</returns>
 public IEnumerable <GroupDefinition> MatchingGroups(GroupImportDefinition groupToLinkTo)
 {
     return(MatchingGroups(groupToLinkTo, null));
 }
示例#31
0
 /// <summary>
 /// Returns a collection containing all the groups which satisfy the given group import and match the given
 /// selection criteria.
 /// </summary>
 /// <param name="groupToLinkTo">The import definition which should be satisfied.</param>
 /// <param name="selectionCriteria">The collection containing all the selection criteria.</param>
 /// <returns>
 /// A collection containing all the groups which satisfy the given group import and match the given
 /// selection criteria.
 /// </returns>
 public IEnumerable <GroupDefinition> MatchingGroups(GroupImportDefinition groupToLinkTo, IDictionary <string, object> selectionCriteria)
 {
     return(m_Repository.Groups()
            .Where(g => Accepts(groupToLinkTo, g.GroupExport) && ExportPassesSelectionCriteria(g.GroupExport, selectionCriteria)));
 }
示例#32
0
        private static GroupDefinition CreateImportingDefinition()
        {
            var groupName = "Import";

            return(new GroupDefinition(groupName)
            {
                InternalConnections = Enumerable.Empty <PartImportToPartExportMap>(),
                Parts = new List <GroupPartDefinition>
                {
                    new GroupPartDefinition(
                        TypeIdentity.CreateDefinition(typeof(List <string>)),
                        0,
                        new Dictionary <ExportRegistrationId, SerializableExportDefinition>(),
                        new Dictionary <ImportRegistrationId, SerializableImportDefinition>
                    {
                        {
                            new ImportRegistrationId(typeof(string), 0, "PartContract1"),
                            PropertyBasedImportDefinition.CreateDefinition(
                                "PartContract1",
                                TypeIdentity.CreateDefinition(typeof(int)),
                                ImportCardinality.ExactlyOne,
                                false,
                                CreationPolicy.Any,
                                typeof(ImportOnPropertyWithType).GetProperty("ImportingProperty"))
                        }
                    },
                        new Dictionary <ScheduleActionRegistrationId, ScheduleActionDefinition>(),
                        new Dictionary <ScheduleConditionRegistrationId, ScheduleConditionDefinition>()),
                    new GroupPartDefinition(
                        TypeIdentity.CreateDefinition(typeof(List <double>)),
                        1,
                        new Dictionary <ExportRegistrationId, SerializableExportDefinition>(),
                        new Dictionary <ImportRegistrationId, SerializableImportDefinition>
                    {
                        {
                            new ImportRegistrationId(typeof(string), 1, "PartContract2"),
                            ConstructorBasedImportDefinition.CreateDefinition(
                                "PartContract2",
                                TypeIdentity.CreateDefinition(typeof(string)),
                                ImportCardinality.ExactlyOne,
                                CreationPolicy.Any,
                                typeof(Version).GetConstructor(
                                    new[]
                            {
                                typeof(string)
                            }).GetParameters().First())
                        }
                    },
                        new Dictionary <ScheduleActionRegistrationId, ScheduleActionDefinition>(),
                        new Dictionary <ScheduleConditionRegistrationId, ScheduleConditionDefinition>()),
                },
                GroupImports = new List <GroupImportDefinition>
                {
                    GroupImportDefinition.CreateDefinition(
                        "ContractName",
                        new GroupRegistrationId(groupName),
                        null,
                        new List <ImportRegistrationId>
                    {
                        new ImportRegistrationId(typeof(string), 0, "PartContract1"),
                        new ImportRegistrationId(typeof(string), 1, "PartContract2"),
                    })
                },
            });
        }
示例#33
0
 /// <summary>
 /// Returns a collection containing all the groups which provide an export that can satisfy the given group import.
 /// </summary>
 /// <param name="groupToLinkTo">The import definition which should be satisfied.</param>
 /// <returns>A collection containing all the groups which satisfy the import condition.</returns>
 public IEnumerable <GroupDescriptor> MatchingGroups(GroupImportDefinition groupToLinkTo)
 {
     return(MatchingGroups(groupToLinkTo, new Dictionary <string, object>()));
 }
        public void CurrentState()
        {
            var lockKey     = new DatasetLockKey();
            var datasetLock = new Mock <ITrackDatasetLocks>();
            {
                datasetLock.Setup(d => d.LockForReading())
                .Returns(lockKey)
                .Verifiable();
                datasetLock.Setup(d => d.RemoveReadLock(It.IsAny <DatasetLockKey>()))
                .Callback <DatasetLockKey>(key => Assert.AreSame(lockKey, key))
                .Verifiable();
            }

            var groups = new Dictionary <GroupCompositionId, Tuple <GroupDefinition, Tuple <GroupImportDefinition, GroupCompositionId> > >
            {
                {
                    new GroupCompositionId(),
                    new Tuple <GroupDefinition, Tuple <GroupImportDefinition, GroupCompositionId> >(
                        new GroupDefinition("a"),
                        new Tuple <GroupImportDefinition, GroupCompositionId>(
                            GroupImportDefinition.CreateDefinition(
                                "c",
                                new GroupRegistrationId("c"),
                                null,
                                Enumerable.Empty <ImportRegistrationId>()),
                            new GroupCompositionId()))
                },
                {
                    new GroupCompositionId(),
                    new Tuple <GroupDefinition, Tuple <GroupImportDefinition, GroupCompositionId> >(
                        new GroupDefinition("d"),
                        new Tuple <GroupImportDefinition, GroupCompositionId>(
                            GroupImportDefinition.CreateDefinition(
                                "e",
                                new GroupRegistrationId("e"),
                                null,
                                Enumerable.Empty <ImportRegistrationId>()),
                            new GroupCompositionId()))
                },
            };
            var storage = new Mock <IStoreGroupsAndConnections>();
            {
                storage.Setup(s => s.Groups())
                .Returns(groups.Keys);
                storage.Setup(s => s.Group(It.IsAny <GroupCompositionId>()))
                .Returns <GroupCompositionId>(id => groups[id].Item1);
                storage.Setup(s => s.SatisfiedImports(It.IsAny <GroupCompositionId>()))
                .Returns <GroupCompositionId>(id => new List <Tuple <GroupImportDefinition, GroupCompositionId> > {
                    groups[id].Item2
                });
            }

            var commands = new CompositionCommands(datasetLock.Object, storage.Object);
            var task     = commands.CurrentState();
            var results  = task.Result;

            Assert.That(
                results.Groups,
                Is.EquivalentTo(
                    groups.Select(p => new Tuple <GroupCompositionId, GroupDefinition>(p.Key, p.Value.Item1))));

            Assert.That(
                results.Connections,
                Is.EquivalentTo(
                    groups.Select(
                        p => new Tuple <GroupCompositionId, GroupImportDefinition, GroupCompositionId>(
                            p.Key,
                            p.Value.Item2.Item1,
                            p.Value.Item2.Item2))));

            datasetLock.Verify(d => d.LockForReading(), Times.Once());
            datasetLock.Verify(d => d.RemoveReadLock(It.IsAny <DatasetLockKey>()), Times.Once());
        }
        /// <summary>
        /// Connects the given export to the given import.
        /// </summary>
        /// <param name="importingGroup">The ID of the group that owns the import.</param>
        /// <param name="importDefinition">The import.</param>
        /// <param name="exportingGroup">The ID of the group that owns the export.</param>
        /// <returns>A task which indicates when the connection has taken place.</returns>
        public Task Connect(
            GroupCompositionId importingGroup,
            GroupImportDefinition importDefinition,
            GroupCompositionId exportingGroup)
        {
            {
                Debug.Assert(importingGroup != null, "The ID of the importing group should not be a null reference.");
                Debug.Assert(importDefinition != null, "The import definition should not be a null reference.");
                Debug.Assert(exportingGroup != null, "The ID of the exporting group should not be a null reference.");
            }

            if (!Contains(importingGroup) || !Contains(exportingGroup))
            {
                throw new UnknownPartGroupException();
            }

            m_Diagnostics.Log(
                LevelToLog.Trace,
                HostConstants.LogPrefix,
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.ProxyCompositionLayer_LogMessage_ConnectingGroups_WithImportAndExport,
                    importingGroup,
                    exportingGroup));

            var parts = m_Connector.GenerateConnectionFor(m_Groups[importingGroup], importDefinition, m_Groups[exportingGroup]);
            var state = new GroupConnection(importingGroup, exportingGroup, importDefinition, parts);
            var remoteTask = m_Commands.Connect(state);
            return remoteTask.ContinueWith(
                t =>
                {
                    lock (m_Lock)
                    {
                        m_GroupConnections.AddEdge(new CompositionLayerGroupEdge(importingGroup, importDefinition, exportingGroup));
                    }
                });
        }
示例#36
0
 public bool CanConnectTo(GroupCompositionId importingGroup, GroupImportDefinition importDefinition, GroupCompositionId exportingGroup)
 {
     return CanConnectTo(importingGroup, importDefinition, new Dictionary<string, object>(), exportingGroup);
 }
示例#37
0
 /// <summary>
 /// Returns a collection containing all the groups which satisfy the given group import and match the given
 /// selection criteria.
 /// </summary>
 /// <param name="groupToLinkTo">The import definition which should be satisfied.</param>
 /// <param name="selectionCriteria">The collection containing all the selection filters.</param>
 /// <returns>
 /// A collection containing all the groups which satisfy the given group import and match the given
 /// selection criteria.
 /// </returns>
 public IEnumerable<GroupDescriptor> MatchingGroups(GroupImportDefinition groupToLinkTo, IDictionary<string, object> selectionCriteria)
 {
     return m_GroupImportEngine.MatchingGroups(groupToLinkTo, selectionCriteria)
         .Select(
             g => new GroupDescriptor(
                 g,
                 OnGroupSelect,
                 OnGroupDeselect,
                 OnGroupConnect,
                 OnGroupDisconnect));
 }
示例#38
0
 /// <summary>
 /// Returns a collection containing all the groups which satisfy the given group import and match the given
 /// selection criteria.
 /// </summary>
 /// <param name="groupToLinkTo">The import definition which should be satisfied.</param>
 /// <param name="selectionCriteria">The collection containing all the selection criteria.</param>
 /// <returns>
 /// A collection containing all the groups which satisfy the given group import and match the given
 /// selection criteria.
 /// </returns>
 public IEnumerable<GroupDefinition> MatchingGroups(GroupImportDefinition groupToLinkTo, IDictionary<string, object> selectionCriteria)
 {
     return m_Repository.Groups()
         .Where(g => Accepts(groupToLinkTo, g.GroupExport) && ExportPassesSelectionCriteria(g.GroupExport, selectionCriteria));
 }
示例#39
0
        private Task OnGroupConnect(
            GroupCompositionId importingGroup,
            GroupImportDefinition importDefinition,
            GroupCompositionId exportingGroup,
            GroupExportDefinition exportDefinition)
        {
            if (!m_GroupImportEngine.Accepts(importDefinition, exportDefinition))
            {
                throw new CannotMapExportToImportException();
            }

            return m_Graph.Connect(importingGroup, importDefinition, exportingGroup);
        }
示例#40
0
 public bool CanConnectTo(GroupCompositionId importingGroup, GroupImportDefinition importDefinition, GroupCompositionId exportingGroup)
 {
     return(CanConnectTo(importingGroup, importDefinition, new Dictionary <string, object>(), exportingGroup));
 }
示例#41
0
        public bool CanConnectTo(
            GroupCompositionId importingGroup,
            GroupImportDefinition importDefinition,
            IDictionary<string, object> selectionCriteria,
            GroupCompositionId exportingGroup)
        {
            if (!m_Graph.Contains(importingGroup))
            {
                return false;
            }

            if (!m_Graph.Contains(exportingGroup))
            {
                return false;
            }

            if (m_Graph.IsConnected(importingGroup, importDefinition))
            {
                return false;
            }

            var group = m_Graph.Group(exportingGroup);
            return m_GroupImportEngine.Accepts(importDefinition, group.GroupExport)
                && m_GroupImportEngine.ExportPassesSelectionCriteria(group.GroupExport, selectionCriteria);
        }
示例#42
0
        private void DisconnectParts(GroupCompositionId importingGroup, GroupImportDefinition importDefinition, GroupCompositionId exportingGroup)
        {
            var definitionId = m_Groups[importingGroup];
            var importingGroupDefinition = m_Definitions[definitionId];
            var importingParts = importDefinition
                .ImportsToMatch
                .Select(id => importingGroupDefinition.Parts.PartByImport(id))
                .Join(
                    m_Parts,
                    partDef => new PartCompositionId(importingGroup, partDef.Id),
                    pair => pair.Key,
                    (partDef, pair) => pair.Key);

            definitionId = m_Groups[exportingGroup];
            var exportingGroupDefinition = m_Definitions[definitionId];
            var exportingParts = exportingGroupDefinition.GroupExport
                .ProvidedExports
                .Select(id => exportingGroupDefinition.Parts.PartByExport(id))
                .Join(
                    m_Parts,
                    partDef => new PartCompositionId(exportingGroup, partDef.Id),
                    pair => pair.Key,
                    (partDef, pair) => pair.Key);

            foreach (var importingPart in importingParts)
            {
                var matchedExports = m_PartConnections
                    .InEdges(importingPart)
                    .Where(edge => exportingParts.Contains(edge.Source))
                    .Select(edge => new Tuple<ImportRegistrationId, PartCompositionId>(edge.ImportRegistration, edge.Source));

                foreach (var pair in matchedExports)
                {
                    DisconnectInstanceFromExport(importingPart, pair.Item1, pair.Item2);
                }

                m_PartConnections.RemoveInEdgeIf(importingPart, edge => exportingParts.Contains(edge.Source));
            }
        }