Ejemplo n.º 1
0
        public virtual AbstractEntityBuilder <T> WithPidUri(string pidUriString, string uriTemplate = "https://pid.bayer.com/kos/19050#cb849b80-6d00-4c3a-8810-6e4f91ee0cd1")
        {
            // Create properties for Pid Uri
            IDictionary <string, List <dynamic> > pidUriProp = new Dictionary <string, List <dynamic> >();

            pidUriProp.Add(RDF.Type, new List <dynamic>()
            {
                Identifier.Type
            });

            if (!string.IsNullOrWhiteSpace(uriTemplate))
            {
                pidUriProp.Add(Identifier.HasUriTemplate, new List <dynamic>()
                {
                    uriTemplate
                });
            }

            // Create Entity and assign properties to PID Uri
            Entity pidUri = new Entity(pidUriString, pidUriProp);

            // Create properties for resource
            CreateOrOverwriteProperty(EnterpriseCore.PidUri, pidUri);

            return(this);
        }
Ejemplo n.º 2
0
        private IList <string> GetAllIdentifiersOfResource(Entity entity)
        {
            IList <string> pidUris = new List <string>();

            if (entity != null)
            {
                foreach (var property in entity.Properties)
                {
                    if (property.Key == Graph.Metadata.Constants.EnterpriseCore.PidUri ||
                        property.Key == Graph.Metadata.Constants.Resource.BaseUri)
                    {
                        pidUris.Add(property.Value?.FirstOrDefault()?.Id);
                    }
                    else if (property.Key == Graph.Metadata.Constants.Resource.Distribution ||
                             property.Key == Graph.Metadata.Constants.Resource.MainDistribution)
                    {
                        foreach (var prop in property.Value)
                        {
                            if (DynamicExtension.IsType <Entity>(prop, out Entity parsedProp))
                            {
                                IList <string> nestedUris = GetAllIdentifiersOfResource(parsedProp);
                                pidUris.AddRange(nestedUris);
                            }
                        }
                    }
                }
            }

            return(pidUris.Where(uri => !string.IsNullOrWhiteSpace(uri)).ToList());
        }
        private IList <UrlCheckingCTO> GetIdentifierAndTargetUrls(Entity resource)
        {
            var identifiers = new List <UrlCheckingCTO>();

            foreach (var property in resource.Properties)
            {
                foreach (var prop in property.Value)
                {
                    if (property.Key == Graph.Metadata.Constants.Resource.DistributionEndpoints.HasNetworkAddress)
                    {
                        identifiers.Add(new UrlCheckingCTO(property.Key, resource.Id, prop));
                    }
                    else if (DynamicExtension.IsType <Entity>(prop, out Entity parsedProp))
                    {
                        if (property.Key == Graph.Metadata.Constants.EnterpriseCore.PidUri || property.Key == Graph.Metadata.Constants.Resource.BaseUri)
                        {
                            if (!string.IsNullOrWhiteSpace(parsedProp.Id))
                            {
                                identifiers.Add(new UrlCheckingCTO(property.Key, resource.Id, parsedProp.Id));
                            }
                        }
                        else
                        {
                            identifiers.AddRange(GetIdentifierAndTargetUrls(parsedProp));
                        }
                    }
                }
            }

            return(identifiers);
        }
        private IList <ValidationResultProperty> CheckDuplicatesInRepository(Entity resource, string resourceId, string previousVersion)
        {
            var duplicateErrors = new List <ValidationResultProperty>();

            var pidUriResults    = GetDuplicateResultsByIdentifierType(Graph.Metadata.Constants.EnterpriseCore.PidUri, resource, out var pidUri);
            var baseUriResults   = GetDuplicateResultsByIdentifierType(Graph.Metadata.Constants.Resource.BaseUri, resource, out var baseUri);
            var targetUriResults = GetDuplicateResultsByTargetUri(resource, out var targetUri);

            // allow the pidURI to be duplicate when changing resource type
            if (pidUri != null && pidUri != string.Empty)
            {
                if (pidUriResults.Count == 2 && pidUriResults[0].Type != pidUriResults[1].Type && resource.Id != null)
                {
                    pidUriResults.Clear();
                }
            }

            // TODO: Piduri has no entry then duplicate, or if entry/entryDraft is not actual resource
            if (CheckIdentifierIsDuplicate(pidUriResults, resource, resourceId, out bool orphanedPid))
            {
                var message = orphanedPid ? Common.Constants.Validation.DuplicateFieldOrphaned : Common.Constants.Validation.DuplicateField;
                var pidUriValidationResult = new ValidationResultProperty(resource.Id, Graph.Metadata.Constants.EnterpriseCore.PidUri, pidUri, message, ValidationResultSeverity.Violation, ValidationResultPropertyType.DUPLICATE);
                duplicateErrors.Add(pidUriValidationResult);
            }

            if (CheckBaseUriIsDuplicate(baseUriResults, resource, resourceId, pidUri, previousVersion, out bool orphanedBaseUri))
            {
                var message = orphanedBaseUri ? Common.Constants.Validation.DuplicateFieldOrphaned : Common.Constants.Validation.DuplicateField;
                var baseUriValidatioResult = new ValidationResultProperty(resource.Id, Graph.Metadata.Constants.Resource.BaseUri, baseUri, message, ValidationResultSeverity.Violation, ValidationResultPropertyType.DUPLICATE, null);
                duplicateErrors.Add(baseUriValidatioResult);
            }

            if (CheckIdentifierIsDuplicate(targetUriResults, resource, resourceId, out _))
            {
                var targetUriValidationResult = new ValidationResultProperty(resource.Id, Graph.Metadata.Constants.Resource.DistributionEndpoints.HasNetworkAddress, targetUri, Common.Constants.Validation.DuplicateField, ValidationResultSeverity.Info, ValidationResultPropertyType.DUPLICATE);
                duplicateErrors.Add(targetUriValidationResult);
            }

            foreach (var property in resource.Properties)
            {
                // TODO: Check metadata property type is permanent identifier
                if (property.Key != Graph.Metadata.Constants.EnterpriseCore.PidUri && property.Key != Graph.Metadata.Constants.Resource.BaseUri)
                {
                    foreach (var prop in property.Value)
                    {
                        if (DynamicExtension.IsType <Entity>(prop, out Entity entity))
                        {
                            duplicateErrors.AddRange(CheckDuplicatesInRepository(entity, resourceId, string.Empty));
                        }
                    }
                }
            }

            return(duplicateErrors);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Delete all Identifiers, that belong to a resource.
        /// </summary>
        /// <param name="resource">The resource to delete from</param>
        public void DeleteAllUnpublishedIdentifiers(Entity resource)
        {
            if (null == resource)
            {
                throw new ArgumentNullException(nameof(resource), Common.Constants.Messages.Resource.NullResource);
            }

            var actualPidUris = GetAllIdentifiersOfResource(resource);

            foreach (var uri in actualPidUris)
            {
                _identifierRepository.Delete(new Uri(uri), GetResourceDraftInstanceGraph());
            }
        }
        private IList <DuplicateResult> GetDuplicateResultsByTargetUri(Entity resource, out string targetUri)
        {
            targetUri = string.Empty;

            if (resource.Properties.ContainsKey(Graph.Metadata.Constants.Resource.DistributionEndpoints.HasNetworkAddress))
            {
                string duplicateRequestTargetUri = resource.Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.DistributionEndpoints.HasNetworkAddress, true);

                if (!string.IsNullOrWhiteSpace(duplicateRequestTargetUri))
                {
                    targetUri = duplicateRequestTargetUri;
                    return(CheckTargetUriDuplicate(duplicateRequestTargetUri));
                }
            }

            return(new List <DuplicateResult>());
        }
        private IList <DuplicateResult> GetDuplicateResultsByIdentifierType(string identifierType, Entity resource, out string identifier)
        {
            identifier = string.Empty;

            if (resource.Properties.ContainsKey(identifierType))
            {
                Entity duplicateRequestEntity = resource.Properties.GetValueOrNull(identifierType, true);

                if (duplicateRequestEntity != null && !string.IsNullOrWhiteSpace(duplicateRequestEntity.Id))
                {
                    identifier = duplicateRequestEntity.Id;
                    return(_identifierService.GetPidUriIdentifierOccurrences(duplicateRequestEntity.Id));
                }
            }

            return(new List <DuplicateResult>());
        }
        private bool ResourceValueChanged(List <dynamic> firstValue, List <dynamic> secondValue)
        {
            if (firstValue.Count != secondValue.Count)
            {
                return(true);
            }
            else
            {
                for (int i = 0; i < firstValue.Count; i++)
                {
                    firstValue.Sort();
                    secondValue.Sort();
                    string firstString;
                    string secondString;
                    if (!(firstValue[i] is string || secondValue[i] is string))
                    {
                        Entity entity  = firstValue[i];
                        Entity entity2 = secondValue[i];
                        entity2.Properties = entity2.Properties.Where(x => x.Value.Count > 0).ToDictionary(x => x.Key, x => x.Value);

                        var entityProps  = entity.Properties.Where(x => x.Key != COLID.Graph.Metadata.Constants.EnterpriseCore.PidUri).ToList().OrderBy(x => x.Key).ToDictionary(t => t.Key, t => t.Value);
                        var entityProps2 = entity2.Properties.Where(x => x.Key != COLID.Graph.Metadata.Constants.EnterpriseCore.PidUri).ToList().OrderBy(x => x.Key).ToDictionary(t => t.Key, t => t.Value);


                        firstString  = JsonConvert.SerializeObject(entityProps).ToString();  //entity.ToString();
                        secondString = JsonConvert.SerializeObject(entityProps2).ToString(); //entity2.ToString();
                    }
                    else
                    {
                        firstString  = firstValue[i].ToString();
                        secondString = secondValue[i].ToString();
                    }
                    using SHA256 sha256 = SHA256.Create();
                    var computedHash  = HashGenerator.GetHash(sha256, firstString);
                    var computedHash2 = HashGenerator.GetHash(sha256, secondString);

                    if (computedHash != computedHash2)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        private IList <string> GetMatchingPidUris(Entity resource, string regexForExistingPidUris)
        {
            var matchingPidUris = new List <string>();

            var activePidUris = _pidUriTemplateRepository.GetMatchingPidUris(regexForExistingPidUris, _metadataService.GetInstanceGraph(COLID.Graph.Metadata.Constants.PIDO.PidConcept), _metadataService.GetInstanceGraph("draft"));

            matchingPidUris.AddRange(activePidUris);

            Entity resourcePidUri  = resource.Properties.GetValueOrNull(Graph.Metadata.Constants.EnterpriseCore.PidUri, true);
            Entity resourceBaseUri = resource.Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.BaseUri, true);

            if (!string.IsNullOrWhiteSpace(resourcePidUri?.Id))
            {
                matchingPidUris.Add(resourcePidUri.Id);
            }

            if (!string.IsNullOrWhiteSpace(resourceBaseUri?.Id))
            {
                matchingPidUris.Add(resourceBaseUri.Id);
            }

            foreach (var property in resource.Properties)
            {
                foreach (var prop in property.Value)
                {
                    if (DynamicExtension.IsType <Entity>(prop, out Entity entity))
                    {
                        Entity nestedPidUri = entity.Properties.GetValueOrNull(Graph.Metadata.Constants.EnterpriseCore.PidUri, true);
                        if (nestedPidUri != null && !string.IsNullOrWhiteSpace(nestedPidUri.Id) && Regex.IsMatch(nestedPidUri.Id, regexForExistingPidUris))
                        {
                            matchingPidUris.Add(nestedPidUri.Id);
                        }

                        Entity nestedBaseUri = entity.Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.BaseUri, true);
                        if (nestedBaseUri != null && !string.IsNullOrWhiteSpace(nestedBaseUri.Id) && Regex.IsMatch(nestedBaseUri.Id, regexForExistingPidUris))
                        {
                            matchingPidUris.Add(nestedBaseUri.Id);
                        }
                    }
                }
            }

            return(matchingPidUris);
        }
        /// <summary>
        /// Checks if the base uri in format of an uri is unique with one exception:
        ///
        /// The base uri may only be the same across different versions of an entry.
        /// </summary>
        /// <param name="baseUriResults">All found entries with the same identifier</param>
        /// <param name="resource">Id of the entity to be checked</param>
        /// <param name="resourceId">Resource id of the main entry (parent entry id)</param>
        /// <param name="pidUri">Pid uri of resource to be checked</param>
        /// <param name="previousVersion">Pid uri of the previous version of the resource to be checked</param>
        private bool CheckBaseUriIsDuplicate(IList <DuplicateResult> baseUriResults, Entity resource, string resourceId, string pidUri, string previousVersion, out bool orphanedBaseUri)
        {
            string resourceType = resource.Properties.GetValueOrNull(Graph.Metadata.Constants.RDF.Type, true);

            orphanedBaseUri = false;

            if (baseUriResults.IsNullOrEmpty())
            {
                return(false);
            }
            else if (baseUriResults.IsAnyDraftAndPublishedNull() || baseUriResults.IsAnyWithDifferentIdentifierType(Graph.Metadata.Constants.Resource.BaseUri))
            {
                orphanedBaseUri = true;
                return(true);
            }
            else if (string.IsNullOrWhiteSpace(resourceId) && string.IsNullOrWhiteSpace(previousVersion))
            {
                return(true);
            }

            var resourceVersions = GetVersions(pidUri, previousVersion);

            if (!baseUriResults.Any(result => resourceVersions.Any(version => result.Published == version.Id || result.Draft == version.Id)))
            {
                if (baseUriResults.IsAnyDraftAndPublishedNotEqualToIdentifier(resourceId))
                {
                    return(true);
                }
                else if (baseUriResults.Any() && string.IsNullOrWhiteSpace(resourceId))
                {
                    return(true);
                }
                else if (baseUriResults.IsAnyResultEqualToIdentifierAndHasDifferentType(resourceId, resourceType))
                {
                    return(true);
                }
            }

            return(false);
        }
        public IList <ValidationResultProperty> CheckDuplicates(Entity resource, string resourceId, string previousVersion)
        {
            var duplicateErrors = CheckDuplicatesInRepository(resource, resourceId, previousVersion);

            // Create a flatten list of all pid, base and target uris of the given resource
            var urls = GetIdentifierAndTargetUrls(resource);

            // Group the flatten lists by uris to find duplicates inside of this (not yet) saved/published resource
            var groupedPidUris = urls.GroupBy(r => r.Url).Where(r => r.Count() > 1);

            foreach (var group in groupedPidUris)
            {
                duplicateErrors = duplicateErrors.Concat(group.Select(r =>
                {
                    if (r.PropertyKey == Graph.Metadata.Constants.Resource.DistributionEndpoints.HasNetworkAddress)
                    {
                        return(new ValidationResultProperty(r.EntityId, r.PropertyKey, group.Key, $"This Target URI is identical with {group.Count() - 1} other Target URI of this entry", ValidationResultSeverity.Info, ValidationResultPropertyType.DUPLICATE));
                    }
                    return(new ValidationResultProperty(r.EntityId, r.PropertyKey, group.Key, $"This identifier is identical with {group.Count() - 1} other identifier of this entry", ValidationResultSeverity.Violation, ValidationResultPropertyType.DUPLICATE));
                }
                                                                      )).ToList();
            }
            return(duplicateErrors);
        }
        public async Task <Resource> AddAdditionalsAndRemovals(Entity Published, Entity DraftToBePublished)
        {
            if (Published.Properties[COLID.Graph.Metadata.Constants.EnterpriseCore.PidUri][0].Id != DraftToBePublished.Properties[COLID.Graph.Metadata.Constants.EnterpriseCore.PidUri][0].Id)
            {
                throw new BusinessException("The resources to be compared do not have the same PidUri");
            }

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

            ignoredProperties.Add(COLID.Graph.Metadata.Constants.Resource.HasEntryLifecycleStatus);
            ignoredProperties.Add(COLID.Graph.Metadata.Constants.Resource.HasRevision);
            ignoredProperties.Add(COLID.Graph.Metadata.Constants.EnterpriseCore.PidUri);
            ignoredProperties.Add(COLID.Graph.Metadata.Constants.Resource.HasSourceID);

            if (DraftToBePublished.Properties.ContainsKey(COLID.Graph.Metadata.Constants.Resource.BaseUri) == Published.Properties.ContainsKey(COLID.Graph.Metadata.Constants.Resource.BaseUri))
            {
                ignoredProperties.Add(COLID.Graph.Metadata.Constants.Resource.BaseUri);
            }
            ignoredProperties.AddRange(COLID.Graph.Metadata.Constants.Resource.LinkTypes.AllLinkTypes);

            var existingRevisions = Published.Properties.TryGetValue(COLID.Graph.Metadata.Constants.Resource.HasRevision, out List <dynamic> revisionValues) ? revisionValues : new List <dynamic>();


            //IList <MetadataProperty> allMetaData = _metadataService.GetMetadataForEntityType(Published.Properties.GetValueOrNull(COLID.Graph.Metadata.Constants.RDF.Type, true));

            List <MetadataProperty> allMetaData     = _metadataService.GetMetadataForEntityTypeInConfig(Published.Properties.GetValueOrNull(COLID.Graph.Metadata.Constants.RDF.Type, true), Published.Properties.GetValueOrNull(COLID.Graph.Metadata.Constants.Resource.MetadataGraphConfiguration, true));
            List <string>           allMetaDataKeys = allMetaData.Select(x => x.Key).ToList();


            List <MetadataProperty> allMetaData2 = _metadataService.GetMetadataForEntityTypeInConfig(DraftToBePublished.Properties.GetValueOrNull(COLID.Graph.Metadata.Constants.RDF.Type, true), DraftToBePublished.Properties.GetValueOrNull(COLID.Graph.Metadata.Constants.Resource.MetadataGraphConfiguration, true));

            allMetaData.AddRange(allMetaData2.Where(x => !allMetaDataKeys.Contains(x.Key)).Select(y => y));


            Dictionary <string, List <dynamic> > additionals = new Dictionary <string, List <dynamic> >();
            Dictionary <string, List <dynamic> > removals    = new Dictionary <string, List <dynamic> >();

            foreach (var metadata in allMetaData)
            {
                if (ignoredProperties.Contains(metadata.Key))
                {
                    continue;
                }

                if (Published.Properties.TryGetValue(metadata.Key, out List <dynamic> firstValue) && DraftToBePublished.Properties.TryGetValue(metadata.Key, out List <dynamic> secondValue))
                {
                    if (ResourceValueChanged(firstValue, secondValue))
                    {
                        additionals.Add(metadata.Key, secondValue);
                        removals.Add(metadata.Key, firstValue);
                    }
                }
                else if (Published.Properties.TryGetValue(metadata.Key, out List <dynamic> OnlyfirstValue) && !DraftToBePublished.Properties.TryGetValue(metadata.Key, out List <dynamic> NotsecondValue))
                {
                    removals.Add(metadata.Key, OnlyfirstValue);
                }
                else if (!Published.Properties.TryGetValue(metadata.Key, out List <dynamic> NotfirstValue) && DraftToBePublished.Properties.TryGetValue(metadata.Key, out List <dynamic> OnlysecondValue))
                {
                    additionals.Add(metadata.Key, OnlysecondValue);
                }
                else
                {
                    continue;
                }
            }

            Resource resource = UpdateResourceProperties(additionals, removals, _mapper.Map <Resource>(Published));

            //if(additionals.Count==1 && removals.Count==1 && additionals.ContainsKey(COLID.Graph.Metadata.Constants.Resource.DateModified))

            string pattern = @"[^Rev]+$";
            Regex  rg      = new Regex(pattern);
            var    revList = existingRevisions.Select(x => Int32.Parse(rg.Match(x).Value)).ToList();
            var    max     = revList.Max();

            string revisionGraphPrefix = Published.Id + "Rev" + (max + 1);

            _resourceRepository.CreateProperty(new Uri(Published.Id), new Uri(COLID.Graph.Metadata.Constants.Resource.HasRevision), revisionGraphPrefix, GetResourceInstanceGraph());

            (additionals, removals) = GetFinalAdditionalsAndRemovals(additionals, removals);
            _resourceRepository.CreateAdditionalsAndRemovalsGraphs(additionals, removals, allMetaData, Published.Id, revisionGraphPrefix);  //letzte revisionwert rausnehmen, counter erhöhen und damit dann die graphen erstellen


            return(resource);
        }
        private (Dictionary <string, List <dynamic> > additionals, Dictionary <string, List <dynamic> > removals) GetFinalAdditionalsAndRemovals(Dictionary <string, List <dynamic> > additionals, Dictionary <string, List <dynamic> > removals)
        {
            Dictionary <string, List <dynamic> > final_additionals = new Dictionary <string, List <dynamic> >();
            Dictionary <string, List <dynamic> > final_removals    = new Dictionary <string, List <dynamic> >();
            List <string> joinedKeys = additionals.Keys.Where(x => removals.Keys.Contains(x)).ToList();

            final_additionals.AddRange(additionals.Where(y => !joinedKeys.Contains(y.Key)).ToList());
            final_removals.AddRange(removals.Where(y => !joinedKeys.Contains(y.Key)).ToList());

            foreach (var key in joinedKeys)
            {
                List <dynamic> AdditionalValues = additionals.GetValueOrDefault(key) != null?additionals.GetValueOrDefault(key) : new List <dynamic>();

                List <dynamic> RemovalValues = removals.GetValueOrDefault(key) != null?removals.GetValueOrDefault(key) : new List <dynamic>();

                List <dynamic> newAdditionalValues = new List <dynamic>();
                List <dynamic> newRemovalValues    = new List <dynamic>();

                foreach (var value in AdditionalValues)
                {
                    if (value.GetType().Name != "Entity")
                    {
                        if (!RemovalValues.Contains(value))
                        {
                            newAdditionalValues.Add(value);
                        }
                    }
                    else
                    {
                        Entity entity  = value;
                        Entity entity2 = RemovalValues.Where(x => x.Id == entity.Id).FirstOrDefault();
                        entity2 = entity2 != null ? entity2 : new Entity();
                        var entityProps  = entity.Properties.Where(x => x.Key != COLID.Graph.Metadata.Constants.EnterpriseCore.PidUri).ToList().OrderBy(x => x.Key).ToDictionary(t => t.Key, t => t.Value);
                        var entityProps2 = entity2.Properties.Where(x => x.Key != COLID.Graph.Metadata.Constants.EnterpriseCore.PidUri).ToList().OrderBy(x => x.Key).ToDictionary(t => t.Key, t => t.Value);


                        var firstString  = JsonConvert.SerializeObject(entityProps).ToString();  //entity.ToString();
                        var secondString = JsonConvert.SerializeObject(entityProps2).ToString(); //entity2.ToString();
                        using SHA256 sha256 = SHA256.Create();
                        var computedHash  = HashGenerator.GetHash(sha256, firstString);
                        var computedHash2 = HashGenerator.GetHash(sha256, secondString);

                        if (computedHash != computedHash2)
                        {
                            newAdditionalValues.Add(value);
                        }
                    }
                }

                foreach (var value in RemovalValues)
                {
                    if (value.GetType().Name != "Entity")
                    {
                        if (!AdditionalValues.Contains(value))
                        {
                            newRemovalValues.Add(value);
                        }
                    }
                    else
                    {
                        Entity entity  = value;
                        Entity entity2 = AdditionalValues.Where(x => x.Id == entity.Id).FirstOrDefault();
                        entity2 = entity2 != null ? entity2 : new Entity();

                        var entityProps  = entity.Properties.Where(x => x.Key != COLID.Graph.Metadata.Constants.EnterpriseCore.PidUri).ToList().OrderBy(x => x.Key).ToDictionary(t => t.Key, t => t.Value);
                        var entityProps2 = entity2.Properties.Where(x => x.Key != COLID.Graph.Metadata.Constants.EnterpriseCore.PidUri).ToList().OrderBy(x => x.Key).ToDictionary(t => t.Key, t => t.Value);


                        var firstString  = JsonConvert.SerializeObject(entityProps).ToString();  //entity.ToString();
                        var secondString = JsonConvert.SerializeObject(entityProps2).ToString(); //entity2.ToString();

                        using SHA256 sha256 = SHA256.Create();
                        var computedHash  = HashGenerator.GetHash(sha256, firstString);
                        var computedHash2 = HashGenerator.GetHash(sha256, secondString);

                        if (computedHash != computedHash2)
                        {
                            newRemovalValues.Add(value);
                        }
                    }
                }

                final_additionals.Add(key, newAdditionalValues);



                final_removals.Add(key, newRemovalValues);
            }

            return(final_additionals, final_removals);
        }
        public string GenerateIdentifierFromTemplate(PidUriTemplateFlattened pidUriTemplateFlat, Entity resource)
        {
            string prefix   = pidUriTemplateFlat.BaseUrl + pidUriTemplateFlat.Route;
            int    idLength = pidUriTemplateFlat.IdLength;
            string id;

            if (pidUriTemplateFlat.IdType == Common.Constants.PidUriTemplateIdType.Guid)
            {
                id = Guid.NewGuid().ToString();
            }
            else if (pidUriTemplateFlat.IdType == Common.Constants.PidUriTemplateIdType.Number)
            {
                var regexForExistingPidUris    = pidUriTemplateFlat.GetRegex();
                var existingPidUrisForTemplate = GetMatchingPidUris(resource, regexForExistingPidUris);

                existingPidUrisForTemplate.AddRange(GeneratedIdentifier.Where(t => Regex.IsMatch(t, regexForExistingPidUris)));

                var pidUriNumbers = existingPidUrisForTemplate
                                    .SelectMany(e => Regex.Matches(e, regexForExistingPidUris).Select(r => r.Groups[1]?.Value))
                                    .Select(s =>
                {
                    long pidUriAsNumber = -1;
                    long.TryParse(s, out pidUriAsNumber);
                    return(pidUriAsNumber);
                })
                                    .OrderBy(d => d);
                long nextFreeNumber = 1;
                foreach (double number in pidUriNumbers)
                {
                    if (number < nextFreeNumber)
                    {
                        // in case we start at negative value
                        continue;
                    }
                    else if (number == nextFreeNumber)
                    {
                        // move forward and check next number
                        nextFreeNumber++;
                    }
                    else if (number > nextFreeNumber)
                    {
                        // found a free spot
                        break;
                    }
                }
                if (idLength > 0)
                {
                    if (nextFreeNumber.ToString().Count() > idLength)
                    {
                        throw new System.Exception($"Next free id number '{nextFreeNumber}' exceeds the defined id length of '{idLength}'.");
                    }
                    var format = "D" + idLength;
                    id = nextFreeNumber.ToString(format);
                }
                else
                {
                    id = nextFreeNumber.ToString();
                }
            }
            else
            {
                throw new System.Exception($"Unrecognized id type {pidUriTemplateFlat.IdType}.");
            }

            var pidUri = prefix + id + pidUriTemplateFlat.Suffix;

            return(pidUri);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Calculates for resource properties with NodeKind IRI and nested metadata the difference between all subproperties in the list.
        /// </summary>
        /// <param name="metadataComparisonProperty">The current metadata property to compare in the given resources</param>
        /// <param name="resources">resources to compare</param>
        /// <returns>The comparison result for a specific property. While the returned key is the metadata key, the list contains the compared properties of both resources.</returns>
        private IDictionary <string, IList <dynamic> > CalculateIRINestedValuesDifference(MetadataComparisonProperty metadataComparisonProperty, params Entity[] resources)
        {
            var propertyResults = new Dictionary <string, IList <dynamic> >();

            var allFirstNestedEntities = resources[0].Properties.ContainsKey(metadataComparisonProperty.Key) ?
                                         resources[0].Properties[metadataComparisonProperty.Key]?.Select(x => ((Entity)x)).ToList() :
                                         null;

            var allSecondNestedEntities = resources[1].Properties.ContainsKey(metadataComparisonProperty.Key) ?
                                          resources[1].Properties[metadataComparisonProperty.Key]?.Select(x => ((Entity)x)).ToList() :
                                          null;

            if (allFirstNestedEntities != null)
            {
                propertyResults.Add(resources[0].Id, new List <dynamic>());

                if (allSecondNestedEntities != null)
                {
                    propertyResults.Add(resources[1].Id, new List <dynamic>());
                }

                // Compare all nested properties that are present in both resources.
                // The existence of the nested properties is given by the fact that both nested properties have the same PID URI and
                // the same resource type, e.g. Browsable Resource
                foreach (var firstEntity in allFirstNestedEntities)
                {
                    if (firstEntity.Properties.TryGetValue(Graph.Metadata.Constants.EnterpriseCore.PidUri, out List <dynamic> pidUriA))
                    {
                        var secondEntity = allSecondNestedEntities?.SingleOrDefault(b =>
                        {
                            if (b.Properties.TryGetValue(Graph.Metadata.Constants.EnterpriseCore.PidUri, out List <dynamic> pidUriB))
                            {
                                if (((Entity)pidUriA.First()).Id != ((Entity)pidUriB.First()).Id)
                                {
                                    return(false);
                                }

                                if (firstEntity.Properties.TryGetValue(Graph.Metadata.Constants.RDF.Type, out List <dynamic> typeA) &&
                                    b.Properties.TryGetValue(Graph.Metadata.Constants.RDF.Type, out List <dynamic> typeB))
                                {
                                    if (typeA[0] == typeB[0])
                                    {
                                        return(true);
                                    }
                                }
                            }

                            return(false);
                        });

                        // If the second resource has no nested property with the same PID URI,
                        // then add the found property to the first resource, mark all sub properties as deleted
                        // and continue with the next property
                        if (secondEntity == null)
                        {
                            // TODO SL: set all entries in entityA to <diffDel>
                            propertyResults[resources[0].Id].Add(firstEntity);
                            continue;
                        }

                        // If both properties are found with the same PID URI and the same resource type,
                        // compare all sub - properties using the resource metadata and calculate the differences
                        if (firstEntity.Properties.TryGetValue(Graph.Metadata.Constants.RDF.Type, out List <dynamic> typeA))
                        {
                            var metadata = metadataComparisonProperty.NestedMetadata.First(m => m.Key == typeA.First());

                            var firstComparedEntity = new Entity()
                            {
                                Id = firstEntity.Id
                            };
                            var secondComparedEntity = new Entity()
                            {
                                Id = secondEntity.Id
                            };

                            foreach (var prop in metadata.Properties)
                            {
                                try
                                {
                                    if (prop.Key == Graph.Metadata.Constants.EnterpriseCore.PidUri)
                                    {
                                        firstComparedEntity.Properties.Add(prop.Key, firstEntity.Properties[Graph.Metadata.Constants.EnterpriseCore.PidUri]);
                                        secondComparedEntity.Properties.Add(prop.Key, secondEntity.Properties[Graph.Metadata.Constants.EnterpriseCore.PidUri]);
                                        continue;
                                    }

                                    var compareResult = CalculateLiteralValuesDifference(prop.Key, new Entity[] { firstEntity, secondEntity });
                                    firstComparedEntity.Properties.Add(prop.Key, compareResult[firstEntity.Id].ToList());
                                    secondComparedEntity.Properties.Add(prop.Key, compareResult[secondEntity.Id].ToList());
                                }
                                catch (KeyNotFoundException)
                                {
                                }
                            }

                            propertyResults[resources[0].Id].Add(firstComparedEntity);
                            propertyResults[resources[1].Id].Add(secondComparedEntity);
                        }
                    }
                }
            }

            // In the previous comparison it was ignored that there are properties of the second resource
            // that were not present in the first one. These must now be added and all sub properties must be marked as inserted.
            var secondEntitiesNotFoundInFirst = allSecondNestedEntities?.Where(b => {
                if (b.Properties.TryGetValue(Graph.Metadata.Constants.EnterpriseCore.PidUri, out List <dynamic> pidUriB))
                {
                    if (allFirstNestedEntities.Any(a => ((Entity)a.Properties[Graph.Metadata.Constants.EnterpriseCore.PidUri].First()).Id == ((Entity)pidUriB.First()).Id))
                    {
                        return(false);
                    }
                    return(true);
                }

                return(false);
            });

            if (secondEntitiesNotFoundInFirst != null)
            {
                // TODO SL: set all entries in entity to <diffIns>
                propertyResults[resources[1].Id].AddRange(secondEntitiesNotFoundInFirst);
            }

            return(propertyResults);
        }
        /// <summary>
        /// Checks if an identifier in format of an uri is unique.
        /// The base uri is a special kind of identifier and is therefore checked separately.
        /// </summary>
        /// <param name="pidUriResults">All found entries with the same identifier</param>
        /// <param name="resource">Id of the entity to be checked</param>
        /// <param name="resourceId">Resource id of the main entry (parent entry id)</param>
        /// <returns></returns>
        private bool CheckIdentifierIsDuplicate(IList <DuplicateResult> pidUriResults, Entity resource, string resourceId, out bool orphaned)
        {
            string resourceType = resource.Properties.GetValueOrNull(Graph.Metadata.Constants.RDF.Type, true);

            orphaned = false;
            if (pidUriResults.IsNullOrEmpty())
            {
                return(false);
            }
            else if (pidUriResults.IsAnyDraftAndPublishedNull())
            {
                orphaned = true;
                return(true);
            }
            else if (string.IsNullOrWhiteSpace(resourceId))
            {
                return(true);
            }
            else if (pidUriResults.IsAnyDraftAndPublishedNotEqualToIdentifier(resourceId))
            {
                return(true);
            }
            else if (pidUriResults.IsAnyResultEqualToIdentifierAndHasDifferentType(resourceId, resourceType))
            {
                return(true);
            }

            return(false);
        }