Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Metadata / Edm / FacetDescription.cs
blob4a8670c2768dbf4aac5721662ac770bafeada339
1 //---------------------------------------------------------------------
2 // <copyright file="FacetDescription.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 //
6 // @owner Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
10 using System;
11 using System.Collections.Generic;
12 using System.Data.Common;
13 using System.Text;
14 using System.Diagnostics;
15 using System.Threading;
17 namespace System.Data.Metadata.Edm
19 /// <summary>
20 /// Class for representing a FacetDescription object
21 /// </summary>
22 public sealed class FacetDescription
24 #region Constructors
28 internal FacetDescription(string facetName,
29 EdmType facetType,
30 int? minValue,
31 int? maxValue,
32 object defaultValue,
33 bool isConstant,
34 string declaringTypeName)
36 _facetName = facetName;
37 _facetType = facetType;
38 _minValue = minValue;
39 _maxValue = maxValue;
41 // this ctor doesn't allow you to set the defaultValue to null
42 if (defaultValue != null)
44 _defaultValue = defaultValue;
46 else
48 _defaultValue = _notInitializedSentinel;
50 _isConstant = isConstant;
52 Validate(declaringTypeName);
53 if (_isConstant)
55 UpdateMinMaxValueForConstant(_facetName, _facetType, ref _minValue, ref _maxValue, _defaultValue);
59 /// <summary>
60 /// The constructor for constructing a facet description object
61 /// </summary>
62 /// <param name="facetName">The name of this facet</param>
63 /// <param name="facetType">The type of this facet</param>
64 /// <param name="minValue">The min value for this facet</param>
65 /// <param name="maxValue">The max value for this facet</param>
66 /// <param name="defaultValue">The default value for this facet</param>
67 /// <exception cref="System.ArgumentNullException">Thrown if either facetName, facetType or applicableType arguments are null</exception>
68 internal FacetDescription(string facetName,
69 EdmType facetType,
70 int? minValue,
71 int? maxValue,
72 object defaultValue)
74 EntityUtil.CheckStringArgument(facetName, "facetName");
75 EntityUtil.GenericCheckArgumentNull(facetType, "facetType");
77 if (minValue.HasValue || maxValue.HasValue)
79 Debug.Assert(FacetDescription.IsNumericType(facetType), "Min and Max Values can only be specified for numeric facets");
81 if (minValue.HasValue && maxValue.HasValue)
83 Debug.Assert(minValue != maxValue, "minValue should not be equal to maxValue");
87 _facetName = facetName;
88 _facetType = facetType;
89 _minValue = minValue;
90 _maxValue = maxValue;
91 _defaultValue = defaultValue;
94 #endregion
96 #region Fields
97 private readonly string _facetName;
98 private readonly EdmType _facetType;
99 private readonly int? _minValue;
100 private readonly int? _maxValue;
101 private readonly object _defaultValue;
102 private readonly bool _isConstant;
104 /// <summary>A facet with the default value for this description.</summary>
105 private Facet _defaultValueFacet;
107 /// <summary>A facet with a null value for this description.</summary>
108 private Facet _nullValueFacet;
110 /// <summary>Type-dependant cache for additional values (possibly null).</summary>
111 private Facet[] _valueCache;
113 // we need to differentiate when the default value is null vs when the default value is not initialized
114 private static object _notInitializedSentinel = new object();
115 #endregion
117 #region Properties
118 /// <summary>
119 /// Gets the name of this facet
120 /// </summary>
121 public string FacetName
125 return _facetName;
129 /// <summary>
130 /// Gets the type of this facet
131 /// </summary>
132 public EdmType FacetType
136 return _facetType;
140 /// <summary>
141 /// Gets the lower bound a facet with this facet description can take
142 /// </summary>
143 public int? MinValue
147 return _minValue;
151 /// <summary>
152 /// Gets the upper bound a facet with this facet description can take
153 /// </summary>
154 public int? MaxValue
158 return _maxValue;
162 /// <summary>
163 /// Gets the default value of a facet with this facet description
164 /// </summary>
165 public object DefaultValue
169 if (_defaultValue == _notInitializedSentinel)
171 return null;
173 return _defaultValue;
177 /// <summary>
178 /// Gets whether the value of this facet must be constant
179 /// </summary>
180 public bool IsConstant
184 return _isConstant;
188 /// <summary>
189 /// Gets whether this facet is a required facet or not
190 /// </summary>
191 public bool IsRequired
195 return _defaultValue == _notInitializedSentinel;
199 #region Internal properties
201 /// <summary>
202 /// Gets a facet with the default value for this description.
203 /// </summary>
204 internal Facet DefaultValueFacet
208 if (_defaultValueFacet == null)
210 Facet defaultValueFacet = Facet.Create(this, this.DefaultValue, true);
211 Interlocked.CompareExchange(ref _defaultValueFacet, defaultValueFacet, null);
213 return _defaultValueFacet;
217 /// <summary>
218 /// Gets a facet with a null value for this description.
219 /// </summary>
220 internal Facet NullValueFacet
224 if (_nullValueFacet == null)
226 Facet nullValueFacet = Facet.Create(this, null, true);
227 Interlocked.CompareExchange(ref _nullValueFacet, nullValueFacet, null);
229 return _nullValueFacet;
233 #endregion Internal properties
235 #endregion
237 #region Methods
238 /// <summary>
239 /// Overriding System.Object.ToString to provide better String representation
240 /// for this type.
241 /// </summary>
242 public override string ToString()
244 return this.FacetName;
247 /// <summary>
248 /// Gets a cached facet instance with the specified boolean value.
249 /// </summary>
250 /// <param name="value">Value for the Facet result.</param>
251 /// <returns>A cached facet instance with the specified boolean value.</returns>
252 internal Facet GetBooleanFacet(bool value)
254 System.Diagnostics.Debug.Assert(this.FacetType.Identity == "Edm.Boolean");
255 if (_valueCache == null)
257 Facet[] valueCache = new Facet[2];
258 valueCache[0] = Facet.Create(this, true, true);
259 valueCache[1] = Facet.Create(this, false, true);
261 System.Threading.Interlocked.CompareExchange(
262 ref _valueCache,
263 valueCache,
264 null
267 return (value) ? _valueCache[0] : _valueCache[1];
270 /// <summary>
271 /// Returns true if the facet type is of numeric type
272 /// </summary>
273 /// <param name="facetType">Type of the facet</param>
274 /// <returns></returns>
275 internal static bool IsNumericType(EdmType facetType)
277 if (Helper.IsPrimitiveType(facetType))
279 PrimitiveType primitiveType = (PrimitiveType)facetType;
281 return primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Byte ||
282 primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.SByte ||
283 primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Int16 ||
284 primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Int32;
287 return false;
290 private static void UpdateMinMaxValueForConstant(string facetName, EdmType facetType, ref int? minValue, ref int? maxValue, object defaultValue)
292 if (FacetDescription.IsNumericType(facetType))
294 if (facetName == EdmProviderManifest.PrecisionFacetName ||
295 facetName == EdmProviderManifest.ScaleFacetName)
297 minValue = (int?)((byte?)defaultValue);
298 maxValue = (int?)((byte?)defaultValue);
300 else
302 minValue = (int?)defaultValue;
303 maxValue = (int?)defaultValue;
308 private void Validate(string declaringTypeName)
310 if (_defaultValue == _notInitializedSentinel)
312 if (_isConstant)
314 throw EntityUtil.MissingDefaultValueForConstantFacet(_facetName, declaringTypeName);
317 else if (FacetDescription.IsNumericType(_facetType))
319 if (_isConstant)
321 // Either both of them are not specified or both of them have the same value
322 if ((_minValue.HasValue != _maxValue.HasValue) ||
323 (_minValue.HasValue && _minValue.Value != _maxValue.Value))
325 throw EntityUtil.MinAndMaxValueMustBeSameForConstantFacet(_facetName, declaringTypeName);
329 // If its not constant, then both of the minValue and maxValue must be specified
330 else if (!_minValue.HasValue || !_maxValue.HasValue)
332 throw EntityUtil.BothMinAndMaxValueMustBeSpecifiedForNonConstantFacet(_facetName, declaringTypeName);
334 else if (_minValue.Value == _maxValue)
336 throw EntityUtil.MinAndMaxValueMustBeDifferentForNonConstantFacet(_facetName, declaringTypeName);
338 else if (_minValue < 0 || _maxValue < 0)
340 throw EntityUtil.MinAndMaxMustBePositive(_facetName, declaringTypeName);
342 else if (_minValue > _maxValue)
344 throw EntityUtil.MinMustBeLessThanMax(_minValue.ToString(), _facetName, declaringTypeName);
349 #endregion