e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
352 lines
12 KiB
C#
352 lines
12 KiB
C#
//---------------------------------------------------------------------
|
|
// <copyright file="FacetDescription.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//
|
|
// @owner [....]
|
|
// @backupOwner [....]
|
|
//---------------------------------------------------------------------
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data.Common;
|
|
using System.Text;
|
|
using System.Diagnostics;
|
|
using System.Threading;
|
|
|
|
namespace System.Data.Metadata.Edm
|
|
{
|
|
/// <summary>
|
|
/// Class for representing a FacetDescription object
|
|
/// </summary>
|
|
public sealed class FacetDescription
|
|
{
|
|
#region Constructors
|
|
|
|
|
|
|
|
internal FacetDescription(string facetName,
|
|
EdmType facetType,
|
|
int? minValue,
|
|
int? maxValue,
|
|
object defaultValue,
|
|
bool isConstant,
|
|
string declaringTypeName)
|
|
{
|
|
_facetName = facetName;
|
|
_facetType = facetType;
|
|
_minValue = minValue;
|
|
_maxValue = maxValue;
|
|
|
|
// this ctor doesn't allow you to set the defaultValue to null
|
|
if (defaultValue != null)
|
|
{
|
|
_defaultValue = defaultValue;
|
|
}
|
|
else
|
|
{
|
|
_defaultValue = _notInitializedSentinel;
|
|
}
|
|
_isConstant = isConstant;
|
|
|
|
Validate(declaringTypeName);
|
|
if (_isConstant)
|
|
{
|
|
UpdateMinMaxValueForConstant(_facetName, _facetType, ref _minValue, ref _maxValue, _defaultValue);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The constructor for constructing a facet description object
|
|
/// </summary>
|
|
/// <param name="facetName">The name of this facet</param>
|
|
/// <param name="facetType">The type of this facet</param>
|
|
/// <param name="minValue">The min value for this facet</param>
|
|
/// <param name="maxValue">The max value for this facet</param>
|
|
/// <param name="defaultValue">The default value for this facet</param>
|
|
/// <exception cref="System.ArgumentNullException">Thrown if either facetName, facetType or applicableType arguments are null</exception>
|
|
internal FacetDescription(string facetName,
|
|
EdmType facetType,
|
|
int? minValue,
|
|
int? maxValue,
|
|
object defaultValue)
|
|
{
|
|
EntityUtil.CheckStringArgument(facetName, "facetName");
|
|
EntityUtil.GenericCheckArgumentNull(facetType, "facetType");
|
|
|
|
if (minValue.HasValue || maxValue.HasValue)
|
|
{
|
|
Debug.Assert(FacetDescription.IsNumericType(facetType), "Min and Max Values can only be specified for numeric facets");
|
|
|
|
if (minValue.HasValue && maxValue.HasValue)
|
|
{
|
|
Debug.Assert(minValue != maxValue, "minValue should not be equal to maxValue");
|
|
}
|
|
}
|
|
|
|
_facetName = facetName;
|
|
_facetType = facetType;
|
|
_minValue = minValue;
|
|
_maxValue = maxValue;
|
|
_defaultValue = defaultValue;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Fields
|
|
private readonly string _facetName;
|
|
private readonly EdmType _facetType;
|
|
private readonly int? _minValue;
|
|
private readonly int? _maxValue;
|
|
private readonly object _defaultValue;
|
|
private readonly bool _isConstant;
|
|
|
|
/// <summary>A facet with the default value for this description.</summary>
|
|
private Facet _defaultValueFacet;
|
|
|
|
/// <summary>A facet with a null value for this description.</summary>
|
|
private Facet _nullValueFacet;
|
|
|
|
/// <summary>Type-dependant cache for additional values (possibly null).</summary>
|
|
private Facet[] _valueCache;
|
|
|
|
// we need to differentiate when the default value is null vs when the default value is not initialized
|
|
private static object _notInitializedSentinel = new object();
|
|
#endregion
|
|
|
|
#region Properties
|
|
/// <summary>
|
|
/// Gets the name of this facet
|
|
/// </summary>
|
|
public string FacetName
|
|
{
|
|
get
|
|
{
|
|
return _facetName;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the type of this facet
|
|
/// </summary>
|
|
public EdmType FacetType
|
|
{
|
|
get
|
|
{
|
|
return _facetType;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the lower bound a facet with this facet description can take
|
|
/// </summary>
|
|
public int? MinValue
|
|
{
|
|
get
|
|
{
|
|
return _minValue;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the upper bound a facet with this facet description can take
|
|
/// </summary>
|
|
public int? MaxValue
|
|
{
|
|
get
|
|
{
|
|
return _maxValue;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the default value of a facet with this facet description
|
|
/// </summary>
|
|
public object DefaultValue
|
|
{
|
|
get
|
|
{
|
|
if (_defaultValue == _notInitializedSentinel)
|
|
{
|
|
return null;
|
|
}
|
|
return _defaultValue;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets whether the value of this facet must be constant
|
|
/// </summary>
|
|
public bool IsConstant
|
|
{
|
|
get
|
|
{
|
|
return _isConstant;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets whether this facet is a required facet or not
|
|
/// </summary>
|
|
public bool IsRequired
|
|
{
|
|
get
|
|
{
|
|
return _defaultValue == _notInitializedSentinel;
|
|
}
|
|
}
|
|
|
|
#region Internal properties
|
|
|
|
/// <summary>
|
|
/// Gets a facet with the default value for this description.
|
|
/// </summary>
|
|
internal Facet DefaultValueFacet
|
|
{
|
|
get
|
|
{
|
|
if (_defaultValueFacet == null)
|
|
{
|
|
Facet defaultValueFacet = Facet.Create(this, this.DefaultValue, true);
|
|
Interlocked.CompareExchange(ref _defaultValueFacet, defaultValueFacet, null);
|
|
}
|
|
return _defaultValueFacet;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a facet with a null value for this description.
|
|
/// </summary>
|
|
internal Facet NullValueFacet
|
|
{
|
|
get
|
|
{
|
|
if (_nullValueFacet == null)
|
|
{
|
|
Facet nullValueFacet = Facet.Create(this, null, true);
|
|
Interlocked.CompareExchange(ref _nullValueFacet, nullValueFacet, null);
|
|
}
|
|
return _nullValueFacet;
|
|
}
|
|
}
|
|
|
|
#endregion Internal properties
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
/// <summary>
|
|
/// Overriding System.Object.ToString to provide better String representation
|
|
/// for this type.
|
|
/// </summary>
|
|
public override string ToString()
|
|
{
|
|
return this.FacetName;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a cached facet instance with the specified boolean value.
|
|
/// </summary>
|
|
/// <param name="value">Value for the Facet result.</param>
|
|
/// <returns>A cached facet instance with the specified boolean value.</returns>
|
|
internal Facet GetBooleanFacet(bool value)
|
|
{
|
|
System.Diagnostics.Debug.Assert(this.FacetType.Identity == "Edm.Boolean");
|
|
if (_valueCache == null)
|
|
{
|
|
Facet[] valueCache = new Facet[2];
|
|
valueCache[0] = Facet.Create(this, true, true);
|
|
valueCache[1] = Facet.Create(this, false, true);
|
|
|
|
System.Threading.Interlocked.CompareExchange(
|
|
ref _valueCache,
|
|
valueCache,
|
|
null
|
|
);
|
|
}
|
|
return (value) ? _valueCache[0] : _valueCache[1];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if the facet type is of numeric type
|
|
/// </summary>
|
|
/// <param name="facetType">Type of the facet</param>
|
|
/// <returns></returns>
|
|
internal static bool IsNumericType(EdmType facetType)
|
|
{
|
|
if (Helper.IsPrimitiveType(facetType))
|
|
{
|
|
PrimitiveType primitiveType = (PrimitiveType)facetType;
|
|
|
|
return primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Byte ||
|
|
primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.SByte ||
|
|
primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Int16 ||
|
|
primitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Int32;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static void UpdateMinMaxValueForConstant(string facetName, EdmType facetType, ref int? minValue, ref int? maxValue, object defaultValue)
|
|
{
|
|
if (FacetDescription.IsNumericType(facetType))
|
|
{
|
|
if (facetName == EdmProviderManifest.PrecisionFacetName ||
|
|
facetName == EdmProviderManifest.ScaleFacetName)
|
|
{
|
|
minValue = (int?)((byte?)defaultValue);
|
|
maxValue = (int?)((byte?)defaultValue);
|
|
}
|
|
else
|
|
{
|
|
minValue = (int?)defaultValue;
|
|
maxValue = (int?)defaultValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Validate(string declaringTypeName)
|
|
{
|
|
if (_defaultValue == _notInitializedSentinel)
|
|
{
|
|
if (_isConstant)
|
|
{
|
|
throw EntityUtil.MissingDefaultValueForConstantFacet(_facetName, declaringTypeName);
|
|
}
|
|
}
|
|
else if (FacetDescription.IsNumericType(_facetType))
|
|
{
|
|
if (_isConstant)
|
|
{
|
|
// Either both of them are not specified or both of them have the same value
|
|
if ((_minValue.HasValue != _maxValue.HasValue) ||
|
|
(_minValue.HasValue && _minValue.Value != _maxValue.Value))
|
|
{
|
|
throw EntityUtil.MinAndMaxValueMustBeSameForConstantFacet(_facetName, declaringTypeName);
|
|
}
|
|
}
|
|
|
|
// If its not constant, then both of the minValue and maxValue must be specified
|
|
else if (!_minValue.HasValue || !_maxValue.HasValue)
|
|
{
|
|
throw EntityUtil.BothMinAndMaxValueMustBeSpecifiedForNonConstantFacet(_facetName, declaringTypeName);
|
|
}
|
|
else if (_minValue.Value == _maxValue)
|
|
{
|
|
throw EntityUtil.MinAndMaxValueMustBeDifferentForNonConstantFacet(_facetName, declaringTypeName);
|
|
}
|
|
else if (_minValue < 0 || _maxValue < 0)
|
|
{
|
|
throw EntityUtil.MinAndMaxMustBePositive(_facetName, declaringTypeName);
|
|
}
|
|
else if (_minValue > _maxValue)
|
|
{
|
|
throw EntityUtil.MinMustBeLessThanMax(_minValue.ToString(), _facetName, declaringTypeName);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|