-
Notifications
You must be signed in to change notification settings - Fork 352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue2467: Support Core.AlternateKeys #2470
Changes from all commits
2986fc5
97064ab
8ba72e2
038ef9c
07e1196
c5a831f
8bffaa3
2aca55d
629d547
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2146,14 +2146,22 @@ public static IEnumerable<IDictionary<string, IEdmProperty>> GetAlternateKeysAnn | |
/// <param name="model">The model to be used.</param> | ||
/// <param name="type">Reference to the calling object.</param> | ||
/// <param name="alternateKey">Dictionary of alias and structural properties for the alternate key.</param> | ||
public static void AddAlternateKeyAnnotation(this EdmModel model, IEdmEntityType type, IDictionary<string, IEdmProperty> alternateKey) | ||
/// <param name="useCore">A flag to indicate which alternate term to use. | ||
/// If ture, 'Org.OData.Core.V1.AlternateKeys' is used, otherwise, 'OData.Community.Keys.V1.AlternateKeys' is used. | ||
/// </param> | ||
public static void AddAlternateKeyAnnotation(this EdmModel model, IEdmEntityType type, IDictionary<string, IEdmProperty> alternateKey, bool useCore = false) | ||
{ | ||
EdmUtil.CheckArgumentNull(model, "model"); | ||
EdmUtil.CheckArgumentNull(type, "type"); | ||
EdmUtil.CheckArgumentNull(alternateKey, "alternateKey"); | ||
|
||
IEdmTerm alternateKeysTerm = useCore ? CoreVocabularyModel.AlternateKeysTerm : AlternateKeysVocabularyModel.AlternateKeysTerm; | ||
|
||
IEdmComplexType propertyRefType = useCore ? CoreVocabularyModel.PropertyRefType : AlternateKeysVocabularyModel.PropertyRefType; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UT and handling of duplicate entries under each annotation namespace? |
||
IEdmComplexType alternateKeyType = useCore ? CoreVocabularyModel.AlternateKeyType : AlternateKeysVocabularyModel.AlternateKeyType; | ||
|
||
EdmCollectionExpression annotationValue = null; | ||
var ann = model.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(type, AlternateKeysVocabularyModel.AlternateKeysTerm).FirstOrDefault(); | ||
var ann = model.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(type, alternateKeysTerm).FirstOrDefault(); | ||
if (ann != null) | ||
{ | ||
annotationValue = ann.Value as EdmCollectionExpression; | ||
|
@@ -2166,21 +2174,21 @@ public static void AddAlternateKeyAnnotation(this EdmModel model, IEdmEntityType | |
foreach (KeyValuePair<string, IEdmProperty> kvp in alternateKey) | ||
{ | ||
IEdmRecordExpression propertyRef = new EdmRecordExpression( | ||
new EdmComplexTypeReference(AlternateKeysVocabularyModel.PropertyRefType, false), | ||
new EdmPropertyConstructor(AlternateKeysVocabularyConstants.PropertyRefTypeAliasPropertyName, new EdmStringConstant(kvp.Key)), | ||
new EdmPropertyConstructor(AlternateKeysVocabularyConstants.PropertyRefTypeNamePropertyName, new EdmPropertyPathExpression(kvp.Value.Name))); | ||
new EdmComplexTypeReference(propertyRefType, false), | ||
new EdmPropertyConstructor("Alias", new EdmStringConstant(kvp.Key)), | ||
new EdmPropertyConstructor("Name", new EdmPropertyPathExpression(kvp.Value.Name))); | ||
propertyRefs.Add(propertyRef); | ||
} | ||
|
||
EdmRecordExpression alternateKeyRecord = new EdmRecordExpression( | ||
new EdmComplexTypeReference(AlternateKeysVocabularyModel.AlternateKeyType, false), | ||
new EdmPropertyConstructor(AlternateKeysVocabularyConstants.AlternateKeyTypeKeyPropertyName, new EdmCollectionExpression(propertyRefs))); | ||
new EdmComplexTypeReference(alternateKeyType, false), | ||
new EdmPropertyConstructor("Key", new EdmCollectionExpression(propertyRefs))); | ||
|
||
alternateKeysCollection.Add(alternateKeyRecord); | ||
|
||
var annotation = new EdmVocabularyAnnotation( | ||
type, | ||
AlternateKeysVocabularyModel.AlternateKeysTerm, | ||
alternateKeysTerm, | ||
new EdmCollectionExpression(alternateKeysCollection)); | ||
|
||
annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline); | ||
|
@@ -3424,42 +3432,56 @@ internal static bool HasAny<T>(this IEnumerable<T> enumerable) where T : class | |
private static IEnumerable<IDictionary<string, IEdmProperty>> GetDeclaredAlternateKeysForType(IEdmEntityType type, IEdmModel model) | ||
{ | ||
IEdmVocabularyAnnotation annotationValue = model.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(type, AlternateKeysVocabularyModel.AlternateKeysTerm).FirstOrDefault(); | ||
IEdmVocabularyAnnotation coreAnnotationValue = model.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(type, CoreVocabularyModel.AlternateKeysTerm).FirstOrDefault(); | ||
|
||
if (annotationValue != null) | ||
if (annotationValue != null || coreAnnotationValue != null) | ||
{ | ||
List<IDictionary<string, IEdmProperty>> declaredAlternateKeys = new List<IDictionary<string, IEdmProperty>>(); | ||
|
||
IEdmCollectionExpression keys = annotationValue.Value as IEdmCollectionExpression; | ||
Debug.Assert(keys != null, "expected IEdmCollectionExpression for alternate key annotation value"); | ||
|
||
foreach (IEdmRecordExpression key in keys.Elements.OfType<IEdmRecordExpression>()) | ||
Action<IEdmVocabularyAnnotation> retrieveAnnotationAction = ann => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Define a private static function rather than this action closure which will incur an extra allocation for each call. |
||
{ | ||
var edmPropertyConstructor = key.Properties.FirstOrDefault(e => e.Name == AlternateKeysVocabularyConstants.AlternateKeyTypeKeyPropertyName); | ||
if (edmPropertyConstructor != null) | ||
if (ann == null) | ||
{ | ||
IEdmCollectionExpression collectionExpression = edmPropertyConstructor.Value as IEdmCollectionExpression; | ||
Debug.Assert(collectionExpression != null, "expected IEdmCollectionExpression type for Key Property"); | ||
|
||
IDictionary<string, IEdmProperty> alternateKey = new Dictionary<string, IEdmProperty>(); | ||
foreach (IEdmRecordExpression propertyRef in collectionExpression.Elements.OfType<IEdmRecordExpression>()) | ||
{ | ||
var aliasProp = propertyRef.Properties.FirstOrDefault(e => e.Name == AlternateKeysVocabularyConstants.PropertyRefTypeAliasPropertyName); | ||
Debug.Assert(aliasProp != null, "expected non null Alias Property"); | ||
string alias = ((IEdmStringConstantExpression)aliasProp.Value).Value; | ||
|
||
var nameProp = propertyRef.Properties.FirstOrDefault(e => e.Name == AlternateKeysVocabularyConstants.PropertyRefTypeNamePropertyName); | ||
Debug.Assert(nameProp != null, "expected non null Name Property"); | ||
string propertyName = ((IEdmPathExpression)nameProp.Value).PathSegments.FirstOrDefault(); | ||
return; | ||
} | ||
|
||
alternateKey[alias] = type.FindProperty(propertyName); | ||
} | ||
IEdmCollectionExpression keys = ann.Value as IEdmCollectionExpression; | ||
Debug.Assert(keys != null, "expected IEdmCollectionExpression for alternate key annotation value"); | ||
|
||
if (alternateKey.Any()) | ||
foreach (IEdmRecordExpression key in keys.Elements.OfType<IEdmRecordExpression>()) | ||
{ | ||
var edmPropertyConstructor = key.Properties.FirstOrDefault(e => e.Name == "Key"); | ||
if (edmPropertyConstructor != null) | ||
{ | ||
declaredAlternateKeys.Add(alternateKey); | ||
IEdmCollectionExpression collectionExpression = edmPropertyConstructor.Value as IEdmCollectionExpression; | ||
Debug.Assert(collectionExpression != null, "expected IEdmCollectionExpression type for Key Property"); | ||
|
||
IDictionary<string, IEdmProperty> alternateKey = new Dictionary<string, IEdmProperty>(); | ||
foreach (IEdmRecordExpression propertyRef in collectionExpression.Elements.OfType<IEdmRecordExpression>()) | ||
{ | ||
var aliasProp = propertyRef.Properties.FirstOrDefault(e => e.Name == "Alias"); | ||
Debug.Assert(aliasProp != null, "expected non null Alias Property"); | ||
string alias = ((IEdmStringConstantExpression)aliasProp.Value).Value; | ||
|
||
var nameProp = propertyRef.Properties.FirstOrDefault(e => e.Name == "Name"); | ||
Debug.Assert(nameProp != null, "expected non null Name Property"); | ||
string propertyName = ((IEdmPathExpression)nameProp.Value).PathSegments.FirstOrDefault(); | ||
|
||
alternateKey[alias] = type.FindProperty(propertyName); | ||
} | ||
|
||
if (alternateKey.Any()) | ||
{ | ||
declaredAlternateKeys.Add(alternateKey); | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
|
||
// For backwards-compability, we merge the alternate keys from community and core vocabulary annotations. | ||
|
||
retrieveAnnotationAction(annotationValue); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The output of
The alternate keys are not "merged" as the comment line 3483 calls out, it's instead an union that occurs. |
||
retrieveAnnotationAction(coreAnnotationValue); | ||
|
||
return declaredAlternateKeys; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo