Esempio n. 1
0
 internal TikListMerge(ITikConnection connection, IEnumerable <TEntity> expected, IEnumerable <TEntity> original)
 {
     _connection = connection;
     _metadata   = TikEntityMetadataCache.GetMetadata <TEntity>();
     _expected   = expected;
     _original   = original;
 }
        private static ITikCommand CreateLoadCommandWithFilter <TEntity> (ITikConnection connection, ITikCommandParameter[] parameters)
        {
            var metadata = TikEntityMetadataCache.GetMetadata <TEntity>();

            ITikCommand command = connection.CreateCommand(metadata.EntityPath + metadata.LoadCommand, metadata.LoadDefaultParameneterFormat);

            // =detail=
            if (metadata.IncludeDetails)
            {
                command.AddParameter("detail", "", TikCommandParameterFormat.NameValue);
            }
            //.proplist
            if (metadata.IncludeProplist)
            {
                command.AddParameter(TikSpecialProperties.Proplist, string.Join(",", metadata.Properties.Select(prop => prop.FieldName).ToArray()), TikCommandParameterFormat.NameValue);
            }
            //filter
            //parameters
            if (parameters != null)
            {
                foreach (ITikCommandParameter param in parameters)
                {
                    command.Parameters.Add(param);
                }
            }

            return(command);
        }
Esempio n. 3
0
        /// <summary>
        /// Compares IDs (.id) of two instances of entity.
        /// </summary>
        /// <param name="entity1">First entity.</param>
        /// <param name="entity2">Seconf entity.</param>
        /// <returns>True if ids are equal.</returns>
        public static bool IdEquals <TEntity>(this TEntity entity1, TEntity entity2)
        {
            var metadata = TikEntityMetadataCache.GetMetadata <TEntity>();

            string id1 = metadata.IdProperty.GetEntityValue(entity1);
            string id2 = metadata.IdProperty.GetEntityValue(entity2);

            return(string.Equals(id1, id2));
        }
Esempio n. 4
0
        /// <summary>
        /// Creates entity string description (for logging, etc.) by its fields.
        /// </summary>
        /// <typeparam name="TEntity">Type of entity.</typeparam>
        /// <param name="entity">Entity instance.</param>
        /// <returns>Readable description of entity and its fields.</returns>
        public static string EntityToString <TEntity>(this TEntity entity)
        {
            var metadata = TikEntityMetadataCache.GetMetadata <TEntity>();

            StringBuilder sb = new StringBuilder(typeof(TEntity).FullName + ":");

            foreach (var property in metadata.Properties)
            {
                sb.AppendLine(string.Format("  {0}={1}", property.FieldName, property.GetEntityValue(entity)));
            }

            return(sb.ToString());
        }
Esempio n. 5
0
        private static TEntity CreateObject <TEntity>(ITikReSentence sentence)
            where TEntity : new()
        {
            var metadata = TikEntityMetadataCache.GetMetadata <TEntity>();

            TEntity result = new TEntity();

            foreach (var property in metadata.Properties)
            {
                property.SetEntityValue(result, GetValueFromSentence(sentence, property));
            }

            return(result);
        }
Esempio n. 6
0
        /// <summary>
        /// Crates clone of given entity by its fields.
        /// </summary>
        /// <typeparam name="TEntity">Type of entity.</typeparam>
        /// <param name="entity">Entity to be cloned.</param>
        /// <returns>Cloned instance of entity.</returns>
        /// <remarks>Clones only fields marked with <see cref="TikPropertyAttribute"/>.</remarks>
        public static TEntity CloneEntity <TEntity>(this TEntity entity)
            where TEntity : new()
        {
            var     metadata = TikEntityMetadataCache.GetMetadata <TEntity>();
            TEntity result   = new TEntity();

            //copy all "field" properties
            foreach (var property in metadata.Properties)
            {
                property.SetEntityValue(result, property.GetEntityValue(entity));
            }

            return(result);
        }
