http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/code/csdlreader.cs ---------------------------------------------------------------------- diff --git a/JSLib/tests/code/csdlreader.cs b/JSLib/tests/code/csdlreader.cs index 47a331e..253cf10 100644 --- a/JSLib/tests/code/csdlreader.cs +++ b/JSLib/tests/code/csdlreader.cs @@ -14,126 +14,90 @@ namespace DataJS.Tests public static class CsdlReader { - static readonly string knownNamespace = "http://schemas.microsoft.com"; + static readonly string knownNamespace = "http://docs.oasis-open.org"; static readonly string[] repeatingElements = { - "End", - "Property", - "PropertyRef", - "EntitySet", - "AssociationSet", - "FunctionImport", - "NavigationProperty", - "Parameter", - "Using", - "EntityContainer", - "EntityType", - "Association", - "ComplexType", - "Function", - "Schema" + "Action", + "ActionImport", + "Annotation", + "Annotations", + "Apply", + "Binary", + "Bool", + "Cast", + "Collection", + "ComplexType", + "Date", + "DateTimeOffset", + "Decimal", + "Duration", + "EntitySet", + "EntityType", + "EnumMember", + "EnumType", + "Float", + "Function", + "FunctionImport", + "Guid", + "If", + "Int", + "IsOf", + "Key", + "LabeledElement", + "LabeledElementReference", + "Member", + "NavigationProperty", + "NavigationPropertyBinding", + "NavigationPropertyPath", + "Null", + "OnDelete", + "Path", + "Parameter", + "Property", + "PropertyPath", + "PropertyRef", + "PropertyValue", + "Record", + "ReferentialConstraint", + "String", + "Schema", + "Singleton", + "Term", + "TimeOfDay", + "TypeDefinition", + "UrlRef", + "Reference", + "Include", + "IncludeAnnotations" }; - public static JsonObject ReadCsdl(TextReader payload) + public static Dictionary<string, object> ReadCsdl(TextReader payload) { return BuildElementJsonObject(XElement.Load(payload)); } /// <summary> - /// Builds the extensions element object - /// extensions = { - /// name: string, // local name of the custom XML element - /// namespace: string, // namespace URI of the custom XML element - /// value: string, // value of the custom XML element - /// attributes: array, // array of attribute extension objects of the custom XML element - /// children: array // array of element extension objects of the custom XML element }; - /// </summary> - /// <param name="customElement">The custom element to be made into an extension object</param> - /// <returns>the custom element json object</returns> - static JsonObject BuildExtensionsElementObject(XElement customElement) - { - string value; - // customElement.Value contains the value of the element's children, but these are already - // captured in the children propterty. - if (customElement.HasElements) - { - value = null; - } - else - { - if (customElement.Value == "") - { - value = null; - } - else - { - value = customElement.Value; - } - } - - JsonObject jsonObject = BuildBaseExtensionsObject(customElement.Name.LocalName, customElement.Name.Namespace.ToString(), value); - - jsonObject["attributes"] = customElement.Attributes().Select( - attribute => BuildBaseExtensionsObject(attribute.Name.LocalName, attribute.Name.Namespace.ToString(), attribute.Value) - ).ToArray(); - jsonObject["children"] = customElement.Elements().Select(element => BuildExtensionsElementObject(element)).ToArray(); - - return jsonObject; - } - - /// <summary> - /// Creates a generic extension object - /// extensions = { - /// name: string, // local name of the custom XML element or attribute - /// namespace: string, // namespace URI of the custom XML element or attribute - /// value: string, // value of the custom XML element or attribute } - /// </summary> - /// <param name="name">name of the object</param> - /// <param name="objectNamespace">namespace of the obect</param> - /// <param name="value">value of the object</param> - /// <returns></returns> - static JsonObject BuildBaseExtensionsObject(string name, string objectNamespace, string value) - { - JsonObject jsonObject = new JsonObject(); - - jsonObject["name"] = name; - jsonObject["namespace"] = objectNamespace; - jsonObject["value"] = value; - - return jsonObject; - } - - /// <summary> /// Build the attribute object /// </summary> /// <param name="xmlAttributes">IEnumberable of XAttributes to build the attribute object</param> /// <returns>The JsonObject containing the name-value pairs for an element's attributes</returns> - static JsonObject BuildAttributeJsonObject(IEnumerable<XAttribute> xmlAttributes) + static Dictionary<string, object> BuildAttributeJsonObject(IEnumerable<XAttribute> xmlAttributes) { - JsonObject jsonObject = new JsonObject(); - List<JsonObject> extensions = new List<JsonObject>(); + Dictionary<string, object> jsonObject = new Dictionary<string, object>(); foreach (XAttribute attribute in xmlAttributes) { if (!attribute.IsNamespaceDeclaration) { string attributeNamespace = attribute.Name.Namespace.ToString(); - if (string.IsNullOrEmpty(attributeNamespace) || attributeNamespace.StartsWith(knownNamespace, StringComparison.InvariantCultureIgnoreCase)) + if (string.IsNullOrEmpty(attributeNamespace) || + attributeNamespace.StartsWith(knownNamespace, StringComparison.InvariantCultureIgnoreCase)) { jsonObject[MakeFirstLetterLowercase(attribute.Name.LocalName)] = attribute.Value; } - else - { - extensions.Add(BuildBaseExtensionsObject(attribute.Name.LocalName, attribute.Name.Namespace.ToString(), attribute.Value)); - } } } - if (extensions.Count > 0) - { - jsonObject["extensions"] = extensions.ToArray(); - } - return jsonObject; } @@ -143,20 +107,19 @@ namespace DataJS.Tests /// <param name="container">The XML container</param> /// <param name="buildValue">Function that builds a value from a property element</param> /// <returns>The JsonObject containing the name-value pairs</returns> - public static JsonObject BuildElementJsonObject(XElement container) + public static Dictionary<string, object> BuildElementJsonObject(XElement container) { if (container == null) { return null; } - JsonObject jsonObject = new JsonObject(); - List<JsonObject> extensions = new List<JsonObject>(); + Dictionary<string, object> jsonObject = new Dictionary<string, object>(); + string keyName = MakeFirstLetterLowercase(container.Name.LocalName); if (container.HasAttributes || container.HasElements) { - Dictionary<string, List<JsonObject>> repeatingObjectArrays = new Dictionary<string, List<JsonObject>>(); - JsonObject extensionObject = new JsonObject(); + Dictionary<string, List<Dictionary<string, object>>> repeatingObjectArrays = new Dictionary<string, List<Dictionary<string, object>>>(); jsonObject = BuildAttributeJsonObject(container.Attributes()); @@ -173,8 +136,9 @@ namespace DataJS.Tests // See if property was already created as an array, if not then create it if (!repeatingObjectArrays.ContainsKey(propertyName)) { - repeatingObjectArrays.Add(propertyName, new List<JsonObject>()); + repeatingObjectArrays.Add(propertyName, new List<Dictionary<string, object>>()); } + repeatingObjectArrays[propertyName].Add(BuildElementJsonObject(propertyElement)); } else @@ -182,15 +146,6 @@ namespace DataJS.Tests jsonObject[propertyName] = BuildElementJsonObject(propertyElement); } } - else - { - extensions.Add(BuildExtensionsElementObject(propertyElement)); - } - } - - if (extensions.Count > 0) - { - jsonObject["extensions"] = extensions.ToArray(); } foreach (string key in repeatingObjectArrays.Keys)
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/code/jsdate.cs ---------------------------------------------------------------------- diff --git a/JSLib/tests/code/jsdate.cs b/JSLib/tests/code/jsdate.cs index 40996d0..a02c69f 100644 --- a/JSLib/tests/code/jsdate.cs +++ b/JSLib/tests/code/jsdate.cs @@ -16,8 +16,8 @@ namespace DataJS.Tests using System.ServiceModel.Web; using System.Xml; using System.Xml.Linq; - using System.Spatial; - using Microsoft.Data.OData; + using Microsoft.Spatial; + using Microsoft.OData.Core; [Serializable] public class JsDate : JsonObject http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/code/readerutils.cs ---------------------------------------------------------------------- diff --git a/JSLib/tests/code/readerutils.cs b/JSLib/tests/code/readerutils.cs index 35b98ba..284ce04 100644 --- a/JSLib/tests/code/readerutils.cs +++ b/JSLib/tests/code/readerutils.cs @@ -1,4 +1,8 @@ -using System.Net; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Web.Script.Serialization; + namespace DataJS.Tests { public static class ReaderUtils @@ -44,5 +48,21 @@ namespace DataJS.Tests return request; } + public static Stream ConvertDictionarytoJsonlightStream(Dictionary<string, object> dict) + { + MemoryStream stream = new MemoryStream(); + if (dict == null) + { + return stream; + } + + string jsonString = new JavaScriptSerializer().Serialize(dict); + StreamWriter writer = new StreamWriter(stream); + writer.Write(jsonString); + writer.Flush(); + stream.Position = 0; + return stream; + } + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/common/ODataReadOracle.js ---------------------------------------------------------------------- diff --git a/JSLib/tests/common/ODataReadOracle.js b/JSLib/tests/common/ODataReadOracle.js index a0c0bbc..4114745 100644 --- a/JSLib/tests/common/ODataReadOracle.js +++ b/JSLib/tests/common/ODataReadOracle.js @@ -14,7 +14,7 @@ // Client for the odata.read oracle service (function (window, undefined) { - var jsonMime = "application/json;odata=verbose"; + var jsonMime = "application/json"; var universalMime = "*/*"; var atomMime = "application/atom+xml"; @@ -25,9 +25,6 @@ /// <param name="mimeType" type="String">The MIME media type in the Accept header</param> var readMethod = getReadMethod(mimeType, "ReadFeed"); oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, function (data) { - if (!data.results) { - data = { results: data }; - } success(data); }); }; @@ -72,9 +69,6 @@ readJson( url, function (data) { - if (!data.results) { - data = { results: data }; - } success(data); } ); @@ -84,13 +78,7 @@ /// <summary>Calls the ReadMetadata endpoint with the specified URL</summary> /// <param name="url" type="String">The URL to read the metadata from</param> /// <param name="success" type="Function">The success callback function</param> - $.getJSON( - "./common/ODataReadOracle.svc/ReadMetadata?url=" + escape(url), - function (data) { - removeProperty(data.d, "__type"); - success(data.d); - } - ); + oracleRequest("GET", "ReadMetadata", typeof url === "string" ? { url: url} : url, null, null, success); }; var readServiceDocument = function (url, success, mimeType) { @@ -98,20 +86,8 @@ /// <param name="url" type="String">The URL to the service</param> /// <param name="success" type="Function">The success callback function</param> /// <param name="mimeType" type="String">The MIME type being tested</param> - - $.getJSON( - "./common/ODataReadOracle.svc/ReadServiceDocument?url=" + escape(url) + "&mimeType=" + mimeType, - function (data) { - removeProperty(data.d, "__type"); - if (mimeType == jsonMime) { - removeProperty(data.d, "extensions"); - $.each(data.d["workspaces"], function (_, workspace) { - delete workspace["title"]; - }); - } - success(data.d); - } - ); + var readMethod = getReadMethod(mimeType, "ReadServiceDocument"); + oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, null, success); }; var readJson = function (url, success) { @@ -121,43 +97,59 @@ dataType: "json", beforeSend: function (xhr) { xhr.setRequestHeader("Accept", jsonMime); - xhr.setRequestHeader("MaxDataServiceVersion", "3.0"); + xhr.setRequestHeader("OData-MaxVersion", "4.0"); }, success: function (data) { - success(data.d); + success(data); } }); }; var readJsonAcrossServerPages = function (url, success) { - var data = []; + var data = {}; var readPage = function (url) { readJson(url, function (feedData) { - var results = feedData.results || feedData; - var next = feedData.__next; + var nextLink = feedData["@odata.nextLink"]; + if (nextLink) { + var index = url.indexOf(".svc/", 0); + if (index != -1) { + nextLink = url.substring(0, index + 5) + nextLink; + } + } + + if (data.value && feedData.value) { + data.value = data.value.concat(feedData.value); + } + else { + for (var property in feedData) { + if (property != "@odata.nextLink") { + data[property] = feedData[property]; + } + } + } - data = data.concat(results); - if (next) { - readPage(next); - } else { + if (nextLink) { + readPage(nextLink); + } + else { success(data); } }); }; readPage(url); - } + }; var getReadMethod = function (mimeType, defaultEndpoint) { switch (mimeType) { - case universalMime: case atomMime: return defaultEndpoint; case jsonMime: + case universalMime: default: return "ReadJson"; } - } + }; var oracleRequest = function (method, endpoint, data, mimeType, recognizeDates, success) { /// <summary>Requests a JSON object from the oracle service, removing WCF-specific artifacts</summary> @@ -166,17 +158,19 @@ /// <param name="data" type="Object">The data to send with the request</param> /// <param name="reviver" type="Function">The reviver function to run on each deserialized object</param> /// <param name="success" type="Function">Success callback</param> - var reviver = mimeType === jsonMime || mimeType === undefined ? (recognizeDates ? odataDateReviver : undefined) : oracleDateReviver; var url = "./common/ODataReadOracle.svc/" + endpoint; + if (mimeType) { + data.mimeType = mimeType; + } + $.ajax({ type: method, url: url, data: data, dataType: "text", success: function (data) { - var json = JSON.parse(data, reviver); - removeProperty(json.d, "__type"); - success(json.d); + var json = JSON.parse(data); + success(json); } }); }; @@ -194,70 +188,6 @@ removeProperty(data[prop], property); } } - } - - var oracleDateReviver = function (key, value) { - /// <summary>Revives date objects received from the oracle service</summary> - if (value && value["__type"] && value["__type"].search("JsDate") > -1) { - var data = new Date(value.milliseconds); - if (value["__edmType"]) { - data["__edmType"] = value["__edmType"]; - } - - if (value["__offset"]) { - data["__offset"] = value["__offset"]; - } - - return data; - } - - return value; - } - - var odataDateReviver = function (key, value) { - /// <summary>Revives date objects received from OData JSON payloads</summary> - var regexp = /^\/Date\((-?\d+)(\+|-)?(\d+)?\)\/$/; - var matches = regexp.exec(value); - if (matches) { - var milliseconds = parseInt(matches[1], 10); - if (!isNaN(milliseconds)) { - var result = new Date(milliseconds); - if (matches[2]) { - var sign = matches[2]; - var offsetMinutes = parseInt(matches[3], 10); - if (sign === "-") { - offsetMinutes = -offsetMinutes; - } - - result.setUTCMinutes(result.getUTCMinutes() - offsetMinutes); - result["__edmType"] = "Edm.DateTimeOffset"; - result["__offset"] = minutesToOffset(offsetMinutes); - } - return result; - } - } - - return value; - } - - var minutesToOffset = function (minutes) { - var padIfNeeded = function (value) { - var result = value.toString(10); - return result.length < 2 ? "0" + result : result; - }; - - var sign; - if (minutes < 0) { - sign = "-"; - minutes = -minutes; - } else { - sign = "+"; - } - - var hours = Math.floor(minutes / 60); - minutes = minutes - (60 * hours); - - return sign + padIfNeeded(hours) + ":" + padIfNeeded(minutes); }; window.ODataReadOracle = { http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/common/ODataReadOracle.svc ---------------------------------------------------------------------- diff --git a/JSLib/tests/common/ODataReadOracle.svc b/JSLib/tests/common/ODataReadOracle.svc index 32b4d50..51ccd62 100644 --- a/JSLib/tests/common/ODataReadOracle.svc +++ b/JSLib/tests/common/ODataReadOracle.svc @@ -31,8 +31,9 @@ namespace DataJS.Tests using System.ServiceModel.Web; using System.Xml; using System.Xml.Linq; - using System.Spatial; - using Microsoft.Data.OData; + using Microsoft.Spatial; + using Microsoft.OData.Core; + using System.Web.Script.Serialization; /// <summary> /// Oracle for the OData.read library function @@ -42,7 +43,7 @@ namespace DataJS.Tests [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class ODataReadOracle { - const string jsonVerboseMediaType = "application/json;odata=verbose"; + const string jsonlightMediaType = "application/json"; /// <summary> /// Reads a URI that will return an OData ATOM feed @@ -78,13 +79,14 @@ namespace DataJS.Tests /// Reads a URI that will return a metadata object /// </summary> /// <param name="url">The URL to send the request to</param> - /// <returns>JSON object expected to be returned by OData.read (plus type metadata markers that will need to be removed)</returns> + /// <returns>Stream of metadata in json light format</returns> [OperationContract] - [WebGet(ResponseFormat = WebMessageFormat.Json)] - public JsonObject ReadMetadata(string url) + [WebGet] + public Stream ReadMetadata(string url) { WebResponse response = WebRequest.Create(ResolveUri(url, UriKind.Absolute)).GetResponse(); - return CsdlReader.ReadCsdl(new StreamReader(response.GetResponseStream())); + Dictionary<string, object> jsonObject = CsdlReader.ReadCsdl(new StreamReader(response.GetResponseStream())); + return ReaderUtils.ConvertDictionarytoJsonlightStream(jsonObject); } /// <summary> @@ -101,7 +103,7 @@ namespace DataJS.Tests string baseUri = string.Empty; // With JSON responses only relative path passed to the library is available - if (mimeType.Equals(jsonVerboseMediaType)) + if (mimeType.Equals(jsonlightMediaType)) { baseUri = ResolveUri(url, UriKind.Relative).ToString(); } @@ -122,10 +124,15 @@ namespace DataJS.Tests /// <returns>Stream of the Json response expected to be returned by OData.read</returns> [OperationContract] [WebGet(ResponseFormat = WebMessageFormat.Json)] - public Stream ReadJson(string url, string user, string password) + public Stream ReadJson(string url, string mimeType, string user, string password) { + if (mimeType == null) + { + mimeType = jsonlightMediaType + ";odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8"; + } + HttpWebRequest request = (HttpWebRequest)ReaderUtils.CreateRequest(ResolveUri(url, UriKind.Absolute), user, password); - request.Accept = jsonVerboseMediaType + "; charset=utf-8"; + request.Accept = mimeType; WebResponse response = request.GetResponse(); return response.GetResponseStream(); http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/common/djstest.js ---------------------------------------------------------------------- diff --git a/JSLib/tests/common/djstest.js b/JSLib/tests/common/djstest.js index c7b2de5..b9df624 100644 --- a/JSLib/tests/common/djstest.js +++ b/JSLib/tests/common/djstest.js @@ -223,6 +223,15 @@ } }; + djstest.addFullTest = function (disable, fn, name, arg, timeout) { + /// <summary>Add the unit test cases</summary> + /// <param name="disable">Indicate whether this test case should be disabled</param> + if (disable != true) { + djstest.addTest(fn, name, arg, timeout); + } + }; + + djstest.addTest = function (fn, name, arg, timeout) { if (!name) { name = extractFunctionName(fn.toString()); @@ -237,7 +246,7 @@ QUnit.stop(); fn.call(this, arg); }); - } + }; djstest.assert = function (test, message) { /// <summary>Asserts that a condition is true.</summary> http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/endpoints/FoodStoreDataService.svc ---------------------------------------------------------------------- diff --git a/JSLib/tests/endpoints/FoodStoreDataService.svc b/JSLib/tests/endpoints/FoodStoreDataService.svc index 9e7e332..b080e47 100644 --- a/JSLib/tests/endpoints/FoodStoreDataService.svc +++ b/JSLib/tests/endpoints/FoodStoreDataService.svc @@ -1,7 +1,7 @@ <%@ ServiceHost Language="C#" Factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services, Version=5.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Service="DataJS.Tests.V1.FoodStoreDataService" %> -// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Copyright (c) Microsoft. All rights reserved. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/endpoints/FoodStoreDataServiceV2.svc ---------------------------------------------------------------------- diff --git a/JSLib/tests/endpoints/FoodStoreDataServiceV2.svc b/JSLib/tests/endpoints/FoodStoreDataServiceV2.svc index 40ddaa7..bcf00fb 100644 --- a/JSLib/tests/endpoints/FoodStoreDataServiceV2.svc +++ b/JSLib/tests/endpoints/FoodStoreDataServiceV2.svc @@ -1,7 +1,7 @@ <%@ ServiceHost Language="C#" Factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services, Version=5.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Service="DataJS.Tests.V2.FoodStoreDataService" %> -// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Copyright (c) Microsoft. All rights reserved. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/endpoints/FoodStoreDataServiceV3.svc ---------------------------------------------------------------------- diff --git a/JSLib/tests/endpoints/FoodStoreDataServiceV3.svc b/JSLib/tests/endpoints/FoodStoreDataServiceV3.svc index 6ad9671..144c8bd 100644 --- a/JSLib/tests/endpoints/FoodStoreDataServiceV3.svc +++ b/JSLib/tests/endpoints/FoodStoreDataServiceV3.svc @@ -1,7 +1,7 @@ <%@ ServiceHost Language="C#" Factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services, Version=5.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Service="DataJS.Tests.V3.FoodStoreDataService" %> -// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Copyright (c) Microsoft. All rights reserved. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/endpoints/FoodStoreDataServiceV4.svc ---------------------------------------------------------------------- diff --git a/JSLib/tests/endpoints/FoodStoreDataServiceV4.svc b/JSLib/tests/endpoints/FoodStoreDataServiceV4.svc new file mode 100644 index 0000000..21f09cf --- /dev/null +++ b/JSLib/tests/endpoints/FoodStoreDataServiceV4.svc @@ -0,0 +1,589 @@ +<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" + Service="DataJS.Tests.V4.FoodStoreDataService" %> + +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +namespace DataJS.Tests.V4 +{ + using System; + using System.Collections.Generic; + using Microsoft.OData.Service; + using Microsoft.OData.Service.Common; + using Microsoft.OData.Service.Providers; + using System.Linq; + using System.ServiceModel.Web; + using System.Web; + using System.IO; + using Microsoft.Spatial; + + /// <summary> + /// Provides a service similar to FoodStoreDataService, but uses V4 and WCF Data Services 6.0.0-beta1 + /// features. + /// </summary> + [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)] + public class FoodStoreDataService : DataService<FoodContainer> + { + // This method is called only once to initialize service-wide policies. + public static void InitializeService(DataServiceConfiguration config) + { + config.SetEntitySetAccessRule("*", EntitySetRights.All); + config.SetServiceOperationAccessRule("*", ServiceOperationRights.All); + config.UseVerboseErrors = true; + // Set Foods page size to 5 for cache testing + config.SetEntitySetPageSize("Foods", 5); + // Make the Categories set paged to have a paged feed + config.SetEntitySetPageSize("Categories", 1); + } + + [WebInvoke] + public string ResetData() + { + this.CurrentDataSource.ResetData(); + return "Data Reset"; + } + + [WebGet] + public IQueryable<string> FoodsAvailable() + { + return this.CurrentDataSource.Foods.Select(food => food.Name); + } + + [WebGet] + public IQueryable<Package> PackagingTypes() + { + return this.CurrentDataSource.Foods.Select(food => food.Packaging); + } + + [WebGet] + public string UserNameAndPassword() + { + var request = WebOperationContext.Current.IncomingRequest; + string authorization = request.Headers["Authorization"]; + if (String.IsNullOrEmpty(authorization)) + { + WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = "Basic realm=\"localhost\""; + throw new DataServiceException(401, "Access denied in UserNameAndPassword"); + } + + return authorization; + } + } + + public class FoodContainer : ReflectionDataContext, IUpdatable, IDataServiceStreamProvider2 + { + private static bool dataInitialized; + + public IQueryable<Category> Categories + { + get { return this.GetResourceSetEntities<Category>("Categories").AsQueryable(); } + } + + public IQueryable<Food> Foods + { + get { return this.GetResourceSetEntities<Food>("Foods").AsQueryable(); } + } + + public void ResetData() + { + this.ClearData(); + + var builder = SpatialImplementation.CurrentImplementation.CreateBuilder(); + builder.GeometryPipeline.SetCoordinateSystem(CoordinateSystem.DefaultGeography); + builder.GeometryPipeline.BeginGeometry(SpatialType.Collection); + builder.GeometryPipeline.BeginFigure(new GeometryPosition(5.0, 5.0)); + builder.GeometryPipeline.EndFigure(); + builder.GeometryPipeline.EndGeometry(); + + int i = 0; + Category[] categories = new Category[] + { + new Category { CategoryID = i++, Name = "Baking Supplies" }, + new Category { CategoryID = i++, Name = "Condiments" }, + new Category { CategoryID = i++, Name = "Empty Category" } + }; + Array.ForEach(categories, (category) => this.GetResourceSetEntities<Category>("Categories").Add(category)); + + i = 0; + Food[] foods = new Food[] + { + new Food() + { + FoodID = i++, + Name = "flour", + UnitPrice = .19999, + ServingSize = 1, + MeasurementUnit = "Cup", + ProteinGrams = 3, + FatGrams = 1, + CarbohydrateGrams = 20, + CaloriesPerServing = 140, + IsAvailable = true, + ExpirationDate = new DateTime(2010, 12, 25, 12, 0, 0), + ItemGUID = new Guid("27272727272727272727272727272727"), + Weight = 10f, + AvailableUnits = 1, + + Packaging = new Package(){ + Type = null, + Color = String.Empty, + NumberPerPackage = int.MaxValue, + RequiresRefridgeration = false, + PackageDimensions = new Dimensions() + { + Length = Decimal.MaxValue, + Height = Int16.MaxValue, + Width = Int64.MaxValue, + Volume = double.MaxValue, + }, + ShipDate = new DateTime(2000, 12, 29) + }, + + CookedSize = new CookedDimensions() + { + Height = 1, + Length = 2, + Width = 3, + Volume = 1 * 2 * 3 + }, + + Category = categories[0], + + AlternativeNames = new List<string>() {"ground cereal", "ground grain"}, + + Providers = new List<Provider> { + new Provider() { + Name= "Flour Provider", + Aliases = new List<string>() {"fp1", "flour provider1"}, + Details = new ProviderDetails() { + Telephone= "555-555-555", + PreferredCode = 1001 + } + }, + new Provider() { + Name= "Ground Grains", + Aliases = new List<string>() + } + }, + + SpatialData = (GeometryCollection)builder.ConstructedGeometry + }, + + new Food() + { + FoodID = i++, + Name = "sugar", + UnitPrice = .2, + ServingSize = 1, + MeasurementUnit = "tsp", + ProteinGrams = 0, + FatGrams = 0, + CarbohydrateGrams = 4, + CaloriesPerServing = 16, + IsAvailable = false, + ExpirationDate = new DateTime(2011, 12, 28), + ItemGUID = new Guid("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), + Weight = 0.1f, + AvailableUnits = 0, + + Packaging = new Package(){ + Type = " ", + Color = "BLUE", + NumberPerPackage = int.MinValue, + RequiresRefridgeration = true, + PackageDimensions = new Dimensions(){ + Length = Decimal.MinValue, + Height = Int16.MinValue, + Width = Int64.MinValue, + Volume = double.MinValue, + }, + ShipDate = new DateTime(2000, 12, 29), + }, + + Category = categories[1], + }, + + new Food() + { + FoodID = i++, + Name = "1 Chicken Egg", + UnitPrice = 0.55, + MeasurementUnit = null, + ServingSize = 1, + ProteinGrams = 6, + FatGrams = 1, + CarbohydrateGrams = 1, + CaloriesPerServing = 70, + IsAvailable = true, + ExpirationDate = new DateTime(2000, 12, 29), + ItemGUID = new Guid("00000000000000000000000000000000"), + Weight = 0, + AvailableUnits = -128, + + Packaging = new Package(){ + Type = "18 - Carton", + Color = " brown ", + NumberPerPackage = 0, + RequiresRefridgeration = true, + PackageDimensions = null, + ShipDate = new DateTime(2000, 12, 29), + }, + + Category = null, + }, + + new Food() + { + FoodID = i++, + Name = "Brown Sugar", + UnitPrice = 1.6, + ServingSize = 1, + MeasurementUnit = "TSP.", + ProteinGrams = 0, + FatGrams = 0, + CarbohydrateGrams = 5, + CaloriesPerServing = 16, + IsAvailable = true, + ExpirationDate = new DateTime(2011, 12, 28), + ItemGUID = new Guid("0123456789abcdef0123456789abcdef"), + Weight = 4.5f, + AvailableUnits = 127, + Packaging = null, + Category = categories[1], + }, + + new PreparedFood() + { + FoodID = i++, + Name = "Cobb Salad", + UnitPrice = 1.99, + ServingSize = -1, + MeasurementUnit = "cups", + ProteinGrams = 6, + FatGrams = 1, + CarbohydrateGrams = 3, + CaloriesPerServing = 5, + IsAvailable = true, + ExpirationDate = new DateTime(2000, 12, 29), + ItemGUID = new Guid("0123456789abcdef0123456789abcdef"), + Weight = 5.674f, + AvailableUnits = 127, + Packaging = null, + Category = categories[1], + Instructions = "1.) Open 2.) Eat", + NumberOfIngredients = 4, + }, + + new PreparedFood() + { + FoodID = i++, + Name = "Lasagna", + UnitPrice = 0, + ServingSize = 8, + MeasurementUnit = " servings", + ProteinGrams = 100, + FatGrams = 4, + CarbohydrateGrams = 27, + CaloriesPerServing = 389, + IsAvailable = true, + ExpirationDate = new DateTime(1904, 2, 29), + ItemGUID = new Guid("0123456789abcdef0123456789abcdef"), + Weight = 0, + AvailableUnits = 4, + Packaging = new Package(){ + Type = "box", + Color = " 1 ", + NumberPerPackage = 1, + RequiresRefridgeration = true, + PackageDimensions = new Dimensions(){ + Length = 3, + Height = 1, + Width = 5, + Volume = 1.5, + }, + ShipDate = new DateTime(2000, 12, 29), + }, + Category = categories[0], + Instructions = "Bake in oven", + NumberOfIngredients = 15, + }, + + new Food() + { + FoodID = i++, + Name = "Chocolate" + }, + + new Food() + { + FoodID = i++, + Name = "Pizza" + }, + + new Food() + { + FoodID = i++, + Name = "Avocados" + }, + + new Food() + { + FoodID = i++, + Name = "Quinoa" + }, + + new Food() + { + FoodID = i++, + Name = "Oatmeal" + }, + + new Food() + { + FoodID = i++, + Name = "Peanut Butter" + }, + + new Food() + { + FoodID = i++, + Name = "Banana" + }, + + new Food() + { + FoodID = i++, + Name = "Yam" + }, + + new Food() + { + FoodID = i++, + Name = "Clam" + }, + + new Food() + { + FoodID = i++, + Name = "Spam" + } + }; + Array.ForEach(foods, (food) => this.GetResourceSetEntities<Food>("Foods").Add(food)); + + categories[0].Foods.Add(foods[0]); + categories[1].Foods.Add(foods[2]); + categories[1].Foods.Add(foods[3]); + } + + protected override void EnsureDataIsInitialized() + { + if (!dataInitialized) + { + this.ResetData(); + dataInitialized = true; + } + } + + public Stream GetReadStream(object entity, ResourceProperty streamProperty, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext) + { + return new MemoryStream(); + } + + public Uri GetReadStreamUri(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext) + { + if (streamProperty.Name == "Icon") + { + return null; + } + return new Uri(operationContext.AbsoluteServiceUri, streamProperty.Name); + } + + public string GetStreamContentType(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext) + { + if (streamProperty.Name == "Icon") + { + return "image/gif"; + } + return "image/png"; + } + + public string GetStreamETag(object entity, ResourceProperty streamProperty, DataServiceOperationContext operationContext) + { + return "W/\"123456789\""; + } + + public Stream GetWriteStream(object entity, ResourceProperty streamProperty, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext) + { + return new MemoryStream(); + } + + public void DeleteStream(object entity, DataServiceOperationContext operationContext) + { + // do nothing. + } + + public Stream GetReadStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext) + { + throw new NotImplementedException(); + } + + public Uri GetReadStreamUri(object entity, DataServiceOperationContext operationContext) + { + throw new NotImplementedException(); + } + + public string GetStreamContentType(object entity, DataServiceOperationContext operationContext) + { + throw new NotImplementedException(); + } + + public string GetStreamETag(object entity, DataServiceOperationContext operationContext) + { + throw new NotImplementedException(); + } + + public Stream GetWriteStream(object entity, string etag, bool? checkETagForEquality, DataServiceOperationContext operationContext) + { + throw new NotImplementedException(); + } + + public string ResolveType(string entitySetName, DataServiceOperationContext operationContext) + { + throw new NotImplementedException(); + } + + public int StreamBufferSize + { + get { return 1024; } + } + } + + /// <summary> + /// The Category class is a simple class with V1-compatible feed customizations. + /// </summary> + [DataServiceKey("CategoryID")] + [EntitySet("Categories")] + [NamedStream("Icon")] + public class Category + { + public Category() + { + this.Foods = new List<Food>(); + } + + public int CategoryID { get; set; } + public string Name { get; set; } + public List<Food> Foods { get; set; } + } + + /// <summary> + /// The Food class has a mixture of V1-compatible and incompatible feed + /// customizations (thus it's V2), and custom mappings. + /// </summary> + [DataServiceKey("FoodID")] + [EntitySet("Foods")] + [NamedStream("Picture")] + public class Food + { + private List<string> alternativeNames = new List<string>(); + private List<Provider> providers = new List<Provider>(); + + // Primitive types + public int FoodID { get; set; } + public string Name { get; set; } + public double UnitPrice { get; set; } + public Decimal ServingSize { get; set; } + public string MeasurementUnit { get; set; } + public Byte ProteinGrams { get; set; } + public Int16 FatGrams { get; set; } + public Int32 CarbohydrateGrams { get; set; } + public Int64 CaloriesPerServing { get; set; } + public Boolean IsAvailable { get; set; } + public DateTime ExpirationDate { get; set; } + public Guid ItemGUID { get; set; } + public Single Weight { get; set; } + public sbyte AvailableUnits { get; set; } + + // Complex types + public Package Packaging { get; set; } + public CookedDimensions CookedSize { get; set; } + + // Navigation properties + public Category Category { get; set; } + + // Collection properties + public List<string> AlternativeNames + { + get { return alternativeNames; } + set { alternativeNames = value; } + } + + public List<Provider> Providers + { + get { return providers; } + set { providers = value; } + } + + public GeometryCollection SpatialData + { + get; + set; + } + + } + + public class Provider + { + public string Name { get; set; } + public List<string> Aliases { get; set; } + public ProviderDetails Details { get; set; } + } + + public class ProviderDetails + { + public string Telephone { get; set; } + public int PreferredCode { get; set; } + } + + public class Package + { + public string Type { get; set; } + public string Color { get; set; } + public int NumberPerPackage { get; set; } + public Boolean RequiresRefridgeration { get; set; } + public DateTime ShipDate { get; set; } + public Dimensions PackageDimensions { get; set; } + } + + public class Dimensions + { + public Decimal Length { get; set; } + public Int16 Height { get; set; } + public Int64 Width { get; set; } + public double Volume { get; set; } + } + + public class CookedDimensions + { + public Decimal Length { get; set; } + public Int16 Height { get; set; } + public Int64 Width { get; set; } + public double Volume { get; set; } + } + + public class PreparedFood : Food + { + public string Instructions { get; set; } + public float NumberOfIngredients { get; set; } + } +} http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/9d81e7e3/JSLib/tests/endpoints/web.config ---------------------------------------------------------------------- diff --git a/JSLib/tests/endpoints/web.config b/JSLib/tests/endpoints/web.config index 4875aa4..5836287 100644 --- a/JSLib/tests/endpoints/web.config +++ b/JSLib/tests/endpoints/web.config @@ -10,10 +10,9 @@ <add assembly='System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/> <add assembly='System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089'/> <add assembly='System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35'/> - - <add assembly='Microsoft.Data.OData, Version=5.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35'/> - <add assembly='Microsoft.Data.Services, Version=5.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35'/> - <add assembly='Microsoft.Data.Services.Client, Version=5.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35'/> + <add assembly="Microsoft.OData.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> + <add assembly="Microsoft.OData.Service, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> + <add assembly="Microsoft.OData.Client, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </assemblies> </compilation> </system.web>
