예제 #1
0
 public bool Contains(GroupCompositionId id)
 {
     lock (m_Lock)
     {
         return((id != null) && m_Groups.ContainsKey(id));
     }
 }
예제 #2
0
        /// <summary>
        /// Adds a new <see cref="GroupDefinition"/> to the graph and returns the ID for that group.
        /// </summary>
        /// <param name="id">The ID of the group that is being added.</param>
        /// <param name="group">The group that should be added to the graph.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="id"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="group"/> is <see langword="null" />.
        /// </exception>
        public void Add(GroupCompositionId id, GroupDefinition group)
        {
            {
                Lokad.Enforce.Argument(() => id);
                Lokad.Enforce.Argument(() => group);
            }

            if (!m_Definitions.ContainsKey(group.Id))
            {
                m_Definitions.Add(group.Id, group);
            }

            m_Groups.Add(id, group.Id);
            m_GroupConnections.AddVertex(id);

            foreach (var part in group.Parts)
            {
                var partId = new PartCompositionId(id, part.Id);
                m_Parts.Add(partId, new PartCompositionInfo(part));
                m_PartConnections.AddVertex(partId);
            }

            var parts = PartsForGroup(id);

            ConnectParts(group.InternalConnections, parts, parts);
        }
예제 #3
0
        /// <summary>
        /// Adds a new <see cref="GroupDefinition"/> to the graph and returns the ID for that group.
        /// </summary>
        /// <param name="group">The group that should be added to the graph.</param>
        /// <returns>
        /// A task which returns the ID for the group.
        /// </returns>
        public Task <GroupCompositionId> Add(GroupDefinition group)
        {
            {
                Debug.Assert(group != null, "The definition that should be added should not be a null reference.");
            }

            var id         = new GroupCompositionId();
            var remoteTask = m_Commands.Add(id, group);

            m_Diagnostics.Log(
                LevelToLog.Trace,
                HostConstants.LogPrefix,
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.ProxyCompositionLayer_LogMessage_AddingGroup_WithId,
                    id));

            return(remoteTask.ContinueWith(
                       t =>
            {
                lock (m_Lock)
                {
                    m_Groups.Add(id, group);
                    m_GroupConnections.AddVertex(id);
                }

                return id;
            }));
        }
        public void Add()
        {
            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 originalId = new GroupCompositionId();
            var originalDefinition = new GroupDefinition("a");
            var storage = new Mock<IStoreGroupsAndConnections>();
            {
                storage.Setup(s => s.Add(It.IsAny<GroupCompositionId>(), It.IsAny<GroupDefinition>()))
                    .Callback<GroupCompositionId, GroupDefinition>(
                        (id, def) =>
                        {
                            Assert.AreSame(originalId, id);
                            Assert.AreSame(originalDefinition, def);
                        });
            }

            var commands = new CompositionCommands(datasetLock.Object, storage.Object);
            var task = commands.Add(originalId, originalDefinition);
            task.Wait();

            datasetLock.Verify(d => d.LockForWriting(), Times.Once());
            datasetLock.Verify(d => d.RemoveWriteLock(It.IsAny<DatasetLockKey>()), Times.Once());
        }
예제 #5
0
        public void Remove()
        {
            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 originalId = new GroupCompositionId();
            var storage    = new Mock <IStoreGroupsAndConnections>();
            {
                storage.Setup(s => s.Remove(It.IsAny <GroupCompositionId>()))
                .Callback <GroupCompositionId>(
                    id =>
                {
                    Assert.AreSame(originalId, id);
                });
            }

            var commands = new CompositionCommands(datasetLock.Object, storage.Object);
            var task     = commands.Remove(originalId);

            task.Wait();

            datasetLock.Verify(d => d.LockForWriting(), Times.Once());
            datasetLock.Verify(d => d.RemoveWriteLock(It.IsAny <DatasetLockKey>()), Times.Once());
        }
예제 #6
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));
        }
예제 #7
0
        /// <summary>
        /// Removes the group that is related to the specified ID.
        /// </summary>
        /// <param name="group">The ID of the group that should be removed.</param>
        /// <returns>A task that indicates when the removal has taken place.</returns>
        public Task Remove(GroupCompositionId group)
        {
            {
                Debug.Assert(group != null, "The ID that should be removed should not be a null reference.");
                Debug.Assert(m_Groups.ContainsKey(group), "The ID should be known.");
            }

            m_Diagnostics.Log(
                LevelToLog.Trace,
                HostConstants.LogPrefix,
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.ProxyCompositionLayer_LogMessage_RemovingGroup_WithId,
                    group));

            var remoteTask = m_Commands.Remove(group);

            return(remoteTask.ContinueWith(
                       t =>
            {
                lock (m_Lock)
                {
                    if (m_GroupConnections.ContainsVertex(group))
                    {
                        m_GroupConnections.RemoveVertex(group);
                    }

                    if (m_Groups.ContainsKey(group))
                    {
                        m_Groups.Remove(group);
                    }
                }
            }));
        }
