/// <summary> /// Processes old XML Schema and incrementally updates them to the current running version /// </summary> static void ProcessSchema(Version NewVersion) { Version runningVersion = null; if (XmlJournal.Element("Journal").Attribute("Schema") != null) { Version.TryParse(XmlJournal.Element("Journal").Attribute("Schema").Value, out runningVersion); } if (runningVersion == null && NewVersion == new Version(1, 1, 0)) { TShockAPI.Log.ConsoleInfo("seconomy xml: upgrading xml schema to v1.1.0"); foreach (XElement bankAccount in XmlJournal.XPathSelectElements("/Journal/BankAccounts/BankAccount")) { //assign a new bank account ID string newId = RandomString(8); string oldID = bankAccount.Attribute("BankAccountK").Value; bankAccount.Attribute("BankAccountK").SetValue(newId); foreach (XElement transElement in XmlJournal.XPathSelectElements(string.Format("/Journal/Transactions/Transaction[@BankAccountFK={0}]", oldID))) { transElement.Attribute("BankAccountFK").SetValue(newId); } } if (XmlJournal.Element("Journal").Attribute("Schema") == null) { XmlJournal.Element("Journal").Add(new XAttribute("Schema", NewVersion.ToString())); } else { XmlJournal.Element("Journal").Attribute("Schema").SetValue(NewVersion.ToString()); } SaveXml(Configuration.JournalPath); } if (runningVersion != null && runningVersion != new Version(1, 2, 0)) { TShockAPI.Log.ConsoleInfo("seconomy xml: upgrading xml schema to v1.2.0"); XmlJournal.Declaration = new XDeclaration("1.0", "utf-8", "yes"); if (XmlJournal.Element("Journal").Attribute("Schema") == null) { XmlJournal.Element("Journal").Add(new XAttribute("Schema", NewVersion.ToString())); } else { XmlJournal.Element("Journal").Attribute("Schema").SetValue(NewVersion.ToString()); } SaveXml(Configuration.JournalPath); } }
/// <summary> /// Adds an XTransaction to the transactions collection. /// </summary> public static XTransaction AddTransaction(XTransaction Transaction) { lock (__staticLock) { Transaction.BankAccountTransactionK = RandomString(8); XmlJournal.XPathSelectElement("/Journal/Transactions").Add((XElement)Transaction); return(Transaction); } }
/// <summary> /// Adds an XBankAccount to the bank account collection. /// </summary> public static XBankAccount AddBankAccount(XBankAccount Account) { lock (__staticLock) { Account.BankAccountK = RandomString(8); XmlJournal.XPathSelectElement("/Journal/BankAccounts").Add((XElement)Account); return(Account); } }
/// <summary> /// Loads a journal from file. /// </summary> public static void LoadFromXmlFile(string Path) { TShockAPI.Log.ConsoleInfo("seconomy xml: Loading journal"); try { byte[] fileData = File.ReadAllBytes(Path); TShockAPI.Log.ConsoleInfo("seconomy xml: decompressing the journal"); byte[] uncompressedData = GZipDecompress(fileData); TShockAPI.Log.ConsoleInfo(string.Format("seconomy xml: gz {0} Kbytes -> {1} Kbytes", fileData.Length / 1024, uncompressedData.Length / 1024)); //You can't use XDocument.Parse when you have an XDeclaration for some even dumber reason than the write //issue, XDocument has to be constructed from a .net 3.5 XmlReader in this case //or you get a parse exception complaining about literal content. using (MemoryStream ms = new MemoryStream(uncompressedData)) { using (XmlTextReader xmlStream = new XmlTextReader(ms)) { XmlJournal = XDocument.Load(xmlStream); } } var accountCount = XmlJournal.XPathEvaluate("count(/Journal/BankAccounts/BankAccount)"); var tranCount = XmlJournal.XPathEvaluate("count(/Journal/Transactions/Transaction)"); //Used for XML Schema updates, make sure everyone is running on the same data structure ProcessSchema(XmlSchemaVersion); TShockAPI.Log.ConsoleInfo(string.Format("seconomy xml: Load clean: {0} accounts and {1} trans.", accountCount, tranCount)); } catch (Exception ex) { if (ex is System.IO.FileNotFoundException || ex is System.IO.DirectoryNotFoundException) { TShockAPI.Log.ConsoleError("seconomy xml: Cannot find file or directory. Creating new one."); XmlJournal = NewJournal(); SaveXml(Path); } else if (ex is System.Security.SecurityException) { TShockAPI.Log.ConsoleError("seconomy xml: Access denied reading file " + Path); } else { TShockAPI.Log.ConsoleError("seconomy xml: error " + ex.ToString()); } } }
/// <summary> /// Deletes all transactions for an account, effectively returning their balance back to 0. /// </summary> public static void ResetAccountTransactions(string BankAccountK) { lock (__staticLock) { do { XElement trans = XmlJournal.XPathSelectElement(string.Format("/Journal/Transactions/Transaction[@BankAccountFK=\"{0}\"]", BankAccountK)); if (trans == null) { break; } var sourceTransactionFK = trans.Attribute("BankAccountTransactionFK").Value; XElement sourceTrans = XmlJournal.XPathSelectElement(string.Format("/Journal/Transactions/Transaction[@BankAccountTransactionK=\"{0}\"]", sourceTransactionFK)); trans.Remove(); sourceTrans.Remove(); } while (true); XBankAccount account = GetBankAccount(BankAccountK); account.SyncBalanceAsync(); } }