Esempio n. 7
0
        /// <summary>
        /// Compares IDs (.id) of two instances of entity.
        /// </summary>
        /// <param name="entity1">First entity.</param>
        /// <param name="entity2">Seconf entity.</param>
        /// <returns>True if ids are equal.</returns>
        public static bool IdEquals <TEntity>(this TEntity entity1, TEntity entity2)
        {
            var metadata = TikEntityMetadataCache.GetMetadata <TEntity>();

            if (!metadata.HasIdProperty)
            {
                throw new InvalidOperationException(string.Format("Can not compare ids of entity which doesn't contains property for '{0}' field.", TikSpecialProperties.Id));
            }

            string id1 = metadata.IdProperty.GetEntityValue(entity1);
            string id2 = metadata.IdProperty.GetEntityValue(entity2);

            return(string.Equals(id1, id2));
        }
        /// <summary>
        /// Deletes entity (.id is the key) on mikrotik router.
        /// </summary>
        /// <typeparam name="TEntity">Deleted entity type.</typeparam>
        /// <param name="connection">Tik connection used to delete entity.</param>
        /// <param name="entity">Entity to be deleted (.id property is the key)</param>
        public static void Delete <TEntity>(this ITikConnection connection, TEntity entity)
        {
            var metadata = TikEntityMetadataCache.GetMetadata <TEntity>();

            EnsureNotReadonlyEntity(metadata);
            string id = metadata.IdProperty.GetEntityValue(entity);

            if (string.IsNullOrEmpty(id))
            {
                throw new ArgumentException("Entity has no .id (entity is not loaded from mikrotik router)", "entity");
            }

            ITikCommand cmd = connection.CreateCommandAndParameters(metadata.EntityPath + "/remove", TikCommandParameterFormat.NameValue,
                                                                    TikSpecialProperties.Id, id);

            cmd.ExecuteNonQuery();
        }
Esempio n. 9
0
        /// <summary>
        /// Compares two instances of entity by their fields and returns different fields (field names).
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entity1">First entity.</param>
        /// <param name="entity2">Seconf entity.</param>
        /// <param name="skipIdCompare">If is true, than coparation of .id property is skipped.</param>
        /// <returns>List of different fields.</returns>
        /// <remarks>Compares only fields marked with <see cref="TikPropertyAttribute"/>.</remarks>
        public static IEnumerable <string> GetDifferentFields <TEntity>(this TEntity entity1, TEntity entity2, bool skipIdCompare = false)
        {
            var metadata = TikEntityMetadataCache.GetMetadata <TEntity>();

            foreach (var property in metadata.Properties)
            {
                if (!skipIdCompare || property.FieldName != TikSpecialProperties.Id)
                {
                    string prop1 = property.GetEntityValue(entity1);
                    string prop2 = property.GetEntityValue(entity2);

                    if (!string.Equals(prop1, prop2))
                    {
                        yield return(property.FieldName);
                    }
                }
            }
        }
