1 //---------------------------------------------------------------------
2 // <copyright file="FacetDescription.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
11 using System
.Collections
.Generic
;
12 using System
.Data
.Common
;
14 using System
.Diagnostics
;
15 using System
.Threading
;
17 namespace System
.Data
.Metadata
.Edm
20 /// Class for representing a FacetDescription object
22 public sealed class FacetDescription
28 internal FacetDescription(string facetName
,
34 string declaringTypeName
)
36 _facetName
= facetName
;
37 _facetType
= facetType
;
41 // this ctor doesn't allow you to set the defaultValue to null
42 if (defaultValue
!= null)
44 _defaultValue
= defaultValue
;
48 _defaultValue
= _notInitializedSentinel
;
50 _isConstant
= isConstant
;
52 Validate(declaringTypeName
);
55 UpdateMinMaxValueForConstant(_facetName
, _facetType
, ref _minValue
, ref _maxValue
, _defaultValue
);
60 /// The constructor for constructing a facet description object
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
,
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
;
91 _defaultValue
= defaultValue
;
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();
119 /// Gets the name of this facet
121 public string FacetName
130 /// Gets the type of this facet
132 public EdmType FacetType
141 /// Gets the lower bound a facet with this facet description can take
152 /// Gets the upper bound a facet with this facet description can take
163 /// Gets the default value of a facet with this facet description
165 public object DefaultValue
169 if (_defaultValue
== _notInitializedSentinel
)
173 return _defaultValue
;
178 /// Gets whether the value of this facet must be constant
180 public bool IsConstant
189 /// Gets whether this facet is a required facet or not
191 public bool IsRequired
195 return _defaultValue
== _notInitializedSentinel
;
199 #region Internal properties
202 /// Gets a facet with the default value for this description.
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
;
218 /// Gets a facet with a null value for this description.
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
239 /// Overriding System.Object.ToString to provide better String representation
242 public override string ToString()
244 return this.FacetName
;
248 /// Gets a cached facet instance with the specified boolean value.
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(
267 return (value) ? _valueCache
[0] : _valueCache
[1];
271 /// Returns true if the facet type is of numeric type
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
;
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
);
302 minValue
= (int?)defaultValue
;
303 maxValue
= (int?)defaultValue
;
308 private void Validate(string declaringTypeName
)
310 if (_defaultValue
== _notInitializedSentinel
)
314 throw EntityUtil
.MissingDefaultValueForConstantFacet(_facetName
, declaringTypeName
);
317 else if (FacetDescription
.IsNumericType(_facetType
))
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
);