Example #1
0
        public TemplateView(EntryTemplate template)
        {
            if (template == null)
                throw new ArgumentNullException("template");

            this.Name = template.Name;
            this.AllowCustomFields = template.AllowCustomFields;
            this.IconIndex = template.IconIndex;

            this.Template = template;

            RegisterDataModelEvents();
        }
Example #2
0
        public void RemoveTemplate(EntryTemplate template)
        {
            if (template == null)
                throw new ArgumentNullException("template");
            if (!_templates.ContainsItem(template))
                throw new ArgumentException("This Database does not contain this template.");

            //find any entries in memory that use this template and convert them to custom fields, calls the db also
            foreach (var field in template.Fields.ToList())
            {
                DemoteTemplateField(template, field);
            }

            var affectedEntries = _entries.Items.Where(e => e.Template == template).ToList();
            foreach (var entry in affectedEntries)
            {
                entry.Template = null;
            }
            CommitEntryChanges(affectedEntries);

            int templateId = _templates[template];

            //call database
            var purgeCommand = new SqlCommand("sp_DeleteTemplate", _connection) { CommandType = System.Data.CommandType.StoredProcedure };
            purgeCommand.Parameters.Add(new SqlParameter("token", "null_token"));    //TODO: token will go here
            purgeCommand.Parameters.Add(new SqlParameter("template_id", templateId));
            purgeCommand.ExecuteNonQuery();

            _templates.Remove(template);
        }
Example #3
0
        public void RefreshTemplates()
        {
            if (!this.Connected)
                throw new InvalidOperationException("Cannot refresh the template list because the database is not connected.");
            if (!this.Authenticated)
                throw new InvalidOperationException("Cannot refresh the template list because the current user is not authenticated with the Database.");

            var getListCommand = new SqlCommand("sp_GetAllTemplates", _connection) { CommandType = System.Data.CommandType.StoredProcedure };
            getListCommand.Parameters.Add(new SqlParameter("token", "null_token"));    //TODO: token will go here

            using (var reader = getListCommand.ExecuteReader())
            {
                HashSet<int> templateIdsInMemory = new HashSet<int>(_templates.Keys);

                while (reader.Read())
                {
                    int templateId = (int)reader[0];
                    if (templateIdsInMemory.Contains(templateId))
                        templateIdsInMemory.Remove(templateId);

                    EntryTemplate template;
                    if (!_templates.TryGetItem(templateId, out template))
                    {
                        template = new EntryTemplate();
                        _templates.Add(templateId, template);
                    }

                    //update all fields
                    template.Name = reader[1] as string;
                    template.IconIndex = (int)reader[2];
                    template.AllowCustomFields = (bool)reader[3];
                }

                //delete templates that were not returned
                foreach (var id in templateIdsInMemory)
                {
                    _templates.Remove(id);
                }

                reader.NextResult();

                HashSet<int> templateFieldIdsInMemory = new HashSet<int>(_templateFields.Keys);

                while (reader.Read())
                {
                    int templateFieldId = (int)reader[0];
                    if (templateFieldIdsInMemory.Contains(templateFieldId))
                        templateFieldIdsInMemory.Remove(templateFieldId);

                    EntryField templateField;
                    if (!_templateFields.TryGetItem(templateFieldId, out templateField))
                    {
                        //add the template field to the appropriate template
                        int templateId = (int)reader[1];
                        EntryTemplate template;
                        if (!_templates.TryGetItem(templateId, out template))
                            throw new InvalidOperationException("A template field was returned for a template that is not defined in the database.");

                        templateField = new EntryField();
                        template.AddField(templateField);

                        _templateFields.Add(templateFieldId, templateField);
                    }

                    templateField.Name = reader[2] as string;
                    templateField.EntryType = (EntryFieldType)reader[3];
                    templateField.DefaultValue = reader[4] as string;
                }

                //remove fields that were not returned
                foreach (int id in templateFieldIdsInMemory)
                {
                    _templateFields.Remove(id);
                }
            }
        }