예제 #8
0
        /// <summary>
        /// Disconnects the group from all imports and exports.
        /// </summary>
        /// <param name="group">The composition ID of the group.</param>
        public void Disconnect(GroupCompositionId group)
        {
            if ((group == null) || !m_GroupConnections.ContainsVertex(group))
            {
                return;
            }

            var matchingExports = m_GroupConnections
                                  .InEdges(group)
                                  .Select(edge => new Tuple <GroupCompositionId, GroupImportDefinition>(edge.Source, edge.Import));

            foreach (var pair in matchingExports)
            {
                DisconnectParts(group, pair.Item2, pair.Item1);
            }

            var matchingImports = m_GroupConnections
                                  .OutEdges(group)
                                  .Select(edge => new Tuple <GroupCompositionId, GroupImportDefinition>(edge.Target, edge.Import));

            foreach (var pair in matchingImports)
            {
                DisconnectParts(pair.Item1, pair.Item2, group);
            }

            m_GroupConnections.RemoveInEdgeIf(group, edge => true);
            m_GroupConnections.RemoveOutEdgeIf(group, edge => true);
        }
예제 #9
0
        public void Create()
        {
            var group = new GroupCompositionId();
            var part  = new PartRegistrationId("a", 1);
            var id    = new PartCompositionId(group, part);

            Assert.AreEqual(group, id.Group);
            Assert.AreEqual(part, id.Part);
        }
예제 #10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PartCompositionId"/> class.
        /// </summary>
        /// <param name="group">The ID of the composed group that owns the current part.</param>
        /// <param name="part">The ID of the part registration that determines what the current part is.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="group"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="part"/> is <see langword="null" />.
        /// </exception>
        public PartCompositionId(GroupCompositionId group, PartRegistrationId part)
        {
            {
                Lokad.Enforce.Argument(() => group);
                Lokad.Enforce.Argument(() => part);
            }

            m_Group = group;
            m_Part  = part;
        }
예제 #11
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));
            }
        }
예제 #12
0
        public void Remove()
        {
            int index       = -1;
            var instanceIds = new List <PartInstanceId>
            {
                new PartInstanceId(),
                new PartInstanceId(),
                new PartInstanceId(),
                new PartInstanceId(),
                new PartInstanceId(),
            };
            var storage = new Mock <IStoreInstances>();
            {
                storage.Setup(
                    s => s.Construct(
                        It.IsAny <GroupPartDefinition>(),
                        It.IsAny <IEnumerable <Tuple <ImportRegistrationId, PartInstanceId, ExportRegistrationId> > >()))
                .Returns(
                    () =>
                {
                    index++;
                    return(instanceIds[index]);
                });

                storage.Setup(s => s.Release(It.IsAny <PartInstanceId>()))
                .Returns <PartInstanceId>(
                    i =>
                {
                    return(new List <InstanceUpdate>
                    {
                        new InstanceUpdate
                        {
                            Instance = i,
                            Change = InstanceChange.Removed,
                        }
                    });
                })
                .Verifiable();
            }

            var layer = CompositionLayer.CreateInstanceWithoutTimeline(storage.Object);

            var groupId    = new GroupCompositionId();
            var definition = CreateExportingDefinition();

            layer.Add(groupId, definition);

            Assert.AreEqual(1, layer.Groups().Count());
            Assert.AreSame(groupId, layer.Groups().First());
            Assert.AreSame(definition, layer.Group(groupId));

            layer.Remove(groupId);
            Assert.AreEqual(0, layer.Groups().Count());
            storage.Verify(s => s.Release(It.IsAny <PartInstanceId>()), Times.Exactly(5));
        }
