PageRenderTime 67ms CodeModel.GetById 44ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Application/Core/Utilities.cs

http://yet-another-music-application.googlecode.com/
C# | 508 lines | 256 code | 60 blank | 192 comment | 65 complexity | a78cd2d0338adbdce236201135d4e911 MD5 | raw file
  1/**
  2 * Utilities.cs
  3 * 
  4 * The swiss armyknife of Stoffi containing, for example, the
  5 * log function.
  6 * 
  7 * * * * * * * * *
  8 * 
  9 * Copyright 2012 Simplare
 10 * 
 11 * This code is part of the Stoffi Music Player Project.
 12 * Visit our website at: stoffiplayer.com
 13 *
 14 * This program is free software; you can redistribute it and/or
 15 * modify it under the terms of the GNU General Public License
 16 * as published by the Free Software Foundation; either version
 17 * 3 of the License, or (at your option) any later version.
 18 * 
 19 * See stoffiplayer.com/license for more information.
 20 **/
 21using System;
 22using System.Collections.Generic;
 23using System.IO;
 24using System.Linq;
 25using System.Text;
 26using System.Diagnostics;
 27using System.Collections.ObjectModel;
 28using System.Globalization;
 29using Tomers.WPF.Localization;
 30
 31namespace Stoffi
 32{
 33	/// <summary>
 34	/// This is the utility class containing all helper methods
 35	/// </summary>
 36	static partial class U
 37	{
 38		#region Members
 39
 40		/// <summary>
 41		/// Contains the time when the class was first initialized
 42		/// </summary>
 43		private static DateTime initTime;
 44
 45		#endregion
 46
 47		#region Properties
 48
 49		/// <summary>
 50		/// Gets or sets the path to the logfile
 51		/// </summary>
 52		public static string LogFile { get; set; }
 53
 54		/// <summary>
 55		/// Gets or sets the minimum level of messages to print/write
 56		/// </summary>
 57		public static LogLevel Level { get; set; }
 58
 59		/// <summary>
 60		/// Gets or sets whether the main window should listen for keyboard shortcuts
 61		/// </summary>
 62		public static bool ListenForShortcut { get; set; }
 63
 64		#endregion
 65
 66		#region Constructor
 67
 68		/// <summary>
 69		/// Creates a utility class with a "Stoffi.log" logfile in the TEMP folder and a Level of Warning
 70		/// </summary>
 71		static U()
 72		{
 73			LogFile = Path.Combine(Environment.GetEnvironmentVariable("TEMP"), "Stoffi.log");
 74			Level = LogLevel.Warning;
 75			initTime = DateTime.Now;
 76		}
 77
 78		#endregion
 79
 80		#region Methods
 81
 82		#region Public
 83
 84		/// <summary>
 85		/// Logs a message to file and/or console.
 86		/// </summary>
 87		/// <param name="level">The level of the message (if this is lower than Level the message will be ignored)</param>
 88		/// <param name="caller">The caller of the message</param>
 89		/// <param name="message">The message</param>
 90		public static void L(LogLevel level, string caller, string message)
 91		{
 92			if (LevelToInt(level) < LevelToInt(Level)) return;
 93
 94			TimeSpan ts = (DateTime.Now - initTime);
 95			string logLine = String.Format("{0} {1}:{2:00}:{3:00}.{4:000} ({5:G}) [{6}] {7}: {8}",
 96				ts.Days, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds, DateTime.Now,
 97				LevelToString(level), // #7
 98				caller.ToUpper(),
 99				message);
100
101			if (Level == LogLevel.Debug)
102				Console.WriteLine(logLine);
103
104#if (!DEBUG)
105			System.IO.StreamWriter sw = null;
106			try
107			{
108				sw = System.IO.File.AppendText(LogFile);
109				sw.WriteLine(logLine);
110			}
111			catch (Exception e)
112			{
113				Console.WriteLine("ERROR: Could not write to logfile: " + e.Message);
114			}
115			if (sw != null)
116				sw.Close();
117#endif
118		}
119
120		/// <summary>
121		/// Logs a HttpWebResponse to file and/or console.
122		/// </summary>
123		/// <param name="level">The level of the message (if this is lower than Level the message will be ignored)</param>
124		/// <param name="caller">The caller of the message</param>
125		/// <param name="response">The HttpWebResponse object.</param>
126		public static void L(LogLevel level, string caller, System.Net.HttpWebResponse response)
127		{
128			if (response == null)
129				U.L(level, caller, "Response was empty.");
130			else
131			{
132				U.L(level, caller, String.Format("Content Encoding: {0}", response.ContentEncoding));
133				U.L(level, caller, String.Format("Content Type: {0}", response.ContentType));
134				U.L(level, caller, String.Format("Status Description: {0}", response.StatusDescription));
135				StreamReader sr = new StreamReader(response.GetResponseStream());
136				string str;
137				while ((str = sr.ReadLine()) != null)
138					U.L(level, caller, str);
139				U.L(level, caller, String.Format("-- End of response. Total bytes: {0} --", response.ContentLength));
140			}
141		}
142
143		/// <summary>
144		/// Looks for a track with a specific path in a collection
145		/// </summary>
146		/// <param name="collection">A collection of tracks</param>
147		/// <param name="path">A path to look for</param>
148		/// <returns>True if any track has a path with <paramref name="path"/> as prefix, otherwise false.</returns>
149		public static bool ContainsPath(ObservableCollection<TrackData> collection, string path)
150		{
151			foreach (TrackData t in collection)
152				if (t.Path.StartsWith(path))
153					return true;
154			return false;
155		}
156
157		/// <summary>
158		/// Looks for all tracks with a specific path in a collection
159		/// </summary>
160		/// <param name="collection">A collection of tracks</param>
161		/// <param name="path">A path to look for</param>
162		/// <returns>Any track that has a path with <paramref name="path"/> as prefix</returns>
163		public static List<TrackData> GetTracks(ObservableCollection<TrackData> collection, string path)
164		{
165			List<TrackData> ret = new List<TrackData>();
166			foreach (TrackData t in collection)
167				if (t.Path.StartsWith(path))
168					ret.Add(t);
169			return ret;
170		}
171
172		/// <summary>
173		/// Turns a size in bytes into a human readable string
174		/// </summary>
175		/// <param name="size">The size</param>
176		/// <returns>A localized string describing the size</returns>
177		public static string HumanSize(long size)
178		{
179			if (size > Math.Pow(10,12))
180				return String.Format(U.T("SizeTb"), Math.Round((double)(size / Math.Pow(10, 12)), 2));
181
182			else if (size > Math.Pow(10, 9))
183				return String.Format(U.T("SizeGb"), Math.Round((double)(size / Math.Pow(10, 9)), 2));
184
185			else if (size > Math.Pow(10, 6))
186				return String.Format(U.T("SizeMb"), Math.Round((double)(size / Math.Pow(10, 6)), 2));
187
188			else if (size > Math.Pow(10, 3))
189				return String.Format(U.T("SizeKb"), Math.Round((double)(size / Math.Pow(10, 3)), 2));
190
191			else
192				return String.Format(U.T("SizeBytes"), size);
193		}
194
195		/// <summary>
196		/// Removes characters that are not valid for an XML file.
197		/// </summary>
198		/// <param name="str">The string to be parsed</param>
199		/// <returns>A copy of the string <paramref name="str"/> but with all invalid characters removed</returns>
200		public static string CleanXMLString(string str)
201		{
202			if (str == null) return null;
203
204			string r = "";
205			foreach (char c in str)
206			{
207				int n = (int)c;
208				if ((n >= 9 && n <= 10) ||
209					(n == 13) ||
210					(n >= 32 && n <= 55295) ||
211					(n >= 57344 && n <= 65533) ||
212					(n >= 65536 && n <= 1114111))
213				{
214					r += c;
215				}
216			}
217			return r;
218		}
219
220		/// <summary>
221		/// Converts back an escaped string passed via Rails CGI.escapeHTML method.
222		/// </summary>
223		/// <param name="str">The escaped string</param>
224		/// <returns>An unescaped version of str</returns>
225		public static string UnescapeHTML(string str)
226		{
227			return str.Replace("&quot;", "\"").Replace("&gt;", ">").Replace("&lt;", "<").Replace("&amp;", "&");
228		}
229
230		/// <summary>
231		/// Parses HTTP query parameters
232		/// </summary>
233		/// <param name="query">The HTTP query</param>
234		/// <returns>A dictionary with key-value pairs</returns>
235		public static Dictionary<string, string> GetParams(string query)
236		{
237			string[] parameters = query.Split('&');
238			Dictionary<string, string> d = new Dictionary<string, string>();
239			foreach (string parameter in parameters)
240			{
241				string[] p = parameter.Split(new char[] { '=' }, 2);
242				d.Add(p[0], p[1]);
243			}
244			return d;
245		}
246
247		/// <summary>
248		/// Retrieves the query from a HTTP URL.
249		/// Will clean up multiple question marks.
250		/// </summary>
251		/// <param name="url">The HTTP URL</param>
252		/// <returns>A query string without any question marks</returns>
253		public static string GetQuery(string url)
254		{
255			string[] tokens = url.Split('?');
256			string ret = "";
257			for (int i = 1; i < tokens.Count(); i++)
258			{
259				ret += "&" + tokens[i];
260			}
261			return ret.Substring(1);
262		}
263
264		/// <summary>
265		/// Creates a HTTP parameter string from a key and a value.
266		/// If value is null then it will return null instead of an
267		/// empty assignment.
268		/// All values and parameters will be encoded
269		/// </summary>
270		/// <param name="key">The parameter name</param>
271		/// <param name="value">The value of the parameter</param>
272		/// <param name="prefix">A prefix to be set on all parameter names</param>
273		/// <returns>key=value if value is not null, otherwise null</returns>
274		public static string CreateParam(string key, string value, string prefix)
275		{
276			if (key == null || value == null)
277				return null;
278			else
279			{
280				if (prefix == null)
281					return String.Format("{0}={1}",
282						OAuth.Manager.UrlEncode(key),
283						OAuth.Manager.UrlEncode(value));
284				else
285					return String.Format("{0}[{1}]={2}",
286						prefix,
287						OAuth.Manager.UrlEncode(key),
288						OAuth.Manager.UrlEncode(value));
289			}
290		}
291
292		/// <summary>
293		/// Creates a HTTP parameter string from a key and a value.
294		/// If value is null then it will return null instead of an
295		/// empty assignment.
296		/// All values and parameters will be encoded
297		/// </summary>
298		/// <param name="key">The parameter name</param>
299		/// <param name="value">The value of the parameter</param>
300		/// <param name="prefix">A prefix to be set on all parameter names</param>
301		/// <returns>key=value if value is not null, otherwise null</returns>
302		public static string CreateParam(string key, int value, string prefix)
303		{
304			return CreateParam(key, value.ToString(), prefix);
305		}
306
307		/// <summary>
308		/// Creates a HTTP parameter string from a key and a value.
309		/// If value is null then it will return null instead of an
310		/// empty assignment.
311		/// All values and parameters will be encoded
312		/// </summary>
313		/// <param name="key">The parameter name</param>
314		/// <param name="value">The value of the parameter</param>
315		/// <param name="prefix">A prefix to be set on all parameter names</param>
316		/// <returns>key=value if value is not null, otherwise null</returns>
317		public static string CreateParam(string key, uint value, string prefix)
318		{
319			return CreateParam(key, value.ToString(), prefix);
320		}
321
322		/// <summary>
323		/// Creates a HTTP parameter string from a key and a value.
324		/// If value is null then it will return null instead of an
325		/// empty assignment.
326		/// All values and parameters will be encoded
327		/// </summary>
328		/// <param name="key">The parameter name</param>
329		/// <param name="value">The value of the parameter</param>
330		/// <param name="prefix">A prefix to be set on all parameter names</param>
331		/// <returns>key=value if value is not null, otherwise null</returns>
332		public static string CreateParam(string key, double value, string prefix)
333		{
334			return CreateParam(key, Convert.ToString(value), prefix);
335		}
336
337		/// <summary>
338		/// Turns the first letter into uppercase and the rest into lowercase.
339		/// </summary>
340		/// <param name="str">The string to modify.</param>
341		/// <returns>The string str with its first letter in uppercase and the rest in lowercase.</returns>
342		public static String Capitalize(String str)
343		{
344			if (str.Length == 0)
345				return "";
346			else
347			{
348				str = str.ToLower();
349				char[] a = str.ToCharArray();
350				a[0] = Char.ToUpper(a[0]);
351				return new String(a);
352			}
353		}
354
355		/// <summary>
356		/// Turns a timespan into a string in the format:
357		/// X days, X hours, X minutes, X seconds
358		/// </summary>
359		/// <param name="ts">The timespan to turn into a string</param>
360		/// <returns>The timespan printed out to a string</returns>
361		public static String TimeSpanToLongString(TimeSpan ts)
362		{
363			String ret = "";
364
365			if (ts.Days > 0)
366				ret += String.Format("{0} {1}, ", ts.Days, T("DateDays"));
367
368			if (ts.Hours > 0)
369				ret += String.Format("{0} {1}, ", ts.Hours, T("DateHours"));
370
371			ret += String.Format("{0} {1}, ", ts.Minutes, T("DateMinutes"));
372			ret += String.Format("{0} {1}", ts.Seconds, T("DateSeconds"));
373
374			return ret;
375		}
376
377		/// <summary>
378		/// Turns a timespan to a short and compact string in the format:
379		/// DD HH:MM:SS (days, hours, minutes, seconds and leading zeroes)
380		/// </summary>
381		/// <param name="ts">The timespan to turn into a string</param>
382		/// <returns>The timespan printed out to a short string</returns>
383		public static String TimeSpanToString(TimeSpan ts)
384		{
385			String ret = "";
386			if (ts.Days > 0)
387				ret += String.Format("{0:00}:", ts.Days);
388
389			if (ts.Hours > 0)
390				ret += String.Format("{0:00}:", ts.Hours);
391
392			ret += String.Format("{0:00}:", ts.Minutes);
393			ret += String.Format("{0:00}", ts.Seconds);
394
395			return ret;
396		}
397
398		/// <summary>
399		/// Translates a string
400		/// </summary>
401		/// <param name="id">The id of the translation value</param>
402		/// <param name="field">The field of the translation value</param>
403		/// <param name="def">The default value (sets to field if empty)</param>
404		/// <returns>The string associated with the translation value</returns>
405		public static string T(string id, string field = "Text", string def = "")
406		{
407			if (def == "") def = field;
408			LanguageDictionary dictionary = LanguageDictionary.GetDictionary(LanguageContext.Instance.Culture);
409			return (string)dictionary.Translate(id, field, def, typeof(string));
410		}
411
412		/// <summary>
413		/// Formats an integer using local culture
414		/// </summary>
415		/// <param name="n">The number to format</param>
416		/// <returns>The number formatted according to localization</returns>
417		public static string T(int n)
418		{
419			return n.ToString("N0", LanguageContext.Instance.Culture);
420		}
421
422		/// <summary>
423		/// Formats a double using local culture
424		/// </summary>
425		/// <param name="n">The number to format</param>
426		/// <returns>The number formatted according to localization</returns>
427		public static string T(double n)
428		{
429			return n.ToString("N", LanguageContext.Instance.Culture);
430		}
431
432		/// <summary>
433		/// Formats a date using local culture
434		/// </summary>
435		/// <param name="dt">The date to format</param>
436		/// <returns>The date formatted according to localization</returns>
437		public static string T(DateTime dt)
438		{
439			return dt.ToString(LanguageContext.Instance.Culture);
440		}
441
442		#endregion
443
444		#region Private
445
446		/// <summary>
447		/// Converts a LogLevel to an integer
448		/// </summary>
449		/// <param name="level">The level to convert</param>
450		/// <returns><paramref name="level"/> represented as an integer where Debug &lt; PropertiesWindow &lt; Warning &lt; Error</returns>
451		private static int LevelToInt(LogLevel level)
452		{
453			if (level == LogLevel.Debug) return 1;
454			else if (level == LogLevel.Information) return 2;
455			else if (level == LogLevel.Warning) return 3;
456			else if (level == LogLevel.Error) return 4;
457			else return 0;
458		}
459
460		/// <summary>
461		/// Converts a LogLevel to a string
462		/// </summary>
463		/// <param name="level">The level to convert</param>
464		/// <returns><paramref name="level"/> represented as a string</returns>
465		private static string LevelToString(LogLevel level)
466		{
467			if (level == LogLevel.Debug) return "DEBUG";
468			else if (level == LogLevel.Information) return "INFO";
469			else if (level == LogLevel.Warning) return "OOPS";
470			else if (level == LogLevel.Error) return "SHIT";
471			else return "HUH?";
472		}
473
474		#endregion
475
476		#endregion
477	}
478
479	#region Enum
480
481	/// <summary>
482	/// Describes the level of a log message
483	/// </summary>
484	public enum LogLevel
485	{
486		/// <summary>
487		/// Messages that are useful when debugging the application
488		/// </summary>
489		Debug,
490
491		/// <summary>
492		/// Messages that show general information about the application's actions
493		/// </summary>
494		Information,
495
496		/// <summary>
497		/// Messages that informs about something that have gone wrong
498		/// </summary>
499		Warning,
500
501		/// <summary>
502		/// Messages informing that something fatal has happened to the application
503		/// </summary>
504		Error
505	}
506
507	#endregion
508}