Example #4
0
        /// <summary>
        /// Saves a template and its field definitions to the database from memory.
        /// </summary>
        /// <param name="template"></param>
        public void CommitTemplate(EntryTemplate template)
        {
            if (!this.Connected)
                throw new InvalidOperationException("Cannot commit the template changes because the database is not connected.");
            if (!this.Authenticated)
                throw new InvalidOperationException("Cannot commit the template changes because the current user is not authenticated with the Database.");

            //create the query first
            var query = new XElement("Template",
                new XAttribute("id", _templates[template]),
                new XAttribute("name", template.Name),
                new XAttribute("icon_id", template.IconIndex),
                new XAttribute("allow_custom_fields", template.AllowCustomFields),
                new XElement("Fields",
                    from f in template.Fields
                    select new XElement("Field",
                        new XAttribute("id", _templateFields.ContainsItem(f) ? _templateFields[f] : -1),
                        new XAttribute("name", f.Name),
                        new XAttribute("type", (int)f.EntryType),
                        new XAttribute("default_value", f.DefaultValue ?? String.Empty))));

            //demote any fields that were deleted second
            var deletedFields = _templateFields.Items.Where(f => f.Container == template && !template.Fields.Contains(f)).ToList();
            foreach (var field in deletedFields)
            {
                DemoteTemplateField(template, field);
            }

            //Query the Database
            var updateCommand = new SqlCommand("sp_UpdateTemplate", _connection) { CommandType = System.Data.CommandType.StoredProcedure };
            updateCommand.Parameters.Add(new SqlParameter("token", "null_token"));    //TODO: token will go here
            updateCommand.Parameters.Add(new SqlParameter("updateXml", query.ToString()));

            //assign IDs from the -1 Fields
            using (var reader = updateCommand.ExecuteReader())
            {
                var unassigned = template.Fields.Where(f => !_templateFields.ContainsItem(f)).ToList();
                int index = 0;
                while (reader.Read())
                {
                    if (index > (unassigned.Count - 1))
                        throw new InvalidOperationException("The database returned new IDs that were not expected.");

                    int id = (int)reader[0];
                    _templateFields.Add(id, unassigned[index]);

                    index++;
                }

                if (index != unassigned.Count)
                    throw new InvalidOperationException("The database did not return new IDs for all the new template fields.");
            }
        }
Example #5
0
        public void AddTemplate(EntryTemplate template)
        {
            if (template == null)
                throw new ArgumentNullException("template");
            if (_templates.ContainsItem(template))
                throw new ArgumentException("This Database already contains this template.");

            var fields = template.Fields.ToList();

            var query = new XElement("Template",
                new XAttribute("name", template.Name),
                new XAttribute("icon_id", template.IconIndex),
                new XAttribute("allow_custom_fields", template.AllowCustomFields),
                new XElement("Fields",
                    from f in fields
                    select new XElement("Field",
                        new XAttribute("name", f.Name),
                        new XAttribute("type", (int)f.EntryType),
                        new XAttribute("default_value", f.DefaultValue ?? String.Empty))));

            //Query the Database
            var addCommand = new SqlCommand("sp_AddTemplate", _connection) { CommandType = System.Data.CommandType.StoredProcedure };
            addCommand.Parameters.Add(new SqlParameter("token", "null_token"));    //TODO: token will go here
            addCommand.Parameters.Add(new SqlParameter("addXml", query.ToString()));

            using (var reader = addCommand.ExecuteReader())
            {
                //assign IDs to the template
                int templateId = -1;
                while (reader.Read())
                {
                    templateId = (int)reader[0];
                    break;
                }
                if (templateId == -1)
                    throw new InvalidOperationException("No template ID was returned by the database.");

                _templates.Add(templateId, template);

                reader.NextResult();

                //assign IDs to the template fields
                int fieldIndex = 0;
                while (reader.Read())
                {
                    if (fieldIndex > fields.Count - 1)
                        throw new InvalidOperationException("More template field IDs were returned from the database than expected.");

                    int fieldId = (int)reader[0];
                    _templateFields.Add(fieldId, fields[fieldIndex]);
                    fieldIndex++;
                }
            }
        }
