Click here to Skip to main content
15,891,951 members
Articles / Hosted Services / Azure

Kerosene ORM: a dynamic, configuration-less and self-adaptive ORM for POCO objects supporting a SQL-like syntax from C#

Rate me:
Please Sign up or sign in to vote.
4.96/5 (71 votes)
1 Mar 2015CPOL35 min read 546.1K   4.6K   212  
The seventh version of the dynamic, configuration-less and self-adaptive Kerosene ORM library, that provides full real support for POCO objects, natural SQL-like syntax from C#, and advanced capabilities while being extremely easy to use.
// ======================================================== StringEx.cs
namespace Kerosene.Tools
{
	using System;

	// ==================================================== 
	/// <summary>
	/// Helpers and extensions for working with <see cref="System.String"/> instances.
	/// </summary>
	public static class StringEx
	{
		/// <summary>
		/// Returns a formatted string using the source one as the format specification.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="args">An optional list of arguments to be used in the formatted string.</param>
		/// <returns>The requested string.</returns>
		public static string FormatWith(this string source, params object[] args)
		{
			if (source == null) throw new NullReferenceException("Source string cannot be null.");
			if (args != null && args.Length != 0) source = string.Format(source, args);

			return source;
		}

		/// <summary>
		/// Returns null if the source string is null or empty. Otherwise returns the trimmed
		/// version of that original string.
		/// </summary>
		/// <param name="source">The original string.</param>
		/// <returns>The trimmed string, or null.</returns>
		public static string NullIfTrimmedIsEmpty(this string source)
		{
			source = source == null || ((source = source.Trim()).Length == 0) ? null : source;
			return source;
		}

		/// <summary>
		/// Returns and empty string if the original one is null. Otherwise returns the trimmed
		/// version of the original string.
		/// </summary>
		/// <param name="source">The original string.</param>
		/// <returns>The trimmed string, or an empty one.</returns>
		public static string EmptyIfTrimmedIsNull(this string source)
		{
			source = source == null || ((source = source.Trim()).Length == 0) ? string.Empty : source;
			return source;
		}

		/// <summary>
		/// Returns a new string containing the n left-most characters of the source string.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="n">The number of characters to obtain.</param>
		/// <returns>The requested string.</returns>
		public static string Left(this string source, int n)
		{
			if (source == null) throw new NullReferenceException("Source string cannot be null.");
			if (n < 0) throw new ArgumentException("Number of characters '{0}' must be cero or bigger.".FormatWith(n));

			if (source.Length == 0) return string.Empty;
			if (n == 0) return string.Empty;

			var str = (n < source.Length) ? source.Substring(0, n) : source;
			return str;
		}

		/// <summary>
		/// Returns a new string containing the n right-most characters of the source string.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="n">The number of characters to obtain.</param>
		/// <returns>The requested string.</returns>
		public static string Right(this string source, int n)
		{
			if (source == null) throw new NullReferenceException("Source string cannot be null.");
			if (n < 0) throw new ArgumentException("Number of characters '{0}' must be cero or bigger.".FormatWith(n));

			if (source.Length == 0) return string.Empty;
			if (n == 0) return string.Empty;

			var str = (n < source.Length) ? source.Substring(source.Length - n) : source;
			return str;
		}

		/// <summary>
		/// Removes from the source string the first ocurrence of the target one, if any, returning
		/// a new string with the result.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="target">The target string to remove, or null.</param>
		/// <param name="comparisonType">The rules for searching for the target string.</param>
		/// <returns>A new string with the result.</returns>
		public static string Remove(this string source, string target, StringComparison comparisonType)
		{
			if (source == null) throw new NullReferenceException("Source string cannot be null.");
			
			if (target == null || target == string.Empty) return source;
			if (source == string.Empty) return string.Empty;

			int start = source.IndexOf(target, comparisonType); if (start < 0) return source;
			return source.Remove(start, target.Length);
		}