예제 #13
0
        public void Remove()
        {
            GroupCompositionId storedId         = null;
            GroupDefinition    storedDefinition = null;

            using (var source = new CancellationTokenSource())
            {
                var commands = new Mock <ICompositionCommands>();
                {
                    commands.Setup(c => c.Add(It.IsAny <GroupCompositionId>(), It.IsAny <GroupDefinition>()))
                    .Callback <GroupCompositionId, GroupDefinition>(
                        (id, def) =>
                    {
                        storedId         = id;
                        storedDefinition = def;
                    })
                    .Returns(
                        Task.Factory.StartNew(
                            () => { },
                            source.Token,
                            TaskCreationOptions.None,
                            new CurrentThreadTaskScheduler()));

                    commands.Setup(c => c.Remove(It.IsAny <GroupCompositionId>()))
                    .Callback <GroupCompositionId>(id => storedId = id)
                    .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 definition = new GroupDefinition("Group1");
                var task       = layer.Add(definition);
                task.Wait();

                Assert.AreSame(storedId, task.Result);
                Assert.AreSame(definition, storedDefinition);
                Assert.IsTrue(layer.Contains(task.Result));

                var otherTask = layer.Remove(task.Result);
                otherTask.Wait();

                Assert.AreSame(task.Result, storedId);
                Assert.IsFalse(layer.Contains(task.Result));
            }
        }
예제 #14
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));
        }
예제 #15
0
        /// <summary>
        /// Returns the <see cref="GroupDefinition"/> that was registered with the given ID.
        /// </summary>
        /// <param name="id">The composition ID of the group.</param>
        /// <returns>The definition for the group with the given ID.</returns>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="id"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="UnknownGroupCompositionIdException">
        ///     Thrown if <paramref name="id"/> does not belong to a known group.
        /// </exception>
        public GroupDefinition Group(GroupCompositionId id)
        {
            {
                Lokad.Enforce.Argument(() => id);
                Lokad.Enforce.With <UnknownGroupCompositionIdException>(
                    m_Groups.ContainsKey(id),
                    Resources.Exceptions_Messages_UnknownGroupCompositionId);
            }

            var definitionId = m_Groups[id];

            Debug.Assert(m_Definitions.ContainsKey(definitionId), "There should be a definition with the given definition ID.");
            return(m_Definitions[definitionId]);
        }
예제 #16
0
        /// <summary>
        /// Selects the current group and adds it to the composition graph.
        /// </summary>
        /// <returns>The task that will return the ID for the group in the graph.</returns>
        public Task <GroupCompositionId> Select()
        {
            var task             = m_OnSelect(m_Group);
            var continuationTask = task.ContinueWith(
                t =>
            {
                lock (m_Lock)
                {
                    m_Id = t.Result;
                }

                return(t.Result);
            });

            return(continuationTask);
        }
예제 #17
0
        /// <summary>
        /// Returns the <see cref="GroupDefinition"/> which is related to the given ID.
        /// </summary>
        /// <param name="id">The ID of the requested group.</param>
        /// <returns>The requested group.</returns>
        public GroupDefinition Group(GroupCompositionId id)
        {
            {
                Debug.Assert(id != null, "The ID that should be removed should not be a null reference.");
            }

            lock (m_Lock)
            {
                if (!m_Groups.ContainsKey(id))
                {
                    throw new UnknownPartGroupException();
                }

                return(m_Groups[id]);
            }
        }
예제 #18
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)));
            }
        }
예제 #19
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;
        }
예제 #20
0
        /// <summary>
        /// Removes the <see cref="GroupDefinition"/> related to the given <paramref name="id"/> from the graph.
        /// </summary>
        /// <param name="id">The ID of the group that should be removed.</param>
        /// <returns>A task that will finish when the action has completed.</returns>
        public Task Remove(GroupCompositionId id)
        {
            var globalTask = Task.Factory.StartNew(
                () =>
            {
                var key = m_DatasetLock.LockForWriting();
                try
                {
                    m_CompositionLayer.Remove(id);
                }
                finally
                {
                    m_DatasetLock.RemoveWriteLock(key);
                }
            });

            return(globalTask);
        }
예제 #21
0
        /// <summary>
        /// Disconnects the given groups from each other.
        /// </summary>
        /// <param name="importingGroup">The ID of the importing group.</param>
        /// <param name="exportingGroup">The ID of the exporting group.</param>
        /// <returns>A task that will finish when the disconnection action has completed.</returns>
        public Task Disconnect(GroupCompositionId importingGroup, GroupCompositionId exportingGroup)
        {
            var globalTask = Task.Factory.StartNew(
                () =>
            {
                var key = m_DatasetLock.LockForWriting();
                try
                {
                    m_CompositionLayer.Disconnect(importingGroup, exportingGroup);
                }
                finally
                {
                    m_DatasetLock.RemoveWriteLock(key);
                }
            });

            return(globalTask);
        }