Esempio n. 10
0
        /// <summary>
        /// List version of <see cref="Save"/> method. Saves differences between given <paramref name="modifiedList"/> and <paramref name="unmodifiedList"/>.
        /// Typical usage is: Load, create list clone, modify list, save diferences.
        /// </summary>
        /// <example>
        /// var list = connection.LoadList{FirewallAddressList}(connection.CreateParameter("list", listName), connection.CreateParameter("address", ipAddress));
        /// var listClonedBackup = list.CloneEntityList(); //creates clone of all entities in list
        /// list.Add(new FirewallAddressList() {Address = ipAddress, List = listName, }); //insert
        /// list[0].Comment = "test comment"; //update
        /// list.RemoveAt(1); //delete
        /// connection.SaveListDifferences(list, listClonedBackup);
        /// </example>
        /// <typeparam name="TEntity">Saved entitie type.</typeparam>
        /// <param name="connection">Tik connection used to save.</param>
        /// <param name="modifiedList">List with modifications.</param>
        /// <param name="unmodifiedList">Original (cloned) unmodified list.</param>
        /// <seealso cref="TikEntityObjectsExtensions.CloneEntity"/>
        /// <seealso cref="TikEntityObjectsExtensions.CloneEntityList"/>
        /// <seealso cref="Save"/>
        public static void SaveListDifferences <TEntity>(this ITikConnection connection, IEnumerable <TEntity> modifiedList, IEnumerable <TEntity> unmodifiedList)
            where TEntity : new()
        {
            var metadata = TikEntityMetadataCache.GetMetadata <TEntity>();

            EnsureNotReadonlyEntity(metadata);
            EnsureHasIdProperty(metadata);
            var idProperty = metadata.IdProperty;

            var entitiesToCreate = modifiedList.Where(entity => string.IsNullOrEmpty(idProperty.GetEntityValue(entity))).ToList(); // new items in modifiedList

            Dictionary <string, TEntity> modifiedEntities = modifiedList
                                                            .Where(entity => !string.IsNullOrEmpty(idProperty.GetEntityValue(entity)))
                                                            .ToDictionary(entity => idProperty.GetEntityValue(entity));   //all entities from modified list with ids
            Dictionary <string, TEntity> unmodifiedEntities = unmodifiedList
                                                                                                                          //.Where(entity => !string.IsNullOrEmpty(idProperty.GetEntityValue(entity))) - entity in unmodified list has id (is loaded from miktrotik)
                                                              .ToDictionary(entity => idProperty.GetEntityValue(entity)); //all entities from unmodified list with ids

            //DELETE
            foreach (string entityId in unmodifiedEntities.Keys.Where(id => !modifiedEntities.ContainsKey(id))) //missing in modified -> deleted
            {
                Delete(connection, unmodifiedEntities[entityId]);
            }

            //CREATE
            foreach (TEntity entity in entitiesToCreate)
            {
                Save(connection, entity);
            }

            //UPDATE
            foreach (string entityId in unmodifiedEntities.Keys.Where(id => modifiedEntities.ContainsKey(id))) // are in both modified and unmodified -> compare values (update/skip)
            {
                TEntity modifiedEntity   = modifiedEntities[entityId];
                TEntity unmodifiedEntity = unmodifiedEntities[entityId];

                if (!modifiedEntity.EntityEquals(unmodifiedEntity))
                {
                    Save(connection, modifiedEntity);
                }
            }

            //TODO support for order!
        }
Esempio n. 11
0
        /// <summary>
        /// Moves given <paramref name="entityToMove"/> before given <paramref name="entityToMoveBefore"/>.
        /// </summary>
        /// <typeparam name="TEntity">Moved entity type.</typeparam>
        /// <param name="connection">Tik connection used to move entity.</param>
        /// <param name="entityToMove">Entity to be moved.</param>
        /// <param name="entityToMoveBefore">Entity before which is given <paramref name="entityToMove"/> moved.</param>
        public static void Move <TEntity>(this ITikConnection connection, TEntity entityToMove, TEntity entityToMoveBefore)
        {
            var metadata = TikEntityMetadataCache.GetMetadata <TEntity>();

            EnsureSupportsOrdering(metadata);

            string idToMove       = metadata.IdProperty.GetEntityValue(entityToMove);
            string idToMoveBefore = entityToMoveBefore != null?metadata.IdProperty.GetEntityValue(entityToMoveBefore) : null;

            ITikCommand cmd = connection.CreateCommandAndParameters(metadata.EntityPath + "/move", TikCommandParameterFormat.NameValue,
                                                                    "numbers", idToMove);

            if (entityToMoveBefore != null)
            {
                cmd.AddParameter("destination", idToMoveBefore);
            }

            cmd.ExecuteNonQuery();
        }
