| 1 | using System;
 | 
|---|
| 2 | using System.Collections.Generic;
 | 
|---|
| 3 | using System.Reflection;
 | 
|---|
| 4 | using System.Text;
 | 
|---|
| 5 | using CLAP;
 | 
|---|
| 6 | using CLAP.Interception;
 | 
|---|
| 7 | using CLAP.Validation;
 | 
|---|
| 8 | 
 | 
|---|
| 9 | namespace xmlTools
 | 
|---|
| 10 | {
 | 
|---|
| 11 |     // Define a class to receive parsed values
 | 
|---|
| 12 |     class ParametersParser
 | 
|---|
| 13 |     {
 | 
|---|
| 14 |         private static string globalFileName = "";
 | 
|---|
| 15 |         private static string globalElement = "";
 | 
|---|
| 16 |         private static string globalParentElement = "";
 | 
|---|
| 17 |         private static bool globalNoBackups = false;
 | 
|---|
| 18 | 
 | 
|---|
| 19 |         [Verb]
 | 
|---|
| 20 |         public static void addValue(
 | 
|---|
| 21 |             [Parameter(Required = true, Description = "Values to add to Element. Separated multiple by spaces.")] string value
 | 
|---|
| 22 |             )
 | 
|---|
| 23 |         {
 | 
|---|
| 24 |             initialChecks();
 | 
|---|
| 25 |             XmlTools myTools = new XmlTools(globalElement, globalParentElement, globalNoBackups);
 | 
|---|
| 26 |             List<string> filesToProcess = getFilesToProcess(globalFileName);
 | 
|---|
| 27 |             foreach (string currentFile in filesToProcess)
 | 
|---|
| 28 |             {
 | 
|---|
| 29 |                 myTools.addValues(currentFile, value);
 | 
|---|
| 30 |             }
 | 
|---|
| 31 |             printProcessedMessage(filesToProcess.Count, MethodBase.GetCurrentMethod().Name);
 | 
|---|
| 32 |         }
 | 
|---|
| 33 | 
 | 
|---|
| 34 |         [Verb]
 | 
|---|
| 35 |         public static void removeValue(
 | 
|---|
| 36 |             [Parameter(Required = true, Description = "Values to remove of Element. Separated multiple by spaces.")] string value
 | 
|---|
| 37 |             )
 | 
|---|
| 38 |         {
 | 
|---|
| 39 |             initialChecks();
 | 
|---|
| 40 |             XmlTools myTools = new XmlTools(globalElement, globalParentElement, globalNoBackups);
 | 
|---|
| 41 |             List<string> filesToProcess = getFilesToProcess(globalFileName);
 | 
|---|
| 42 |             foreach (string currentFile in filesToProcess)
 | 
|---|
| 43 |             {
 | 
|---|
| 44 |                 myTools.removeValues(currentFile, value);
 | 
|---|
| 45 |             }
 | 
|---|
| 46 |             printProcessedMessage(filesToProcess.Count, MethodBase.GetCurrentMethod().Name);
 | 
|---|
| 47 |         }
 | 
|---|
| 48 | 
 | 
|---|
| 49 |         [Verb]
 | 
|---|
| 50 |         public static void updateChainValues(
 | 
|---|
| 51 |             [Parameter(Required = true, Description = "The new first value of the chain. All the chain will be updated based on this value")] string newValue,
 | 
|---|
| 52 |             [Parameter(Description = "Value which have some kind of relation with -newVal \n Together with -newVal updates all the values based on the" +
 | 
|---|
| 53 |                 "-newvalue and another position specified on -valrelation parameter (basically starts with (newvalue-valrelation) ) Is especially useful when" +
 | 
|---|
| 54 |                 "updating multiple related chains (on different files), like multiple objects from one position to another. Don't use with -filename, because" +
 | 
|---|
| 55 |                 "it will only update one file. \nExample: xmlTools.exe updatechainvalues -filename:OBANheli_body_center.xml -newvalue:\"1 1 1\" -valrelation:\"4 4 4\" -element:Translation -parelement:" +
 | 
|---|
| 56 |                 "OBANKeyFrame")] string valRelation,
 | 
|---|
| 57 |             [Parameter(Description = "Only update specific positions. Positions starts with 0, separted multiple positions with space. Example: valpositions=\"0 1 4\"")] [MoreThan(-1)]  string valPositions
 | 
|---|
| 58 |             )
 | 
|---|
| 59 |         {
 | 
|---|
| 60 |             initialChecks();
 | 
|---|
| 61 |             XmlTools myTools = new XmlTools(globalElement, globalParentElement, globalNoBackups);
 | 
|---|
| 62 |             List<string> filesToProcess = getFilesToProcess(globalFileName);
 | 
|---|
| 63 |             foreach (string currentFile in filesToProcess)
 | 
|---|
| 64 |             {
 | 
|---|
| 65 |                 myTools.changeValue(currentFile, newValue, valRelation, valPositions);
 | 
|---|
| 66 |             }
 | 
|---|
| 67 |             printProcessedMessage(filesToProcess.Count, MethodBase.GetCurrentMethod().Name);
 | 
|---|
| 68 |         }
 | 
|---|
| 69 | 
 | 
|---|
| 70 |         [Verb(Description = "Inverts a chain (like an OBAN animation). Example: xmlTools.exe -filename OBANheli_rotorblades08.xml -invert -valElement Translation -valParentElement OBANKeyFrame (inverts translation chain)")]
 | 
|---|
| 71 |         public static void Invert()
 | 
|---|
| 72 |         {
 | 
|---|
| 73 |             initialChecks();
 | 
|---|
| 74 |             XmlTools myTools = new XmlTools(globalElement, globalParentElement, globalNoBackups);
 | 
|---|
| 75 |             List<string> filesToProcess = getFilesToProcess(globalFileName);
 | 
|---|
| 76 |             foreach (string currentFile in filesToProcess)
 | 
|---|
| 77 |             {
 | 
|---|
| 78 |                 myTools.invert(currentFile); //Inverting the element order
 | 
|---|
| 79 |             }
 | 
|---|
| 80 |             printProcessedMessage(filesToProcess.Count, MethodBase.GetCurrentMethod().Name);
 | 
|---|
| 81 |         }
 | 
|---|
| 82 | 
 | 
|---|
| 83 |         [Verb]
 | 
|---|
| 84 |         public static void replaceValue(
 | 
|---|
| 85 |             [Parameter(Required = true, Description = "Old value to replace in Element.")] string oldValue,
 | 
|---|
| 86 |             [Parameter(Required = true, Description = "New value to replace in Element.")] string newValue
 | 
|---|
| 87 |             )
 | 
|---|
| 88 |         {
 | 
|---|
| 89 |             XmlTools myTools = new XmlTools(globalElement, globalParentElement, globalNoBackups);
 | 
|---|
| 90 |             List<string> filesToProcess = getFilesToProcess(globalFileName);
 | 
|---|
| 91 |             foreach (string currentFile in filesToProcess)
 | 
|---|
| 92 |             {
 | 
|---|
| 93 |                 myTools.replaceValue(currentFile, oldValue, newValue);
 | 
|---|
| 94 |             }
 | 
|---|
| 95 |             printProcessedMessage(filesToProcess.Count, MethodBase.GetCurrentMethod().Name);
 | 
|---|
| 96 |         }
 | 
|---|
| 97 | 
 | 
|---|
| 98 |         [Verb]
 | 
|---|
| 99 |         public static void replaceAll(
 | 
|---|
| 100 |             [Parameter(Required = true, Description = "Value to replace in Element. Replace all values of a element by another value.")] string value,
 | 
|---|
| 101 |             [Parameter(Description = "Only replace specific positions. Positions starts with 0, separted multiple positions with space. Example: valPositions=0 1 4")] [MoreThan(-1)] string valPositions
 | 
|---|
| 102 |             )
 | 
|---|
| 103 |         {
 | 
|---|
| 104 |             initialChecks();
 | 
|---|
| 105 |             XmlTools myTools = new XmlTools(globalElement, globalParentElement, globalNoBackups);
 | 
|---|
| 106 |             List<string> filesToProcess = getFilesToProcess(globalFileName);
 | 
|---|
| 107 |             foreach (string currentFile in filesToProcess)
 | 
|---|
| 108 |             {
 | 
|---|
| 109 |                 if (!String.IsNullOrEmpty(valPositions))
 | 
|---|
| 110 |                 {
 | 
|---|
| 111 |                     myTools.replaceAll(currentFile, value, valPositions);
 | 
|---|
| 112 |                 }
 | 
|---|
| 113 |                 else
 | 
|---|
| 114 |                 {
 | 
|---|
| 115 |                     myTools.replaceAll(currentFile, value);
 | 
|---|
| 116 |                 }
 | 
|---|
| 117 |             }
 | 
|---|
| 118 |             printProcessedMessage(filesToProcess.Count, MethodBase.GetCurrentMethod().Name);
 | 
|---|
| 119 |         }
 | 
|---|
| 120 | 
 | 
|---|
| 121 |         /// <summary>
 | 
|---|
| 122 |         /// Patch in files can be used with wildcard or empty filename instead
 | 
|---|
| 123 |         /// </summary>
 | 
|---|
| 124 |         /// <param name="filename"></param>
 | 
|---|
| 125 |         [Verb]
 | 
|---|
| 126 |         public static void patchFile(
 | 
|---|
| 127 |             [Parameter(Description = "Force the specified patch to run in specified files")] string forceInFiles
 | 
|---|
| 128 |             )
 | 
|---|
| 129 |         {
 | 
|---|
| 130 |             XmlPatch myPatch;
 | 
|---|
| 131 | 
 | 
|---|
| 132 |             if (!String.IsNullOrEmpty(forceInFiles))
 | 
|---|
| 133 |             {
 | 
|---|
| 134 |                 myPatch = new XmlPatch(globalFileName, forceInFiles, globalNoBackups);
 | 
|---|
| 135 |             }
 | 
|---|
| 136 |             else
 | 
|---|
| 137 |             {
 | 
|---|
| 138 |                 myPatch = new XmlPatch(globalFileName, globalNoBackups);
 | 
|---|
| 139 |             }
 | 
|---|
| 140 | 
 | 
|---|
| 141 |             myPatch.startPatch();
 | 
|---|
| 142 |         }
 | 
|---|
| 143 | 
 | 
|---|
| 144 |         [Verb(Description = "Displays current XmlTools version.")]
 | 
|---|
| 145 |         public static void version()
 | 
|---|
| 146 |         {
 | 
|---|
| 147 |             Console.WriteLine("xmlTools v" + Program.XmlToolsVersion);
 | 
|---|
| 148 |             Console.WriteLine("\nWritten by s10k");
 | 
|---|
| 149 |         }
 | 
|---|
| 150 | 
 | 
|---|
| 151 |         [Verb(Description = "Displays extra informations about XmlTools.")]
 | 
|---|
| 152 |         public static void about()
 | 
|---|
| 153 |         {
 | 
|---|
| 154 |             version();
 | 
|---|
| 155 |             Console.WriteLine();
 | 
|---|
| 156 |             Console.WriteLine("For extra XmlTools support check it page at: http://wiki.oni2.net/XmlTools");
 | 
|---|
| 157 |             Console.WriteLine();
 | 
|---|
| 158 |             Console.WriteLine("This program uses the following free libraries: ");
 | 
|---|
| 159 |             Console.WriteLine("-CLAP: for parameter parsing. (http://adrianaisemberg.github.io/CLAP/)");
 | 
|---|
| 160 |             Console.WriteLine("-IronJS: for custom javascript code execution. (https://github.com/fholm/IronJS)");
 | 
|---|
| 161 |             Console.WriteLine();
 | 
|---|
| 162 |             Console.WriteLine("A big thanks to all the oni.bungie.org community!");
 | 
|---|
| 163 |         }
 | 
|---|
| 164 | 
 | 
|---|
| 165 |         [Verb]
 | 
|---|
| 166 |         public static void showErrTypes()
 | 
|---|
| 167 |         {
 | 
|---|
| 168 |             Array values = Enum.GetValues(typeof(Program.appErrors));
 | 
|---|
| 169 | 
 | 
|---|
| 170 |             foreach (Program.appErrors val in values)
 | 
|---|
| 171 |             {
 | 
|---|
| 172 |                 Console.WriteLine(Enum.GetName(typeof(Program.appErrors),val) + " : " + (int)val);
 | 
|---|
| 173 |             }
 | 
|---|
| 174 |         }
 | 
|---|
| 175 | 
 | 
|---|
| 176 |         // Global Parameters
 | 
|---|
| 177 |         [Global(Description = "Filename to apply the operations (with patchFile specifies the patch filename). Wildcards accepted for multiple files. No filename = search all .xml files in current path.")]
 | 
|---|
| 178 |         public static void fileName(
 | 
|---|
| 179 |              [Parameter(Required = true)] string filename // xml filename. Wildcards accepted.
 | 
|---|
| 180 |             )
 | 
|---|
| 181 |         {
 | 
|---|
| 182 |             globalFileName = filename;
 | 
|---|
| 183 |         }
 | 
|---|
| 184 | 
 | 
|---|
| 185 |         [Global(Description = "Element to apply the operation.")]
 | 
|---|
| 186 |         public static void element(
 | 
|---|
| 187 |              [Parameter(Required = true)] string element
 | 
|---|
| 188 |             )
 | 
|---|
| 189 |         {
 | 
|---|
| 190 |             globalElement = element;
 | 
|---|
| 191 |         }
 | 
|---|
| 192 | 
 | 
|---|
| 193 |         [Global(Description = "Parent of the Element to apply the operation.")]
 | 
|---|
| 194 |         public static void parElement(
 | 
|---|
| 195 |              [Parameter(Required = true)] string parentElement
 | 
|---|
| 196 |             )
 | 
|---|
| 197 |         {
 | 
|---|
| 198 |             globalParentElement = parentElement;
 | 
|---|
| 199 |         }
 | 
|---|
| 200 | 
 | 
|---|
| 201 |         [Global(Description = "Don't make backup of the files modified. Improves the overall program processing performance.")]
 | 
|---|
| 202 |         public static void noBackups()
 | 
|---|
| 203 |         {
 | 
|---|
| 204 |             globalNoBackups = true;
 | 
|---|
| 205 |         }
 | 
|---|
| 206 | 
 | 
|---|
| 207 |         // Private functions
 | 
|---|
| 208 |         private static List<String> getFilesToProcess(String filename)
 | 
|---|
| 209 |         {
 | 
|---|
| 210 |             List<String> filesToProccess = new List<String>();
 | 
|---|
| 211 | 
 | 
|---|
| 212 |             if (String.IsNullOrEmpty(filename)) // No filename? Process everything xml file found.
 | 
|---|
| 213 |             {
 | 
|---|
| 214 |                 List<string> allXmlFiles = Util.getAllXmlFiles();
 | 
|---|
| 215 |                 foreach (String file in allXmlFiles)
 | 
|---|
| 216 |                 {
 | 
|---|
| 217 |                     filesToProccess.Add(file);
 | 
|---|
| 218 |                 }
 | 
|---|
| 219 |             }
 | 
|---|
| 220 |             else if (Util.containsWildcard(filename)) // Contains wildcards? Get all files that match it.
 | 
|---|
| 221 |             {
 | 
|---|
| 222 |                 List<string> matchingWildcardFiles = Util.getXmlFilesWildcard(filename);
 | 
|---|
| 223 |                 foreach (String file in matchingWildcardFiles)
 | 
|---|
| 224 |                 {
 | 
|---|
| 225 |                     filesToProccess.Add(file);
 | 
|---|
| 226 |                 }
 | 
|---|
| 227 |             }
 | 
|---|
| 228 |             else // Add the file specified
 | 
|---|
| 229 |             {
 | 
|---|
| 230 |                 if (System.IO.File.Exists(filename))
 | 
|---|
| 231 |                 {
 | 
|---|
| 232 |                     filesToProccess.Add(filename);
 | 
|---|
| 233 |                 }
 | 
|---|
| 234 |                 else
 | 
|---|
| 235 |                 {
 | 
|---|
| 236 |                     Program.printAppError(Program.appErrors.FILE_NOT_FOUND, "The file specified: " + filename + " doesn't exists.", true);
 | 
|---|
| 237 |                 }
 | 
|---|
| 238 |             }
 | 
|---|
| 239 |             return filesToProccess;
 | 
|---|
| 240 |         }
 | 
|---|
| 241 | 
 | 
|---|
| 242 |         private static void printProcessedMessage(int count, string methodName)
 | 
|---|
| 243 |         {
 | 
|---|
| 244 |             Console.WriteLine(count + " files processed with " + methodName + " command.");
 | 
|---|
| 245 |         }
 | 
|---|
| 246 | 
 | 
|---|
| 247 |         private static void initialChecks()
 | 
|---|
| 248 |         {
 | 
|---|
| 249 |             if (String.IsNullOrEmpty(globalElement.Trim()))
 | 
|---|
| 250 |             {
 | 
|---|
| 251 |                 Program.printAppError(Program.appErrors.ELEMENT_NOT_FOUND, "You must specify the element parameter where the operations will be processed.", true);
 | 
|---|
| 252 |             }
 | 
|---|
| 253 | 
 | 
|---|
| 254 |         }
 | 
|---|
| 255 |     }
 | 
|---|
| 256 | }
 | 
|---|