예제 #22
0
        /// <summary>
        /// Adds a new <see cref="GroupDefinition"/> to the graph and returns the ID for that group.
        /// </summary>
        /// <param name="id">The ID of the group.</param>
        /// <param name="group">The group that should be added to the graph.</param>
        /// <returns>A task that will finish when the action has completed.</returns>
        public Task Add(GroupCompositionId id, GroupDefinition group)
        {
            var globalTask = Task.Factory.StartNew(
                () =>
                {
                    var key = m_DatasetLock.LockForWriting();
                    try
                    {
                        m_CompositionLayer.Add(id, group);
                    }
                    finally
                    {
                        m_DatasetLock.RemoveWriteLock(key);
                    }
                });

            return globalTask;
        }
예제 #23
0
        /// <summary>
        /// Returns a collection of all imports owned by the specified group that have not been provided with an export.
        /// </summary>
        /// <param name="importOwner">The composition ID of the group that owns the imports.</param>
        /// <returns>A collection containing all imports that have not been provided with an export.</returns>
        public IEnumerable <GroupImportDefinition> UnsatisfiedImports(GroupCompositionId importOwner)
        {
            {
                Lokad.Enforce.Argument(() => importOwner);
                Lokad.Enforce.With <UnknownGroupCompositionIdException>(
                    m_Groups.ContainsKey(importOwner),
                    Resources.Exceptions_Messages_UnknownGroupCompositionId);
            }

            var definitionId = m_Groups[importOwner];

            Debug.Assert(m_Definitions.ContainsKey(definitionId), "There should be a definition for the current group.");
            var definition = m_Definitions[definitionId];

            var inEdges = m_GroupConnections.InEdges(importOwner);

            return(definition.GroupImports.Where(i => !inEdges.Any(e => e.Import.Equals(i))));
        }
예제 #24
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));
        }
예제 #25
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));
        }
예제 #26
0
        /// <summary>
        /// Removes the group that is related to the specified ID.
        /// </summary>
        /// <param name="group">The ID of the group that should be removed.</param>
        public void Remove(GroupCompositionId group)
        {
            if (group == null)
            {
                return;
            }

            if (!m_Groups.ContainsKey(group))
            {
                return;
            }

            var definitionId = m_Groups[group];
            var definition   = m_Definitions[definitionId];

            foreach (var part in definition.Parts)
            {
                var partId = new PartCompositionId(group, part.Id);
                Debug.Assert(m_Parts.ContainsKey(partId), "The part collection should have the given part ID.");
                Debug.Assert(m_PartConnections.ContainsVertex(partId), "The part connections graph should have the given part ID.");

                var info = m_Parts[partId];
                if (info.Instance != null)
                {
                    ReleaseInstance(partId);
                }

                m_PartConnections.RemoveVertex(partId);
                m_Parts.Remove(partId);
            }

            Debug.Assert(m_GroupConnections.ContainsVertex(group), "The connections graph should have the given group ID.");
            m_GroupConnections.RemoveVertex(group);

            m_Groups.Remove(group);
            if (!m_Groups.Any(p => p.Value.Equals(definitionId)))
            {
                m_Definitions.Remove(definitionId);
            }
        }
예제 #27
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));
            }
        }
예제 #28
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());
            }
        }
예제 #29
0
        /// <summary>
        /// Disconnects the exporting group from the importing group.
        /// </summary>
        /// <param name="importingGroup">The composition ID of the importing group.</param>
        /// <param name="exportingGroup">The composition ID of the exporting group.</param>
        public void Disconnect(GroupCompositionId importingGroup, GroupCompositionId exportingGroup)
        {
            if ((importingGroup == null) || (exportingGroup == null))
            {
                return;
            }

            if (!m_GroupConnections.ContainsVertex(importingGroup) || (!m_GroupConnections.ContainsVertex(exportingGroup)))
            {
                return;
            }

            var importDefinition = m_GroupConnections
                                   .InEdges(importingGroup)
                                   .Where(edge => edge.Source.Equals(exportingGroup))
                                   .Select(edge => edge.Import)
                                   .FirstOrDefault();

            m_GroupConnections.RemoveInEdgeIf(importingGroup, edge => edge.Source.Equals(exportingGroup));

            DisconnectParts(importingGroup, importDefinition, exportingGroup);
        }
예제 #30
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));
                }
            }));
        }
예제 #31
0
        /// <summary>
        /// Disconnects all connection to and from the given group.
        /// </summary>
        /// <param name="group">The ID of the group.</param>
        /// <returns>A task which indicates when the disconnection has taken place.</returns>
        public Task Disconnect(GroupCompositionId group)
        {
            {
                Debug.Assert(group != null, "The ID of the group should not be a null reference.");
            }

            m_Diagnostics.Log(
                LevelToLog.Trace,
                HostConstants.LogPrefix,
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.ProxyCompositionLayer_LogMessage_DisconnectingAllFromGroup_WithId,
                    group));

            var remoteTask = m_Commands.Disconnect(group);

            return(remoteTask.ContinueWith(
                       t =>
            {
                m_GroupConnections.RemoveInEdgeIf(group, edge => true);
                m_GroupConnections.RemoveOutEdgeIf(group, edge => true);
            }));
        }
예제 #32
0
        /// <summary>
        /// Disconnects the two groups.
        /// </summary>
        /// <remarks>
        /// This method assumes that two groups will only be connected via one import - export relation. This
        /// method will remove all connections from the exporting group to the importing group.
        /// </remarks>
        /// <param name="importingGroup">The ID of the group that owns the import.</param>
        /// <param name="exportingGroup">The ID of the group that owns the export.</param>
        /// <returns>A task which indicates when the disconnection has taken place.</returns>
        public Task Disconnect(GroupCompositionId importingGroup, GroupCompositionId exportingGroup)
        {
            {
                Debug.Assert(importingGroup != null, "The ID of the importing group should not be a null reference.");
                Debug.Assert(exportingGroup != null, "The ID of the exporting group should not be a null reference.");
            }

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

            var remoteTask = m_Commands.Disconnect(importingGroup, exportingGroup);

            return(remoteTask.ContinueWith(
                       t =>
            {
                m_GroupConnections.RemoveInEdgeIf(importingGroup, edge => edge.Source.Equals(exportingGroup));
            }));
        }
예제 #33
0
        /// <summary>
        /// Disconnects the two groups.
        /// </summary>
        /// <remarks>
        /// This method assumes that two groups will only be connected via one import - export relation. This
        /// method will remove all connections from the exporting group to the importing group.
        /// </remarks>
        /// <param name="importingGroup">The ID of the group that owns the import.</param>
        /// <param name="exportingGroup">The ID of the group that owns the export.</param>
        /// <returns>A task which indicates when the disconnection has taken place.</returns>
        public Task Disconnect(GroupCompositionId importingGroup, GroupCompositionId exportingGroup)
        {
            {
                Debug.Assert(importingGroup != null, "The ID of the importing group should not be a null reference.");
                Debug.Assert(exportingGroup != null, "The ID of the exporting group should not be a null reference.");
            }

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

            var remoteTask = m_Commands.Disconnect(importingGroup, exportingGroup);
            return remoteTask.ContinueWith(
                t =>
                {
                    m_GroupConnections.RemoveInEdgeIf(importingGroup, edge => edge.Source.Equals(exportingGroup));
                });
        }
예제 #34
0
        /// <summary>
        /// Returns the <see cref="GroupDefinition"/> which is related to the given ID.
        /// </summary>
        /// <param name="id">The ID of the requested group.</param>
        /// <returns>The requested group.</returns>
        public GroupDefinition Group(GroupCompositionId id)
        {
            {
                Debug.Assert(id != null, "The ID that should be removed should not be a null reference.");
            }

            lock (m_Lock)
            {
                if (!m_Groups.ContainsKey(id))
                {
                    throw new UnknownPartGroupException();
                }

                return m_Groups[id];
            }
        }
예제 #35
0
        /// <summary>
        /// Disconnects all connection to and from the given group.
        /// </summary>
        /// <param name="group">The ID of the group.</param>
        /// <returns>A task which indicates when the disconnection has taken place.</returns>
        public Task Disconnect(GroupCompositionId group)
        {
            {
                Debug.Assert(group != null, "The ID of the group should not be a null reference.");
            }

            m_Diagnostics.Log(
                LevelToLog.Trace,
                HostConstants.LogPrefix,
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.ProxyCompositionLayer_LogMessage_DisconnectingAllFromGroup_WithId,
                    group));

            var remoteTask = m_Commands.Disconnect(group);
            return remoteTask.ContinueWith(
                t =>
                {
                    m_GroupConnections.RemoveInEdgeIf(group, edge => true);
                    m_GroupConnections.RemoveOutEdgeIf(group, edge => true);
                });
        }
