private static DataKeyPropertyCollection CopyFieldValues(DataType dataType, IData data, XElement addElement) { var dataKeyPropertyCollection = new DataKeyPropertyCollection(); var properties = GetDataTypeProperties(dataType.InterfaceType); foreach (XAttribute attribute in addElement.Attributes()) { string fieldName = attribute.Name.LocalName; if (IsObsoleteField(dataType, fieldName)) { continue; } PropertyInfo propertyInfo = properties[fieldName]; object fieldValue = ValueTypeConverter.Convert(attribute.Value, propertyInfo.PropertyType); propertyInfo.SetValue(data, fieldValue, null); if (dataType.InterfaceType.GetKeyPropertyNames().Contains(fieldName)) { dataKeyPropertyCollection.AddKeyProperty(fieldName, fieldValue); } } return(dataKeyPropertyCollection); }
/// <exclude /> public bool IsPendingForDeletionData(IData data) { Verify.ArgumentNotNull(data, "data"); if (_typesToBeDeleted.Contains(data.DataSourceId.InterfaceType)) { return(true); } DataKeyPropertyCollection dataKeyPropertyCollection = data.CreateDataKeyPropertyCollection(); return(IsPendingForDeletionData(data.DataSourceId.InterfaceType, data.DataSourceId.DataScopeIdentifier, data.DataSourceId.LocaleScope, dataKeyPropertyCollection)); }
private void RegisterKeyToBeAdded(DataType dataType, DataKeyPropertyCollection dataKeyPropertyCollection) { if (dataKeyPropertyCollection.Count != 1) { return; } var typeKeyInstallationData = _dataKeysToBeInstalled.GetOrAdd(dataType.InterfaceType, () => new TypeKeyInstallationData(dataType.InterfaceType)); var keyValuePair = dataKeyPropertyCollection.KeyProperties.First(); typeKeyInstallationData.RegisterKeyUsage(dataType, keyValuePair); }
private void ValidateDynamicAddedType(DataType dataType) { DataTypeDescriptor dataTypeDescriptor = this.InstallerContext.GetPendingDataTypeDescriptor(dataType.InterfaceTypeName); if (dataTypeDescriptor == null) { _validationResult.AddFatal(GetText("DataPackageFragmentInstaller.MissingTypeDescriptor").FormatWith(dataType.InterfaceTypeName)); return; } bool dataTypeLocalized = dataTypeDescriptor.SuperInterfaces.Contains(typeof(ILocalizedControlled)); if (!ValidateTargetLocaleInfo(dataType, dataTypeLocalized)) { return; } foreach (XElement addElement in dataType.Dataset) { var dataKeyPropertyCollection = new DataKeyPropertyCollection(); bool propertyValidationPassed = true; var fieldValues = new Dictionary <string, object>(); foreach (XAttribute attribute in addElement.Attributes()) { string fieldName = attribute.Name.LocalName; // A compatibility fix if (IsObsoleteField(dataTypeDescriptor, fieldName)) { continue; } DataFieldDescriptor dataFieldDescriptor = dataTypeDescriptor.Fields[fieldName]; if (dataFieldDescriptor == null) { _validationResult.AddFatal(Texts.DataPackageFragmentInstaller_MissingProperty(dataTypeDescriptor, fieldName)); propertyValidationPassed = false; continue; } object fieldValue; try { fieldValue = ValueTypeConverter.Convert(attribute.Value, dataFieldDescriptor.InstanceType); } catch (Exception) { _validationResult.AddFatal(Texts.DataPackageFragmentInstaller_ConversionFailed(attribute.Value, dataFieldDescriptor.InstanceType)); propertyValidationPassed = false; continue; } if (dataTypeDescriptor.KeyPropertyNames.Contains(fieldName)) { dataKeyPropertyCollection.AddKeyProperty(fieldName, fieldValue); } fieldValues.Add(fieldName, fieldValue); } if (!propertyValidationPassed) { continue; } if (!dataType.AllowOverwrite && !dataType.OnlyUpdate) { // TODO: implement check if the same key has already been added } // TODO: to be implemented for dynamic types // RegisterKeyToBeAdded(dataType, dataKeyPropertyCollection); // Checking foreign key references foreach (var referenceField in dataTypeDescriptor.Fields.Where(f => f.ForeignKeyReferenceTypeName != null)) { object propertyValue; if (!fieldValues.TryGetValue(referenceField.Name, out propertyValue) || propertyValue == null || (propertyValue is Guid && (Guid)propertyValue == Guid.Empty) || propertyValue is string && (string)propertyValue == "") { continue; } string referredTypeName = referenceField.ForeignKeyReferenceTypeName; var referredType = TypeManager.TryGetType(referredTypeName); if (referredType == null) { // TODO: implement reference check for dynamic types as well continue; } string targetKeyPropertyName = referredType.GetKeyPropertyNames().SingleOrDefault(); CheckForBrokenReference(dataType, referredType, targetKeyPropertyName, propertyValue); } } }
private void ValidateNonDynamicAddedType(DataType dataType) { if (dataType.InterfaceType == null) { _validationResult.AddFatal(GetText("DataPackageFragmentInstaller.TypeNotConfigured").FormatWith(dataType.InterfaceTypeName)); return; } if (!typeof(IData).IsAssignableFrom(dataType.InterfaceType)) { _validationResult.AddFatal(GetText("DataPackageFragmentInstaller.TypeNotInheriting").FormatWith(dataType.InterfaceType, typeof(IData))); return; } bool dataTypeLocalized = DataLocalizationFacade.IsLocalized(dataType.InterfaceType); if (!ValidateTargetLocaleInfo(dataType, dataTypeLocalized)) { return; } int itemsAlreadyPresentInDatabase = 0; DataTypeDescriptor dataTypeDescriptor = DynamicTypeManager.BuildNewDataTypeDescriptor(dataType.InterfaceType); bool isVersionedDataType = typeof(IVersioned).IsAssignableFrom(dataType.InterfaceType); var requiredPropertyNames = (from dfd in dataTypeDescriptor.Fields where !dfd.IsNullable && !(isVersionedDataType && dfd.Name == nameof(IVersioned.VersionId)) // Compatibility fix select dfd.Name).ToList(); var nonRequiredPropertyNames = dataTypeDescriptor.Fields.Select(f => f.Name) .Except(requiredPropertyNames).ToList(); foreach (XElement addElement in dataType.Dataset) { var dataKeyPropertyCollection = new DataKeyPropertyCollection(); bool propertyValidationPassed = true; var assignedPropertyNames = new List <string>(); var fieldValues = new Dictionary <string, object>(); var properties = GetDataTypeProperties(dataType.InterfaceType); foreach (XAttribute attribute in addElement.Attributes()) { string fieldName = attribute.Name.LocalName; PropertyInfo propertyInfo; if (!properties.TryGetValue(fieldName, out propertyInfo)) { // A compatibility fix if (IsObsoleteField(dataType, fieldName)) { continue; } _validationResult.AddFatal(GetText("DataPackageFragmentInstaller.MissingProperty").FormatWith(dataType.InterfaceType, fieldName)); propertyValidationPassed = false; continue; } if (!propertyInfo.CanWrite) { _validationResult.AddFatal(GetText("DataPackageFragmentInstaller.MissingWritableProperty").FormatWith(dataType.InterfaceType, fieldName)); propertyValidationPassed = false; continue; } object fieldValue; try { fieldValue = ValueTypeConverter.Convert(attribute.Value, propertyInfo.PropertyType); } catch (Exception) { _validationResult.AddFatal(GetText("DataPackageFragmentInstaller.ConversionFailed").FormatWith(attribute.Value, propertyInfo.PropertyType)); propertyValidationPassed = false; continue; } if (dataType.InterfaceType.GetKeyPropertyNames().Contains(fieldName)) { dataKeyPropertyCollection.AddKeyProperty(fieldName, fieldValue); } assignedPropertyNames.Add(fieldName); fieldValues.Add(fieldName, fieldValue); } if (!propertyValidationPassed) { continue; } var notAssignedRequiredProperties = requiredPropertyNames.Except(assignedPropertyNames.Except(nonRequiredPropertyNames)).ToArray(); if (notAssignedRequiredProperties.Any()) { bool missingValues = false; foreach (string propertyName in notAssignedRequiredProperties) { PropertyInfo propertyInfo = dataType.InterfaceType.GetPropertiesRecursively().Single(f => f.Name == propertyName); if (propertyInfo.CanWrite) { var defaultValueAttribute = propertyInfo.GetCustomAttributesRecursively <NewInstanceDefaultFieldValueAttribute>().SingleOrDefault(); if (defaultValueAttribute == null || !defaultValueAttribute.HasValue) { _validationResult.AddFatal(GetText("DataPackageFragmentInstaller.MissingPropertyVaule").FormatWith(propertyName, dataType.InterfaceType)); missingValues = true; } } } if (missingValues) { continue; } } // Validating keys already present if (!dataType.AllowOverwrite && !dataType.OnlyUpdate) { bool dataLocaleExists = !DataLocalizationFacade.IsLocalized(dataType.InterfaceType) || (!dataType.AddToAllLocales && !dataType.AddToCurrentLocale) || (dataType.Locale != null && !this.InstallerContext.IsLocalePending(dataType.Locale)); if (dataLocaleExists) { using (new DataScope(dataType.DataScopeIdentifier, dataType.Locale)) { IData data = DataFacade.TryGetDataByUniqueKey(dataType.InterfaceType, dataKeyPropertyCollection); if (data != null) { itemsAlreadyPresentInDatabase++; } } } } RegisterKeyToBeAdded(dataType, dataKeyPropertyCollection); // Checking foreign key references foreach (var foreignKeyProperty in DataAttributeFacade.GetDataReferenceProperties(dataType.InterfaceType)) { if (!fieldValues.ContainsKey(foreignKeyProperty.SourcePropertyName)) { continue; } object propertyValue = fieldValues[foreignKeyProperty.SourcePropertyName]; if (propertyValue == null || propertyValue == foreignKeyProperty.NullReferenceValue) { continue; } CheckForBrokenReference(dataType, foreignKeyProperty.TargetType, foreignKeyProperty.TargetKeyPropertyName, propertyValue); } } if (itemsAlreadyPresentInDatabase > 0) { _validationResult.AddFatal(GetText("DataPackageFragmentInstaller.DataExists").FormatWith(dataType.InterfaceType, itemsAlreadyPresentInDatabase)); } }
private void RegisterKeyToBeAdded(DataType dataType, DataTypeDescriptor dataTypeDescriptor, DataKeyPropertyCollection dataKeyPropertyCollection) { if (dataKeyPropertyCollection.Count != 1) { return; } TypeKeyInstallationData typeKeyInstallationData; if (dataType.InterfaceType != null) { // Static types typeKeyInstallationData = _dataKeysToBeInstalled.GetOrAdd(dataType.InterfaceType, () => new TypeKeyInstallationData(dataType.InterfaceType)); } else { // Dynamic types typeKeyInstallationData = _dataKeysToBeInstalledByTypeId.GetOrAdd(dataTypeDescriptor.DataTypeId, () => new TypeKeyInstallationData(dataTypeDescriptor)); } var keyValuePair = dataKeyPropertyCollection.KeyProperties.First(); typeKeyInstallationData.RegisterKeyUsage(dataType, keyValuePair); }
/// <summary> /// This method finds the callers tree node own entity token by searching up/down using filters. /// In some cases this can be expensive. /// </summary> /// <param name="treeNode"></param> /// <param name="entityToken"></param> /// <param name="dynamicContext"></param> /// <returns></returns> private EntityToken FindOwnEntityToken(TreeNode treeNode, EntityToken entityToken, TreeNodeDynamicContext dynamicContext) { DataElementsTreeNode dataElementsTreeNode = treeNode as DataElementsTreeNode; if (dataElementsTreeNode != null) { if (dataElementsTreeNode.InterfaceType == this.OwnerNode.InterfaceType) // We found it :) { return(entityToken); } } TreeDataFieldGroupingElementEntityToken dataFieldGroupingElementEntityToken = entityToken as TreeDataFieldGroupingElementEntityToken; if (dataFieldGroupingElementEntityToken != null) // Search 'downwards' { ParameterExpression parameterExpression = Expression.Parameter(this.OwnerNode.InterfaceType, "data"); DataKeyPropertyCollection dataKeyPropertyCollection = new DataKeyPropertyCollection(); dataKeyPropertyCollection.AddKeyProperty("Id", dataFieldGroupingElementEntityToken.ChildGeneratingDataElementsReferenceValue); Type dataType = dataFieldGroupingElementEntityToken.ChildGeneratingDataElementsReferenceType; IData parentData = DataFacade.GetDataByUniqueKey(dataType, dataKeyPropertyCollection); TreeNodeDynamicContext dummyContext = new TreeNodeDynamicContext(TreeNodeDynamicContextDirection.Down); dummyContext.CustomData.Add("ParentData", parentData); IData resultData; if (this.OwnerNode.InterfaceType == TypeManager.GetType(dataFieldGroupingElementEntityToken.Type)) { Expression filterExpression = this.CreateDownwardsFilterExpression(parameterExpression, dummyContext); Expression whereExpression = ExpressionHelper.CreateWhereExpression(DataFacade.GetData(this.OwnerNode.InterfaceType).Expression, parameterExpression, filterExpression); resultData = (IData)DataFacade.GetData(this.OwnerNode.InterfaceType).Provider.CreateQuery(whereExpression).ToEnumerableOfObjects().First(); } else { resultData = parentData; } return(resultData.GetDataEntityToken()); } AncestorResult ancestorResult = treeNode.GetParentEntityToken(entityToken, this.ParentFilterType, dynamicContext); if ((this.OwnerNode.Id == ancestorResult.TreeNode.Id) || (this.OwnerNode.IsDescendant(ancestorResult.TreeNode))) // Search upwards { return(FindOwnEntityToken(ancestorResult.TreeNode, ancestorResult.EntityToken, dynamicContext)); } // Search 'downwards' by using the parent datas key value to get DataElementsTreeNode parentDataElementsTreeNode = (DataElementsTreeNode)ancestorResult.TreeNode; if (this.ParentFilterType == parentDataElementsTreeNode.InterfaceType) { DataEntityToken dataEntityToken = (DataEntityToken)ancestorResult.EntityToken; ParameterExpression parameterExpression = Expression.Parameter(this.OwnerNode.InterfaceType, "data"); TreeNodeDynamicContext dummyContext = new TreeNodeDynamicContext(TreeNodeDynamicContextDirection.Down); dummyContext.CustomData.Add("ParentData", dataEntityToken.Data); Expression filterExpression = this.CreateDownwardsFilterExpression(parameterExpression, dummyContext); Expression whereExpression = ExpressionHelper.CreateWhereExpression(DataFacade.GetData(this.OwnerNode.InterfaceType).Expression, parameterExpression, filterExpression); IData resultData = (IData)DataFacade.GetData(this.OwnerNode.InterfaceType).Provider.CreateQuery(whereExpression).ToEnumerableOfObjects().First(); return(resultData.GetDataEntityToken()); } throw new InvalidOperationException("Missing parent id filtering or try to simplify the parent id filterings (Unable to find own entity token)"); }
/// <exclude /> public bool IsPendingForDeletionData(Type interfaceType, DataScopeIdentifier dataScopeIdentifier, CultureInfo locale, DataKeyPropertyCollection dataKeyPropertyCollection) { Verify.ArgumentNotNull(interfaceType, "interfaceType"); Verify.ArgumentNotNull(dataScopeIdentifier, "dataScopeIdentifier"); Verify.ArgumentNotNull(dataKeyPropertyCollection, "dataKeyPropertyCollection"); List <DataKeyPropertyCollection> dataKeyPropertyCollections = GetDataKeyPropertyCollection(interfaceType, dataScopeIdentifier, locale); return(dataKeyPropertyCollections.Contains(dataKeyPropertyCollection)); }
/// <exclude /> public void AddPendingForDeletionData(Type interfaceType, DataScopeIdentifier dataScopeIdentifier, CultureInfo locale, DataKeyPropertyCollection dataKeyPropertyCollection) { Verify.ArgumentNotNull(interfaceType, "interfaceType"); Verify.ArgumentNotNull(dataScopeIdentifier, "dataScopeIdentifier"); Verify.ArgumentNotNull(dataKeyPropertyCollection, "dataKeyPropertyCollection"); List <DataKeyPropertyCollection> dataKeyPropertyCollections = GetDataKeyPropertyCollection(interfaceType, dataScopeIdentifier, locale); if (dataKeyPropertyCollections.Contains(dataKeyPropertyCollection)) { throw new ArgumentException(string.Format("The data item of type '{0}' with the key '{1}' has already been added", interfaceType, dataKeyPropertyCollection)); } dataKeyPropertyCollections.Add(dataKeyPropertyCollection); }
private void AddDataToDelete(Type interfaceType, DataScopeIdentifier dataScopeIdentifier, CultureInfo locale, DataKeyPropertyCollection dataKeyPropertyCollection) { DataType dataType = _dataToDelete.SingleOrDefault(dt => dt.InterfaceType == interfaceType && dt.DataScopeIdentifier.Equals(dataScopeIdentifier) && ((dt.Locale == null && locale == null) || (dt.Locale != null && dt.Locale.Equals(locale)))); if (dataType == null) { dataType = new DataType { InterfaceType = interfaceType, DataScopeIdentifier = dataScopeIdentifier, Locale = locale }; _dataToDelete.Add(dataType); } dataType.DataKeys.Add(dataKeyPropertyCollection); this.UninstallerContext.AddPendingForDeletionData(interfaceType, dataScopeIdentifier, locale, dataKeyPropertyCollection); }
/// <exclude /> public override IEnumerable <PackageFragmentValidationResult> Validate() { var validationResult = new List <PackageFragmentValidationResult>(); if (this.Configuration.Count(f => f.Name == "Types") > 1) { validationResult.AddFatal(Texts.DataPackageFragmentUninstaller_OnlyOneElement); return(validationResult); } _dataToDelete = new List <DataType>(); XElement typesElement = this.Configuration.SingleOrDefault(f => f.Name == "Types"); if (typesElement == null) { return(validationResult); } foreach (XElement typeElement in typesElement.Elements("Type").Reverse()) { XAttribute typeAttribute = typeElement.Attribute("type"); XAttribute dataScopeIdentifierAttribute = typeElement.Attribute("dataScopeIdentifier"); if (typeAttribute == null) { validationResult.AddFatal(Texts.DataPackageFragmentUninstaller_MissingAttribute("type"), typeElement); continue; } if (dataScopeIdentifierAttribute == null) { validationResult.AddFatal(Texts.DataPackageFragmentUninstaller_MissingAttribute("dataScopeIdentifier"), typeElement); continue; } Type type = TypeManager.TryGetType(typeAttribute.Value); if (type == null) { continue; } if (!DataFacade.GetAllInterfaces().Contains(type)) { continue; } DataScopeIdentifier dataScopeIdentifier; try { dataScopeIdentifier = DataScopeIdentifier.Deserialize(dataScopeIdentifierAttribute.Value); } catch (Exception) { validationResult.AddFatal("Wrong DataScopeIdentifier ({0}) name in the configuration".FormatWith(dataScopeIdentifierAttribute.Value), dataScopeIdentifierAttribute); continue; } foreach (XElement datasElement in typeElement.Elements("Datas").Reverse()) { CultureInfo locale = null; XAttribute localeAttribute = datasElement.Attribute("locale"); if (localeAttribute != null) { locale = CultureInfo.CreateSpecificCulture(localeAttribute.Value); } foreach (XElement keysElement in datasElement.Elements("Keys").Reverse()) { bool allKeyPropertiesValidated = true; var dataKeyPropertyCollection = new DataKeyPropertyCollection(); foreach (XElement keyElement in keysElement.Elements("Key")) { XAttribute keyNameAttribute = keyElement.Attribute("name"); XAttribute keyValueAttribute = keyElement.Attribute("value"); if (keyNameAttribute == null || keyValueAttribute == null) { if (keyNameAttribute == null) { validationResult.AddFatal(GetText("DataPackageFragmentUninstaller.MissingAttribute").FormatWith("name"), keyElement); } if (keyValueAttribute == null) { validationResult.AddFatal(GetText("DataPackageFragmentUninstaller.MissingAttribute").FormatWith("value"), keyElement); } allKeyPropertiesValidated = false; continue; } string keyName = keyNameAttribute.Value; PropertyInfo keyPropertyInfo = type.GetPropertiesRecursively().SingleOrDefault(f => f.Name == keyName); if (keyPropertyInfo == null) { validationResult.AddFatal(GetText("DataPackageFragmentUninstaller.MissingKeyProperty").FormatWith(type, keyName)); allKeyPropertiesValidated = false; } else { try { object keyValue = ValueTypeConverter.Convert(keyValueAttribute.Value, keyPropertyInfo.PropertyType); dataKeyPropertyCollection.AddKeyProperty(keyName, keyValue); } catch (Exception) { allKeyPropertiesValidated = false; validationResult.AddFatal(GetText("DataPackageFragmentUninstaller.DataPackageFragmentUninstaller").FormatWith(keyValueAttribute.Value, keyPropertyInfo.PropertyType)); } } } if (allKeyPropertiesValidated) { IData data; using (new DataScope(dataScopeIdentifier, locale)) { data = DataFacade.TryGetDataByUniqueKey(type, dataKeyPropertyCollection); } if (data != null) { CheckForPotentialBrokenReferences(data, validationResult, type, dataScopeIdentifier, locale, dataKeyPropertyCollection); } } } } } if (validationResult.Count > 0) { _dataToDelete = null; } return(validationResult); }
private void CheckForPotentialBrokenReferences(IData data, List <PackageFragmentValidationResult> validationResult, Type type, DataScopeIdentifier dataScopeIdentifier, CultureInfo locale, DataKeyPropertyCollection dataKeyPropertyCollection) { var pagesReferencingPageTypes = new HashSet <string>(); var dataReferencingDataToBeUninstalled = new HashSet <string>(); List <IData> referees = data.GetReferees(); bool addToDelete = true; foreach (IData referee in referees) { if (this.UninstallerContext.IsPendingForDeletionData(referee)) { continue; } addToDelete = false; if (referee is IPage && data is IPageType) { string pathToPage; using (new DataScope(referee.DataSourceId.PublicationScope, referee.DataSourceId.LocaleScope)) { pathToPage = GetPathToPage(referee as IPage); } if (!pagesReferencingPageTypes.Contains(pathToPage)) { validationResult.AddFatal(Texts.DataPackageFragmentUninstaller_PageTypeIsReferenced( data.GetLabel(), pathToPage)); pagesReferencingPageTypes.Add(pathToPage); } } else { var refereeType = referee.DataSourceId.InterfaceType; string label = referee.GetLabel(); string key = label + refereeType.FullName; if (!dataReferencingDataToBeUninstalled.Contains(key)) { validationResult.AddFatal(Texts.DataPackageFragmentUninstaller_DataIsReferenced( data.GetLabel(), type.FullName, label, refereeType.FullName)); dataReferencingDataToBeUninstalled.Add(key); } } } if (addToDelete) { AddDataToDelete(type, dataScopeIdentifier, locale, dataKeyPropertyCollection); } }