public void ExpandBlankString()
        {
            // Arrange
            var macros = new ProjectMacros();

            macros.Substitutions["ProjectDir"] = "pd";

            // Act
            string results = macros.ExpandMacros("");

            // Assert
            Assert.AreEqual("", results);
        }
        public void ExpandRepeatedValue()
        {
            // Arrange
            var macros = new ProjectMacros();

            macros.Substitutions["ProjectDir"]  = "pd";
            macros.Substitutions["ProjectPath"] = "{ProjectDir}/p";

            // Act
            string results = macros.ExpandMacros("{ProjectPath}");

            // Assert
            Assert.AreEqual("pd/p", results);
        }
        /// <summary>
        /// Setups the macros.
        /// </summary>
        /// <param name="directory">The directory.</param>
        /// <returns>The populated macros object.</returns>
        private ProjectMacros SetupMacros(DirectoryInfo directory)
        {
            // Create the macros and substitute the values.
            var macros = new ProjectMacros();

            macros.Substitutions["ProjectDirectory"]         = directory.FullName;
            macros.Substitutions["ProjectFilename"]          = Settings.ProjectFilename;
            macros.Substitutions["DataDirectory"]            = Settings.DataDirectory;
            macros.Substitutions["InternalContentDirectory"] =
                Settings.InternalContentDirectory;
            macros.Substitutions["ExternalSettingsDirectory"] =
                Settings.ExternalSettingsDirectory;

            // Return the resulting macros.
            return(macros);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="Project"/> class.
        /// </summary>
        public Project(
            ProjectProcessingState initialProcessingState =
            ProjectProcessingState.Interactive)
        {
            // Set up the initial states.
            ProcessingState = initialProcessingState;

            // We need the settings set up first since it may contribute
            // to the loading of other components of the project.
            Settings   = new ProjectSettings();
            Properties = new PropertiesDictionary();
            BlockTypes = new BlockTypeSupervisor(this);
            Blocks     = new ProjectBlockCollection(this);
            Commands   = new BlockCommandSupervisor(this);
            Plugins    = new PluginSupervisor(this);
            Macros     = new ProjectMacros();
        }
        /// <summary>
        /// Gets the macro or project XML writer. If the given variable expands to
        /// a value, an XML writer is created and returned. Otherwise, the given
        /// project writer is used instead.
        /// </summary>
        /// <param name="projectWriter">The project writer.</param>
        /// <param name="macros">The macros.</param>
        /// <param name="variable">The variable.</param>
        /// <param name="createdWriter">if set to <c>true</c> [created writer].</param>
        /// <returns></returns>
        protected static XmlWriter GetXmlWriter(
            XmlWriter projectWriter,
            ProjectMacros macros,
            string variable,
            out bool createdWriter)
        {
            // Expand the variable to get the filename.
            string filename = macros.ExpandMacros(variable);

            // If the value is null, then we use the project writer.
            if (string.IsNullOrWhiteSpace(filename))
            {
                createdWriter = false;
                return(projectWriter);
            }

            // Create the writer and return it.
            var       file   = new FileInfo(filename);
            XmlWriter writer = GetXmlWriter(file);

            createdWriter = true;

            return(writer);
        }
        public Project ReadProject(FileInfo projectFile)
        {
            // Open up an XML reader to pull out the critical components we
            // need to finish loading the file.
            FilesystemPersistenceSettings settings = null;

            using (FileStream stream = projectFile.Open(FileMode.Open, FileAccess.Read))
            {
                using (XmlReader reader = XmlReader.Create(stream))
                {
                    // Read until we get the file-persistent-settings file.
                    while (reader.Read())
                    {
                        // Ignore everything but the settings object we need to read.
                        if (reader.NamespaceURI != XmlConstants.ProjectNamespace ||
                            reader.NodeType != XmlNodeType.Element ||
                            reader.LocalName != FilesystemPersistenceSettings.XmlElementName)
                        {
                            continue;
                        }

                        // Load the settings object into memory.
                        var serializer = new XmlSerializer(typeof(FilesystemPersistenceSettings));
                        settings = (FilesystemPersistenceSettings)serializer.Deserialize(reader);
                    }
                }
            }

            // If we finish reading the file without getting the settings, blow up.
            if (settings == null)
            {
                throw new FileLoadException("Cannot load project: " + projectFile);
            }

            // Populate the macros we'll be using.
            var macros = new ProjectMacros();

            macros.Substitutions["ProjectDirectory"]         = projectFile.Directory.FullName;
            macros.Substitutions["ProjectFile"]              = projectFile.FullName;
            macros.Substitutions["DataDirectory"]            = settings.DataDirectory;
            macros.Substitutions["InternalContentDirectory"] =
                settings.InternalContentDirectory;
            macros.Substitutions["ExternalSettingsDirectory"] =
                settings.ExternalSettingsDirectory;

            // Load the project starting with the project. We create the project
            // in batch mode to avoid excessive processing.
            var project             = new Project(ProjectProcessingState.Batch);
            var projectReaderWriter = new FilesystemPersistenceProjectReader(
                project, settings, macros);

            projectReaderWriter.Read(projectFile);

            // Since we created the project in batch mode, we need to change it
            // back to interactive mode.
            project.SetProcessingState(ProjectProcessingState.Interactive);

            // Trigger any missing block analysis.
            project.Plugins.ProcessBlockAnalysis();

            // Return the resulting project.
            return(project);
        }