예제 #36
0
        /// <summary>
        /// Disconnects the exporting group from the importing group.
        /// </summary>
        /// <param name="importingGroup">The composition ID of the importing group.</param>
        /// <param name="exportingGroup">The composition ID of the exporting group.</param>
        public void Disconnect(GroupCompositionId importingGroup, GroupCompositionId exportingGroup)
        {
            if ((importingGroup == null) || (exportingGroup == null))
            {
                return;
            }

            if (!m_GroupConnections.ContainsVertex(importingGroup) || (!m_GroupConnections.ContainsVertex(exportingGroup)))
            {
                return;
            }

            var importDefinition = m_GroupConnections
                .InEdges(importingGroup)
                .Where(edge => edge.Source.Equals(exportingGroup))
                .Select(edge => edge.Import)
                .FirstOrDefault();
            m_GroupConnections.RemoveInEdgeIf(importingGroup, edge => edge.Source.Equals(exportingGroup));

            DisconnectParts(importingGroup, importDefinition, exportingGroup);
        }
예제 #37
0
        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));
            }
        }
예제 #38
0
        /// <summary>
        /// Returns a collection of all imports owned by the specified group that have not been provided with an export.
        /// </summary>
        /// <param name="importOwner">The composition ID of the group that owns the imports.</param>
        /// <returns>A collection containing all imports that have not been provided with an export.</returns>
        public IEnumerable<GroupImportDefinition> UnsatisfiedImports(GroupCompositionId importOwner)
        {
            {
                Lokad.Enforce.Argument(() => importOwner);
                Lokad.Enforce.With<UnknownGroupCompositionIdException>(
                    m_Groups.ContainsKey(importOwner),
                    Resources.Exceptions_Messages_UnknownGroupCompositionId);
            }

            var definitionId = m_Groups[importOwner];

            Debug.Assert(m_Definitions.ContainsKey(definitionId), "There should be a definition for the current group.");
            var definition = m_Definitions[definitionId];

            var inEdges = m_GroupConnections.InEdges(importOwner);
            return definition.GroupImports.Where(i => !inEdges.Any(e => e.Import.Equals(i)));
        }
예제 #39
0
        /// <summary>
        /// Disconnects the given group from all imports and exports.
        /// </summary>
        /// <param name="group">The group that should be disconnected.</param>
        /// <returns>A task that will finish when the disconnection action has completed.</returns>
        public Task Disconnect(GroupCompositionId group)
        {
            var globalTask = Task.Factory.StartNew(
                () =>
                {
                    var key = m_DatasetLock.LockForWriting();
                    try
                    {
                        m_CompositionLayer.Disconnect(group);
                    }
                    finally
                    {
                        m_DatasetLock.RemoveWriteLock(key);
                    }
                });

            return globalTask;
        }
예제 #40
0
        /// <summary>
        /// Selects the current group and adds it to the composition graph.
        /// </summary>
        /// <returns>The task that will return the ID for the group in the graph.</returns>
        public Task<GroupCompositionId> Select()
        {
            var task = m_OnSelect(m_Group);
            var continuationTask = task.ContinueWith(
                t =>
                {
                    lock (m_Lock)
                    {
                        m_Id = t.Result;
                    }

                    return t.Result;
                });

            return continuationTask;
        }
예제 #41
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));
            }
        }
예제 #42
0
 /// <summary>
 /// Disconnects the current group from the import of the given group.
 /// </summary>
 /// <param name="group">The ID of the importing group.</param>
 /// <returns>The task that will finish once the given connection is removed.</returns>
 public Task DisconnectFrom(GroupCompositionId group)
 {
     return m_OnDisconnect(group, m_Id);
 }
예제 #43
0
        /// <summary>
        /// Returns the <see cref="GroupDefinition"/> that was registered with the given ID.
        /// </summary>
        /// <param name="id">The composition ID of the group.</param>
        /// <returns>The definition for the group with the given ID.</returns>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="id"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="UnknownGroupCompositionIdException">
        ///     Thrown if <paramref name="id"/> does not belong to a known group.
        /// </exception>
        public GroupDefinition Group(GroupCompositionId id)
        {
            {
                Lokad.Enforce.Argument(() => id);
                Lokad.Enforce.With<UnknownGroupCompositionIdException>(
                    m_Groups.ContainsKey(id),
                    Resources.Exceptions_Messages_UnknownGroupCompositionId);
            }

            var definitionId = m_Groups[id];

            Debug.Assert(m_Definitions.ContainsKey(definitionId), "There should be a definition with the given definition ID.");
            return m_Definitions[definitionId];
        }
예제 #44
0
        /// <summary>
        /// Removes the group that is related to the specified ID.
        /// </summary>
        /// <param name="group">The ID of the group that should be removed.</param>
        public void Remove(GroupCompositionId group)
        {
            if (group == null)
            {
                return;
            }

            if (!m_Groups.ContainsKey(group))
            {
                return;
            }

            var definitionId = m_Groups[group];
            var definition = m_Definitions[definitionId];

            foreach (var part in definition.Parts)
            {
                var partId = new PartCompositionId(group, part.Id);
                Debug.Assert(m_Parts.ContainsKey(partId), "The part collection should have the given part ID.");
                Debug.Assert(m_PartConnections.ContainsVertex(partId), "The part connections graph should have the given part ID.");

                var info = m_Parts[partId];
                if (info.Instance != null)
                {
                    ReleaseInstance(partId);
                }

                m_PartConnections.RemoveVertex(partId);
                m_Parts.Remove(partId);
            }

            Debug.Assert(m_GroupConnections.ContainsVertex(group), "The connections graph should have the given group ID.");
            m_GroupConnections.RemoveVertex(group);

            m_Groups.Remove(group);
            if (!m_Groups.Any(p => p.Value.Equals(definitionId)))
            {
                m_Definitions.Remove(definitionId);
            }
        }
예제 #45
0
 private IEnumerable <Tuple <PartCompositionId, GroupPartDefinition> > PartsForGroup(GroupCompositionId group)
 {
     return(m_Parts
            .Where(pair => pair.Key.Group.Equals(group))
            .Select(pair => new Tuple <PartCompositionId, GroupPartDefinition>(pair.Key, m_Parts[pair.Key].Definition)));
 }
예제 #46
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);
 }
예제 #47
0
        /// <summary>
        /// Disconnects the group from all imports and exports.
        /// </summary>
        /// <param name="group">The composition ID of the group.</param>
        public void Disconnect(GroupCompositionId group)
        {
            if ((group == null) || !m_GroupConnections.ContainsVertex(group))
            {
                return;
            }

            var matchingExports = m_GroupConnections
                .InEdges(group)
                .Select(edge => new Tuple<GroupCompositionId, GroupImportDefinition>(edge.Source, edge.Import));
            foreach (var pair in matchingExports)
            {
                DisconnectParts(group, pair.Item2, pair.Item1);
            }

            var matchingImports = m_GroupConnections
                .OutEdges(group)
                .Select(edge => new Tuple<GroupCompositionId, GroupImportDefinition>(edge.Target, edge.Import));
            foreach (var pair in matchingImports)
            {
                DisconnectParts(pair.Item1, pair.Item2, group);
            }

            m_GroupConnections.RemoveInEdgeIf(group, edge => true);
            m_GroupConnections.RemoveOutEdgeIf(group, edge => true);
        }
예제 #48
0
 private Task OnGroupDeselect(GroupCompositionId id)
 {
     return m_Graph.Remove(id);
 }
예제 #49
0
 public bool Contains(GroupCompositionId id)
 {
     lock (m_Lock)
     {
         return (id != null) && m_Groups.ContainsKey(id);
     }
 }
예제 #50
0
 public bool CanConnectTo(GroupCompositionId importingGroup, GroupImportDefinition importDefinition, GroupCompositionId exportingGroup)
 {
     return CanConnectTo(importingGroup, importDefinition, new Dictionary<string, object>(), exportingGroup);
 }
예제 #51
0
        public void DisconnectImportFromExport()
        {
            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 originalImportId = new GroupCompositionId();
            var originalExportId = new GroupCompositionId();
            var storage = new Mock<IStoreGroupsAndConnections>();
            {
                storage.Setup(s => s.Disconnect(It.IsAny<GroupCompositionId>(), It.IsAny<GroupCompositionId>()))
                    .Callback<GroupCompositionId, GroupCompositionId>(
                        (importId, exportId) =>
                        {
                            Assert.AreSame(originalImportId, importId);
                            Assert.AreSame(originalExportId, exportId);
                        });
            }

            var commands = new CompositionCommands(datasetLock.Object, storage.Object);
            var task = commands.Remove(originalImportId);
            task.Wait();

            datasetLock.Verify(d => d.LockForWriting(), Times.Once());
            datasetLock.Verify(d => d.RemoveWriteLock(It.IsAny<DatasetLockKey>()), Times.Once());
        }
