aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Properties/Resources.resx
blob: af7dbebbacef595e3089c01c05671016c21a8304 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?xml version="1.0" encoding="utf-8"?>
<root>
  <!-- 
    Microsoft ResX Schema 
    
    Version 2.0
    
    The primary goals of this format is to allow a simple XML format 
    that is mostly human readable. The generation and parsing of the 
    various data types are done through the TypeConverter classes 
    associated with the data types.
    
    Example:
    
    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
                
    There are any number of "resheader" rows that contain simple 
    name/value pairs.
    
    Each data row contains a name, and value. The row also contains a 
    type or mimetype. Type corresponds to a .NET class that support 
    text/value conversion through the TypeConverter architecture. 
    Classes that don't support this are serialized and stored with the 
    mimetype set.
    
    The mimetype is used for serialized objects, and tells the 
    ResXResourceReader how to depersist the object. This is currently not 
    extensible. For a given mimetype the value must be set accordingly:
    
    Note - application/x-microsoft.net.object.binary.base64 is the format 
    that the ResXResourceWriter will generate, however the reader can 
    read any of the formats listed below.
    
    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with 
            : System.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.
    
    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with 
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.

    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array 
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
</root>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Tango.Core;
using Tango.DAL.Remote.DB;
using Tango.DAL.Remote;
using Tango.Settings;
using Tango.Core.Helpers;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Runtime.CompilerServices;
using System.Data.Entity.Core.Objects;
using Tango.Serialization;
using System.Xml.Serialization;
using Newtonsoft.Json;
using Tango.Logging;
using System.ComponentModel;

namespace Tango.BL
{
    internal class ObservableEntitiesContainer
    {
        static ObservableEntitiesContainer()
        {
            RegisteredEntities = new List<IObservableEntity>();
        }

        /// <summary>
        /// Gets the list of all registered entities ever created.
        /// </summary>
        internal static List<IObservableEntity> RegisteredEntities { get; private set; }
    }

    /// <summary>
    /// Represents a generic observable entity base class.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <seealso cref="Tango.Core.ExtendedObject" />
    /// <seealso cref="Tango.BL.Entities.IObservableEntity" />
    [Serializable]
    public abstract class ObservableEntity<T> : ExtendedObject, IObservableEntity where T : class, IObservableEntity
    {
        #region Events

        /// <summary>
        /// Occurs after this observable has been modified and saved by this entity context or another.
        /// </summary>
        public event EventHandler<ObservableModifiedEventArgs> Modified;

        #endregion

        #region Properties

        private Int32 _id;
        /// <summary>
        /// Gets or sets the entity identifier.
        /// </summary>
        [Column("ID")]
        [JsonIgnore]
        [ParameterIgnore]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public Int32 ID
        {
            get { return _id; }
            set { _id = value; RaisePropertyChanged(nameof(ID)); }
        }

        private String _guid;
        /// <summary>
        /// Gets or sets the entity unique identifier.
        /// </summary>
        [Key]
        [Column("GUID")]
        [ParameterIgnore]
        [JsonIgnore]
        public String Guid
        {
            get { return _guid; }
            set { _guid = value; RaisePropertyChanged(nameof(Guid)); }
        }

        private DateTime _lastUpdated;
        /// <summary>
        /// Gets or sets the entity last updated data and time.
        /// </summary>
        [Column("LAST_UPDATED")]
        [ParameterIgnore]
        [JsonIgnore]
        public DateTime LastUpdated
        {
            get { return _lastUpdated; }
            set { _lastUpdated = value; RaisePropertyChanged(nameof(LastUpdated)); }
        }

