xenadmin/XenModel/XenAPI-Extensions/XenObject.cs
Konstantina Chremmou ae22560ce8 Converted all extension get properties of the API classes to methods in order to
prevent them from being serialised alongside the API properties. This will also
be useful for moving the API bindings out of XenModel.

Signed-off-by: Konstantina Chremmou <konstantina.chremmou@citrix.com>
2017-09-03 03:35:30 +01:00

322 lines
10 KiB
C#

/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using XenAdmin.Core;
using XenAdmin.Network;
using XenAdmin;
namespace XenAPI
{
public abstract partial class XenObject<S> : IComparable<S> where S : XenObject<S>
{
protected const String HIDE_FROM_XENCENTER = "HideFromXenCenter";
private IXenConnection m_Connection = null;
private bool _locked;
public IXenConnection Connection
{
get { return m_Connection; }
set { m_Connection = value; }
}
public virtual string Description()
{
return string.Empty;
}
/// <summary>
/// True if the Xen server knows about this object; false otherwise, e.g., when the user has created an object
/// but not yet saved it to the server.
/// </summary>
public bool ExistsOnServer()
{
return this.opaque_ref != null;
}
/// <summary>
/// True if a server request is in progress.
/// </summary>
public bool Locked
{
get { return _locked; }
set
{
if (_locked != value)
{
_locked = value;
this.NotifyPropertyChanged("Locked");
}
}
}
protected static T Get<T>(Dictionary<string, T> d, string k) where T : class
{
return d != null && d.ContainsKey(k) ? d[k] : null;
}
private String path = String.Empty;
public String Path
{
get { return path; }
set
{
if (!Helper.AreEqual(value, path))
{
path = value;
Changed = true;
NotifyPropertyChanged("Path");
}
}
}
public IXenObject Clone()
{
IXenObject result = (IXenObject)MemberwiseClone();
result.ClearEventListeners();
result.Locked = false;
return result;
}
public virtual bool Show(bool showHiddenVMs)
{
return true;
}
public virtual bool IsHidden()
{
return false;
}
public string SaveChanges(Session session)
{
return SaveChanges(session, null);
}
public string SaveChanges(Session session, IXenObject beforeObject)
{
S server =
opaque_ref == null ?
null :
session.Connection.Resolve(new XenRef<S>(opaque_ref));
if (server == null && opaque_ref != null)
return null;
if (opaque_ref != null && !server.Locked)
throw new InvalidOperationException("Instance must be locked before calling SaveChanges()");
if (beforeObject == null)
beforeObject = server;
return SaveChanges(session, opaque_ref, (S)beforeObject);
}
public virtual int CompareTo(S other)
{
if (other == null)
return -1;
int result = StringUtility.NaturalCompare(Name(), other.Name());
if (result != 0)
return result;
return this.opaque_ref.CompareTo(other.opaque_ref);
}
public int CompareTo(object obj)
{
S other = obj as S;
if (other != null)
return CompareTo(other);
IXenObject o = obj as IXenObject;
if (o == null)
return -1;
return StringUtility.NaturalCompare(Name(), o.Name());
}
/// <summary>
/// This method can be overridden by the derived classes. This is why the implementation is here and the typed
/// equals calls this one.
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public override bool Equals(object other)
{
IXenObject otherIXenObject = other as IXenObject;
if (otherIXenObject != null)
return opaque_ref == otherIXenObject.opaque_ref;
return false;
}
/// <summary>
/// Returns a hash code for this instance. This is required if you want to use this type as a key in a hashtable.
/// </summary>
public override int GetHashCode()
{
return opaque_ref.GetHashCode();
}
#region IEquatable<IXenObject> Members
/// <summary>
/// This is the implementation of IEquatable of IXenObject which is defined in IXenObject. This calls the virtual
/// Equals so that any derived classes can override Equals and it will used the derived class implementation in
/// all circumstances.
/// </summary>
public bool Equals(IXenObject other)
{
return Equals((object)other);
}
#endregion
public object Get(String property)
{
PropertyInfo pi = GetType().GetProperty(property);
if (pi == null)
return null;
return pi.GetValue(this, null);
}
public void Set(String property, object val)
{
PropertyInfo pi = GetType().GetProperty(property);
if (pi != null)
pi.SetValue(this, val, null);
}
public void Do(String method, params Object[] methodParams)
{
MethodInfo mi = GetType().GetMethod(method, BindingFlags.Public | BindingFlags.Static);
if (mi == null)
return;
try
{
mi.Invoke(this, methodParams);
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
}
public static Dictionary<string, string> SetDictionaryKey(Dictionary<string, string> dict, string key, string value)
{
return SetDictionaryKeys(dict, new KeyValuePair<string, string>(key, value));
}
public static Dictionary<string, string> SetDictionaryKeys(Dictionary<string, string> dict, params KeyValuePair<string, string>[] kvps)
{
var newDict = dict == null
? new Dictionary<string, string>()
: new Dictionary<string, string>(dict);
foreach (var kvp in kvps)
{
string key = kvp.Key;
string value = kvp.Value;
if (value == null)
newDict.Remove(key);
else
newDict[key] = value;
}
return newDict;
}
/// <summary>
/// If d[k] == "true", then return true. Anything else is false.
/// Handles all the cases with d being null or not containing k.
/// </summary>
protected static bool BoolKey(Dictionary<string, string> d, string k)
{
string v = Get(d, k);
return v != null && v == "true";
}
/// <summary>
/// Converts dictionary pair to a bool.
/// Only return false if it's looked up otherwise return true
///
/// This is similar to BoolKey but BoolKey prefers to return false,
/// whereas BoolKeyPreferTrue prefers true;
/// </summary>
protected static bool BoolKeyPreferTrue(Dictionary<string, string> d, string k)
{
string v = Get(d, k);
return String.IsNullOrEmpty(v) || v != "false";
}
/// <summary>
/// If d[k] is parseable as an integer, then return it, otherwise return def.
/// Handles all the cases with d being null or not containing k.
/// </summary>
protected int IntKey(Dictionary<string, string> d, string k, int def)
{
int result;
string s = Get(d, k);
return s != null && int.TryParse(s, out result) ? result : def;
}
public virtual string Name()
{
return "";
}
public virtual string NameWithLocation()
{
return string.Format(Messages.NAME_WITH_LOCATION, Name(), LocationString());
}
internal virtual string LocationString()
{
if (Connection == null || string.IsNullOrEmpty(Connection.Name))
return string.Empty;
if (Helpers.IsPool(Connection))
return string.Format(Messages.IN_POOL, Connection.Name);
return string.Format(Messages.ON_SERVER, Connection.Name);
}
}
}