예제 #52
0
        /// <summary>
        /// Returns a collection of all imports owned by the specified group that have been provided with an export.
        /// </summary>
        /// <param name="importOwner">The composition ID of the group that owns the imports.</param>
        /// <returns>A collection containing all the imports with the group ID of the group providing the connected export.</returns>
        public IEnumerable<Tuple<GroupImportDefinition, GroupCompositionId>> SatisfiedImports(GroupCompositionId importOwner)
        {
            {
                Lokad.Enforce.Argument(() => importOwner);
                Lokad.Enforce.With<UnknownGroupCompositionIdException>(
                    m_Groups.ContainsKey(importOwner),
                    Resources.Exceptions_Messages_UnknownGroupCompositionId);
            }

            return m_GroupConnections.InEdges(importOwner).Select(e => new Tuple<GroupImportDefinition, GroupCompositionId>(e.Import, e.Source));
        }
예제 #53
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);
        }
예제 #54
0
        /// <summary>
        /// Removes the group that is related to the specified ID.
        /// </summary>
        /// <param name="group">The ID of the group that should be removed.</param>
        /// <returns>A task that indicates when the removal has taken place.</returns>
        public Task Remove(GroupCompositionId group)
        {
            {
                Debug.Assert(group != null, "The ID that should be removed should not be a null reference.");
                Debug.Assert(m_Groups.ContainsKey(group), "The ID should be known.");
            }

            m_Diagnostics.Log(
                LevelToLog.Trace,
                HostConstants.LogPrefix,
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.ProxyCompositionLayer_LogMessage_RemovingGroup_WithId,
                    group));

            var remoteTask = m_Commands.Remove(group);
            return remoteTask.ContinueWith(
                t =>
                {
                    lock (m_Lock)
                    {
                        if (m_GroupConnections.ContainsVertex(group))
                        {
                            m_GroupConnections.RemoveVertex(group);
                        }

                        if (m_Groups.ContainsKey(group))
                        {
                            m_Groups.Remove(group);
                        }
                    }
                });
        }
예제 #55
0
 private Task OnGroupDisconnect(GroupCompositionId importingGroup, GroupCompositionId exportingGroup)
 {
     return m_Graph.Disconnect(importingGroup, exportingGroup);
 }
예제 #56
0
        /// <summary>
        /// Returns a collection of all imports owned by the specified group that have been provided with an export.
        /// </summary>
        /// <param name="importOwner">The composition ID of the group that owns the imports.</param>
        /// <returns>A collection containing all the imports with the group ID of the group providing the connected export.</returns>
        public IEnumerable <Tuple <GroupImportDefinition, GroupCompositionId> > SatisfiedImports(GroupCompositionId importOwner)
        {
            {
                Lokad.Enforce.Argument(() => importOwner);
                Lokad.Enforce.With <UnknownGroupCompositionIdException>(
                    m_Groups.ContainsKey(importOwner),
                    Resources.Exceptions_Messages_UnknownGroupCompositionId);
            }

            return(m_GroupConnections.InEdges(importOwner).Select(e => new Tuple <GroupImportDefinition, GroupCompositionId>(e.Import, e.Source)));
        }
예제 #57
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);
        }
        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));
            }
        }
예제 #59
0
 private IEnumerable<Tuple<PartCompositionId, GroupPartDefinition>> PartsForGroup(GroupCompositionId group)
 {
     return m_Parts
         .Where(pair => pair.Key.Group.Equals(group))
         .Select(pair => new Tuple<PartCompositionId, GroupPartDefinition>(pair.Key, m_Parts[pair.Key].Definition));
 }
예제 #60
0
        /// <summary>
        /// Adds a new <see cref="GroupDefinition"/> to the graph and returns the ID for that group.
        /// </summary>
        /// <param name="id">The ID of the group that is being added.</param>
        /// <param name="group">The group that should be added to the graph.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="id"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="group"/> is <see langword="null" />.
        /// </exception>
        public void Add(GroupCompositionId id, GroupDefinition group)
        {
            {
                Lokad.Enforce.Argument(() => id);
                Lokad.Enforce.Argument(() => group);
            }

            if (!m_Definitions.ContainsKey(group.Id))
            {
                m_Definitions.Add(group.Id, group);
            }

            m_Groups.Add(id, group.Id);
            m_GroupConnections.AddVertex(id);

            foreach (var part in group.Parts)
            {
                var partId = new PartCompositionId(id, part.Id);
                m_Parts.Add(partId, new PartCompositionInfo(part));
                m_PartConnections.AddVertex(partId);
            }

            var parts = PartsForGroup(id);
            ConnectParts(group.InternalConnections, parts, parts);
        }