Example #6
0
        private void RefreshClientEntriesInternal(ClientRecord client)
        {
            //preparation
            int clientId = _clients[client];
            if (!_clients.TryGetKey(client, out clientId))
                throw new ArgumentException("The specified client is not in this database.");

            var newEntries = new List<ClientEntry>();
            var prevEntryIds = client.Entries.Select(e => _entries[e]).ToList();

            //Query the Database
            var getListCommand = new SqlCommand("sp_GetClientEntries", _connection) { CommandType = System.Data.CommandType.StoredProcedure };
            getListCommand.Parameters.Add(new SqlParameter("token", "null_token"));    //TODO: token will go here
            getListCommand.Parameters.Add(new SqlParameter("client_id", clientId));

            using (var reader = getListCommand.ExecuteReader())
            {
                //result set 1: entry list for the specified client
                while (reader.Read())
                {
                    ClientEntry entry;
                    int clientEntryDbId = (int)reader[0];

                    //index the entry if it is new
                    if (!_entries.TryGetItem(clientEntryDbId, out entry))
                    {
                        entry = new ClientEntry();
                        _entries.Add(clientEntryDbId, entry);
                        newEntries.Add(entry);
                    }

                    //update the properties of the entry, regardless if it existed before
                    entry.Name = (string)reader[2];
                    entry.IconIndex = (int)reader[3];
                    entry.Notes = WebUtility.HtmlDecode((reader[5] as string ?? String.Empty).Replace("<br>", Environment.NewLine));

                    //set the template, it will get updated later if it doesn't exist yet
                    //we index the new template right away
                    EntryTemplate template;
                    int templateId = (reader[4] == DBNull.Value) ? -1 : (int)reader[4];
                    if (templateId == -1)
                    {
                        template = null;    //orphaned record
                    }
                    else if (!_templates.TryGetItem(templateId, out template))
                    {
                        template = new EntryTemplate();
                        _templates.Add(templateId, template);
                    }
                    entry.Template = template;
                }

                //result set 2: template definition
                reader.NextResult();
                while (reader.Read())
                {
                    EntryTemplate template;
                    int templateDbId = (int)reader[0];

                    if (!_templates.TryGetItem(templateDbId, out template))
                        throw new InvalidOperationException("A template was returned that was not part of the first result set.");

                    //update the properties
                    template.Name = reader[1] as string;
                    template.IconIndex = (int)reader[2];
                    template.AllowCustomFields = (bool)reader[3];
                }

                //result set 3: fields for the previous templates
                reader.NextResult();
                while (reader.Read())
                {
                    EntryField templateField;
                    EntryTemplate template;
                    int templateFieldId = (int)reader[0];
                    int templateId = (int)reader[1];
                    if (!_templates.TryGetItem(templateId, out template))
                        throw new InvalidOperationException("A template field was returned that belongs to a template that was not returned in the previous result set.");

                    if (!_templateFields.TryGetItem(templateFieldId, out templateField))
                    {
                        templateField = new EntryField();
                        _templateFields.Add(templateFieldId, templateField);
                    }

                    if (!template.Fields.Contains(templateField))
                        template.AddField(templateField);

                    //update the properties
                    templateField.Name = reader[2] as string;
                    templateField.EntryType = (EntryFieldType)reader[3];
                    templateField.DefaultValue = reader[4] as string;
                }
                //TODO: remove any fields that were not returned

                //result set 4: field values
                reader.NextResult();
                while (reader.Read())
                {
                    int fieldValueId = (int)reader[0];
                    int entryId = (int)reader[1];

                    ClientEntry entry;
                    if (!_entries.TryGetItem(entryId, out entry))
                        throw new InvalidOperationException("A ClientEntry was returned that was not defined in a previous result set.");

                    int templateFieldId = (reader[2] == DBNull.Value) ? -1 : (int)reader[2];
                    string entryValue = reader[4] as string;

                    //indexing of fields values:
                    //  template field values are indexed by TFVR objects in the _templateFieldsById dictionary
                    //  custom field values are indexed by just the EntryField object in the _customFieldsById dictionary
                    if (templateFieldId == -1)
                    {
                        //custom field
                        string fieldName = reader[3] as string;
                        EntryField customField;
                        if (!_customFields.TryGetItem(fieldValueId, out customField))
                        {
                            customField = new EntryField() { Name = fieldName };    //todo: type
                            entry.AddCustomField(customField);
                            _customFields.Add(fieldValueId, customField);
                        }

                        //update the name and value
                        customField.Name = fieldName;
                        entry.SetValue(customField, DataSecurity.DecryptStringAES(entryValue));
                    }
                    else
                    {
                        //find the template EntryField by ID
                        EntryField templateField;
                        if (_templateFields.TryGetItem(templateFieldId, out templateField))
                        {
                            //save the ID of the field value for saving later
                            if (!_templateValues.Values.Any(tfvr => tfvr.ClientEntry == entry && tfvr.TemplateField == templateField))
                                _templateValues.Add(fieldValueId, new TemplateFieldValueRelation() { ClientEntry = entry, TemplateField = templateField });

                            entry.SetValue(templateField, DataSecurity.DecryptStringAES(entryValue));
                        }
                        else
                        {
                            throw new InvalidOperationException("A template field was returned that cannot be matched to an existing template.");
                        }
                    }
                }
                //TODO: remove any fields that were not returned
            }

            //clean up the internal list, and raise events for the UI
            var deletedEntryIds = prevEntryIds.Except(_entries.Keys).ToList();
            if (deletedEntryIds.Any())
            {
                var deletedEntries = new List<ClientEntry>();
                foreach (var id in deletedEntryIds)
                {
                    var entry = _entries[id];
                    deletedEntries.Add(entry);
                    _entries.Remove(entry);
                }

                client.RemoveEntries(deletedEntries);
            }

            if (newEntries.Any())
                client.AddEntries(newEntries);
        }
Example #7
0
        private void DemoteTemplateField(EntryTemplate template, EntryField field)
        {
            foreach (var entry in _entries.Items.Where(e => e.Template == template))
            {
                //transfer the value to the custom field if applicable
                var relation = _templateValues.FirstOrDefault(tfvr => tfvr.Value.ClientEntry == entry && tfvr.Value.TemplateField == field);
                if (relation.Value != null)
                {
                    var newField = new EntryField() { Name = field.Name, EntryType = field.EntryType };
                    entry.AddCustomField(newField);

                    var value = entry.GetOrphanedValue(field);
                    entry.SetValue(newField, DataSecurity.DecryptStringAES(value));

                    _templateValues.Remove(relation.Key);
                    _customFields.Add(relation.Key, newField);
                }
            }

            //call the DB to do the same as above
            int fieldId = _templateFields[field];
            var purgeCommand = new SqlCommand("sp_DeleteTemplateField", _connection) { CommandType = System.Data.CommandType.StoredProcedure };
            purgeCommand.Parameters.Add(new SqlParameter("token", "null_token"));    //TODO: token will go here
            purgeCommand.Parameters.Add(new SqlParameter("template_field_id", fieldId));
            purgeCommand.ExecuteNonQuery();

            _templateFields.Remove(fieldId);
        }