private void LogMessageIfMultipleValuesForSingleField(WorkerResult result, string propertyName, Field field, List <string> values, string firstVal, string mergedVal) { if (values != null && values.Count > 1) { result.Messages.Add($"Property '{propertyName}' contains multiple values, while the Field '{field.FieldType.Id}' and datatype {field.FieldType.DataType} only needs one. Taking the value '{firstVal}' of the list of values '{mergedVal}'."); } }
/// <summary> /// Deletes the resource in inRiver, associated with the asset id of bynder /// </summary> /// <param name="bynderAssetId"></param> /// <returns></returns> public WorkerResult Execute(string bynderAssetId) { var result = new WorkerResult(); // only process if we are allowed to delete entities if (!GetDeleteResourceOnDeletedEvents()) { return(result); } // find resourceEntity based on bynderAssetId Entity resourceEntity = _inRiverContext.ExtensionManager.DataService.GetEntityByUniqueValue(FieldTypeIds.ResourceBynderId, bynderAssetId, LoadLevel.DataAndLinks); // delete if exist if (resourceEntity != null) { _inRiverContext.Log(LogLevel.Verbose, $"Deleting Resource {resourceEntity.Id}, which is associated with the deleted bynder asset {bynderAssetId}"); _inRiverContext.ExtensionManager.DataService.DeleteEntity(resourceEntity.Id); result.Messages.Add($"Deleted Resource {resourceEntity.Id}, which was associated with the deleted bynder asset {bynderAssetId}"); } else { _inRiverContext.Log(LogLevel.Debug, $"Nothing to remove. Deleted asset {bynderAssetId} does not exist in inRiver as Resource."); result.Messages.Add($"Nothing to remove. Deleted asset {bynderAssetId} does not exist in inRiver as Resource."); } return(result); }
private WorkerResult CreateOrUpdateEntityAndRelations(WorkerResult result, Asset asset, FilenameEvaluator.Result evaluatorResult, Entity resourceEntity) { _inRiverContext.Log(LogLevel.Verbose, $"Create or update entity, metadata and relations for bynder asset {asset.Id}"); if (resourceEntity == null) { resourceEntity = CreateResourceEntity(asset); } SetAssetProperties(resourceEntity, asset, result); SetMetapropertyData(resourceEntity, asset, result); var filenameData = evaluatorResult.GetResourceDataInFilename(); SetResourceFilenameData(resourceEntity, asset, filenameData); var resultString = new StringBuilder(); resourceEntity = AddOrUpdateEntityInInRiver(resourceEntity, resultString); var relatedEntityData = evaluatorResult.GetRelatedEntityDataInFilename(); AddRelations(relatedEntityData, resourceEntity, resultString); result.Messages.Add(resultString.ToString()); return(result); }
/// <summary> /// /// </summary> /// <param name="result"></param> /// <param name="bynderAssetId"></param> /// <param name="resourceEntity"></param> /// <returns></returns> private WorkerResult SetValuesOnResource(WorkerResult result, string bynderAssetId, Entity resourceEntity) { var fieldValueCombinations = GetFieldValueCombinations(); if (fieldValueCombinations.Count == 0) { _inRiverContext.Log(LogLevel.Verbose, $"No fieldvalue combinations found. Not updating resource for archived bynder asset {bynderAssetId}"); return(result); } var fieldsToUpdate = new List <Field>(); var dateTimeSettings = GetDateTimeSettings(); foreach (var fvc in fieldValueCombinations) { if (string.IsNullOrWhiteSpace(fvc.FieldTypeId)) { _inRiverContext.Log(LogLevel.Verbose, $"Field value combination found without FieldTypeId setting filled in setting '{Settings.FieldValuesToSetOnArchiveEvent}'!"); continue; } var field = resourceEntity.GetField(fvc.FieldTypeId); if (field == null) { _inRiverContext.Log(LogLevel.Verbose, $"Field '{fvc.FieldTypeId}' used in the setting '{Settings.FieldValuesToSetOnArchiveEvent}' does not exist on Resource!"); continue; } if (fvc.SetTimestamp) { if (dateTimeSettings == null) { _inRiverContext.Log(LogLevel.Verbose, $"Field value combination found with {nameof(FieldValueCombination.SetTimestamp)} on true, but the setting '{Settings.TimestampSettings}' is empty!"); continue; } field.Data = DateTimeHelper.GetTimestamp(dateTimeSettings); } else { field.Data = fvc.Value.ConvertTo(field.FieldType.DataType); } fieldsToUpdate.Add(field); } if (fieldsToUpdate.Count > 0) { _inRiverContext.Log(LogLevel.Verbose, $"Setting values on Resource {resourceEntity.Id} for archived bynder asset {bynderAssetId}"); resourceEntity = _inRiverContext.ExtensionManager.DataService.UpdateFieldsForEntity(fieldsToUpdate); result.Messages.Add($"Updated field(s) on Resource {resourceEntity.Id} for archived bynder asset {bynderAssetId}"); } else { _inRiverContext.Log(LogLevel.Verbose, $"No fields to update on Resource {resourceEntity.Id} for archived bynder asset {bynderAssetId}"); } return(result); }
private WorkerResult UpdateMetadata(WorkerResult result, Asset asset, Entity resourceEntity) { _inRiverContext.Log(LogLevel.Verbose, $"Update metadata only for Resource {resourceEntity.Id}"); SetAssetProperties(resourceEntity, asset, result); SetMetapropertyData(resourceEntity, asset, result); resourceEntity = _inRiverContext.ExtensionManager.DataService.UpdateEntity(resourceEntity); result.Messages.Add($"Resource {resourceEntity.Id} updated"); return(result); }
/// <summary> /// check the necesaary prereqs for the bynder-inriver integration /// </summary> public WorkerResult Execute() { // create result object _workerResult = new WorkerResult(); AssumeSettingIsSet(SettingNames.ConsumerSecret); AssumeSettingIsSet(SettingNames.ConsumerKey); AssumeSettingIsSet(SettingNames.Token); AssumeSettingIsSet(SettingNames.TokenSecret); AssumeSettingIsSet(SettingNames.CustomerBynderUrl); AssumeSettingIsValidUrl(SettingNames.CustomerBynderUrl); return(_workerResult); }
public WorkerResult Execute() { var result = new WorkerResult(); result.Messages.AddRange(_modelValidationWorker.Execute().Messages); result.Messages.AddRange(_bynderSettingsValidationWorker.Execute().Messages); // test bynder bynderClient result.Messages.Add("Test Bynder API Connection:"); var account = _bynderClient.GetAccount(); result.Messages.Add($"Got access to account '{account?.Name}'"); return(result); }
private void SetAssetProperties(Entity resourceEntity, Asset asset, WorkerResult result) { _inRiverContext.Log(LogLevel.Verbose, $"Setting asset properties on entity {resourceEntity.Id}"); var propertyMap = GetConfiguredAssetPropertyMap(); var assetProperties = asset.GetType().GetProperties(); foreach (var kvp in propertyMap) { var assetProperty = assetProperties.FirstOrDefault(x => x.Name.ToCamelCase().Equals(kvp.Key)); if (assetProperty == null) { var message = $"Property '{kvp.Key}' does not exist on an Asset!"; result.Messages.Add(message); _inRiverContext.Log(LogLevel.Warning, message); continue; } var field = resourceEntity.GetField(kvp.Value); if (field == null) { var message = $"Field '{kvp.Value}' does not exist on a Resource!"; result.Messages.Add(message); _inRiverContext.Log(LogLevel.Warning, message); continue; } object propertyVal = assetProperty.GetValue(asset, null); // for now we know that the Asset only holds List<string> so we do it this way, would be nicer to add this in the ConvertTo as well bool isIEnumerable = propertyVal != null && propertyVal.GetType().IsIEnumerable() && !(propertyVal is string); List <string> values; if (isIEnumerable) { values = propertyVal as List <string>; } else { values = new List <string> { propertyVal.ConvertTo <string>() }; } field.Data = GetParsedValueForField(result, assetProperty.Name, values, field); } }
private void SetMetapropertyData(Entity resourceEntity, Asset asset, WorkerResult result) { _inRiverContext.Log(LogLevel.Verbose, $"Setting metaproperties on entity {resourceEntity.Id}"); var metaPropertyMapping = GetConfiguredMetaPropertyMap(); var metaPropertiesToProcess = asset.MetaProperties.Where(property => metaPropertyMapping.ContainsKey(property.Name) && metaPropertyMapping[property.Name] != null); foreach (var property in metaPropertiesToProcess) { var fieldTypeId = metaPropertyMapping[property.Name]; var field = resourceEntity.GetField(fieldTypeId); if (field == null) { result.Messages.Add($"FieldType '{fieldTypeId}' in MetaPropertyMapping does not exist on Resource EntityType"); _inRiverContext.Logger.Log(LogLevel.Warning, $"FieldType '{fieldTypeId}' does not exist on Resource EntityType"); continue; } field.Data = GetParsedValueForField(result, property.Name, property.Values, field); } }
/// <summary> /// check the necesaary prereqs for the bynder-inriver integration in the inriver model /// </summary> public WorkerResult Execute() { // create result object _workerResult = new WorkerResult(); // check existance of resource fields AssumeFieldTypeExists(FieldTypeIds.ResourceBynderId); AssumeFieldTypeExists(FieldTypeIds.ResourceBynderIdHash); AssumeFieldTypeExists(FieldTypeIds.ResourceBynderDownloadState); AssumeFieldTypeExists(FieldTypeIds.ResourceFileId); AssumeFieldTypeExists(FieldTypeIds.ResourceFilename); AssumeFieldTypeExists(FieldTypeIds.ResourceMimeType); // check existance of CVL AssumeCVLExists(CvlIds.ResourceBynderState); AssumeCVLValuesExists(CvlIds.ResourceBynderState, new[] { BynderStates.Todo, BynderStates.Done, BynderStates.Error }); // check if field downloadstate linked to right CVL AssumeFieldTypeIsCVL(FieldTypeIds.ResourceBynderDownloadState, CvlIds.ResourceBynderState); return(_workerResult); }
public WorkerResult Execute(string bynderAssetId) { var result = new WorkerResult(); // get original filename, as we need to evaluate this for further processing var asset = _bynderClient.GetAssetByAssetId(bynderAssetId); string originalFileName = asset.GetOriginalFileName(); // evaluate filename var evaluatorResult = _fileNameEvaluator.Evaluate(originalFileName); if (!evaluatorResult.IsMatch()) { result.Messages.Add($"Not processing '{originalFileName}'; does not match regex."); return(result); } // find resourceEntity based on bynderAssetId Entity resourceEntity = _inRiverContext.ExtensionManager.DataService.GetEntityByUniqueValue(FieldTypeIds.ResourceBynderId, bynderAssetId, LoadLevel.DataAndLinks); if (resourceEntity == null) { EntityType resourceType = _inRiverContext.ExtensionManager.ModelService.GetEntityType(EntityTypeIds.Resource); resourceEntity = Entity.CreateEntity(resourceType); // add asset id to new ResourceEntity resourceEntity.GetField(FieldTypeIds.ResourceBynderId).Data = bynderAssetId; // set filename (only for *new* resource) resourceEntity.GetField(FieldTypeIds.ResourceFilename).Data = $"{bynderAssetId}_{asset.GetOriginalFileName()}"; } // status for new and existing ResourceEntity resourceEntity.GetField(FieldTypeIds.ResourceBynderDownloadState).Data = BynderStates.Todo; // resource fields from regular expression created from filename foreach (var keyValuePair in evaluatorResult.GetResourceDataInFilename()) { resourceEntity.GetField(keyValuePair.Key.Id).Data = keyValuePair.Value; } // save IdHash for re-creation of public CDN Urls in inRiver resourceEntity.GetField(FieldTypeIds.ResourceBynderIdHash).Data = asset.IdHash; var resultString = new StringBuilder(); if (resourceEntity.Id == 0) { resourceEntity = _inRiverContext.ExtensionManager.DataService.AddEntity(resourceEntity); resultString.Append($"Resource {resourceEntity.Id} added"); } else { resourceEntity = _inRiverContext.ExtensionManager.DataService.UpdateEntity(resourceEntity); resultString.Append($"Resource {resourceEntity.Id} updated"); } // get related entity data found in filename so we can create or update link to these entities // all found field/values are supposed to be unique fields in the correspondent entitytype // get all *inbound* linktypes towards the Resource entitytype in the model (e.g. ProductResource, ItemResource NOT ResourceOtherEntity) var inboundResourceLinkTypes = _inRiverContext.ExtensionManager.ModelService.GetLinkTypesForEntityType(EntityTypeIds.Resource) .Where(lt => lt.TargetEntityTypeId == EntityTypeIds.Resource).OrderBy(lt => lt.Index).ToList(); foreach (var keyValuePair in evaluatorResult.GetRelatedEntityDataInFilename()) { var fieldTypeId = keyValuePair.Key.Id; var value = keyValuePair.Value; // find sourcentity (e.g. Product) var sourceEntity = _inRiverContext.ExtensionManager.DataService.GetEntityByUniqueValue(fieldTypeId, value, LoadLevel.Shallow); if (sourceEntity == null) { continue; } // find linktype in our previously found list var linkType = inboundResourceLinkTypes.FirstOrDefault(lt => lt.SourceEntityTypeId == sourceEntity.EntityType.Id); if (linkType == null) { continue; } if (!_inRiverContext.ExtensionManager.DataService.LinkAlreadyExists(sourceEntity.Id, resourceEntity.Id, null, linkType.Id)) { _inRiverContext.ExtensionManager.DataService.AddLink(new Link() { Source = sourceEntity, Target = resourceEntity, LinkType = linkType }); } resultString.Append($"; {sourceEntity.EntityType.Id} entity {sourceEntity.Id} found and linked"); } result.Messages.Add(resultString.ToString()); return(result); }
private object GetParsedValueForField(WorkerResult result, string propertyName, List <string> values, Field field) { var mergedVal = values == null ? null : string.Join(GetMultivalueSeparator(), values); var singleVal = values?.FirstOrDefault(); switch (field.FieldType.DataType.ToLower()) { case "localestring": var languagesToSet = GetLanguagesToSet(); var ls = (LocaleString)field.Data; if (ls == null) { ls = new LocaleString(_inRiverContext.ExtensionManager.UtilityService.GetAllLanguages()); } foreach (var lang in languagesToSet) { var culture = new CultureInfo(lang); if (!ls.ContainsCulture(culture)) { continue; } ls[culture] = mergedVal; } return(ls); case "string": return(mergedVal); case "cvl": var parsedCvlVal = GeParsedCvlValueForField(field, values, result, out singleVal); if (!field.FieldType.Multivalue) { LogMessageIfMultipleValuesForSingleField(result, propertyName, field, values, singleVal, mergedVal); } return(parsedCvlVal); case "datetime": LogMessageIfMultipleValuesForSingleField(result, propertyName, field, values, singleVal, mergedVal); if (string.IsNullOrEmpty(singleVal)) { return(null); } else if (singleVal.Contains('/')) // when using the date property { // 07/28/2017 return(singleVal.ConvertTo <DateTime?>(dateTimeFormat: "MM/dd/yyyy")); } else // added this just to be sure, it is used in example outputs of the Bynder API { //2017-03-28T14:28:56Z yyyy-mm-ddThh:mm:ssZ (ISO 8601) // grab the UTC variant of the culture invariant datetime, because Bynder writes the DateTimes for its selected culture. So the given value of the datetime is the whole truth, // and does not have to be converted. The DateTime parse takes the local time so we need to grab ourself the UTC time. return(singleVal.ConvertTo <DateTime?>()?.ToUniversalTime()); } default: LogMessageIfMultipleValuesForSingleField(result, propertyName, field, values, singleVal, mergedVal); return(singleVal.ConvertTo(field.FieldType.DataType)); } }
/// <summary> /// Main method of the worker /// </summary> /// <param name="bynderAssetId"></param> /// <param name="notificationType"></param> /// <returns></returns> public WorkerResult Execute(string bynderAssetId, NotificationType notificationType) { var result = new WorkerResult(); // get original filename, as we need to evaluate this for further processing var asset = _bynderClient.GetAssetByAssetId(bynderAssetId); // evaluate filename string originalFileName = asset.GetOriginalFileName(); var evaluatorResult = _fileNameEvaluator.Evaluate(originalFileName); if (!evaluatorResult.IsMatch()) { result.Messages.Add($"Not processing '{originalFileName}'; does not match regex."); return(result); } // evaluate conditions if (!AssetAppliesToConditions(asset)) { _inRiverContext.Log(LogLevel.Debug, $"Asset {bynderAssetId} does not apply to the conditions"); result.Messages.Add($"Not processing '{originalFileName}'; does not apply to import conditions."); return(result); } _inRiverContext.Log(LogLevel.Debug, $"Asset {asset.Id} applies to conditions."); // find resourceEntity based on bynderAssetId Entity resourceEntity = _inRiverContext.ExtensionManager.DataService.GetEntityByUniqueValue(FieldTypeIds.ResourceBynderId, bynderAssetId, LoadLevel.DataAndLinks); // handle notification logic switch (notificationType) { case NotificationType.DataUpsert: return(CreateOrUpdateEntityAndRelations(result, asset, evaluatorResult, resourceEntity)); case NotificationType.MetadataUpdated: if (resourceEntity != null) { return(UpdateMetadata(result, asset, resourceEntity)); } else { return(CreateOrUpdateEntityAndRelations(result, asset, evaluatorResult, resourceEntity)); } case NotificationType.IsArchived: if (resourceEntity != null) { return(SetValuesOnResource(result, bynderAssetId, resourceEntity)); } else { _inRiverContext.Log(LogLevel.Debug, $"Archived asset {bynderAssetId}, does not exist in inRiver as Resource."); result.Messages.Add($"Archived asset {bynderAssetId}, does not exist in inRiver as Resource."); return(result); } default: _inRiverContext.Log(LogLevel.Warning, $"Notification type {notificationType} is not implemented yet! This notification will not be processed for asset {bynderAssetId}."); result.Messages.Add($"Notification type {notificationType} is not implemented yet! This notification will not be processed for asset {bynderAssetId}."); return(result); } }
/// <summary> /// Returns the parsed cvl value. /// Checks if the values exist in the CVL. If not they get added if the setting CREATE_MISSING_CVL_KEYS is true. /// returns valid CVL values or null. /// </summary> /// <param name="field"></param> /// <param name="values"></param> /// <param name="result"></param> /// <param name="singleVal">returns the first valid CVL value</param> /// <returns></returns> private string GeParsedCvlValueForField(Field field, List <string> values, WorkerResult result, out string singleVal) { singleVal = string.Empty; if (values == null || values.Count == 0) { return(null); } List <string> validatedCvlKeys = new List <string>(values.Count); List <CVLValue> cvlValues = _inRiverContext.ExtensionManager.ModelService.GetCVLValuesForCVL(field.FieldType.CVLId, true); foreach (string cvlKey in values) { if (string.IsNullOrWhiteSpace(cvlKey)) { continue; } if (cvlValues.Any(c => c.Key.Equals(cvlKey))) { validatedCvlKeys.Add(cvlKey); continue; } string cleanCvlKey = cvlKey.ToStringWithoutControlCharactersForCvlKey(); if (cvlValues.Any(c => c.Key.Equals(cleanCvlKey))) { validatedCvlKeys.Add(cleanCvlKey); continue; } // create new CVL value when the setting CREATE_MISSING_CVL_KEYS is true if (GetConfiguredCreateMissingCvlKeys()) { CVLValue newCvlValue = new CVLValue() { CVLId = field.FieldType.CVLId, Key = cleanCvlKey, Value = cvlKey }; try { newCvlValue = _inRiverContext.ExtensionManager.ModelService.AddCVLValue(newCvlValue); cvlValues.Add(newCvlValue); validatedCvlKeys.Add(newCvlValue.Key); } catch (Exception e) { result.Messages.Add($"Could not add CVLKey '{cleanCvlKey}' ({cvlKey})."); _inRiverContext.Log(LogLevel.Error, $"Could not add CVLKey '{cleanCvlKey}' ({cvlKey}).", e); } } else { result.Messages.Add($"Missing CVLKey '{cleanCvlKey}' ({cvlKey}) has not been added."); } } if (validatedCvlKeys.Any()) { if (field.FieldType.Multivalue) { // cvlkeys are always separated by semicolon in inRiver return(string.Join(";", validatedCvlKeys)); } else { singleVal = validatedCvlKeys.FirstOrDefault(); return(singleVal); } } return(null); }