// ========================================================
namespace Kerosene.ORM.Core.Concrete
{
using Kerosene.Tools;
using System;
using System.Collections;
// ====================================================
/// <summary>
/// Represents a command whose contents can be set explicitly using any arbitrary text and parameters.
/// <para>
/// This class is provided to support specialized scenarios not covered by the standard methods of the other
/// command types, and it can also be used to invoke stored procedures.
/// </para>
/// </summary>
public class KCommandRawBase : KCommandBase, IKCommandRaw
{
protected string DataText = null;
/// <summary>
/// Create a new raw command.
/// </summary>
/// <param name="link">The link this command will be associated with.</param>
public KCommandRawBase(IKLink link) : base(link) { }
protected override void OnDispose(bool disposing)
{
if (!IsDisposed && disposing) { }
base.OnDispose(disposing);
}
/// <summary>
/// Returns a new instance that is a copy of this original one.
/// </summary>
public KCommandRawBase Clone()
{
if (IsDisposed) throw new ObjectDisposedException(this.ToString());
var cloned = new KCommandRawBase(this.Link);
OnClone(cloned); return cloned;
}
IKCommandRaw IKCommandRaw.Clone()
{
return this.Clone();
}
IKCommand IKCommand.Clone()
{
return this.Clone();
}
object ICloneable.Clone()
{
return this.Clone();
}
protected override void OnClone(object cloned)
{
var temp = (KCommandRawBase)cloned;
base.OnClone(temp);
temp.DataText = DataText;
}
/// <summary>
/// Returns a new instance that is a copy of this original one, but associated with the new link reference
/// given.
/// </summary>
/// <param name="newlink">The link reference the new cloned instance will be associated with.</param>
public KCommandRawBase Clone(IKLink newlink)
{
if (IsDisposed) throw new ObjectDisposedException(this.ToString());
var cloned = new KCommandRawBase(newlink);
OnClone(cloned); return cloned;
}
IKCommandRaw IKCommandRaw.Clone(IKLink link)
{
return this.Clone(link);
}
IKCommand IKCommand.Clone(IKLink link)
{
return this.Clone(link);
}
object ICloneableWithLink.Clone(IKLink link)
{
return this.Clone(link);
}
/// <summary>
/// Returns an enumerator object able to execute this command.
/// </summary>
public IKEnumerator GetEnumerator()
{
if (IsDisposed) throw new ObjectDisposedException(this.ToString());
return Link.CreateEnumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
/// <summary>
/// Returns an executor object able to execute this command.
/// </summary>
public IKExecutor GetExecutor()
{
if (IsDisposed) throw new ObjectDisposedException(this.ToString());
return Link.CreateExecutor(this);
}
/// <summary>
/// Generates an string containing the actual text of the command to be executed in the syntax understood
/// by the underlying database.
/// </summary>
/// <param name="iterable">Whether to produce the iterable version of the command, or the non-iterable one.</param>
public override string GenerateCommandText(bool iterable)
{
return DataText ?? string.Empty;
}
/// <summary>
/// Sets the new contents of this command using the text given and the optional list of parameters.
/// <para>Returns this instance to permit a fluent syntax chaining.</para>
/// </summary>
/// <param name="text">The new text of this command.</param>
/// <param name="args">An optional collection with the values of the arguments specified in the text. The
/// parameters shall be specified in the text using the standard positional '{n}' placeholder.</param>
public KCommandRawBase Set(string text, params object[] args)
{
if (IsDisposed) throw new ObjectDisposedException(this.ToString());
DataText = null;
Parameters.Clear();
return this.Append(text, args);
}
IKCommandRaw IKCommandRaw.Set(string text, params object[] args)
{
return this.Set(text, args);
}
/// <summary>
/// Sets the new contents of this command parsing the dynamic lambda expression given that resolves into
/// the logic of this command.
/// <para>Returns this instance to permit a fluent syntax chaining.</para>
/// </summary>
/// <param name="specs">A dynamic lambda expression that resolves into the logic of the command.</param>
public KCommandRawBase Set(Func<dynamic, object> specs)
{
if (IsDisposed) throw new ObjectDisposedException(this.ToString());
DataText = null;
Parameters.Clear();
return this.Append(specs);
}
IKCommandRaw IKCommandRaw.Set(Func<dynamic, object> specs)
{
return this.Set(specs);
}
/// <summary>
/// Appends to the previous contents of the command the ones obtained using the text given and the optional
/// list of parameters.
/// <para>An space character is injected, if needed, as a separator between the previous and new contents.</para>
/// <para>Returns this instance to permit a fluent syntax chaining.</para>
/// </summary>
/// <param name="text">The new text of this command.</param></param>
/// <param name="args">An optional collection with the values of the arguments specified in the text. The
/// parameters shall be specified in the text using the standard positional '{n}' placeholder.</param>
public KCommandRawBase Append(string text, params object[] args)
{
if (IsDisposed) throw new ObjectDisposedException(this.ToString());
if (text == null) throw new ArgumentNullException("text", "Command text cannot be null.");
if (args != null)
{
for (int i = 0; i < args.Length; i++)
{
if (args[i] is IKParameter) throw new ArgumentException(
string.Format("Argument #{0}: '{1}' cannot be a IKParameter instance.", i, args[i].Sketch()));
var par = Parameters.AddCreate(args[i]);
var old = string.Format("{{{0}}}", i);
text = text.Replace(old, par.Name);
}
}
bool space = text.StartsWith(" ");
DataText = DataText == null ? text : string.Format("{0}{1}{2}", DataText, space ? string.Empty : " ", text);
return this;
}
IKCommandRaw IKCommandRaw.Append(string text, params object[] args)
{
return this.Append(text, args);
}
/// <summary>
/// Appends to the contents of this command the ones obtained by parsing the dynamic lambda expression given
/// that resolves into the logic to append to this command.
/// <para>An space character is injected, if needed, as a separator between the previous and new contents.</para>
/// <para>Returns this instance to permit a fluent syntax chaining.</para>
/// </summary>
/// <param name="specs">A dynamic lambda expression that resolves into the logic to append to the command.</param>
public KCommandRawBase Append(Func<dynamic, object> specs)
{
if (IsDisposed) throw new ObjectDisposedException(this.ToString());
if (specs == null) throw new ArgumentNullException("spec", "Specification cannot be null.");
var text = Link.Parser.Parse(specs, Parameters);
bool space = text.StartsWith(" ");
DataText = DataText == null ? text : string.Format("{0}{1}{2}", DataText, space ? string.Empty : " ", text);
return this;
}
IKCommandRaw IKCommandRaw.Append(Func<dynamic, object> specs)
{
return this.Append(specs);
}
}
}
// ========================================================