1 //---------------------------------------------------------------------
2 // <copyright file="EdmProviderManifestFunctionBuilder.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9 
10 using System.Collections.Generic;
11 using System.Diagnostics;
12 using System.Linq;
13 
14 namespace System.Data.Metadata.Edm
15 {
16     internal sealed class EdmProviderManifestFunctionBuilder
17     {
18         private readonly List<EdmFunction> functions = new List<EdmFunction>();
19         private readonly TypeUsage[] primitiveTypes;
20 
EdmProviderManifestFunctionBuilder(System.Collections.ObjectModel.ReadOnlyCollection<PrimitiveType> edmPrimitiveTypes)21         internal EdmProviderManifestFunctionBuilder(System.Collections.ObjectModel.ReadOnlyCollection<PrimitiveType> edmPrimitiveTypes)
22         {
23             Debug.Assert(edmPrimitiveTypes != null, "Primitive types should not be null");
24 
25             // Initialize all the various parameter types. We do not want to create new instance of parameter types
26             // again and again for perf reasons
27             TypeUsage[] primitiveTypeUsages = new TypeUsage[edmPrimitiveTypes.Count];
28             foreach (PrimitiveType edmType in edmPrimitiveTypes)
29             {
30                 Debug.Assert((int)edmType.PrimitiveTypeKind < primitiveTypeUsages.Length && (int)edmType.PrimitiveTypeKind >= 0, "Invalid PrimitiveTypeKind value?");
31                 Debug.Assert(primitiveTypeUsages[(int)edmType.PrimitiveTypeKind] == null, "Duplicate PrimitiveTypeKind value in EDM primitive types?");
32 
33                 primitiveTypeUsages[(int)edmType.PrimitiveTypeKind] = TypeUsage.Create(edmType);
34             }
35 
36             this.primitiveTypes = primitiveTypeUsages;
37         }
38 
ToFunctionCollection()39         internal System.Collections.ObjectModel.ReadOnlyCollection<EdmFunction> ToFunctionCollection()
40         {
41             return this.functions.AsReadOnly();
42         }
43 
ForAllTypes(Action<PrimitiveTypeKind> forEachType)44         internal void ForAllTypes(Action<PrimitiveTypeKind> forEachType)
45         {
46             for (int idx = 0; idx < EdmConstants.NumPrimitiveTypes; idx++)
47             {
48                 forEachType((PrimitiveTypeKind)idx);
49             }
50         }
51 
ForAllBasePrimitiveTypes(Action<PrimitiveTypeKind> forEachType)52         internal void ForAllBasePrimitiveTypes(Action<PrimitiveTypeKind> forEachType)
53         {
54             for (int idx = 0; idx < EdmConstants.NumPrimitiveTypes; idx++)
55             {
56                 PrimitiveTypeKind typeKind = (PrimitiveTypeKind)idx;
57                 if (!Helper.IsStrongSpatialTypeKind(typeKind))
58                 {
59                     forEachType(typeKind);
60                 }
61             }
62         }
63 
ForTypes(IEnumerable<PrimitiveTypeKind> typeKinds, Action<PrimitiveTypeKind> forEachType)64         internal void ForTypes(IEnumerable<PrimitiveTypeKind> typeKinds, Action<PrimitiveTypeKind> forEachType)
65         {
66             foreach (PrimitiveTypeKind kind in typeKinds)
67             {
68                 forEachType(kind);
69             }
70         }
71 
AddAggregate(string aggregateFunctionName, PrimitiveTypeKind collectionArgumentElementTypeKind)72         internal void AddAggregate(string aggregateFunctionName, PrimitiveTypeKind collectionArgumentElementTypeKind)
73         {
74             this.AddAggregate(collectionArgumentElementTypeKind, aggregateFunctionName, collectionArgumentElementTypeKind);
75         }
76 
AddAggregate(PrimitiveTypeKind returnTypeKind, string aggregateFunctionName, PrimitiveTypeKind collectionArgumentElementTypeKind)77         internal void AddAggregate(PrimitiveTypeKind returnTypeKind, string aggregateFunctionName, PrimitiveTypeKind collectionArgumentElementTypeKind)
78         {
79             Debug.Assert(!string.IsNullOrEmpty(aggregateFunctionName) && !string.IsNullOrWhiteSpace(aggregateFunctionName), "Aggregate function name should be valid");
80 
81             FunctionParameter returnParameter = CreateReturnParameter(returnTypeKind);
82             FunctionParameter collectionParameter = CreateAggregateParameter(collectionArgumentElementTypeKind);
83 
84             EdmFunction function = new EdmFunction(aggregateFunctionName,
85                 EdmConstants.EdmNamespace,
86                 DataSpace.CSpace,
87                 new EdmFunctionPayload
88                 {
89                     IsAggregate = true,
90                     IsBuiltIn = true,
91                     ReturnParameters = new FunctionParameter[] {returnParameter},
92                     Parameters = new FunctionParameter[1] { collectionParameter },
93                     IsFromProviderManifest = true,
94                 });
95 
96             function.SetReadOnly();
97 
98             this.functions.Add(function);
99         }
100 
AddFunction(PrimitiveTypeKind returnType, string functionName)101         internal void AddFunction(PrimitiveTypeKind returnType, string functionName)
102         {
103             this.AddFunction(returnType, functionName, new KeyValuePair<string, PrimitiveTypeKind>[] { });
104         }
105 
AddFunction(PrimitiveTypeKind returnType, string functionName, PrimitiveTypeKind argumentTypeKind, string argumentName)106         internal void AddFunction(PrimitiveTypeKind returnType, string functionName, PrimitiveTypeKind argumentTypeKind, string argumentName)
107         {
108             this.AddFunction(returnType, functionName, new[] { new KeyValuePair<string, PrimitiveTypeKind>(argumentName, argumentTypeKind) });
109         }
110 
AddFunction(PrimitiveTypeKind returnType, string functionName, PrimitiveTypeKind argument1TypeKind, string argument1Name, PrimitiveTypeKind argument2TypeKind, string argument2Name)111         internal void AddFunction(PrimitiveTypeKind returnType, string functionName, PrimitiveTypeKind argument1TypeKind, string argument1Name, PrimitiveTypeKind argument2TypeKind, string argument2Name)
112         {
113             this.AddFunction(returnType, functionName,
114                 new[] { new KeyValuePair<string, PrimitiveTypeKind>(argument1Name, argument1TypeKind),
115                         new KeyValuePair<string, PrimitiveTypeKind>(argument2Name, argument2TypeKind)});
116         }
117 
AddFunction(PrimitiveTypeKind returnType, string functionName, PrimitiveTypeKind argument1TypeKind, string argument1Name, PrimitiveTypeKind argument2TypeKind, string argument2Name, PrimitiveTypeKind argument3TypeKind, string argument3Name)118         internal void AddFunction(PrimitiveTypeKind returnType, string functionName, PrimitiveTypeKind argument1TypeKind, string argument1Name, PrimitiveTypeKind argument2TypeKind, string argument2Name, PrimitiveTypeKind argument3TypeKind, string argument3Name)
119         {
120             this.AddFunction(returnType, functionName,
121                 new[] { new KeyValuePair<string, PrimitiveTypeKind>(argument1Name, argument1TypeKind),
122                         new KeyValuePair<string, PrimitiveTypeKind>(argument2Name, argument2TypeKind),
123                         new KeyValuePair<string, PrimitiveTypeKind>(argument3Name, argument3TypeKind)});
124         }
125 
AddFunction(PrimitiveTypeKind returnType, string functionName, PrimitiveTypeKind argument1TypeKind, string argument1Name, PrimitiveTypeKind argument2TypeKind, string argument2Name, PrimitiveTypeKind argument3TypeKind, string argument3Name, PrimitiveTypeKind argument4TypeKind, string argument4Name, PrimitiveTypeKind argument5TypeKind, string argument5Name, PrimitiveTypeKind argument6TypeKind, string argument6Name)126         internal void AddFunction(PrimitiveTypeKind returnType, string functionName, PrimitiveTypeKind argument1TypeKind, string argument1Name,
127                                                                                      PrimitiveTypeKind argument2TypeKind, string argument2Name,
128                                                                                      PrimitiveTypeKind argument3TypeKind, string argument3Name,
129                                                                                      PrimitiveTypeKind argument4TypeKind, string argument4Name,
130                                                                                      PrimitiveTypeKind argument5TypeKind, string argument5Name,
131                                                                                      PrimitiveTypeKind argument6TypeKind, string argument6Name)
132         {
133             this.AddFunction(returnType, functionName,
134                 new[] { new KeyValuePair<string, PrimitiveTypeKind>(argument1Name, argument1TypeKind),
135                         new KeyValuePair<string, PrimitiveTypeKind>(argument2Name, argument2TypeKind),
136                         new KeyValuePair<string, PrimitiveTypeKind>(argument3Name, argument3TypeKind),
137                         new KeyValuePair<string, PrimitiveTypeKind>(argument4Name, argument4TypeKind),
138                         new KeyValuePair<string, PrimitiveTypeKind>(argument5Name, argument5TypeKind),
139                         new KeyValuePair<string, PrimitiveTypeKind>(argument6Name, argument6TypeKind)});
140         }
141 
AddFunction(PrimitiveTypeKind returnType, string functionName, PrimitiveTypeKind argument1TypeKind, string argument1Name, PrimitiveTypeKind argument2TypeKind, string argument2Name, PrimitiveTypeKind argument3TypeKind, string argument3Name, PrimitiveTypeKind argument4TypeKind, string argument4Name, PrimitiveTypeKind argument5TypeKind, string argument5Name, PrimitiveTypeKind argument6TypeKind, string argument6Name, PrimitiveTypeKind argument7TypeKind, string argument7Name)142         internal void AddFunction(PrimitiveTypeKind returnType, string functionName, PrimitiveTypeKind argument1TypeKind, string argument1Name,
143                                                                                      PrimitiveTypeKind argument2TypeKind, string argument2Name,
144                                                                                      PrimitiveTypeKind argument3TypeKind, string argument3Name,
145                                                                                      PrimitiveTypeKind argument4TypeKind, string argument4Name,
146                                                                                      PrimitiveTypeKind argument5TypeKind, string argument5Name,
147                                                                                      PrimitiveTypeKind argument6TypeKind, string argument6Name,
148                                                                                      PrimitiveTypeKind argument7TypeKind, string argument7Name)
149         {
150             this.AddFunction(returnType, functionName,
151                 new[] { new KeyValuePair<string, PrimitiveTypeKind>(argument1Name, argument1TypeKind),
152                         new KeyValuePair<string, PrimitiveTypeKind>(argument2Name, argument2TypeKind),
153                         new KeyValuePair<string, PrimitiveTypeKind>(argument3Name, argument3TypeKind),
154                         new KeyValuePair<string, PrimitiveTypeKind>(argument4Name, argument4TypeKind),
155                         new KeyValuePair<string, PrimitiveTypeKind>(argument5Name, argument5TypeKind),
156                         new KeyValuePair<string, PrimitiveTypeKind>(argument6Name, argument6TypeKind),
157                         new KeyValuePair<string, PrimitiveTypeKind>(argument7Name, argument7TypeKind)});
158         }
159 
AddFunction(PrimitiveTypeKind returnType, string functionName, KeyValuePair<string, PrimitiveTypeKind>[] parameterDefinitions)160         private void AddFunction(PrimitiveTypeKind returnType, string functionName, KeyValuePair<string, PrimitiveTypeKind>[] parameterDefinitions)
161         {
162             FunctionParameter returnParameter = CreateReturnParameter(returnType);
163             FunctionParameter[] parameters = parameterDefinitions.Select(paramDef => CreateParameter(paramDef.Value, paramDef.Key)).ToArray();
164 
165             EdmFunction function = new EdmFunction(functionName,
166                 EdmConstants.EdmNamespace,
167                 DataSpace.CSpace,
168                 new EdmFunctionPayload
169                 {
170                     IsBuiltIn = true,
171                     ReturnParameters = new FunctionParameter[] {returnParameter},
172                     Parameters = parameters,
173                     IsFromProviderManifest = true,
174                 });
175 
176             function.SetReadOnly();
177 
178             this.functions.Add(function);
179         }
180 
CreateParameter(PrimitiveTypeKind primitiveParameterType, string parameterName)181         private FunctionParameter CreateParameter(PrimitiveTypeKind primitiveParameterType, string parameterName)
182         {
183             return new FunctionParameter(parameterName, this.primitiveTypes[(int)primitiveParameterType], ParameterMode.In);
184         }
185 
CreateAggregateParameter(PrimitiveTypeKind collectionParameterTypeElementTypeKind)186         private FunctionParameter CreateAggregateParameter(PrimitiveTypeKind collectionParameterTypeElementTypeKind)
187         {
188             return new FunctionParameter("collection", TypeUsage.Create(this.primitiveTypes[(int)collectionParameterTypeElementTypeKind].EdmType.GetCollectionType()), ParameterMode.In);
189         }
190 
CreateReturnParameter(PrimitiveTypeKind primitiveReturnType)191         private FunctionParameter CreateReturnParameter(PrimitiveTypeKind primitiveReturnType)
192         {
193             return new FunctionParameter(EdmConstants.ReturnType, this.primitiveTypes[(int)primitiveReturnType], ParameterMode.ReturnValue);
194         }
195     }
196 }
197