		/// <summary>
		/// Removes from the source string the last ocurrence of the target one, if any, returning
		/// a new string with the result.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="target">The target string to remove, or null.</param>
		/// <param name="comparisonType">The rules for searching for the target string.</param>
		/// <returns>A new string with the result.</returns>
		public static string RemoveLast(this string source, string target, StringComparison comparisonType)
		{
			if (source == null) throw new NullReferenceException("Source string cannot be null.");

			if (target == null || target == string.Empty) return source;
			if (source == string.Empty) return string.Empty;

			int start = source.LastIndexOf(target, comparisonType); if (start < 0) return source;
			return source.Remove(start, target.Length);
		}

		/// <summary>
		/// Removes from the source string the first ocurrence of the target one, if any, returning
		/// a new string with the result, using the current culture for comparisons.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="target">The target string to remove, or null.</param>
		/// <returns>A new string with the result.</returns>
		public static string Remove(this string source, string target)
		{
			return source.Remove(target, StringComparison.CurrentCulture);
		}

		/// <summary>
		/// Removes from the source string the last ocurrence of the target one, if any, returning
		/// a new string with the result, using the current culture for comparisons.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="target">The target string to remove, or null.</param>
		/// <returns>A new string with the result.</returns>
		public static string RemoveLast(this string source, string target)
		{
			return source.RemoveLast(target, StringComparison.CurrentCulture);
		}

		/// <summary>
		/// Returns the zero-based index of the first ocurrence of the given target character in
		/// the source string.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="target">The character to find.</param>
		/// <param name="comparisonType">The rules to perform the comparisons.</param>
		/// <returns>The zero-based index of the first ocurrence of the given target character in
		/// the source string.</returns>
		public static int IndexOf(this string source, char target, StringComparison comparisonType)
		{
			if (source == null) throw new NullReferenceException("Source string cannot be null.");
			return source.IndexOf(target.ToString(), comparisonType);
		}

		/// <summary>
		/// Returns the zero-based index of the first ocurrence in the source string of any of
		/// given characters, or -1 if no one is found.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="anyOf">An array containing the characters to find.</param>
		/// <param name="comparisonType">The rules to perform the comparisons.</param>
		/// <returns>The zero-based index of the first ocurrence in the source string of any of
		/// given characters, or -1 if no one is found.</returns>
		public static int IndexOfAny(this string source, char[] anyOf, StringComparison comparisonType)
		{
			if (source == null) throw new NullReferenceException("Source string cannot be null.");
			if (anyOf == null) throw new ArgumentNullException("any", "Array of characters is null.");

			if (source.Length == 0) return -1;
			if (anyOf.Length == 0) return -1;

			for (int i = 0; i < anyOf.Length; i++)
			{
				int k = source.IndexOf(anyOf[i].ToString(), comparisonType);
				if (k >= 0) return k;
			}

			return -1;
		}

		/// <summary>
		/// Returns the zero-based index of the first ocurrence in the source string of an invalid
		/// character not contained in the given array of valid ones.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="valids">An array containing the valid characters.</param>
		/// <param name="comparisonType">The rules to perform the comparisons.</param>
		/// <returns>The zero-based index of the first ocurrence in the source string of an invalid
		/// character not contained in the given array of valid ones.</returns>
		public static int IndexOfNotValid(this string source, char[] valids, StringComparison comparisonType)
		{
			if (source == null) throw new NullReferenceException("Source string cannot be null.");
			if (valids == null) throw new ArgumentNullException("valids", "Array of characters is null.");

			if (source.Length == 0) throw new EmptyException("Source string is empty.");
			if (valids.Length == 0) return 0;

			var temp = new string(valids); for (int i = 0; i < source.Length; i++)
			{
				int k = temp.IndexOf(source[i].ToString(), comparisonType);
				if (k < 0) return i;
			}

			return -1;
		}

		/// <summary>
		/// Returns the zero-based index of the first ocurrence in the source string of an invalid
		/// character not contained in the given array of valid ones.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="valids">An array containing the valid characters.</param>
		/// <returns>The zero-based index of the first ocurrence in the source string of an invalid
		/// character not contained in the given array of valid ones.</returns>
		public static int IndexOfNotValid(this string source, char[] valids)
		{
			return source.IndexOfNotValid(valids, StringComparison.CurrentCulture);
		}

