/// <summary> /// Computes the specified item1. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="item1">The item1.</param> /// <param name="item2">The item2.</param> /// <param name="computeOperator">The compute operator.</param> /// <returns><c>true</c> if compute as true, <c>false</c> otherwise.</returns> private static bool Compute <T>(T item1, T item2, ComputeOperator computeOperator) where T : struct, IComparable { switch (computeOperator) { case ComputeOperator.GreatThan: return(item1.CompareTo(item2) > 0); case ComputeOperator.GreatThanOrEquals: return(item1.CompareTo(item2) >= 0); case ComputeOperator.LessThan: return(item1.CompareTo(item2) < 0); case ComputeOperator.LessThanOrEquals: return(item1.CompareTo(item2) <= 0); case ComputeOperator.NotEquals: return(!item1.Equals(item2)); case ComputeOperator.Equals: return(item1.Equals(item2)); default: throw ExceptionFactory.CreateInvalidObjectException(nameof(computeOperator), new { ComputeOperator = computeOperator.EnumToString(), Type = typeof(T).FullName }); } }
/// <summary> /// Computes as string. /// </summary> /// <param name="item1">The item1.</param> /// <param name="item2">The item2.</param> /// <param name="computeOperator">The compute operator.</param> /// <returns><c>true</c> if compute as true, <c>false</c> otherwise.</returns> private static bool ComputeAsString(string item1, string item2, ComputeOperator computeOperator) { switch (computeOperator) { case ComputeOperator.EndWith: return(!string.IsNullOrEmpty(item1) && !string.IsNullOrEmpty(item2) && item1.EndsWith(item2)); case ComputeOperator.StartWith: return(!string.IsNullOrEmpty(item1) && !string.IsNullOrEmpty(item2) && item1.StartsWith(item2)); case ComputeOperator.Equals: return(!string.IsNullOrEmpty(item1) && !string.IsNullOrEmpty(item2) && item1.Equals(item2)); case ComputeOperator.NotEquals: return(!string.IsNullOrEmpty(item1) && !string.IsNullOrEmpty(item2) && !item1.Equals(item2)); case ComputeOperator.Contains: return(!string.IsNullOrEmpty(item1) && !string.IsNullOrEmpty(item2) && item1.Contains(item2)); case ComputeOperator.NotContains: return(!string.IsNullOrEmpty(item1) && !string.IsNullOrEmpty(item2) && !item1.Contains(item2)); default: throw ExceptionFactory.CreateInvalidObjectException(nameof(computeOperator), new { ComputeOperator = computeOperator.EnumToString() }); } }
/// <summary> /// Creates the push request. /// </summary> /// <param name="request">The request.</param> /// <returns>HttpWebRequest.</returns> protected HttpWebRequest CreatePushRequest(PushMessageRequestV3 request) { HttpWebRequest httpRequest = null; if (request != null) { httpRequest = (HttpWebRequest)HttpWebRequest.Create(apiBaseUrl + "push"); FillAuthenticationV3(httpRequest); var jsonObject = new JObject(); jsonObject.Add(request.Platform.ToJson()); jsonObject.Add(request.Audience.ToJson()); if (request.Notification == null && request.AppMessage == null) { throw ExceptionFactory.CreateInvalidObjectException(nameof(request), reason: "Notification/AppMessage"); } if (request.Notification != null) { jsonObject.Add(new JProperty("notification", JObject.FromObject(request.Notification))); } if (request.AppMessage != null) { jsonObject.Add(new JProperty("message", JObject.FromObject(request.AppMessage))); } jsonObject.Add(new JProperty("options", JObject.FromObject(CreateRequestOptions(request)))); httpRequest.FillData(HttpConstants.HttpMethod.Post, jsonObject.ToString()); } return(httpRequest); }
/// <summary> /// Validates the stamp. /// </summary> /// <returns><c>true</c> if Validation passed, <c>false</c> otherwise.</returns> private static void ValidateStamp(DateTime?stamp) { if (!stamp.HasValue || (Math.Abs((stamp.Value - DateTime.UtcNow).TotalSeconds) > _allowedStampSecondDeviation)) { throw ExceptionFactory.CreateInvalidObjectException(nameof(stamp), stamp, "OverDeviation"); } }
/// <summary> /// Gets the int16. /// </summary> /// <param name="data">The data.</param> /// <returns>Int16.</returns> /// <exception cref="ExceptionSystem.FriendlyHint"></exception> protected Int16 GetInt16(byte[] data) { if (data == null || data.Length < 2) { throw ExceptionFactory.CreateInvalidObjectException(nameof(data), data, hint: new ExceptionSystem.FriendlyHint { Message = "Data too short (2 bytes expected)" }); } return((short)(data[1] << 8 | data[0])); }
/// <summary> /// Gets the int32. /// </summary> /// <param name="data">The data.</param> /// <returns>Int32.</returns> /// <exception cref="ExceptionSystem.FriendlyHint"></exception> protected Int32 GetInt32(byte[] data) { if (data == null || data.Length < 4) { throw ExceptionFactory.CreateInvalidObjectException(nameof(data), data, hint: new ExceptionSystem.FriendlyHint { Message = "Data too short (4 bytes expected)" }); } return(data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]); }
/// <summary> /// Initializes a new instance of the <see cref="TimeBlockSize" /> class. /// </summary> /// <param name="blockMinutes">The minute.</param> /// <exception cref="FriendlyHint"></exception> public TimeBlockSize(int blockMinutes = 5) { if (blockMinutes < 1 || blockMinutes > dayMinutes || dayMinutes % blockMinutes != 0) { throw ExceptionFactory.CreateInvalidObjectException(nameof(blockMinutes), blockMinutes, "OutOfRange", new FriendlyHint { Message = "Value of minute should be between [1, 1440] and integer dividable by 1440." }); } BlockMinutes = blockMinutes; }
/// <summary> /// Computes as object. /// </summary> /// <param name="item1">The item1.</param> /// <param name="item2">The item2.</param> /// <param name="computeOperator">The compute operator.</param> /// <returns><c>true</c> if compute as true, <c>false</c> otherwise.</returns> private static bool ComputeAsObject(JObject item1, string item2, ComputeOperator computeOperator) { switch (computeOperator) { case ComputeOperator.Exists: return(item1 != null && !string.IsNullOrWhiteSpace(item2) && item1.GetProperty(item2) != null); default: throw ExceptionFactory.CreateInvalidObjectException(nameof(computeOperator), new { ComputeOperator = computeOperator.EnumToString() }); } }
/// <summary> /// Checks the type of the class. /// </summary> /// <param name="type">The type.</param> protected void CheckClassType(Type type) { if (type != null) { if (type.IsAbstract) { throw ExceptionFactory.CreateInvalidObjectException(nameof(type), type?.FullName, "NotAllowAbstract"); } if (type.IsGenericType) { throw ExceptionFactory.CreateInvalidObjectException(nameof(type), type?.FullName, "NotAllowGeneric"); } } }
/// <summary> /// Computes as array. /// </summary> /// <param name="item1">The item1.</param> /// <param name="item2">The item2.</param> /// <param name="computeOperator">The compute operator.</param> /// <returns><c>true</c> if compute as true, <c>false</c> otherwise.</returns> private static bool ComputeAsArray(JArray item1, string item2, ComputeOperator computeOperator) { switch (computeOperator) { case ComputeOperator.Contains: return(item1.Contains <JToken, string>(item2, x => x.ToObject <string>(), (x, y) => x.Equals(y, StringComparison.OrdinalIgnoreCase))); case ComputeOperator.NotContains: return(!item1.Contains <JToken, string>(item2, x => x.ToObject <string>(), (x, y) => x.Equals(y, StringComparison.OrdinalIgnoreCase))); default: throw ExceptionFactory.CreateInvalidObjectException(nameof(computeOperator), new { ComputeOperator = computeOperator.EnumToString() }); } }
/// <summary> /// Computes as boolean. /// </summary> /// <param name="item1">if set to <c>true</c> [item1].</param> /// <param name="item2">if set to <c>true</c> [item2].</param> /// <param name="computeOperator">The compute operator.</param> /// <returns><c>true</c> if compute as true, <c>false</c> otherwise.</returns> private static bool ComputeAsBoolean(bool item1, bool item2, ComputeOperator computeOperator) { switch (computeOperator) { case ComputeOperator.Equals: return(item1 == item2); case ComputeOperator.NotEquals: return(item1 != item2); default: throw ExceptionFactory.CreateInvalidObjectException(nameof(computeOperator), new { ComputeOperator = computeOperator.EnumToString() }); } }
/// <summary> /// Initializes the type of the API. /// </summary> /// <param name="doneInterfaceTypes">The done interface types.</param> /// <param name="routes">The routes.</param> /// <param name="interfaceType">Type of the interface.</param> /// <param name="instance">The instance.</param> /// <param name="settings">The settings.</param> /// <param name="parentApiContractAttribute">The parent API class attribute.</param> /// <param name="parentApiModuleAttribute">The parent API module attribute.</param> /// <param name="omitApiTrackingAttribute">The omit API tracking attribute.</param> /// <param name="parentTokenRequiredAttribute">The parent token required attribute.</param> /// <exception cref="DataConflictException">routeKey</exception> private static void InitializeApiType(List <string> doneInterfaceTypes, Dictionary <ApiRouteIdentifier, RuntimeRoute> routes, Type interfaceType, object instance, RestApiSettings settings = null, ApiContractAttribute parentApiContractAttribute = null, ApiModuleAttribute parentApiModuleAttribute = null, OmitApiTrackingAttribute omitApiTrackingAttribute = null, TokenRequiredAttribute parentTokenRequiredAttribute = null) { if (routes != null && interfaceType != null && doneInterfaceTypes != null) { if (doneInterfaceTypes.Contains(interfaceType.FullName)) { return; } var apiContract = parentApiContractAttribute ?? interfaceType.GetCustomAttribute <ApiContractAttribute>(true); var omitApiTracking = omitApiTrackingAttribute ?? interfaceType.GetCustomAttribute <OmitApiTrackingAttribute>(true); var apiModule = parentApiModuleAttribute ?? interfaceType.GetCustomAttribute <ApiModuleAttribute>(true); var tokenRequiredAttribute = parentTokenRequiredAttribute ?? interfaceType.GetCustomAttribute <TokenRequiredAttribute>(true); var moduleName = apiModule?.ToString(); if (apiContract != null && !string.IsNullOrWhiteSpace(apiContract.Version)) { if (apiContract.Version.SafeEquals(ApiConstants.BuiltInFeatureVersionKeyword, StringComparison.OrdinalIgnoreCase)) { throw ExceptionFactory.CreateInvalidObjectException(nameof(apiContract.Version), reason: "<builtin> cannot be used as version due to it is used internally."); } foreach (var method in interfaceType.GetMethods()) { var apiOperationAttribute = method.GetCustomAttribute <ApiOperationAttribute>(true); #region Initialize based on ApiOperation if (apiOperationAttribute != null) { var permissions = new Dictionary <string, ApiPermissionAttribute>(); var additionalHeaderKeys = new HashSet <string>(); var apiPermissionAttributes = method.GetCustomAttributes <ApiPermissionAttribute>(true); var apiCacheAttribute = method.GetCustomAttribute <ApiCacheAttribute>(true); if (apiPermissionAttributes != null) { foreach (var one in apiPermissionAttributes) { permissions.Merge(one.PermissionIdentifier, one); } } var headerKeyAttributes = method.GetCustomAttributes <ApiHeaderAttribute>(true); if (headerKeyAttributes != null) { foreach (var one in headerKeyAttributes) { additionalHeaderKeys.Add(one.HeaderKey); } } var routeKey = ApiRouteIdentifier.FromApiObjects(apiContract, apiOperationAttribute); var tokenRequired = method.GetCustomAttribute <TokenRequiredAttribute>(true) ?? tokenRequiredAttribute; // If method can not support API cache, consider as no api cache. if (apiCacheAttribute != null && (!apiOperationAttribute.HttpMethod.Equals(HttpConstants.HttpMethod.Get, StringComparison.OrdinalIgnoreCase) || !apiCacheAttribute.InitializeParameterNames(method))) { apiCacheAttribute = null; } var runtimeRoute = new RuntimeRoute(routeKey, method, interfaceType, instance, !string.IsNullOrWhiteSpace(apiOperationAttribute.Action), tokenRequired != null && tokenRequired.TokenRequired, moduleName, apiOperationAttribute.ContentType, settings, apiCacheAttribute, omitApiTracking ?? method.GetCustomAttribute <OmitApiTrackingAttribute>(true), permissions, additionalHeaderKeys.ToList()); if (routes.ContainsKey(routeKey)) { throw new DataConflictException(nameof(routeKey), objectIdentity: routeKey?.ToString(), data: new { existed = routes[routeKey].SafeToString(), newMethod = method.GetFullName(), newInterface = interfaceType.FullName }); } // EntitySynchronizationModeAttribute var entitySynchronizationModeAttribute = method.GetCustomAttribute <EntitySynchronizationModeAttribute>(true); if (entitySynchronizationModeAttribute != null) { if (EntitySynchronizationModeAttribute.IsReturnTypeMatched(method.ReturnType)) { runtimeRoute.OperationParameters.EntitySynchronizationMode = entitySynchronizationModeAttribute; } } routes.Add(routeKey, runtimeRoute); } #endregion Initialize based on ApiOperation } foreach (var one in interfaceType.GetInterfaces()) { InitializeApiType(doneInterfaceTypes, routes, one, instance, settings, apiContract, apiModule, omitApiTracking, tokenRequiredAttribute); } //Special NOTE: // Move this add action in scope of if apiContract is valid. // Reason: in complicated cases, when [A:Interface1] without ApiContract, but [Interface2: Interface] with defining ApiContract, and [B: A, Interface2], then correct contract definition might be missed. doneInterfaceTypes.Add(interfaceType.FullName); } } }