/// <summary>
        /// 
        /// </summary>
        private DestinationFilePattern[] CreateStaticElements(WatchFolder wf, DestinationFilePattern[] pattern)
        {
            if (wf == null) return null;

            // There is only one WatchAction per WatchFolder

            Log.Instance.Debug("CreateStaticFileNameElements: Processing " + wf.FolderToWatch.QuoteWrap() + " destination folder pattern.");

            foreach (DestinationFilePattern fp in pattern)
            {
                if (fp.IsField)
                {
                    switch (fp.Element)
                    {
                        case "METERNAME":
                            if (string.IsNullOrEmpty(wf.MeterInfo.Name))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.Name;
                            fp.IsField = false;
                            break;
                        case "METERSN":
                            if (string.IsNullOrEmpty(wf.MeterInfo.SN))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.SN;
                            fp.IsField = false;
                            break;
                        case "METERASSETID":
                            if (string.IsNullOrEmpty(wf.MeterInfo.AssetID))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.AssetID;
                            fp.IsField = false;
                            break;
                        case "METERALIAS":
                            if (string.IsNullOrEmpty(wf.MeterInfo.Alias))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.Alias;
                            fp.IsField = false;
                            break;
                        case "METERSUBSTATATIONNAME":
                            if (string.IsNullOrEmpty(wf.MeterInfo.StationName))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.StationName;
                            fp.IsField = false;
                            break;
                        case "METERVENDOR":
                            if (string.IsNullOrEmpty(wf.MeterInfo.Vendor))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.Vendor;
                            fp.IsField = false;
                            break;
                        case "METERSUBSTATIONID":
                            if (string.IsNullOrEmpty(wf.MeterInfo.StationID))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.StationID;
                            fp.IsField = false;
                            break;
                        case "APPPATH":
                            fp.PathPieceText = Path.GetDirectoryName(Assembly.GetAssembly(typeof(XDAFileWatcher)).CodeBase);
                            fp.IsField = false;
                            break;
                    }
                }
                else
                {
                    // Not a field
                    fp.PathPieceText = fp.Element;
                }
            }
            return pattern;
        }
        private string BuildDestinationName(string sourceFullPath, DestinationFilePattern[] patternSet, bool isFolderPathPiece)
        {
            StringBuilder outString = new StringBuilder();

            string[] folders = FilePath.DropPathRoot(FilePath.GetAbsolutePath(sourceFullPath))
                .Split(Path.DirectorySeparatorChar)
                .Where(f => !string.IsNullOrEmpty(f))
                .ToArray();

            int level;

            foreach (DestinationFilePattern p in patternSet)
            {
                if (p.IsField)
                {
                    switch (p.Element)
                    {
                        case "FOLDER":
                            outString.Append(folders[folders.Length - 1]);
                            break;

                        case "FILEDATETIME":
                            outString.Append(Directory.GetCreationTime(sourceFullPath).ToShortDateString().Replace('/', '-').RemoveCharacters(c => c == ':'));
                            outString.Append(" ");
                            outString.Append(Directory.GetCreationTime(sourceFullPath).ToShortTimeString().RemoveCharacters(c => c == ':'));
                            break;

                        case "FILEDATE":
                            outString.Append(Directory.GetCreationTime(sourceFullPath).ToShortDateString().Replace('/', '-'));
                            break;

                        case "FILETIME":
                            outString.Append(Directory.GetCreationTime(sourceFullPath).ToShortTimeString().RemoveCharacters(c => c == ':'));
                            break;

                        case "CURRENTDATETIME":
                            outString.Append(DateTime.UtcNow.ToShortDateString().Replace('/', '-').RemoveCharacters(c => c == ':'));
                            outString.Append(" ");
                            outString.Append(DateTime.UtcNow.ToShortTimeString().RemoveCharacters(c => c == ':'));
                            break;

                        case "CURRENTDATE":
                            outString.Append(DateTime.UtcNow.ToShortDateString().Replace('/', '-'));
                            break;

                        case "CURRENTTIME":
                            outString.Append(DateTime.UtcNow.ToShortTimeString().RemoveCharacters(c => c == ':'));
                            break;

                        case "EXISTINGFILENAME":
                            outString.Append(FilePath.GetFileNameWithoutExtension(sourceFullPath));
                            break;

                        default:
                            if (p.Element.StartsWith("FOLDER") && int.TryParse(p.Element.Substring("FOLDER".Length).Trim(), out level))
                                outString.Append(folders[folders.Length - (level + 1)]);

                            break;
                    }
                }
                else if (isFolderPathPiece)
                {
                    string pathPieceText = p.PathPieceText.Trim();

                    if (pathPieceText != "\\" && pathPieceText.StartsWith("\\") || pathPieceText.EndsWith("\\"))
                        outString = new StringBuilder(Path.Combine(outString.ToString(), pathPieceText));
                    else
                        outString.Append(pathPieceText);
                }
                else
                {
                    outString.Append(p.PathPieceText.Trim());
                }
            }

            return outString.ToString();
        }
        /// <summary>
        /// Parses the output file inPatternString from the destination parameter in each action tag
        /// </summary>
        private DestinationFilePattern[] CreateOutputPattern(string inPatternString)
        {
            List<DestinationFilePattern> outputPatterns;
            DestinationFilePattern outputPattern;

            string element;
            bool isField;

            if (string.IsNullOrEmpty(inPatternString))
                return null;

            outputPatterns = new List<DestinationFilePattern>();
            isField = false;

            element = GetNextElement(ref inPatternString, ref isField);

            while (inPatternString.Length > 0 || element.Length > 0)
            {
                if (isField)
                {
                    // Case insensitive
                    element = element.ToUpper();
                }
                else
                {
                    // Can't let element form improper filename
                    element = element.RemoveCharacters(c => Path.GetInvalidPathChars().Contains(c));
                }

                if (element.Length > 0)
                {
                    outputPattern = new DestinationFilePattern();
                    outputPattern.Element = element;
                    outputPattern.IsField = isField;
                    Log.Instance.Debug("CreateOutputFileNamePattern: Index = " + outputPatterns.Count + " IsField = " + isField.ToString() + " Element = " + element.QuoteWrap());
                    outputPatterns.Add(outputPattern);
                }

                element = GetNextElement(ref inPatternString, ref isField);
            }

            return (outputPatterns.Count > 0) ? outputPatterns.ToArray() : null;
        }
        /// <summary>
        /// 
        /// </summary>
        private void LogPatternString(DestinationFilePattern[] pattern, bool isFolderPathPiece, int folderID)
        {
            StringBuilder sb = new StringBuilder();
            int j = 0;
            foreach (DestinationFilePattern p in pattern)
            {
                j++;
                sb.Append("Element ");
                sb.Append(j.ToString());
                sb.Append(": ");
                if (p.IsField)
                {
                    sb.Append("{" + p.Element + "}");
                }
                else
                {
                    sb.Append(p.PathPieceText.QuoteWrap());
                }
                sb.Append(";  ");
            }

            string message = "File";
            if (isFolderPathPiece) message = "Folder";

            Log.Instance.Info("watchFolder " + folderID.ToString() + ": Destination " + message + " Parms = " + sb.ToString());
        }