		/// <summary>
		/// Returns a new validated string using the rules given, or throws an exception if any
		/// rule is not met.
		/// </summary>
		/// <param name="source">The source string.</param>
		/// <param name="desc">A description of the source string for presentation purposes.</param>
		/// <param name="canbeNull">True is null strings are considered valid.</param>
		/// <param name="canbeEmpty">True is empty strings are considered valid.</param>
		/// <param name="emptyAsNull">True to return null in case of an empty source string.</param>
		/// <param name="trim">True to trim the source string.</param>
		/// <param name="trimStart">True to trim the source string from the left.</param>
		/// <param name="trimEnd">True to trim the source string from the right.</param>
		/// <param name="padLeft">If not cero the character to use to left-pad the source string.</param>
		/// <param name="padRight">If not cero the character to use to right-pad the source string.</param>
		/// <param name="minLen">If possitive the minimum lenght of the resulting string.</param>
		/// <param name="maxLen">If possitive the maximun lenght of the resulting string.</param>
		/// <param name="valids">If not null an array containing explicitly the valid characters.</param>
		/// <param name="invalids">If not null an array containing explicitly the invalid characters.</param>
		/// <param name="comparisonType">The rules for performing comparisons.</param>
		/// <returns>The requested validated string.</returns>
		public static string Validated(
			this string source, string desc = null,
			bool canbeNull = false, bool canbeEmpty = false, bool emptyAsNull = false,
			bool trim = true, bool trimStart = false, bool trimEnd = false,
			char padLeft = '\0', char padRight = '\0',
			int minLen = -1, int maxLen = -1,
			char[] valids = null, char[] invalids = null,
			StringComparison comparisonType = StringComparison.CurrentCulture)
		{
			if ((desc = desc.NullIfTrimmedIsEmpty()) == null) desc = "Source";

			if (emptyAsNull) canbeNull = true;
			if (source == null)
			{
				if (!canbeNull) throw new ArgumentNullException("source", "{0} cannot be null".FormatWith(desc));
				return null;
			}

			if (!canbeEmpty || emptyAsNull) trim = true;
			if (trim) source = source.Trim();
			else
			{
				if (trimStart) source = source.TrimStart(' ');
				if (trimEnd) source = source.TrimEnd(' ');
			}
			if (minLen > 0)
			{
				if (padLeft != '\0') source = source.PadLeft(minLen, padLeft);
				if (padRight != '\0') source = source.PadRight(minLen, padRight);
			}
			if (maxLen > 0)
			{
				if (padLeft != '\0') source = source.PadLeft(maxLen, padLeft);
				if (padRight != '\0') source = source.PadRight(maxLen, padRight);
			}

			if (source.Length == 0)
			{
				if (emptyAsNull) return null;
				if (canbeEmpty) return string.Empty;
				throw new EmptyException("{0} cannot be empty.".FormatWith(desc));
			}

			if (minLen >= 0 && source.Length < minLen) throw new ArgumentException(
				"Lenght of {0} '{1}' is less than {2}."
				.FormatWith(desc, source, minLen));

			if (maxLen >= 0 && source.Length > maxLen) throw new ArgumentException(
				"Lenght of {0} '{1}' is bigger than {2}."
				.FormatWith(desc, source, maxLen));

			if (valids != null)
			{
				int i = source.IndexOfNotValid(valids, comparisonType);
				if (i > 0) throw new ArgumentException(
					"{0} '{1}' contains invalid character '{2}'."
					.FormatWith(desc, source, source[i]));
			}
			if (invalids != null)
			{
				int i = source.IndexOfAny(invalids, comparisonType);
				if (i > 0) throw new ArgumentException(
					"{0} '{1}' contains invalid character '{2}'."
					.FormatWith(desc, source, source[i]));
			}

			return source;
		}
	}
}
// ======================================================== 

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Spain Spain
mbarbac has worked in start-ups, multinational tech companies, and consulting ones, serving as CIO, CTO, SW Development Director, and Consulting Director, among many other roles.

Solving complex puzzles and getting out of them business value has ever been among his main interests - and that's why he has spent his latest 25 years trying to combine his degree in Theoretical Physics with his MBA... and he is still trying to figure out how all these things can fit together.

Even if flying a lot across many countries, along with the long working days that are customary in IT management and Consultancy, he can say that, after all, he lives in Spain (at least the weekends).

Comments and Discussions