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); }
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); }
/// <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); }
/// <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); }