private static bool IsNullableStringReference(PropertyInfo propertyInfo) { var dataType = propertyInfo.DeclaringType; return(DataAttributeFacade.GetDataReferenceProperties(dataType) .Any(foreignKey => foreignKey.SourcePropertyName == propertyInfo.Name && foreignKey.IsNullableString)); }
private Func <object, string> GetLabelFunction(out bool shouldBeSortedByLabel) { if (this.PropertyInfo.PropertyType == typeof(DateTime)) { shouldBeSortedByLabel = false; return(f => this.DateTimeFormater.FormatLabel(f)); } var referenceProperties = DataAttributeFacade.GetDataReferenceProperties(PropertyInfo.DeclaringType); var referenceInfo = referenceProperties.FirstOrDefault(p => p.SourcePropertyName == this.PropertyInfo.Name); if (referenceInfo == null) { shouldBeSortedByLabel = false; return(f => (f ?? "(NULL)").ToString()); } shouldBeSortedByLabel = true; return(key => { if (key == null) { return "(NULL)"; } IData reference = DataFacade.TryGetDataByUniqueKey(referenceInfo.TargetType, key); return reference != null?reference.GetLabel() : key.ToString(); }); }
private static void AddNewType(Type interfaceType) { var foreignKeyProperties = DataAttributeFacade.GetDataReferenceProperties(interfaceType); foreach (ForeignPropertyInfo foreignKeyPropertyInfo in foreignKeyProperties) { if (!foreignKeyPropertyInfo.SourcePropertyInfo.CanRead) { throw new InvalidOperationException( $"The property '{foreignKeyPropertyInfo.SourcePropertyInfo}' shoud have a getter"); } if (foreignKeyPropertyInfo.TargetType.IsNotReferenceable()) { throw new InvalidOperationException( $"The referenced type '{foreignKeyPropertyInfo.TargetType}' is marked NotReferenceable and can not be referenced by the interfaceType '{interfaceType}'"); } PropertyInfo propertyInfo = foreignKeyPropertyInfo.TargetType.GetDataPropertyRecursively(foreignKeyPropertyInfo.TargetKeyPropertyName); Verify.IsNotNull(propertyInfo, "The data type '{0}' does not contain a property named '{1}' as specified by the '{2}' attribute on the data type '{3}'", foreignKeyPropertyInfo.TargetType, foreignKeyPropertyInfo.TargetKeyPropertyName, typeof(ForeignKeyAttribute), foreignKeyPropertyInfo.SourcePropertyInfo.DeclaringType); Verify.That(propertyInfo.CanRead, "The property '{0}' should have a getter", propertyInfo); if (foreignKeyPropertyInfo.IsNullableString && (propertyInfo.PropertyType != typeof(string))) { throw new InvalidOperationException("NullableString can only be used when the foreign key is of type string"); } Type sourcePropertyType = foreignKeyPropertyInfo.SourcePropertyInfo.PropertyType; if (sourcePropertyType.IsGenericType && (sourcePropertyType.GetGenericTypeDefinition() == typeof(Nullable <>))) { // Handling og Nullable<> sourcePropertyType = sourcePropertyType.GetGenericArguments()[0]; } if (propertyInfo.PropertyType != sourcePropertyType) { throw new InvalidOperationException( $"Type mismatch '{propertyInfo.PropertyType}' and '{foreignKeyPropertyInfo.SourcePropertyInfo.PropertyType}' does not match from the two properties '{propertyInfo}' and '{foreignKeyPropertyInfo.SourcePropertyInfo}'"); } foreignKeyPropertyInfo.TargetKeyPropertyInfo = propertyInfo; } _foreignKeyProperties.Add(interfaceType, foreignKeyProperties); foreach (ForeignPropertyInfo foreignKeyPropertyInfo in foreignKeyProperties) { List <Type> referees; if (!_referencedToReferees.TryGetValue(foreignKeyPropertyInfo.TargetType, out referees)) { referees = new List <Type>(); _referencedToReferees.Add(foreignKeyPropertyInfo.TargetType, referees); } else { if (referees.Contains(interfaceType)) { continue; } } referees.Add(interfaceType); if (!DataProviderRegistry.AllInterfaces.Contains(foreignKeyPropertyInfo.TargetType)) { Log.LogCritical(LogTitle, $"The one type '{interfaceType}' is referring the non supported data type '{foreignKeyPropertyInfo.TargetType}'"); } } }
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)); } }