Projekt

Obecné

Profil

Stáhnout (23.4 KB) Statistiky
| Větev: | Tag: | Revize:
1 eff8ec56 Vojtěch Bartička
using Core.Contexts;
2
using Core.Entities;
3
using Models.Annotations;
4
using Models.Enums;
5
using Serilog;
6
using System;
7
using System.Collections.Generic;
8
using System.Linq;
9
using System.Text;
10
using System.Threading.Tasks;
11 6bdb3d95 Vojtěch Bartička
using Microsoft.EntityFrameworkCore;
12 a6675a6d Vojtěch Bartička
using AutoMapper;
13
using Models.Tags;
14 3c185841 Vojtěch Bartička
using Ganss.XSS;
15
using HtmlAgilityPack;
16
using System.Text.RegularExpressions;
17 553486ad Vojtěch Bartička
using Newtonsoft.Json;
18 8dc25caa Vojtěch Bartička
using Core.GraphUtils;
19 eff8ec56 Vojtěch Bartička
20
namespace Core.Services.AnnotationService
21
{
22
    public class AnnotationServiceEF : IAnnotationService
23
    {
24
        private readonly DatabaseContext context;
25
        private readonly ILogger logger;
26 a6675a6d Vojtěch Bartička
        private readonly IMapper mapper;
27 2c9afc72 Vojtěch Bartička
        private readonly IHTMLService htmlService;
28 eff8ec56 Vojtěch Bartička
29 0a9f9349 Vojtěch Bartička
30 2c9afc72 Vojtěch Bartička
        public AnnotationServiceEF(DatabaseContext context, ILogger logger, IMapper mapper, IHTMLService htmlService)
31 eff8ec56 Vojtěch Bartička
        {
32
            this.context = context;
33
            this.logger = logger;
34 a6675a6d Vojtěch Bartička
            this.mapper = mapper;
35 2c9afc72 Vojtěch Bartička
            this.htmlService = htmlService;
36 eff8ec56 Vojtěch Bartička
        }
37
38
        public void CreateDocumentAnnotations(AnnotationsAddRequest request, Guid clientUserId)
39
        {
40
            User addingUser = context.Users.Single(u => u.Id == clientUserId);
41
42
            // Check the documents exist
43 153d77a8 Vojtěch Bartička
            var documents = context.Documents.Where(d => request.DocumentIdList.Contains(d.Id)).ToList();
44
            if (documents.Count() != request.DocumentIdList.Count)
45 eff8ec56 Vojtěch Bartička
            {
46 153d77a8 Vojtěch Bartička
                logger.Information($"Received a non-existent Document ID when assigning documents to users");
47
                throw new InvalidOperationException($"{request.DocumentIdList.Count - documents.Count()} of the received documents do not exist");
48 eff8ec56 Vojtěch Bartička
            }
49
50 6bdb3d95 Vojtěch Bartička
            var users = context.Users.Where(u => request.UserIdList.Contains(u.Id)).ToList();
51 153d77a8 Vojtěch Bartička
            foreach (var user in users)
52 eff8ec56 Vojtěch Bartička
            {
53 153d77a8 Vojtěch Bartička
                var userAnnotatedDocuments = context.Annotations.Where(a => a.User == user).Select(a => a.Document).ToList();
54
                foreach (var doc in documents)
55 eff8ec56 Vojtěch Bartička
                {
56 153d77a8 Vojtěch Bartička
                    if (userAnnotatedDocuments.Contains(doc))
57 eff8ec56 Vojtěch Bartička
                    {
58 153d77a8 Vojtěch Bartička
                        logger.Information($"User {user.Username} has already been assigned the document {doc.Id}, ignoring");
59
                        continue;
60 eff8ec56 Vojtěch Bartička
                    }
61
62
                    context.Annotations.Add(new Annotation()
63
                    {
64
                        User = user,
65
                        UserAssigned = addingUser,
66
                        DateAssigned = DateTime.Now,
67
                        DateLastChanged = DateTime.Now,
68 153d77a8 Vojtěch Bartička
                        Document = doc,
69 eff8ec56 Vojtěch Bartička
                        State = EState.NEW,
70
                        Note = ""
71
                    });
72
                }
73
            }
74
75
            context.SaveChanges();
76
        }
77 6bdb3d95 Vojtěch Bartička
78
        public AnnotationListResponse GetUserAnnotations(Guid userId)
79
        {
80
            var annotations = context.Annotations.Where(a => a.User.Id == userId).Include(a => a.Document).ToList();
81
            var documentIds = annotations.Select(a => a.Document.Id).ToList();
82
            var documents = context.Documents.Where(d => documentIds.Contains(d.Id));
83
            var infos = new List<AnnotationListInfo>();
84
85
            var annotationsDocuments = annotations.Zip(documents, (a, d) => new { Annotation = a, Document = d });
86
            foreach (var ad in annotationsDocuments)
87
            {
88
                infos.Add(new AnnotationListInfo()
89
                {
90
                    AnnotationId = ad.Annotation.Id,
91
                    DocumentName = ad.Document.Name,
92
                    State = ad.Annotation.State
93
                });
94
            }
95
96
            return new AnnotationListResponse()
97
            {
98
                Annotations = infos
99
            };
100
        }
101 a6675a6d Vojtěch Bartička
102 f2275185 Vojtěch Bartička
        public void AddNoteToAnnotation(Guid annotationId, Guid userId, ERole userRole, AddNoteToAnnotationRequest request)
103
        {
104
            Annotation annotation = null;
105
            try
106
            {
107
                annotation = context.Annotations.Include(a => a.User).First(a => a.Id == annotationId);
108
            }
109
            catch (Exception)
110
            {
111
                throw new InvalidOperationException("Annotation not found");
112
            }
113
114
            if (userRole < ERole.ADMINISTRATOR && annotation.User.Id != userId)
115
            {
116
                throw new UnauthorizedAccessException("User does not have access to this annotation");
117
            }
118
119
            annotation.Note = request.Note;
120
            context.SaveChanges();
121
        }
122
123
124 a6675a6d Vojtěch Bartička
        public AnnotationInfo GetAnnotation(Guid annotationId, Guid userId, ERole userRole)
125
        {
126 c2a89232 Vojtěch Bartička
            var annotation = context.Annotations
127
                .Where(a => a.Id == annotationId)
128
                .Include(a => a.User)
129
                .Include(a => a.Document).ThenInclude(d => d.Content)
130
                .First();
131 3c185841 Vojtěch Bartička
132 a6675a6d Vojtěch Bartička
            if (userRole < ERole.ADMINISTRATOR)
133
            {
134
                if (annotation.User.Id != userId)
135
                {
136
                    throw new UnauthorizedAccessException($"User {userId} does not have assigned annotation {annotationId}");
137
                }
138
            }
139
140 c2a89232 Vojtěch Bartička
            var documentContent = context.Documents.Where(d => d.Id == annotation.Document.Id).Select(d => d.Content).First();
141 a6675a6d Vojtěch Bartička
142 c2a89232 Vojtěch Bartička
            var tags = context.AnnotationTags.Where(at => at.Annotation.Id == annotationId)
143 553486ad Vojtěch Bartička
                .Include(at => at.Tag)
144
                .ThenInclude(t => t.Category)
145 c2a89232 Vojtěch Bartička
                .Include(at => at.SubTag)
146 3c89e947 Vojtěch Bartička
                .OrderBy(at => at.Position)
147 2c9afc72 Vojtěch Bartička
                .Select(at => at as AnnotationTagGeneric)
148 c2a89232 Vojtěch Bartička
                .ToList();
149
150 0a9f9349 Vojtěch Bartička
            List<TagInstanceInfo> tagInstanceInfos = new();
151 a6675a6d Vojtěch Bartička
            foreach (var tag in tags)
152
            {
153
                var tagInstance = mapper.Map<TagInstanceInfo>(tag);
154 0a9f9349 Vojtěch Bartička
                tagInstanceInfos.Add(tagInstance);
155 a6675a6d Vojtěch Bartička
            }
156
157 553486ad Vojtěch Bartička
            var docToRender = "";
158 2c9afc72 Vojtěch Bartička
            HTMLService.CachedInfo cachedInfoToReturn = new(); 
159 553486ad Vojtěch Bartička
            if (annotation.CachedDocumentHTML == "")
160
            {
161 2c9afc72 Vojtěch Bartička
                var result = htmlService.FullPreprocessHTML(documentContent.Content, tags);
162
                cachedInfoToReturn = result.Item2;
163
                docToRender = result.Item1;
164
165
                annotation.CachedStartPositions = JsonConvert.SerializeObject(cachedInfoToReturn.TagStartPositions);
166
                annotation.CachedLengths = JsonConvert.SerializeObject(cachedInfoToReturn.TagStartLengths);
167
                annotation.CachedClosingPositions = JsonConvert.SerializeObject(cachedInfoToReturn.TagClosingPositions);
168
                annotation.CachedClosingLengths = JsonConvert.SerializeObject(cachedInfoToReturn.TagClosingLengths);
169
                annotation.CachedCSS = JsonConvert.SerializeObject(cachedInfoToReturn.TagInstanceCSS);
170 553486ad Vojtěch Bartička
                annotation.ModifiedType = EModified.NONE;
171
                annotation.CachedDocumentHTML = docToRender;
172
                context.SaveChanges();
173
            }
174
            else
175
            {
176
                docToRender = annotation.CachedDocumentHTML;
177 2c9afc72 Vojtěch Bartička
                HTMLService.CachedInfo cachedInfo = new()
178
                {
179
                    TagStartPositions = JsonConvert.DeserializeObject<List<int>>(annotation.CachedStartPositions),
180
                    TagStartLengths = JsonConvert.DeserializeObject<List<int>>(annotation.CachedLengths),
181
                    TagClosingPositions = JsonConvert.DeserializeObject<List<int>>(annotation.CachedClosingPositions),
182
                    TagClosingLengths = JsonConvert.DeserializeObject<List<int>>(annotation.CachedClosingLengths)
183
                };
184
                
185 553486ad Vojtěch Bartička
                // The annotation has been modified and we need to either add the new tag or remove the tag
186
                if (annotation.ModifiedType != EModified.NONE)
187
                {
188
                    if (annotation.ModifiedType == EModified.ADDED)
189
                    {
190
                        var lastModifiedTag = context.AnnotationTags.Where(at => at.Id == annotation.LastModifiedTagId).First();
191 2c9afc72 Vojtěch Bartička
                        var result = htmlService.PartialPreprocessHTMLAddTag(docToRender, documentContent.Content, lastModifiedTag, tags, cachedInfo);
192
                        docToRender = result.Item1;
193
                        cachedInfoToReturn = result.Item2;
194 553486ad Vojtěch Bartička
                    }
195
                    else if (annotation.ModifiedType == EModified.REMOVED)
196
                    {
197 2c9afc72 Vojtěch Bartička
                        var result = htmlService.PartialPreprocessHTMLRemoveTag(docToRender, documentContent.Content, new AnnotationTag() { Id = annotation.LastModifiedTagId.Value }, tags, cachedInfo);
198
                        docToRender = result.Item1;
199
                        cachedInfoToReturn = result.Item2;
200 553486ad Vojtěch Bartička
                    }
201
202
                    annotation.ModifiedType = EModified.NONE;
203 2c9afc72 Vojtěch Bartička
                    annotation.CachedStartPositions = JsonConvert.SerializeObject(cachedInfoToReturn.TagStartPositions);
204
                    annotation.CachedLengths = JsonConvert.SerializeObject(cachedInfoToReturn.TagStartLengths);
205
                    annotation.CachedClosingPositions = JsonConvert.SerializeObject(cachedInfoToReturn.TagClosingPositions);
206
                    annotation.CachedClosingLengths = JsonConvert.SerializeObject(cachedInfoToReturn.TagClosingLengths);
207 553486ad Vojtěch Bartička
                    annotation.CachedDocumentHTML = docToRender;
208 2c9afc72 Vojtěch Bartička
                    annotation.CachedCSS = JsonConvert.SerializeObject(cachedInfoToReturn.TagInstanceCSS);
209 553486ad Vojtěch Bartička
                    context.SaveChanges();
210
                }
211
            }
212 0a9f9349 Vojtěch Bartička
213
            // We probably cannot use AutoMapper since we are dealing with too many different entities
214
            AnnotationInfo annotationInfo = new()
215
            {
216
                SourceDocumentContent = documentContent.Content,
217
                DocumentToRender = docToRender,
218 2c9afc72 Vojtěch Bartička
                TagStartPositions = cachedInfoToReturn.TagStartPositions.ToArray(),
219
                TagLengths = cachedInfoToReturn.TagStartLengths.ToArray(),
220 0a9f9349 Vojtěch Bartička
                Note = annotation.Note,
221
                State = annotation.State,
222
                Type = IsHtml(documentContent.Content) ? EDocumentType.HTML : EDocumentType.TEXT,
223 26671569 Vojtěch Bartička
                TagInstances = tagInstanceInfos,
224 2c9afc72 Vojtěch Bartička
                CSSInfo = cachedInfoToReturn.TagInstanceCSS
225 0a9f9349 Vojtěch Bartička
            };
226
227 a6675a6d Vojtěch Bartička
            return annotationInfo;
228
        }
229
230
        // TODO temporary
231
        private bool IsHtml(string text)
232
        {
233 0a9f9349 Vojtěch Bartička
            return text.Contains("<html>");
234 a6675a6d Vojtěch Bartička
        }
235 be4deff8 Vojtěch Bartička
236
        public void AddAnnotationInstance(Guid annotationId, Guid userId, ERole userRole, AnnotationInstanceAddRequest request)
237
        {
238
            var annotation = context.Annotations
239
               .Where(a => a.Id == annotationId)
240
               .Include(a => a.User)
241
               .Include(a => a.Document).ThenInclude(d => d.Content)
242
               .First();
243
244
            if (userRole < ERole.ADMINISTRATOR)
245
            {
246
                if (annotation.User.Id != userId)
247
                {
248
                    throw new UnauthorizedAccessException($"User {userId} does not have assigned annotation {annotationId}");
249
                }
250
            }
251
252 2f3821f0 Vojtěch Bartička
            if (annotation.State == EState.NEW)
253
            {
254
                annotation.State = EState.IN_PROGRESS;
255
            }
256
257 be4deff8 Vojtěch Bartička
            AnnotationTag annotationTag = new()
258
            {
259 553486ad Vojtěch Bartička
                Id = Guid.NewGuid(),
260 be4deff8 Vojtěch Bartička
                Annotation = annotation,
261
                Instance = request.InstanceId == null ? Guid.NewGuid() : request.InstanceId.Value,
262
                Length = request.Length,
263
                Position = request.Position,
264 f6f1ca65 Vojtěch Bartička
                SelectedText = request.SelectedText,
265 be4deff8 Vojtěch Bartička
                Note = ""
266
            };
267
268
            if (request.Type == ETagType.TAG)
269
            {
270
                annotationTag.Tag = context.Tags.Where(t => t.Id == request.Id).Single();
271
                annotationTag.SubTag = null;
272 15c88dc1 Vojtěch Bartička
273
                if (annotationTag.Tag.SentimentEnabled)
274
                {
275
                    annotationTag.Sentiment = ETagSentiment.NEUTRAL;
276
                }
277 2f3821f0 Vojtěch Bartička
278 58363b44 Vojtěch Bartička
                // If for the same annotation exists a tag with same position and length and of the same type, ignore
279 2f3821f0 Vojtěch Bartička
                if (context.AnnotationTags.Any(at =>
280 58363b44 Vojtěch Bartička
                at.Position == annotationTag.Position &&
281
                at.Length == annotationTag.Length &&
282
                at.Annotation == annotation &&
283
                at.Tag == annotationTag.Tag))
284
                {
285
                    throw new InvalidOperationException("Duplicate tag");
286
                }
287
288 be4deff8 Vojtěch Bartička
            }
289
            else if (request.Type == ETagType.SUBTAG)
290
            {
291
                var subTag = context.SubTags.Where(st => st.Id == request.Id).Include(st => st.Tag).Single();
292
                annotationTag.SubTag = subTag;
293
                annotationTag.Tag = subTag.Tag;
294 15c88dc1 Vojtěch Bartička
295
                if (annotationTag.SubTag.SentimentEnabled)
296
                {
297
                    annotationTag.Sentiment = ETagSentiment.NEUTRAL;
298
                }
299 2f3821f0 Vojtěch Bartička
300
                if (context.AnnotationTags.Any(at =>
301 58363b44 Vojtěch Bartička
                at.Position == annotationTag.Position &&
302
                at.Length == annotationTag.Length &&
303
                at.Annotation == annotation &&
304
                at.Tag == annotationTag.Tag &&
305
                at.SubTag == annotationTag.SubTag))
306
                {
307
                    throw new InvalidOperationException("Duplicate tag");
308
                }
309 be4deff8 Vojtěch Bartička
            }
310
            else
311
            {
312
                throw new ArgumentException($"Unknown tag type {request.Type}");
313
            }
314
315 553486ad Vojtěch Bartička
            annotation.LastModifiedTagId = annotationTag.Id;
316
            annotation.ModifiedType = EModified.ADDED;
317
318 abf94f21 Lukáš Vlček
            context.AnnotationTags.Add(annotationTag);
319 be4deff8 Vojtěch Bartička
            context.SaveChanges();
320
        }
321 0f8d6304 Vojtěch Bartička
322
        public void DeleteAnnotationInstance(Guid annotationId, Guid tagInstanceId, Guid loggedUserId, ERole userRole)
323
        {
324
            Annotation annotation = null;
325
            try
326
            {
327
                annotation = context.Annotations
328
                   .Where(a => a.Id == annotationId)
329
                   .Include(a => a.User)
330
                   .Include(a => a.Document).ThenInclude(d => d.Content)
331
                   .First();
332
333
            }
334
            catch (Exception ex)
335
            {
336
                throw new InvalidOperationException("Could not find annotation");
337
            }
338
339
340
            if (userRole < ERole.ADMINISTRATOR)
341
            {
342
                if (annotation.User.Id != loggedUserId)
343
                {
344
                    throw new UnauthorizedAccessException($"User {loggedUserId} does not have assigned annotation {annotationId}");
345
                }
346
            }
347
348
            if (!context.AnnotationTags.Any(at => at.Id == tagInstanceId))
349
            {
350
                throw new InvalidOperationException("Could not find tag instance");
351
            }
352
353 553486ad Vojtěch Bartička
354
            var annotationTag = context.AnnotationTags.First(at => at.Id == tagInstanceId);
355
            annotation.LastModifiedTagId = annotationTag.Id;
356
            annotation.ModifiedType = EModified.REMOVED;
357
358
            context.AnnotationTags.Remove(annotationTag);
359 0a9f9349 Vojtěch Bartička
360 0f8d6304 Vojtěch Bartička
            context.SaveChanges();
361
        }
362 15c88dc1 Vojtěch Bartička
363
        public void SetTagInstanceSentiment(Guid annotationId, Guid instanceId, Guid userId, ERole userRole, ETagSentiment sentiment)
364
        {
365
            Annotation annotation = null;
366
            try
367
            {
368
                annotation = context.Annotations
369
                   .Where(a => a.Id == annotationId)
370
                   .Include(a => a.User)
371
                   .Include(a => a.Document).ThenInclude(d => d.Content)
372
                   .First();
373
374
            }
375
            catch (Exception ex)
376
            {
377
                throw new InvalidOperationException("Could not find annotation");
378
            }
379
380
381
            if (userRole < ERole.ADMINISTRATOR)
382
            {
383
                if (annotation.User.Id != userId)
384
                {
385
                    throw new UnauthorizedAccessException($"User {userId} does not have assigned annotation {annotationId}");
386
                }
387
            }
388
389
390
            var tagInstances = context.AnnotationTags.Where(at => at.Instance == instanceId).ToList();
391
            if (tagInstances.Count() == 0)
392
            {
393
                throw new InvalidOperationException("No such instance found");
394
            }
395
396
            foreach (var tagInstance in tagInstances)
397
            {
398
                tagInstance.Sentiment = sentiment;
399
            }
400
401
            context.SaveChanges();
402
        }
403 0ea30313 Vojtěch Bartička
404
        public void MarkAnnotationAsDone(Guid annotationId, Guid userId, ERole userRole, bool done)
405
        {
406
            Annotation annotation = null;
407
            try
408
            {
409
                annotation = context.Annotations
410
                   .Where(a => a.Id == annotationId)
411
                   .Include(a => a.User)
412
                   .Include(a => a.Document).ThenInclude(d => d.Content)
413
                   .First();
414
415
            }
416
            catch (Exception ex)
417
            {
418
                throw new InvalidOperationException("Could not find annotation");
419
            }
420
421
422
            if (userRole < ERole.ADMINISTRATOR)
423
            {
424
                if (annotation.User.Id != userId)
425
                {
426
                    throw new UnauthorizedAccessException($"User {userId} does not have assigned annotation {annotationId}");
427
                }
428
            }
429
430
            annotation.State = done ? EState.DONE : EState.IN_PROGRESS;
431
            context.SaveChanges();
432
        }
433 440997e0 Vojtěch Bartička
434
        public Guid CreateFinalAnnotation(Guid documentId, Guid userId)
435
        {
436
            var document = context.Documents.Single(d => d.Id == documentId);
437
            var user = context.Users.Single(u => u.Id == userId);
438
439
            // Remove existing 
440
            if (context.FinalAnnotations.Any(fa => fa.Document == document))
441
            {
442
                var finalAnnotationOld = context.FinalAnnotations.Single(fa => fa.Document == document);
443
                context.FinalAnnotations.Remove(finalAnnotationOld);
444
            }
445
446
            var annotations = context.Annotations
447
                .Include(a => a.Document)
448
                .Where(a => a.Document == document && a.State == EState.DONE)
449
                .ToList();
450
451
            var finalAnnotation = new FinalAnnotation()
452
            {
453
                Id = Guid.NewGuid(),
454
                DateAssigned = DateTime.Now,
455
                DateLastChanged = DateTime.Now,
456
                Document = document,
457
                User = user,
458
                UserAssigned = user,
459
                Annotations = annotations,
460
                State = EState.NEW
461
            };
462
463
            List<AnnotationTag> annotationTagsAll = new();
464
            foreach (var annotation in annotations)
465
            {
466
                annotationTagsAll.AddRange(context.AnnotationTags
467
                    .Where(at => at.Annotation == annotation)
468
                    .Include(at => at.Tag)
469
                    .Include(at => at.SubTag)
470
                    .Include(at => at.Annotation)
471
                    .ThenInclude(a => a.User)
472
                    .ToList());
473
            }
474
            annotationTagsAll = annotationTagsAll.OrderBy(at => at.Position).ToList();
475
476
            Dictionary<Guid, List<AnnotationTag>> occurenceDict = new();
477
            foreach (var annotationTag in annotationTagsAll)
478
            {
479
                if (occurenceDict.ContainsKey(annotationTag.Instance))
480
                {
481
                    occurenceDict[annotationTag.Instance].Add(annotationTag);
482
                }
483
                else
484
                {
485
                    occurenceDict[annotationTag.Instance] = new();
486
                    occurenceDict[annotationTag.Instance].Add(annotationTag);
487
                }
488
            }
489
490
            List<List<AnnotationTag>> occurenceLists = new();
491
            foreach (var key in occurenceDict.Keys)
492
            {
493
                occurenceLists.Add(occurenceDict[key]);
494
            }
495
496
            List<List<AnnotationTag>> annotationTagsProcessed = new();
497
            List<FinalAnnotationTag> finalAnnotationTags = new();
498
            for (int i = 0; i < occurenceLists.Count; i++)
499
            {
500
                var occurrenceList1 = occurenceLists[i];
501
                List<List<AnnotationTag>> sameLists = new();
502
503
                for (int j = 0; j < occurenceLists.Count; j++)
504
                {
505
                    var occurrenceList2 = occurenceLists[j];
506
507
                    if (annotationTagsProcessed.Contains(occurrenceList2))
508
                    {
509
                        continue;
510
                    }
511
512
                    if (SelectionsAreSame(occurrenceList1, occurrenceList2))
513
                    {
514
                        sameLists.Add(occurrenceList2);
515
                    }
516
                }
517
518
                // This means that this occurrence ahs already been processed as matching a previous tag
519
                if (sameLists.Count() == 0)
520
                {
521
                    continue;
522
                }
523
524
                List<User> relatedUsers = new();
525
                foreach (var list in sameLists)
526
                {
527
                    relatedUsers.Add(list[0].Annotation.User);
528
                }
529
530
                foreach (var tag in sameLists[0])
531
                {
532
                    finalAnnotationTags.Add(new()
533
                    {
534
                        Id = Guid.NewGuid(),
535
                        Tag = tag.Tag,
536
                        SubTag = tag.SubTag,
537
                        Annotation = finalAnnotation,
538
                        SelectedText = tag.SelectedText,
539
                        Sentiment = tag.Sentiment,
540
                        Instance = tag.Instance,
541
                        IsFinal = sameLists.Count == annotations.Count,
542
                        Length = tag.Length,
543
                        Position = tag.Position,
544
                        Note = "",
545
                        Users = relatedUsers
546
                    });
547
                }
548
549
                annotationTagsProcessed.AddRange(sameLists);
550
            }
551
552
            context.FinalAnnotations.Add(finalAnnotation);
553
            context.SaveChanges();
554
            context.FinalAnnotationTags.AddRange(finalAnnotationTags);
555
556
            context.SaveChanges();
557
            return finalAnnotation.Id;
558
        }
559
560
        private bool SelectionsAreSame(List<AnnotationTag> list1, List<AnnotationTag> list2)
561
        {
562
            if (list1.Count != list2.Count)
563
            {
564
                return false;
565
            }
566
567
            bool sentimentEnabled = list1[0].Tag.SentimentEnabled;
568
569
            if (sentimentEnabled)
570
            {
571
                for (int i = 0; i < list1.Count; i++)
572
                {
573
                    var tag1 = list1[i];
574
                    var tag2 = list2[i];
575
                    if (tag1.Position == tag2.Position &&
576
                        tag1.Length == tag2.Length &&
577
                        tag1.Sentiment == tag2.Sentiment &&
578
                        tag1.Tag == tag2.Tag &&
579
                        tag1.SubTag == tag2.SubTag)
580
                    {
581
                        continue;
582
                    }
583
                    else
584
                    {
585
                        return false;
586
                    }
587
                }
588
            }
589
            else
590
            {
591
                for (int i = 0; i < list1.Count; i++)
592
                {
593
                    var tag1 = list1[i];
594
                    var tag2 = list2[i];
595
                    if (tag1.Position == tag2.Position &&
596
                        tag1.Length == tag2.Length &&
597
                        tag1.Tag == tag2.Tag &&
598
                        tag1.SubTag == tag2.SubTag)
599
                    {
600
                        continue;
601
                    }
602
                    else
603
                    {
604
                        return false;
605
                    }
606
                }
607
            }
608
609
            return true;
610
        }
611 eff8ec56 Vojtěch Bartička
    }
612
}