<commit_before>using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Newtonsoft.Json;
using XPlatUtils;

namespace Toggl.Phoebe.Data
{
    /**
     * TODO: Test for:
     * - correct MarkDirty behaviour
     */
    [JsonObject (MemberSerialization.OptIn)]
    public abstract partial class Model : ObservableObject
    {
        private static readonly Dictionary<Type, Dictionary<string, bool>> dontDirtyCache =
            new Dictionary<Type, Dictionary<string, bool>> ();

        private static bool CanDirty (Type objectType, string property)
        {
            Dictionary<string, bool> typeCache;
            if (!dontDirtyCache.TryGetValue (objectType, out typeCache)) {
                dontDirtyCache [objectType] = typeCache = new Dictionary<string, bool> ();
            }
            bool hasAttr;
            if (!typeCache.TryGetValue (property, out hasAttr)) {
                var propInfo = objectType.GetProperty (property);
                hasAttr = propInfo.GetCustomAttributes (typeof(DontDirtyAttribute), true).Length > 0;
            }
            return !hasAttr;
        }

        private static string GetPropertyName<T> (Expression<Func<Model, T>> expr)
        {
            return expr.ToPropertyName ();
        }

        protected override void OnPropertyChanged (string property)
        {
            base.OnPropertyChanged (property);

            Validate (property);

            ServiceContainer.Resolve<MessageBus> ().Send (new ModelChangedMessage (this, property));

            // Automatically mark the object dirty, if property doesn't explicitly disable it
            if (CanDirty (GetType (), property)) {
                MarkDirty (property != PropertyModifiedAt);
            }
        }

        protected void MarkDirty (bool updateModTime = true)
        {
            if (!IsShared || IsMerging)
                return;

            if (updateModTime)
                ModifiedAt = DateTime.UtcNow;
            IsDirty = true;
        }

        public virtual void Delete ()
        {
            DeletedAt = DateTime.UtcNow;<commit_msg>Disable most of OnPropertyChanged logic for non-shared models.<commit_after>using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Newtonsoft.Json;
using XPlatUtils;

namespace Toggl.Phoebe.Data
{
    /**
     * TODO: Test for:
     * - correct MarkDirty behaviour
     */
    [JsonObject (MemberSerialization.OptIn)]
    public abstract partial class Model : ObservableObject
    {
        private static readonly Dictionary<Type, Dictionary<string, bool>> dontDirtyCache =
            new Dictionary<Type, Dictionary<string, bool>> ();

        private static bool CanDirty (Type objectType, string property)
        {
            Dictionary<string, bool> typeCache;
            if (!dontDirtyCache.TryGetValue (objectType, out typeCache)) {
                dontDirtyCache [objectType] = typeCache = new Dictionary<string, bool> ();
            }
            bool hasAttr;
            if (!typeCache.TryGetValue (property, out hasAttr)) {
                var propInfo = objectType.GetProperty (property);
                hasAttr = propInfo.GetCustomAttributes (typeof(DontDirtyAttribute), true).Length > 0;
            }
            return !hasAttr;
        }

        private static string GetPropertyName<T> (Expression<Func<Model, T>> expr)
        {
            return expr.ToPropertyName ();
        }

        protected override void OnPropertyChanged (string property)
        {
            base.OnPropertyChanged (property);

            if (IsShared) {
                if (property == PropertyIsShared) {
                    // Validate whole model when being promoted to shared
                    Validate ();
                } else {
                    Validate (property);
                }

                ServiceContainer.Resolve<MessageBus> ().Send (new ModelChangedMessage (this, property));

                // Automatically mark the object dirty, if property doesn't explicitly disable it
                if (CanDirty (GetType (), property)) {
                    MarkDirty (property != PropertyModifiedAt);
                }
            }
        }

        protected void MarkDirty (bool updateModTime = true)
        {
            if (!IsShared || IsMerging)
                return;

            if (updateModTime)
                ModifiedAt = DateTime.UtcNow;
            IsDirty = true;
        }

        public virtual void Delete ()
        {
            DeletedAt = DateTime.UtcNow;
{'fraction_non_alphanumeric': 0.08473834026713378, 'fraction_numerical': 0.0004379242391066346, 'mean_word_length': 1.9319640564826701, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1416086', 'n_tokens_mistral': 1141, 'n_tokens_neox': 1101, 'n_words': 305}