Ejemplo n.º 1
0
        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());
        }
Ejemplo n.º 2
0
        public void AddGroup()
        {
            var repository = new PluginRepository();
            var definition = new GroupDefinition("a");

            var fileInfo = new PluginFileInfo("a", DateTimeOffset.Now);
            repository.AddGroup(definition, fileInfo);

            var groups = repository.Groups();
            Assert.AreEqual(1, groups.Count());
            Assert.AreSame(definition, groups.First());
            Assert.AreSame(definition, repository.Group(new GroupRegistrationId("a")));

            var files = repository.KnownPluginFiles();
            Assert.AreEqual(1, files.Count());
            Assert.AreSame(fileInfo, files.First());
        }
Ejemplo n.º 3
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;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Adds a new part group to the repository.
        /// </summary>
        /// <param name="group">The part group definition.</param>
        /// <param name="pluginFileInfo">The file info of the assembly which owns the group.</param>
        public void AddGroup(GroupDefinition group, PluginFileInfo pluginFileInfo)
        {
            lock (m_Lock)
            {
                {
                    Lokad.Enforce.Argument(() => group);
                    Lokad.Enforce.Argument(() => pluginFileInfo);
                    Lokad.Enforce.With<DuplicateGroupDefinitionException>(
                        !m_Groups.ContainsKey(group.Id),
                        Resources.Exceptions_Messages_DuplicateGroupDefinition);
                }

                m_Groups.Add(group.Id, new Tuple<GroupDefinition, PluginFileInfo>(group, pluginFileInfo));
                if (!m_PluginFiles.Contains(pluginFileInfo))
                {
                    m_PluginFiles.Add(pluginFileInfo);
                }
            }
        }
        public void Add()
        {
            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()));
                }

                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));
            }
        }
Ejemplo n.º 6
0
        /// <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;
        }
Ejemplo n.º 7
0
 private Task<GroupCompositionId> OnGroupSelect(GroupDefinition exportingGroup)
 {
     return m_Graph.Add(exportingGroup);
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Adds a new part group to the repository.
 /// </summary>
 /// <param name="group">The part group definition.</param>
 /// <param name="pluginFileInfo">The file info of the assembly which owns the group.</param>
 public void AddGroup(GroupDefinition group, PluginFileInfo pluginFileInfo)
 {
     m_Repository.AddGroup(group, pluginFileInfo);
 }
        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));
            }
        }
        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));
            }
        }
        public void ConnectWithUnknownImportingGroup()
        {
            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(new GroupCompositionId(), importDefinition, task.Result));
            }
        }
Ejemplo n.º 12
0
        public void RemovePlugins()
        {
            var currentlyBuilding = new Dictionary<Type, TypeIdentity>();
            var repository = new PluginRepository();

            Func<Type, TypeIdentity> identityGenerator = TypeIdentityBuilder.IdentityFactory(repository, currentlyBuilding);
            PartDefinition partDefinition = new PartDefinition
                {
                    Identity = identityGenerator(typeof(ExportOnProperty)),
                };

            var partFileInfo = new PluginFileInfo("a", DateTimeOffset.Now);
            repository.AddPart(partDefinition, partFileInfo);

            var groupDefinition = new GroupDefinition("b");
            var groupFileInfo = new PluginFileInfo("c", DateTimeOffset.Now);
            repository.AddGroup(groupDefinition, groupFileInfo);

            Assert.That(
                repository.KnownPluginFiles(),
                Is.EquivalentTo(
                    new List<PluginFileInfo>
                    {
                        partFileInfo,
                        groupFileInfo,
                    }));

            repository.RemovePlugins(
                new List<string>
                    {
                        partFileInfo.Path
                    });

            Assert.That(
                repository.KnownPluginFiles(),
                Is.EquivalentTo(
                    new List<PluginFileInfo>
                    {
                        groupFileInfo,
                    }));
            Assert.AreEqual(0, repository.Parts().Count());
            Assert.AreEqual(1, repository.Groups().Count());
            Assert.IsFalse(repository.ContainsDefinitionForType(typeof(ExportOnProperty).AssemblyQualifiedName));
        }
Ejemplo n.º 13
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);
        }
Ejemplo n.º 14
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;
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GroupDescriptor"/> class.
        /// </summary>
        /// <param name="group">The object that stores the data describing the current group.</param>
        /// <param name="onSelect">The method used to add the current group to the composition graph.</param>
        /// <param name="onDeselect">The method used to remove the current group from the composition graph.</param>
        /// <param name="onConnect">The method used to connect the export of the current group to an import of another group.</param>
        /// <param name="onDisconnect">The method used to disconnect the export of the current group from an import of another group.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="group"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="onSelect"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="onDeselect"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="onConnect"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="onDisconnect"/> is <see langword="null" />.
        /// </exception>
        public GroupDescriptor(
            GroupDefinition group,
            Func<GroupDefinition, Task<GroupCompositionId>> onSelect,
            Func<GroupCompositionId, Task> onDeselect,
            Func<GroupCompositionId, GroupImportDefinition, GroupCompositionId, GroupExportDefinition, Task> onConnect,
            Func<GroupCompositionId, GroupCompositionId, Task> onDisconnect)
        {
            {
                Lokad.Enforce.Argument(() => group);
                Lokad.Enforce.Argument(() => onSelect);
                Lokad.Enforce.Argument(() => onDeselect);
                Lokad.Enforce.Argument(() => onConnect);
                Lokad.Enforce.Argument(() => onDisconnect);
            }

            m_Group = group;
            m_OnSelect = onSelect;
            m_OnDeselect = onDeselect;
            m_OnConnect = onConnect;
            m_OnDisconnect = onDisconnect;
        }
Ejemplo n.º 16
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;
                });
        }