// needs to be tested for reflection speed
        // Goes through all properties/fields with DataMember attributes and tries to copy them from passed object
        public virtual void Replace(BaseNoun obj)
        {
            if (!(this.GetType().Equals(obj.GetType()) || this.GetType().IsSubclassOf(obj.GetType())))
            {
                return;
            }

            BindingFlags        allFields  = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
            List <PropertyInfo> properties = this.GetType().GetProperties(allFields)
                                             .Where(x => Attribute.IsDefined(x, typeof(JsonPropertyAttribute)))
                                             .ToList();

            foreach (PropertyInfo property in properties)
            {
                property.SetValue(this, property.GetValue(obj, null), null);
            }
            List <FieldInfo> fields = this.GetType().GetFields(allFields)
                                      .Where(x => Attribute.IsDefined(x, typeof(JsonPropertyAttribute)))
                                      .ToList();

            foreach (FieldInfo field in fields)
            {
                field.SetValue(this, field.GetValue(obj));
            }
        }
        public virtual int CompareTo(object obj)
        {
            if (obj == null)
            {
                return(1);
            }

            BaseNoun noun = obj as BaseNoun;

            if (noun != null)
            {
                if (noun.UniqueCodeField.Equals("id"))
                {
                    return(this.Id.CompareTo(noun.Id));
                }
                else
                {
                    return(this.UniqueCode.CompareTo(noun.UniqueCode));
                }
            }
            else
            {
                throw new ArgumentException("Object is not a Noun");
            }
        }
        public override bool Equals(object obj)
        {
            BaseNoun otherObj = obj as BaseNoun;

            if (otherObj == null)
            {
                return(false);
            }
            return(otherObj.id == this.id && obj.GetType().Equals(this.GetType()));
        }
        // Nested send supported when parent not null, will return full list of values no matter what method you use
        // Method used by for nested createNew:  false - replace with list, true - add to list
        public virtual List <T> SendObjects <T>(Noun.Base.BaseNoun parent, List <T> sendingObject, bool createNew = false) where T : Noun.Base.BaseNoun, new()
        {
            if (parent != null && parent.Id <= 0)
            {
                throw new RESTAPIException("Parent noun (" + parent + ") must have a valid id");
            }

            // serialize sending object
            string   jsonOut  = JsonConvert.SerializeObject(sendingObject);
            Encoding encoding = Encoding.UTF8;

            byte[] output = encoding.GetBytes(jsonOut);
            // send post/put request
            string urlNoun = "/" + Noun.Base.BaseNoun.GetNoun(typeof(T));

            if (parent != null)
            {
                urlNoun = "/" + Noun.Base.BaseNoun.GetNoun(parent.GetType()) + "/" + parent.Id + urlNoun;
            }
            string contentType = "application/json";
            Dictionary <string, string> requestHeaders = null;

            if (!createNew && this.UseIfUnmodifiedSince)
            {
                DateTime updated = DateTime.MinValue;
                if (parent == null && sendingObject is List <IUpdatedNoun> )
                {
                    foreach (IUpdatedNoun updateObject in (sendingObject as List <IUpdatedNoun>))
                    {
                        if (updated < updateObject.Updated)
                        {
                            updated = updateObject.Updated;
                        }
                    }
                }
                else if (parent != null && parent is IUpdatedNoun)
                {
                    updated = (parent as IUpdatedNoun).Updated;
                }
                if (updated != DateTime.MinValue)
                {
                    requestHeaders = new Dictionary <string, string>();
                    requestHeaders["If-Unmodified-Since"] = updated.ToUniversalTime().ToString("r");
                }
            }
            string responseText = sendObjectStringResponse(output, createNew, urlNoun, contentType, requestHeaders);

            // fill values list
            List <T> values = JsonConvert.DeserializeObject <List <T> >(responseText);

            return(values);
        }
 public virtual Information.Options GetOptions(Noun.Base.BaseNoun noun)
 {
     return(GetOptions(noun.GetType(), noun.Id));
 }
 // Empty response on success, throws error on failure
 // Handles new option to delete a single nested noun item
 public virtual void DeleteObject <T>(int id, Noun.Base.BaseNoun parent = null) where T : Noun.Base.BaseNoun
 {
     deleteObject(typeof(T), id, parent);
 }