        private ReadOnlyObservableCollection<ParameterItem> _parameters;
        /// <summary>
        /// Gets a bind-able observable collection of the component properties.
        /// </summary>
        [NotMapped]
        [XmlIgnore]
        [JsonIgnore]
        [ParameterIgnore]
        public ReadOnlyObservableCollection<ParameterItem> Parameters
        {
            get
            {
                if (_parameters == null)
                {
                    _parameters = new ReadOnlyObservableCollection<ParameterItem>(this.CreateParametersCollection(ParameterItemMode.Binding));
                }

                return _parameters;
            }
            private set { _parameters = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Gets or sets the entity last updated data and time.
        /// </summary>
        [ParameterIgnore]
        [JsonIgnore]
        [NotMapped]
        public Type ObjectType
        {
            get { return GetType(); }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ObservableEntity{T}"/> class.
        /// </summary>
        public ObservableEntity()
        {
            ObservableEntitiesContainer.RegisteredEntities.Add(this);

            Guid = System.Guid.NewGuid().ToString();
            LastUpdated = DateTime.UtcNow;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Saves the changes on this entity to database.
        /// </summary>
        public virtual void Save(ObservablesContext context)
        {
            if (context == ObservablesEntitiesAdapter.Instance.Context)
            {
                var tableName = this.GetType().GetCustomAttribute<TableAttribute>().Name;

                String propName = tableName.FromDalNameToTitleCase();

                DbSet<T> set = ObservablesEntitiesAdapter.Instance.Context.GetType().GetProperty(propName, BindingFlags.Instance | BindingFlags.Public).GetValue(context) as DbSet<T>;
                ObservableCollection<T> obs = ObservablesEntitiesAdapter.Instance.GetType().GetProperty(propName, BindingFlags.Instance | BindingFlags.Public).GetValue(ObservablesEntitiesAdapter.Instance) as ObservableCollection<T>;

                if (!obs.Contains(this as T))
                {
                    set.Add(this as T);
                }

                ObservablesEntitiesAdapter.Instance.SaveChanges();
            }
            else
            {
                context.SaveChanges();
            }
        }

        /// <summary>
        /// Attaches this entity to the proper DbSet.
        /// </summary>
        public virtual void Attach(ObservablesContext context)
        {
            GetDbSet(context).Add(this as T);
        }

        /// <summary>
        /// Detaches this observable from the proper DbSet.
        /// </summary>
        public virtual void Detach(ObservablesContext context)
        {
            GetDbSet(context).Remove(this as T);
        }

        /// <summary>
        /// Saves the changes on this entity to database asynchronously.
        /// </summary>
        /// <returns></returns>
        public Task SaveAsync(ObservablesContext context)
        {
            return Task.Factory.StartNew(() =>
            {
                Save(context);
            });
        }

        /// <summary>
        /// Reloads this observable entity.
        /// </summary>
        /// <returns></returns>
        public Task Reload(ObservablesContext context)
        {
            return context.Entry(this).ReloadAsync();
        }

        /// <summary>
        /// Deletes this entity from the database
        /// </summary>
        public virtual void Delete(ObservablesContext context)
        {
            var delProp = this.GetType().GetProperty("Deleted");

            if (delProp != null)
            {
                delProp.SetValue(this, true);
                Save(context);
            }
            else
            {
                GetDbSet(context).Remove(this as T);
                Save(context);
            }
        }

        /// <summary>
        /// Deletes this entity without saving changes to data base.
        /// </summary>
        public virtual void DefferedDelete(ObservablesContext context)
        {
            try
            {
                GetDbSet(context).Remove(this as T);
            }
            catch (InvalidOperationException)
            {
                LogManager.Default.Log(
@"An attempt to deffer delete an entity but was not found on context.
Maybe you have deleted an entity that was no yet inserted into database?", LogCategory.Warning);
            }
            catch (Exception ex)
            {
                LogManager.Default.Log(ex);
            }
        }

        /// <summary>
        /// Deletes this entity from the database
        /// </summary>
        public Task DeleteAsync(ObservablesContext context)
        {
            return Task.Factory.StartNew(() =>
            {
                Delete(context);
            });
        }

        /// <summary>
        /// Gets the database set.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public DbSet<T> GetDbSet(ObservablesContext context)
        {
            String tabelName = this.GetType().Name.PluralizeMVC();
            var p = typeof(ObservablesContext).GetProperty(tabelName);
            if (p != null)
            {
                var set1 = p.GetValue(context) as DbSet<T>;
                return set1;
            }
            else
            {
                tabelName = this.GetType().BaseType.Name.PluralizeMVC();
                p = typeof(ObservablesContext).GetProperty(tabelName);
                if (p != null)
                {
                    var set2 = p.GetValue(context) as DbSet<T>;
                    return set2;
                }
            }

            return null;
        }

        /// <summary>
        /// Gets the database set.
        /// </summary>
        /// <typeparam name="T1">The type of the 1.</typeparam>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public DbSet<T1> GetDbSet<T1>(ObservablesContext context) where T1 : class, IObservableEntity
        {
            return GetDbSet(context) as DbSet<T1>;
        }

        /// <summary>
        /// Clones this entity.
        /// </summary>
        /// <returns></returns>
        public virtual T Clone()
        {
            return Clone(null);
        }

        public T Clone(Action<T> action)
        {
            var cloned = Activator.CreateInstance<T>();

            foreach (var prop in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.SetMethod != null))
            {
                if (!prop.PropertyType.IsGenericType)
                {
                    prop.SetValue(cloned, prop.GetValue(this));
                }
            }

            cloned.ID = 0;
            cloned.Guid = System.Guid.NewGuid().ToString();
            cloned.LastUpdated = DateTime.UtcNow;

            action?.Invoke(cloned);

            return cloned;
        }

        /// <summary>
        /// Compares another entity using a a JSON string comparison.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        public bool CompareUsingJson(T entity)
        {
            String me = JsonConvert.SerializeObject(this);
            String other = JsonConvert.SerializeObject(entity);
            return me == other;
        }

        /// <summary>
        /// Deletes this entity using an SQL statement which will cause the database delete  cascade effect.
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task DeleteCascadeAsync(ObservablesContext context)
        {
            return context.Database.ExecuteSqlCommandAsync(String.Format("DELETE FROM {0} WHERE GUID='{1}'", this.GetType().GetCustomAttribute<TableAttribute>().Name, Guid));
        }

        /// <summary>
        /// Raises the <see cref="Modified" /> event.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="source"></param>
        /// <param name="target"></param>
        public void RaiseModified(ObservablesContext context, IObservableEntity source, IObservableEntity target)
        {
            Modified?.Invoke(this, new ObservableModifiedEventArgs(context, source, target));
        }

        public ObjectContext GetObjectContext()
        {
            return GetObjectContextFromEntity(this);
        }

        public DbContext GetDbContext()
        {
            return GetDbContextFromEntity(this);
        }

        #endregion

        #region Private Methods

        private static DbContext GetDbContextFromEntity(object entity)
        {
            var object_context = GetObjectContextFromEntity(entity);

            if (object_context == null)
                return null;

            return new DbContext(object_context, dbContextOwnsObjectContext: false);
        }

        private static ObjectContext GetObjectContextFromEntity(object entity)
        {
            var field = entity.GetType().GetField("_entityWrapper");

            if (field == null)
                return null;

            var wrapper = field.GetValue(entity);
            var property = wrapper.GetType().GetProperty("Context");
            var context = (ObjectContext)property.GetValue(wrapper, null);

            return context;
        }

        #endregion

        #region Validation

        //Holds the current validation errors.
        private List<KeyValuePair<String, String>> _currentErrors = new List<KeyValuePair<string, string>>();

        /// <summary>
        /// Occurs when the validation errors have changed for a property or for the entire entity.
        /// </summary>
        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        private ObservableCollection<String> _validationErrors;
        /// <summary>
        /// Gets or sets the validation errors.
        /// </summary>
        [NotMapped]
        [ParameterIgnore]
        [XmlIgnore]
        public ObservableCollection<String> ValidationErrors
        {
            get { return _validationErrors; }
            protected set { _validationErrors = value; RaisePropertyChangedAuto(); }
        }

        private bool _validateOnPropertyChanged;
        [NotMapped]
        [ParameterIgnore]
        [XmlIgnore]
        public bool ValidateOnPropertyChanged
        {
            get { return _validateOnPropertyChanged; }
            set { _validateOnPropertyChanged = value; RaisePropertyChangedAuto(); }
        }

        private bool _hasErrors;
        /// <summary>
        /// Gets a value that indicates whether the entity has validation errors.
        /// </summary>
        [NotMapped]
        [ParameterIgnore]
        [XmlIgnore]
        public bool HasErrors
        {
            get { return _hasErrors; }
            set { _hasErrors = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Performs entity field validation.
        /// Will throw an exception with the proper message if one of the fields is invalid.
        /// </summary>
        /// <param name="context">The context.</param>
        public virtual bool Validate(ObservablesContext context)
        {
            HasErrors = false;
            _currentErrors.Clear();

            if (ValidationErrors == null)
            {
                ValidationErrors = new ObservableCollection<string>();
            }

            ValidationErrors.Clear();

            OnValidating(context);

            foreach (var prop in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                foreach (var validation in prop.GetCustomAttributes<ValidationAttribute>())
                {
                    if (!validation.IsValid(prop.GetValue(this)))
                    {
                        _currentErrors.Add(new KeyValuePair<string, string>(prop.Name, validation.ErrorMessage));
                        ValidationErrors.Add(validation.ErrorMessage);
                    }
                }

                HasErrors = _currentErrors.Count > 0;
                RaiseError(prop.Name);
            }

            return !HasErrors;
        }

        /// <summary>
        /// Gets the validation errors for a specified property or for the entire entity.
        /// </summary>
        /// <param name="propertyName">The name of the property to retrieve validation errors for; or null or <see cref="F:System.String.Empty" />, to retrieve entity-level errors.</param>
        /// <returns>
        /// The validation errors for the property or entity.
        /// </returns>
        public IEnumerable GetErrors(string propertyName)
        {
            return _currentErrors.Where(x => x.Key == propertyName).Select(x => x.Value).ToList();
        }

        /// <summary>
        /// Called when entity is validating.
        /// </summary>
        protected virtual void OnValidating(ObservablesContext context)
        {

        }

        /// <summary>
        /// Inserts the error.
        /// </summary>
        /// <param name="propName">Name of the property.</param>
        /// <param name="error">The error.</param>
        protected void InsertError(String propName, String error)
        {
            _currentErrors.Add(new KeyValuePair<string, string>(propName, error));
        }

        /// <summary>
        /// Invoked the <see cref="ErrorsChanged"/> event.
        /// </summary>
        /// <param name="propName">Name of the property.</param>
        protected void RaiseError(String propName)
        {
            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propName));
        }

        #endregion

        #region INotify Property Changed

        /// <summary>
        /// Raises the property changed event.
        /// </summary>
        /// <param name="propName">Name of the property.</param>
        protected override void RaisePropertyChanged(string propName)
        {
            base.RaisePropertyChanged(propName);

            if (ValidateOnPropertyChanged)
            {
                Validate(null);
            }
        }

        #endregion

        #region Operator Overloading

        //public static bool operator ==(ObservableEntity<T> observable1, ObservableEntity<T> observable2)
        //{
        //    if (object.ReferenceEquals(observable1, null) || object.ReferenceEquals(observable2, null))
        //    {
        //        return object.ReferenceEquals(observable1, observable2);
        //    }

        //    return observable1.Guid.ToLower() == observable2.Guid.ToLower();
        //}

        //public static bool operator !=(ObservableEntity<T> observable1, ObservableEntity<T> observable2)
        //{
        //    if (object.ReferenceEquals(observable1, null) || object.ReferenceEquals(observable2, null))
        //    {
        //        return !object.ReferenceEquals(observable1, observable2);
        //    }

        //    return observable1.Guid.ToLower() != observable2.Guid.ToLower();
        //}

        //public override bool Equals(object obj)
        //{
        //    if (object.ReferenceEquals(this, null) || object.ReferenceEquals(obj, null))
        //    {
        //        return object.ReferenceEquals(this, obj);
        //    }

        //    if (obj is ObservableEntity<T>)
        //    {
        //        return Guid.ToLower() == (obj as ObservableEntity<T>).Guid.ToLower();
        //    }
        //    else
        //    {
        //        return false;
        //    }
        //}

        //public override int GetHashCode()
        //{
        //    return base.GetHashCode();
        //}

        #endregion
    }
}