Esempio n. 12
0
        /// <summary>
        /// Saves entity to mikrotik router. Does insert (/add) whan entity has empty id and update(/set + /unset) when id is present).
        /// Behavior of save is modified via <see cref="TikPropertyAttribute"/> on properties.
        /// See <see cref="TikPropertyAttribute.DefaultValue"/>, <see cref="TikPropertyAttribute.UnsetOnDefault"/>.
        /// </summary>
        /// <typeparam name="TEntity">Saved entitie type.</typeparam>
        /// <param name="connection">Tik connection used to save.</param>
        /// <param name="entity">Saved entity.</param>
        /// <param name="usedFieldsFilter">List of field names (on mikrotik) which should be modified. If is not null, only listed fields will be modified.</param>
        public static void Save <TEntity>(this ITikConnection connection, TEntity entity, IEnumerable <string> usedFieldsFilter = null)
            where TEntity : new()
        {
            var metadata = TikEntityMetadataCache.GetMetadata <TEntity>();

            EnsureNotReadonlyEntity(metadata);

            string id;

            if (metadata.IsSingleton)
            {
                id = null;
            }
            else
            {
                EnsureHasIdProperty(metadata);
                id = metadata.IdProperty.GetEntityValue(entity);
            }

            if (!metadata.IsSingleton && string.IsNullOrEmpty(id))
            {
                //create
                ITikCommand createCmd = connection.CreateCommand(metadata.EntityPath + "/add", TikCommandParameterFormat.NameValue);

                foreach (var property in metadata.Properties
                         .Where(pm => !pm.IsReadOnly)
                         .Where(pm => usedFieldsFilter == null || usedFieldsFilter.Contains(pm.FieldName, StringComparer.OrdinalIgnoreCase)))
                {
                    if (!property.HasDefaultValue(entity))
                    {
                        createCmd.AddParameter(property.FieldName, property.GetEntityValue(entity));
                    }
                }

                id = createCmd.ExecuteScalar();
                if (metadata.HasIdProperty)
                {
                    metadata.IdProperty.SetEntityValue(entity, id); // update saved id into entity
                }
            }
            else
            {
                //update (set+unset)
                ITikCommand setCmd = connection.CreateCommand(metadata.EntityPath + "/set", TikCommandParameterFormat.NameValue);

                if (!metadata.IsSingleton && usedFieldsFilter == null)
                {
                    //compare state on mikrotik and update different fields only
                    var unmodifiedEntity = connection.LoadById <TEntity>(id); //TODO some kind of "loaded entities" session cache could be used to avoid another load before save.
                    usedFieldsFilter = entity.GetDifferentFields(unmodifiedEntity);
                }

                List <string> fieldsToUnset = new List <string>();

                foreach (var property in metadata.Properties
                         .Where(pm => !pm.IsReadOnly)
                         .Where(pm => usedFieldsFilter == null || usedFieldsFilter.Contains(pm.FieldName, StringComparer.OrdinalIgnoreCase)))
                {
                    if (property.HasDefaultValue(entity) && property.UnsetOnDefault)
                    {
                        fieldsToUnset.Add(property.FieldName);
                    }
                    else
                    {
                        setCmd.AddParameter(property.FieldName, property.GetEntityValue(entity)); //full update (all values)
                    }
                }

                if (fieldsToUnset.Count > 0)
                {
                    // this should also work (see http://forum.mikrotik.com/viewtopic.php?t=28821 )
                    //ip/route/unset
                    //=.id = *1
                    //= value-name=routing-mark

                    foreach (string fld in fieldsToUnset)
                    {
                        ITikCommand unsetCmd = connection.CreateCommand(metadata.EntityPath + "/unset", TikCommandParameterFormat.NameValue);
                        unsetCmd.AddParameter(TikSpecialProperties.Id, id, TikCommandParameterFormat.NameValue);
                        unsetCmd.AddParameter(TikSpecialProperties.UnsetValueName, fld);

                        unsetCmd.ExecuteNonQuery();
                    }
                }
                if (setCmd.Parameters.Any())
                {
                    if (!metadata.IsSingleton)
                    {
                        setCmd.AddParameter(TikSpecialProperties.Id, id, TikCommandParameterFormat.NameValue);
                    }
                    setCmd.ExecuteNonQuery();
                }
            }
        }