Modify package structure and pom file
[vfc/nfvo/driver/ems.git] / ems / boco / src / main / resources / api-doc / lib / shred / content.js
1 /*\r
2  * Copyright (C) 2015 CMCC, Inc. and others. All rights reserved. (CMCC)\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *         http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 // The purpose of the `Content` object is to abstract away the data conversions\r
18 // to and from raw content entities as strings. For example, you want to be able\r
19 // to pass in a Javascript object and have it be automatically converted into a\r
20 // JSON string if the `content-type` is set to a JSON-based media type.\r
21 // Conversely, you want to be able to transparently get back a Javascript object\r
22 // in the response if the `content-type` is a JSON-based media-type.\r
23 \r
24 // One limitation of the current implementation is that it [assumes the `charset` is UTF-8](https://github.com/spire-io/shred/issues/5).\r
25 \r
26 // The `Content` constructor takes an options object, which *must* have either a\r
27 // `body` or `data` property and *may* have a `type` property indicating the\r
28 // media type. If there is no `type` attribute, a default will be inferred.\r
29 var Content = function(options) {\r
30   this.body = options.body;\r
31   this.data = options.data;\r
32   this.type = options.type;\r
33 };\r
34 \r
35 Content.prototype = {\r
36   // Treat `toString()` as asking for the `content.body`. That is, the raw content entity.\r
37   //\r
38   //     toString: function() { return this.body; }\r
39   //\r
40   // Commented out, but I've forgotten why. :/\r
41 };\r
42 \r
43 \r
44 // `Content` objects have the following attributes:\r
45 Object.defineProperties(Content.prototype,{\r
46 \r
47 // - **type**. Typically accessed as `content.type`, reflects the `content-type`\r
48 //   header associated with the request or response. If not passed as an options\r
49 //   to the constructor or set explicitly, it will infer the type the `data`\r
50 //   attribute, if possible, and, failing that, will default to `text/plain`.\r
51   type: {\r
52     get: function() {\r
53       if (this._type) {\r
54         return this._type;\r
55       } else {\r
56         if (this._data) {\r
57           switch(typeof this._data) {\r
58             case "string": return "text/plain";\r
59             case "object": return "application/json";\r
60           }\r
61         }\r
62       }\r
63       return "text/plain";\r
64     },\r
65     set: function(value) {\r
66       this._type = value;\r
67       return this;\r
68     },\r
69     enumerable: true\r
70   },\r
71 \r
72 // - **data**. Typically accessed as `content.data`, reflects the content entity\r
73 //   converted into Javascript data. This can be a string, if the `type` is, say,\r
74 //   `text/plain`, but can also be a Javascript object. The conversion applied is\r
75 //   based on the `processor` attribute. The `data` attribute can also be set\r
76 //   directly, in which case the conversion will be done the other way, to infer\r
77 //   the `body` attribute.\r
78   data: {\r
79     get: function() {\r
80       if (this._body) {\r
81         return this.processor.parser(this._body);\r
82       } else {\r
83         return this._data;\r
84       }\r
85     },\r
86     set: function(data) {\r
87       if (this._body&&data) Errors.setDataWithBody(this);\r
88       this._data = data;\r
89       return this;\r
90     },\r
91     enumerable: true\r
92   },\r
93 \r
94 // - **body**. Typically accessed as `content.body`, reflects the content entity\r
95 //   as a UTF-8 string. It is the mirror of the `data` attribute. If you set the\r
96 //   `data` attribute, the `body` attribute will be inferred and vice-versa. If\r
97 //   you attempt to set both, an exception is raised.\r
98   body: {\r
99     get: function() {\r
100       if (this._data) {\r
101         return this.processor.stringify(this._data);\r
102       } else {\r
103         return this._body.toString();\r
104       }\r
105     },\r
106     set: function(body) {\r
107       if (this._data&&body) Errors.setBodyWithData(this);\r
108       this._body = body;\r
109       return this;\r
110     },\r
111     enumerable: true\r
112   },\r
113 \r
114 // - **processor**. The functions that will be used to convert to/from `data` and\r
115 //   `body` attributes. You can add processors. The two that are built-in are for\r
116 //   `text/plain`, which is basically an identity transformation and\r
117 //   `application/json` and other JSON-based media types (including custom media\r
118 //   types with `+json`). You can add your own processors. See below.\r
119   processor: {\r
120     get: function() {\r
121       var processor = Content.processors[this.type];\r
122       if (processor) {\r
123         return processor;\r
124       } else {\r
125         // Return the first processor that matches any part of the\r
126         // content type. ex: application/vnd.foobar.baz+json will match json.\r
127         var main = this.type.split(";")[0];\r
128         var parts = main.split(/\+|\//);\r
129         for (var i=0, l=parts.length; i < l; i++) {\r
130           processor = Content.processors[parts[i]]\r
131         }\r
132         return processor || {parser:identity,stringify:toString};\r
133       }\r
134     },\r
135     enumerable: true\r
136   },\r
137 \r
138 // - **length**. Typically accessed as `content.length`, returns the length in\r
139 //   bytes of the raw content entity.\r
140   length: {\r
141     get: function() {\r
142       if (typeof Buffer !== 'undefined') {\r
143         return Buffer.byteLength(this.body);\r
144       }\r
145       return this.body.length;\r
146     }\r
147   }\r
148 });\r
149 \r
150 Content.processors = {};\r
151 \r
152 // The `registerProcessor` function allows you to add your own processors to\r
153 // convert content entities. Each processor consists of a Javascript object with\r
154 // two properties:\r
155 // - **parser**. The function used to parse a raw content entity and convert it\r
156 //   into a Javascript data type.\r
157 // - **stringify**. The function used to convert a Javascript data type into a\r
158 //   raw content entity.\r
159 Content.registerProcessor = function(types,processor) {\r
160 \r
161 // You can pass an array of types that will trigger this processor, or just one.\r
162 // We determine the array via duck-typing here.\r
163   if (types.forEach) {\r
164     types.forEach(function(type) {\r
165       Content.processors[type] = processor;\r
166     });\r
167   } else {\r
168     // If you didn't pass an array, we just use what you pass in.\r
169     Content.processors[types] = processor;\r
170   }\r
171 };\r
172 \r
173 // Register the identity processor, which is used for text-based media types.\r
174 var identity = function(x) { return x; }\r
175   , toString = function(x) { return x.toString(); }\r
176 Content.registerProcessor(\r
177   ["text/html","text/plain","text"],\r
178   { parser: identity, stringify: toString });\r
179 \r
180 // Register the JSON processor, which is used for JSON-based media types.\r
181 Content.registerProcessor(\r
182   ["application/json; charset=utf-8","application/json","json"],\r
183   {\r
184     parser: function(string) {\r
185       return JSON.parse(string);\r
186     },\r
187     stringify: function(data) {\r
188       return JSON.stringify(data); }});\r
189 \r
190 var qs = require('querystring');\r
191 // Register the post processor, which is used for JSON-based media types.\r
192 Content.registerProcessor(\r
193   ["application/x-www-form-urlencoded"],\r
194   { parser : qs.parse, stringify : qs.stringify });\r
195 \r
196 // Error functions are defined separately here in an attempt to make the code\r
197 // easier to read.\r
198 var Errors = {\r
199   setDataWithBody: function(object) {\r
200     throw new Error("Attempt to set data attribute of a content object " +\r
201         "when the body attributes was already set.");\r
202   },\r
203   setBodyWithData: function(object) {\r
204     throw new Error("Attempt to set body attribute of a content object " +\r
205         "when the data attributes was already set.");\r
206   }\r
207 }\r
208 module.exports = Content;