Add wso2bpel-ext code
[vfc/nfvo/wfengine.git] / wso2bpel-ext / wso2bpel-core / wso2bpel-mgr / src / main / resources / api-doc / lib / swagger-client.js
1 /**
2  * swagger-client - swagger.js is a javascript client for use with swaggering APIs.
3  * @version v2.1.9-M1
4  * @link http://swagger.io
5  * @license apache 2.0
6  */
7 (function(){
8 var ArrayModel = function(definition) {
9   this.name = "arrayModel";
10   this.definition = definition || {};
11   this.properties = [];
12   
13   var requiredFields = definition.enum || [];
14   var innerType = definition.items;
15   if(innerType) {
16     if(innerType.type) {
17       this.type = typeFromJsonSchema(innerType.type, innerType.format);
18     }
19     else {
20       this.ref = innerType.$ref;
21     }
22   }
23   return this;
24 };
25
26 ArrayModel.prototype.createJSONSample = function(modelsToIgnore) {
27   var result;
28   modelsToIgnore = (modelsToIgnore||{});
29   if(this.type) {
30     result = this.type;
31   }
32   else if (this.ref) {
33     var name = simpleRef(this.ref);
34     if(typeof modelsToIgnore[name] === 'undefined') {
35       modelsToIgnore[name] = this;
36       result = models[name].createJSONSample(modelsToIgnore);
37     }
38     else {
39       return name;
40     }
41   }
42   return [ result ];
43 };
44
45 ArrayModel.prototype.getSampleValue = function(modelsToIgnore) {
46   var result;
47   modelsToIgnore = (modelsToIgnore || {});
48   if(this.type) {
49     result = type;
50   }
51   else if (this.ref) {
52     var name = simpleRef(this.ref);
53     result = models[name].getSampleValue(modelsToIgnore);
54   }
55   return [ result ];
56 };
57
58 ArrayModel.prototype.getMockSignature = function(modelsToIgnore) {
59   var propertiesStr = [];
60   var i, prop;
61   for (i = 0; i < this.properties.length; i++) {
62     prop = this.properties[i];
63     propertiesStr.push(prop.toString());
64   }
65
66   var strong = '<span class="strong">';
67   var stronger = '<span class="stronger">';
68   var strongClose = '</span>';
69   var classOpen = strong + 'array' + ' {' + strongClose;
70   var classClose = strong + '}' + strongClose;
71   var returnVal = classOpen + '<div>' + propertiesStr.join(',</div><div>') + '</div>' + classClose;
72
73   if (!modelsToIgnore)
74     modelsToIgnore = {};
75   modelsToIgnore[this.name] = this;
76   for (i = 0; i < this.properties.length; i++) {
77     prop = this.properties[i];
78     var ref = prop.$ref;
79     var model = models[ref];
80     if (model && typeof modelsToIgnore[ref] === 'undefined') {
81       returnVal = returnVal + ('<br>' + model.getMockSignature(modelsToIgnore));
82     }
83   }
84   return returnVal;
85 };
86
87
88 /**
89  * SwaggerAuthorizations applys the correct authorization to an operation being executed
90  */
91 var SwaggerAuthorizations = function() {
92   this.authz = {};
93 };
94
95 SwaggerAuthorizations.prototype.add = function(name, auth) {
96   this.authz[name] = auth;
97   return auth;
98 };
99
100 SwaggerAuthorizations.prototype.remove = function(name) {
101   return delete this.authz[name];
102 };
103
104 SwaggerAuthorizations.prototype.apply = function (obj, authorizations) {
105   var status = null;
106   var key, name, value, result;
107
108   // if the "authorizations" key is undefined, or has an empty array, add all keys
109   if (typeof authorizations === 'undefined' || Object.keys(authorizations).length === 0) {
110     for (key in this.authz) {
111       value = this.authz[key];
112       result = value.apply(obj, authorizations);
113       if (result === true)
114         status = true;
115     }
116   }
117   else {
118     // 2.0 support
119     if (Array.isArray(authorizations)) {
120
121       for (var i = 0; i < authorizations.length; i++) {
122         var auth = authorizations[i];
123         for (name in auth) {
124           for (key in this.authz) {
125             if (key == name) {
126               value = this.authz[key];
127               result = value.apply(obj, authorizations);
128               if (result === true)
129                 status = true;
130             }
131           }
132         }
133       }
134     }
135     else {
136       // 1.2 support
137       for (name in authorizations) {
138         for (key in this.authz) {
139           if (key == name) {
140             value = this.authz[key];
141             result = value.apply(obj, authorizations);
142             if (result === true)
143               status = true;
144           }
145         }
146       }
147     }
148   }
149
150   return status;
151 };
152
153 /**
154  * ApiKeyAuthorization allows a query param or header to be injected
155  */
156 var ApiKeyAuthorization = function(name, value, type) {
157   this.name = name;
158   this.value = value;
159   this.type = type;
160 };
161
162 ApiKeyAuthorization.prototype.apply = function(obj, authorizations) {
163   if (this.type === "query") {
164     if (obj.url.indexOf('?') > 0)
165       obj.url = obj.url + "&" + this.name + "=" + this.value;
166     else
167       obj.url = obj.url + "?" + this.name + "=" + this.value;
168     return true;
169   } else if (this.type === "header") {
170     obj.headers[this.name] = this.value;
171     return true;
172   }
173 };
174
175 var CookieAuthorization = function(cookie) {
176   this.cookie = cookie;
177 };
178
179 CookieAuthorization.prototype.apply = function(obj, authorizations) {
180   obj.cookieJar = obj.cookieJar || CookieJar();
181   obj.cookieJar.setCookie(this.cookie);
182   return true;
183 };
184
185 /**
186  * Password Authorization is a basic auth implementation
187  */
188 var PasswordAuthorization = function(name, username, password) {
189   this.name = name;
190   this.username = username;
191   this.password = password;
192   this._btoa = null;
193   if (typeof window !== 'undefined')
194     this._btoa = btoa;
195   else
196     this._btoa = require("btoa");
197 };
198
199 PasswordAuthorization.prototype.apply = function(obj, authorizations) {
200   var base64encoder = this._btoa;
201   obj.headers.Authorization = "Basic " + base64encoder(this.username + ":" + this.password);
202   return true;
203 };
204 var __bind = function(fn, me){
205   return function(){
206     return fn.apply(me, arguments);
207   };
208 };
209
210 fail = function(message) {
211   log(message);
212 };
213
214 log = function(){
215   log.history = log.history || [];
216   log.history.push(arguments);
217   if(this.console){
218     console.log( Array.prototype.slice.call(arguments)[0] );
219   }
220 };
221
222 if (!Array.prototype.indexOf) {
223   Array.prototype.indexOf = function(obj, start) {
224     for (var i = (start || 0), j = this.length; i < j; i++) {
225       if (this[i] === obj) { return i; }
226     }
227     return -1;
228   };
229 }
230
231 /**
232  * allows override of the default value based on the parameter being
233  * supplied
234  **/
235 var applyParameterMacro = function (operation, parameter) {
236   var e = (typeof window !== 'undefined' ? window : exports);
237   if(e.parameterMacro)
238     return e.parameterMacro(operation, parameter);
239   else
240     return parameter.defaultValue;
241 };
242
243 /**
244  * allows overriding the default value of an model property
245  **/
246 var applyModelPropertyMacro = function (model, property) {
247   var e = (typeof window !== 'undefined' ? window : exports);
248   if(e.modelPropertyMacro)
249     return e.modelPropertyMacro(model, property);
250   else
251     return property.defaultValue;
252 };
253
254 /**
255  * PrimitiveModel
256  **/
257 var PrimitiveModel = function(definition) {
258   this.name = "name";
259   this.definition = definition || {};
260   this.properties = [];
261
262   var requiredFields = definition.enum || [];
263   this.type = typeFromJsonSchema(definition.type, definition.format);
264 };
265
266 PrimitiveModel.prototype.createJSONSample = function(modelsToIgnore) {
267   var result = this.type;
268   return result;
269 };
270
271 PrimitiveModel.prototype.getSampleValue = function() {
272   var result = this.type;
273   return null;
274 };
275
276 PrimitiveModel.prototype.getMockSignature = function(modelsToIgnore) {
277   var propertiesStr = [];
278   var i, prop;
279   for (i = 0; i < this.properties.length; i++) {
280     prop = this.properties[i];
281     propertiesStr.push(prop.toString());
282   }
283
284   var strong = '<span class="strong">';
285   var stronger = '<span class="stronger">';
286   var strongClose = '</span>';
287   var classOpen = strong + this.name + ' {' + strongClose;
288   var classClose = strong + '}' + strongClose;
289   var returnVal = classOpen + '<div>' + propertiesStr.join(',</div><div>') + '</div>' + classClose;
290
291   if (!modelsToIgnore)
292     modelsToIgnore = {};
293   modelsToIgnore[this.name] = this;
294   for (i = 0; i < this.properties.length; i++) {
295     prop = this.properties[i];
296     var ref = prop.$ref;
297     var model = models[ref];
298     if (model && typeof modelsToIgnore[ref] === 'undefined') {
299       returnVal = returnVal + ('<br>' + model.getMockSignature(modelsToIgnore));
300     }
301   }
302   return returnVal;
303 };
304 /** 
305  * Resolves a spec's remote references
306  */
307 var Resolver = function (){};
308
309 Resolver.prototype.resolve = function(spec, callback, scope) {
310   this.scope = (scope || this);
311   var host, name, path, property, propertyName, type;
312   var processedCalls = 0, resolvedRefs = {}, unresolvedRefs = {};
313
314   // store objects for dereferencing
315   var resolutionTable = {};
316
317   // models
318   for(name in spec.definitions) {
319     var model = spec.definitions[name];
320     for(propertyName in model.properties) {
321       property = model.properties[propertyName];
322       this.resolveTo(property, resolutionTable);
323     }
324   }
325   // operations
326   for(name in spec.paths) {
327     var method, operation, responseCode;
328     path = spec.paths[name];
329     for(method in path) {
330       operation = path[method];
331       var i, parameters = operation.parameters;
332       for(i in parameters) {
333         var parameter = parameters[i];
334         if(parameter.in === 'body' && parameter.schema) {
335           this.resolveTo(parameter.schema, resolutionTable);
336         }
337         if(parameter.$ref) {
338           this.resolveInline(spec, parameter, resolutionTable, unresolvedRefs);
339         }
340       }
341       for(responseCode in operation.responses) {
342         var response = operation.responses[responseCode];
343         if(response.schema) {
344           this.resolveTo(response.schema, resolutionTable);
345         }
346       }
347     }
348   }
349   // get hosts
350   var opts = {}, expectedCalls = 0;
351   for(name in resolutionTable) {
352     var parts = name.split('#');
353     if(parts.length == 2) {
354       host = parts[0]; path = parts[1];
355       if(!Array.isArray(opts[host])) {
356         opts[host] = [];
357         expectedCalls += 1;
358       }
359       opts[host].push(path);
360     }
361   }
362
363   for(name in opts) {
364     var self = this, opt = opts[name];
365     host = name;
366
367     var obj = {
368       useJQuery: false,  // TODO
369       url: host,
370       method: "get",
371       headers: {
372         accept: this.scope.swaggerRequestHeaders || 'application/json'
373       },
374       on: {
375         error: function(response) {
376           processedCalls += 1;
377           var i;
378           for(i = 0; i < opt.length; i++) {
379             // fail all of these
380             var resolved = host + '#' + opt[i];
381             unresolvedRefs[resolved] = null;
382           }
383           if(processedCalls === expectedCalls)
384             self.finish(spec, resolutionTable, resolvedRefs, unresolvedRefs, callback);
385         },
386         response: function(response) {
387           var i, j, swagger = response.obj;
388           processedCalls += 1;
389           for(i = 0; i < opt.length; i++) {
390             var location = swagger, path = opt[i], parts = path.split('/');
391             for(j = 0; j < parts.length; j++) {
392               var segment = parts[j];
393               if(typeof location === 'undefined')
394                 break;
395               if(segment.length > 0)
396                 location = location[segment];
397             }
398             var resolved = host + '#' + path, resolvedName = parts[j-1];
399             if(typeof location !== 'undefined') {
400               resolvedRefs[resolved] = {
401                 name: resolvedName,
402                 obj: location
403               };
404             }
405             else unresolvedRefs[resolved] = null;
406           }
407           if(processedCalls === expectedCalls)
408             self.finish(spec, resolutionTable, resolvedRefs, unresolvedRefs, callback);
409         }
410       }
411     };
412     authorizations.apply(obj);
413     new SwaggerHttp().execute(obj);
414   }
415   if(Object.keys(opts).length === 0)
416     callback.call(this.scope, spec, unresolvedRefs);
417 };
418
419 Resolver.prototype.finish = function(spec, resolutionTable, resolvedRefs, unresolvedRefs, callback) {
420   // walk resolution table and replace with resolved refs
421   var ref;
422   for(ref in resolutionTable) {
423     var i, locations = resolutionTable[ref];
424     for(i = 0; i < locations.length; i++) {
425       var resolvedTo = resolvedRefs[locations[i].obj.$ref];
426       if(resolvedTo) {
427         if(!spec.definitions)
428           spec.definitions = {};
429         if(locations[i].resolveAs === '$ref') {
430           spec.definitions[resolvedTo.name] = resolvedTo.obj;
431           locations[i].obj.$ref = '#/definitions/' + resolvedTo.name;
432         }
433         else if (locations[i].resolveAs === 'inline') {
434           var key;
435           var targetObj = locations[i].obj;
436           delete targetObj.$ref;
437           for(key in resolvedTo.obj) {
438             targetObj[key] = resolvedTo.obj[key];
439           }
440         }
441       }
442     }
443   }
444   callback.call(this.scope, spec, unresolvedRefs);
445 };
446
447 /**
448  * immediately in-lines local refs, queues remote refs
449  * for inline resolution
450  */
451 Resolver.prototype.resolveInline = function (spec, property, objs, unresolvedRefs) {
452   var ref = property.$ref;
453   if(ref) {
454     if(ref.indexOf('http') === 0) {
455       if(Array.isArray(objs[ref])) {
456         objs[ref].push({obj: property, resolveAs: 'inline'});
457       }
458       else {
459         objs[ref] = [{obj: property, resolveAs: 'inline'}];
460       }
461     }
462     else if (ref.indexOf('#') === 0) {
463       // local resolve
464       var shortenedRef = ref.substring(1);
465       var i, parts = shortenedRef.split('/'), location = spec;
466       for(i = 0; i < parts.length; i++) {
467         var part = parts[i];
468         if(part.length > 0) {
469           location = location[part];
470         }
471       }
472       if(location) {
473         delete property.$ref;
474         var key;
475         for(key in location) {
476           property[key] = location[key];
477         }
478       }
479       else unresolvedRefs[ref] = null;
480     }
481   }
482   else if(property.type === 'array') {
483     this.resolveTo(property.items, objs);
484   }
485 };
486
487 Resolver.prototype.resolveTo = function (property, objs) {
488   var ref = property.$ref;
489   if(ref) {
490     if(ref.indexOf('http') === 0) {
491       if(Array.isArray(objs[ref])) {
492         objs[ref].push({obj: property, resolveAs: '$ref'});
493       }
494       else {
495         objs[ref] = [{obj: property, resolveAs: '$ref'}];
496       }
497     }
498   }
499   else if(property.type === 'array') {
500     var items = property.items;
501     this.resolveTo(items, objs);
502   }
503 };
504 var addModel = function(name, model) {
505   models[name] = model;
506 };
507
508 var SwaggerClient = function(url, options) {
509   this.isBuilt = false;
510   this.url = null;
511   this.debug = false;
512   this.basePath = null;
513   this.modelsArray = [];
514   this.authorizations = null;
515   this.authorizationScheme = null;
516   this.isValid = false;
517   this.info = null;
518   this.useJQuery = false;
519   this.resourceCount = 0;
520
521   if(typeof url !== 'undefined')
522     return this.initialize(url, options);
523 };
524
525 SwaggerClient.prototype.initialize = function (url, options) {
526   this.models = models = {};
527
528   options = (options||{});
529
530   if(typeof url === 'string')
531     this.url = url;
532   else if(typeof url === 'object') {
533     options = url;
534     this.url = options.url;
535   }
536   this.swaggerRequstHeaders = options.swaggerRequstHeaders || 'application/json;charset=utf-8,*/*';
537   this.defaultSuccessCallback = options.defaultSuccessCallback || null;
538   this.defaultErrorCallback = options.defaultErrorCallback || null;
539
540   if (typeof options.success === 'function')
541     this.success = options.success;
542
543   if (options.useJQuery)
544     this.useJQuery = options.useJQuery;
545
546   if (options.authorizations) {
547     this.clientAuthorizations = options.authorizations;
548   } else {
549     this.clientAuthorizations = authorizations;
550   }
551
552   this.supportedSubmitMethods = options.supportedSubmitMethods || [];
553   this.failure = options.failure || function() {};
554   this.progress = options.progress || function() {};
555   this.spec = options.spec;
556   this.options = options;
557
558   if (typeof options.success === 'function') {
559     this.ready = true;
560     this.build();
561   }
562 };
563
564 SwaggerClient.prototype.build = function(mock) {
565   if (this.isBuilt) return this;
566   var self = this;
567   this.progress('fetching resource list: ' + this.url);
568   var obj = {
569     useJQuery: this.useJQuery,
570     url: this.url,
571     method: "get",
572     headers: {
573       accept: this.swaggerRequstHeaders
574     },
575     on: {
576       error: function(response) {
577         if (self.url.substring(0, 4) !== 'http')
578           return self.fail('Please specify the protocol for ' + self.url);
579         else if (response.status === 0)
580           return self.fail('Can\'t read from server.  It may not have the appropriate access-control-origin settings.');
581         else if (response.status === 404)
582           return self.fail('Can\'t read swagger JSON from ' + self.url);
583         else
584           return self.fail(response.status + ' : ' + response.statusText + ' ' + self.url);
585       },
586       response: function(resp) {
587         var responseObj = resp.obj || JSON.parse(resp.data);
588         self.swaggerVersion = responseObj.swaggerVersion;
589
590         if(responseObj.swagger && parseInt(responseObj.swagger) === 2) {
591           self.swaggerVersion = responseObj.swagger;
592           new Resolver().resolve(responseObj, self.buildFromSpec, self);
593           self.isValid = true;
594         }
595         else {
596           if (self.swaggerVersion === '1.2') {
597             return self.buildFrom1_2Spec(responseObj);
598           } else {
599             return self.buildFrom1_1Spec(responseObj);
600           }
601         }
602       }
603     }
604   };
605   if(this.spec) {
606     setTimeout(function() {
607       new Resolver().resolve(self.spec, self.buildFromSpec, self);
608    }, 10);
609   }
610   else {
611     authorizations.apply(obj);
612     if(mock)
613       return obj;
614     new SwaggerHttp().execute(obj);
615   }
616   return this;
617 };
618
619 SwaggerClient.prototype.buildFromSpec = function(response) {
620   if(this.isBuilt) return this;
621
622   this.info = response.info || {};
623   this.title = response.title || '';
624   this.host = response.host || '';
625   this.schemes = response.schemes || [];
626   this.basePath = response.basePath || '';
627   this.apis = {};
628   this.apisArray = [];
629   this.consumes = response.consumes;
630   this.produces = response.produces;
631   this.securityDefinitions = response.securityDefinitions;
632
633   // legacy support
634   this.authSchemes = response.securityDefinitions;
635
636   var definedTags = {};
637   if(Array.isArray(response.tags)) {
638     definedTags = {};
639     for(k = 0; k < response.tags.length; k++) {
640       var t = response.tags[k];
641       definedTags[t.name] = t;
642     }
643   }
644
645   var location;
646   if(typeof this.url === 'string') {
647     location = this.parseUri(this.url);
648   }
649
650   if(typeof this.schemes === 'undefined' || this.schemes.length === 0) {
651     this.scheme = location.scheme || 'http';
652   }
653   else {
654     this.scheme = this.schemes[0];
655   }
656
657   if(typeof this.host === 'undefined' || this.host === '') {
658     this.host = location.host;
659     if (location.port) {
660       this.host = this.host + ':' + location.port;
661     }
662   }
663
664   this.definitions = response.definitions;
665   var key;
666   for(key in this.definitions) {
667     var model = new Model(key, this.definitions[key]);
668     if(model) {
669       models[key] = model;
670     }
671   }
672
673   // get paths, create functions for each operationId
674   var path;
675   var operations = [];
676   for(path in response.paths) {
677     if(typeof response.paths[path] === 'object') {
678       var httpMethod;
679       for(httpMethod in response.paths[path]) {
680         if(['delete', 'get', 'head', 'options', 'patch', 'post', 'put'].indexOf(httpMethod) === -1) {
681           continue;
682         }
683         var operation = response.paths[path][httpMethod];
684         var tags = operation.tags;
685         if(typeof tags === 'undefined') {
686           operation.tags = [ 'default' ];
687           tags = operation.tags;
688         }
689         var operationId = this.idFromOp(path, httpMethod, operation);
690         var operationObject = new Operation (
691           this,
692           operation.scheme,
693           operationId,
694           httpMethod,
695           path,
696           operation,
697           this.definitions
698         );
699         // bind this operation's execute command to the api
700         if(tags.length > 0) {
701           var i;
702           for(i = 0; i < tags.length; i++) {
703             var tag = this.tagFromLabel(tags[i]);
704             var operationGroup = this[tag];
705             if(typeof this.apis[tag] === 'undefined')
706               this.apis[tag] = {};
707             if(typeof operationGroup === 'undefined') {
708               this[tag] = [];
709               operationGroup = this[tag];
710               operationGroup.operations = {};
711               operationGroup.label = tag;
712               operationGroup.apis = [];
713               var tagObject = definedTags[tag];
714               if(typeof tagObject === 'object') {
715                 operationGroup.description = tagObject.description;
716                 operationGroup.externalDocs = tagObject.externalDocs;
717               }
718               this[tag].help = this.help.bind(operationGroup);
719               this.apisArray.push(new OperationGroup(tag, operationGroup.description, operationGroup.externalDocs, operationObject));
720             }
721             if(typeof this.apis[tag].help !== 'function')
722               this.apis[tag].help = this.help.bind(operationGroup);
723             // bind to the apis object
724             this.apis[tag][operationId] = operationObject.execute.bind(operationObject);
725             this.apis[tag][operationId].help = operationObject.help.bind(operationObject);
726             this.apis[tag][operationId].asCurl = operationObject.asCurl.bind(operationObject);
727             operationGroup[operationId] = operationObject.execute.bind(operationObject);
728             operationGroup[operationId].help = operationObject.help.bind(operationObject);
729             operationGroup[operationId].asCurl = operationObject.asCurl.bind(operationObject);
730
731             operationGroup.apis.push(operationObject);
732             operationGroup.operations[operationId] = operationObject;
733
734             // legacy UI feature
735             var j;
736             var api;
737             for(j = 0; j < this.apisArray.length; j++) {
738               if(this.apisArray[j].tag === tag) {
739                 api = this.apisArray[j];
740               }
741             }
742             if(api) {
743               api.operationsArray.push(operationObject);
744             }
745           }
746         }
747         else {
748           log('no group to bind to');
749         }
750       }
751     }
752   }
753   this.isBuilt = true;
754   if (this.success) {
755     this.isValid = true;
756     this.isBuilt = true;
757     this.success();
758   }
759   return this;
760 };
761
762 SwaggerClient.prototype.parseUri = function(uri) {
763   var urlParseRE = /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/;
764   var parts = urlParseRE.exec(uri);
765   return {
766     scheme: parts[4].replace(':',''),
767     host: parts[11],
768     port: parts[12],
769     path: parts[15]
770   };
771 };
772
773 SwaggerClient.prototype.help = function(dontPrint) {
774   var i;
775   var output = 'operations for the "' + this.label + '" tag';
776   for(i = 0; i < this.apis.length; i++) {
777     var api = this.apis[i];
778     output += '\n  * ' + api.nickname + ': ' + api.operation.summary;
779   }
780   if(dontPrint)
781     return output;
782   else {
783     log(output);
784     return output;
785   }
786 };
787
788 SwaggerClient.prototype.tagFromLabel = function(label) {
789   return label;
790 };
791
792 SwaggerClient.prototype.idFromOp = function(path, httpMethod, op) {
793   var opId = op.operationId || (path.substring(1) + '_' + httpMethod);
794   return opId.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()\+\s]/g,'_');
795 };
796
797 SwaggerClient.prototype.fail = function(message) {
798   this.failure(message);
799   throw message;
800 };
801
802 var OperationGroup = function(tag, description, externalDocs, operation) {
803   this.tag = tag;
804   this.path = tag;
805   this.description = description;
806   this.externalDocs = externalDocs;
807   this.name = tag;
808   this.operation = operation;
809   this.operationsArray = [];
810 };
811
812 var Operation = function(parent, scheme, operationId, httpMethod, path, args, definitions) {
813   var errors = [];
814   parent = parent||{};
815   args = args||{};
816
817   this.operations = {};
818   this.operation = args;
819   this.deprecated = args.deprecated;
820   this.consumes = args.consumes;
821   this.produces = args.produces;
822   this.parent = parent;
823   this.host = parent.host || 'localhost';
824   this.schemes = parent.schemes;
825   this.scheme = scheme || parent.scheme || 'http';
826   this.basePath = parent.basePath || '/';
827   this.nickname = (operationId||errors.push('Operations must have a nickname.'));
828   this.method = (httpMethod||errors.push('Operation ' + operationId + ' is missing method.'));
829   this.path = (path||errors.push('Operation ' + this.nickname + ' is missing path.'));
830   this.parameters = args !== null ? (args.parameters||[]) : {};
831   this.summary = args.summary || '';
832   this.responses = (args.responses||{});
833   this.type = null;
834   this.security = args.security;
835   this.authorizations = args.security;
836   this.description = args.description;
837   this.useJQuery = parent.useJQuery;
838
839   if(typeof this.deprecated === 'string') {
840     switch(this.deprecated.toLowerCase()) {
841       case 'true': case 'yes': case '1': {
842         this.deprecated = true;
843         break;
844       }
845       case 'false': case 'no': case '0': case null: {
846         this.deprecated = false;
847         break;
848       }
849       default: this.deprecated = Boolean(this.deprecated);
850     }
851   }
852
853   var i, model;
854
855   if(definitions) {
856     // add to global models
857     var key;
858     for(key in this.definitions) {
859       model = new Model(key, definitions[key]);
860       if(model) {
861         models[key] = model;
862       }
863     }
864   }
865   for(i = 0; i < this.parameters.length; i++) {
866     var param = this.parameters[i];
867     if(param.type === 'array') {
868       param.isList = true;
869       param.allowMultiple = true;
870     }
871     var innerType = this.getType(param);
872     if(innerType && innerType.toString().toLowerCase() === 'boolean') {
873       param.allowableValues = {};
874       param.isList = true;
875       param['enum'] = ["true", "false"];
876     }
877     if(typeof param['enum'] !== 'undefined') {
878       var id;
879       param.allowableValues = {};
880       param.allowableValues.values = [];
881       param.allowableValues.descriptiveValues = [];
882       for(id = 0; id < param['enum'].length; id++) {
883         var value = param['enum'][id];
884         var isDefault = (value === param.default) ? true : false;
885         param.allowableValues.values.push(value);
886         param.allowableValues.descriptiveValues.push({value : value, isDefault: isDefault});
887       }
888     }
889     if(param.type === 'array') {
890       innerType = [innerType];
891       if(typeof param.allowableValues === 'undefined') {
892         // can't show as a list if no values to select from
893         delete param.isList;
894         delete param.allowMultiple;
895       }
896     }
897     param.signature = this.getModelSignature(innerType, models).toString();
898     param.sampleJSON = this.getModelSampleJSON(innerType, models);
899     param.responseClassSignature = param.signature;
900   }
901
902   var defaultResponseCode, response, responses = this.responses;
903
904   if(responses['200']) {
905     response = responses['200'];
906     defaultResponseCode = '200';
907   }
908   else if(responses['201']) {
909     response = responses['201'];
910     defaultResponseCode = '201';
911   }
912   else if(responses['202']) {
913     response = responses['202'];
914     defaultResponseCode = '202';
915   }
916   else if(responses['203']) {
917     response = responses['203'];
918     defaultResponseCode = '203';
919   }
920   else if(responses['204']) {
921     response = responses['204'];
922     defaultResponseCode = '204';
923   }
924   else if(responses['205']) {
925     response = responses['205'];
926     defaultResponseCode = '205';
927   }
928   else if(responses['206']) {
929     response = responses['206'];
930     defaultResponseCode = '206';
931   }
932   else if(responses['default']) {
933     response = responses['default'];
934     defaultResponseCode = 'default';
935   }
936
937   if(response && response.schema) {
938     var resolvedModel = this.resolveModel(response.schema, definitions);
939     delete responses[defaultResponseCode];
940     if(resolvedModel) {
941       this.successResponse = {};
942       this.successResponse[defaultResponseCode] = resolvedModel;
943     }
944     else {
945       this.successResponse = {};
946       this.successResponse[defaultResponseCode] = response.schema.type;
947     }
948     this.type = response;
949   }
950
951   if (errors.length > 0) {
952     if(this.resource && this.resource.api && this.resource.api.fail)
953       this.resource.api.fail(errors);
954   }
955
956   return this;
957 };
958
959 OperationGroup.prototype.sort = function(sorter) {
960
961 };
962
963 Operation.prototype.getType = function (param) {
964   var type = param.type;
965   var format = param.format;
966   var isArray = false;
967   var str;
968   if(type === 'integer' && format === 'int32')
969     str = 'integer';
970   else if(type === 'integer' && format === 'int64')
971     str = 'long';
972   else if(type === 'integer')
973     str = 'integer';
974   else if(type === 'string') {
975     if(format === 'date-time')
976       str = 'date-time';
977     else if(format === 'date')
978       str = 'date';
979     else
980       str = 'string';
981   }
982   else if(type === 'number' && format === 'float')
983     str = 'float';
984   else if(type === 'number' && format === 'double')
985     str = 'double';
986   else if(type === 'number')
987     str = 'double';
988   else if(type === 'boolean')
989     str = 'boolean';
990   else if(type === 'array') {
991     isArray = true;
992     if(param.items)
993       str = this.getType(param.items);
994   }
995   if(param.$ref)
996     str = param.$ref;
997
998   var schema = param.schema;
999   if(schema) {
1000     var ref = schema.$ref;
1001     if(ref) {
1002       ref = simpleRef(ref);
1003       if(isArray)
1004         return [ ref ];
1005       else
1006         return ref;
1007     }
1008     else
1009       return this.getType(schema);
1010   }
1011   if(isArray)
1012     return [ str ];
1013   else
1014     return str;
1015 };
1016
1017 Operation.prototype.resolveModel = function (schema, definitions) {
1018   if(typeof schema.$ref !== 'undefined') {
1019     var ref = schema.$ref;
1020     if(ref.indexOf('#/definitions/') === 0)
1021       ref = ref.substring('#/definitions/'.length);
1022     if(definitions[ref]) {
1023       return new Model(ref, definitions[ref]);
1024     }
1025   }
1026   if(schema.type === 'array')
1027     return new ArrayModel(schema);
1028   else
1029     return null;
1030 };
1031
1032 Operation.prototype.help = function(dontPrint) {
1033   var out = this.nickname + ': ' + this.summary + '\n';
1034   for(var i = 0; i < this.parameters.length; i++) {
1035     var param = this.parameters[i];
1036     var typeInfo = param.signature;
1037     out += '\n  * ' + param.name + ' (' + typeInfo + '): ' + param.description;
1038   }
1039   if(typeof dontPrint === 'undefined')
1040     log(out);
1041   return out;
1042 };
1043
1044 Operation.prototype.getModelSignature = function(type, definitions) {
1045   var isPrimitive, listType;
1046
1047   if(type instanceof Array) {
1048     listType = true;
1049     type = type[0];
1050   }
1051   else if(typeof type === 'undefined')
1052     type = 'undefined';
1053
1054   if(type === 'string')
1055     isPrimitive = true;
1056   else
1057     isPrimitive = (listType && definitions[listType]) || (definitions[type]) ? false : true;
1058   if (isPrimitive) {
1059     if(listType)
1060       return 'Array[' + type + ']';
1061     else
1062       return type.toString();
1063   } else {
1064     if (listType)
1065       return 'Array[' + definitions[type].getMockSignature() + ']';
1066     else
1067       return definitions[type].getMockSignature();
1068   }
1069 };
1070
1071 Operation.prototype.supportHeaderParams = function () {
1072   return true;
1073 };
1074
1075 Operation.prototype.supportedSubmitMethods = function () {
1076   return this.parent.supportedSubmitMethods;
1077 };
1078
1079 Operation.prototype.getHeaderParams = function (args) {
1080   var headers = this.setContentTypes(args, {});
1081   for(var i = 0; i < this.parameters.length; i++) {
1082     var param = this.parameters[i];
1083     if(typeof args[param.name] !== 'undefined') {
1084       if (param.in === 'header') {
1085         var value = args[param.name];
1086         if(Array.isArray(value))
1087           value = value.toString();
1088         headers[param.name] = value;
1089       }
1090     }
1091   }
1092   return headers;
1093 };
1094
1095 Operation.prototype.urlify = function (args) {
1096   var formParams = {};
1097   var requestUrl = this.path;
1098
1099   // grab params from the args, build the querystring along the way
1100   var querystring = '';
1101   for(var i = 0; i < this.parameters.length; i++) {
1102     var param = this.parameters[i];
1103     if(typeof args[param.name] !== 'undefined') {
1104       if(param.in === 'path') {
1105         var reg = new RegExp('\{' + param.name + '\}', 'gi');
1106         var value = args[param.name];
1107         if(Array.isArray(value))
1108           value = this.encodePathCollection(param.collectionFormat, param.name, value);
1109         else
1110           value = this.encodePathParam(value);
1111         requestUrl = requestUrl.replace(reg, value);
1112       }
1113       else if (param.in === 'query' && typeof args[param.name] !== 'undefined') {
1114         if(querystring === '')
1115           querystring += '?';
1116         else
1117           querystring += '&';
1118         if(typeof param.collectionFormat !== 'undefined') {
1119           var qp = args[param.name];
1120           if(Array.isArray(qp))
1121             querystring += this.encodeQueryCollection(param.collectionFormat, param.name, qp);
1122           else
1123             querystring += this.encodeQueryParam(param.name) + '=' + this.encodeQueryParam(args[param.name]);
1124         }
1125         else
1126           querystring += this.encodeQueryParam(param.name) + '=' + this.encodeQueryParam(args[param.name]);
1127       }
1128       else if (param.in === 'formData')
1129         formParams[param.name] = args[param.name];
1130     }
1131   }
1132   var url = this.scheme + '://' + this.host;
1133
1134   if(this.basePath !== '/')
1135     url += this.basePath;
1136
1137   return url + requestUrl + querystring;
1138 };
1139
1140 Operation.prototype.getMissingParams = function(args) {
1141   var missingParams = [];
1142   // check required params, track the ones that are missing
1143   var i;
1144   for(i = 0; i < this.parameters.length; i++) {
1145     var param = this.parameters[i];
1146     if(param.required === true) {
1147       if(typeof args[param.name] === 'undefined')
1148         missingParams = param.name;
1149     }
1150   }
1151   return missingParams;
1152 };
1153
1154 Operation.prototype.getBody = function(headers, args, opts) {
1155   var formParams = {}, body, key;
1156
1157   for(var i = 0; i < this.parameters.length; i++) {
1158     var param = this.parameters[i];
1159     if(typeof args[param.name] !== 'undefined') {
1160       if (param.in === 'body') {
1161         body = args[param.name];
1162       } else if(param.in === 'formData') {
1163         formParams[param.name] = args[param.name];
1164       }
1165     }
1166   }
1167
1168   // handle form params
1169   if(headers['Content-Type'] === 'application/x-www-form-urlencoded') {
1170     var encoded = "";
1171     for(key in formParams) {
1172       value = formParams[key];
1173       if(typeof value !== 'undefined'){
1174         if(encoded !== "")
1175           encoded += "&";
1176         encoded += encodeURIComponent(key) + '=' + encodeURIComponent(value);
1177       }
1178     }
1179     body = encoded;
1180   }
1181   else if (headers['Content-Type'] && headers['Content-Type'].indexOf('multipart/form-data') >= 0) {
1182     if(opts.useJQuery) {
1183       var bodyParam = new FormData();
1184       bodyParam.type = 'formData';
1185       for (key in formParams) {
1186         value = args[key];
1187         if (typeof value !== 'undefined') {
1188           // required for jquery file upload
1189           if(value.type === 'file' && value.value) {
1190             delete headers['Content-Type'];
1191             bodyParam.append(key, value.value);
1192           }
1193           else
1194             bodyParam.append(key, value);
1195         }
1196       }
1197       body = bodyParam;
1198     }
1199   }
1200
1201   return body;
1202 };
1203
1204 /**
1205  * gets sample response for a single operation
1206  **/
1207 Operation.prototype.getModelSampleJSON = function(type, models) {
1208   var isPrimitive, listType, sampleJson;
1209
1210   listType = (type instanceof Array);
1211   isPrimitive = models[type] ? false : true;
1212   sampleJson = isPrimitive ? void 0 : models[type].createJSONSample();
1213   if (sampleJson) {
1214     sampleJson = listType ? [sampleJson] : sampleJson;
1215     if(typeof sampleJson == 'string')
1216       return sampleJson;
1217     else if(typeof sampleJson === 'object') {
1218       var t = sampleJson;
1219       if(sampleJson instanceof Array && sampleJson.length > 0) {
1220         t = sampleJson[0];
1221       }
1222       if(t.nodeName) {
1223         var xmlString = new XMLSerializer().serializeToString(t);
1224         return this.formatXml(xmlString);
1225       }
1226       else
1227         return JSON.stringify(sampleJson, null, 2);
1228     }
1229     else
1230       return sampleJson;
1231   }
1232 };
1233
1234 /**
1235  * legacy binding
1236  **/
1237 Operation.prototype["do"] = function(args, opts, callback, error, parent) {
1238   return this.execute(args, opts, callback, error, parent);
1239 };
1240
1241
1242 /**
1243  * executes an operation
1244  **/
1245 Operation.prototype.execute = function(arg1, arg2, arg3, arg4, parent) {
1246   var args = arg1 || {};
1247   var opts = {}, success, error;
1248   if(typeof arg2 === 'object') {
1249     opts = arg2;
1250     success = arg3;
1251     error = arg4;
1252   }
1253
1254   if(typeof arg2 === 'function') {
1255     success = arg2;
1256     error = arg3;
1257   }
1258
1259   success = (success||log);
1260   error = (error||log);
1261
1262   if(opts.useJQuery)
1263     this.useJQuery = opts.useJQuery;
1264
1265   var missingParams = this.getMissingParams(args);
1266   if(missingParams.length > 0) {
1267     var message = 'missing required params: ' + missingParams;
1268     fail(message);
1269     return;
1270   }
1271   var allHeaders = this.getHeaderParams(args);
1272   var contentTypeHeaders = this.setContentTypes(args, opts);
1273
1274   var headers = {}, attrname;
1275   for (attrname in allHeaders) { headers[attrname] = allHeaders[attrname]; }
1276   for (attrname in contentTypeHeaders) { headers[attrname] = contentTypeHeaders[attrname]; }
1277
1278   var body = this.getBody(headers, args, opts);
1279   var url = this.urlify(args);
1280
1281   var obj = {
1282     url: url,
1283     method: this.method.toUpperCase(),
1284     body: body,
1285     useJQuery: this.useJQuery,
1286     headers: headers,
1287     on: {
1288       response: function(response) {
1289         return success(response, parent);
1290       },
1291       error: function(response) {
1292         return error(response, parent);
1293       }
1294     }
1295   };
1296   var status = authorizations.apply(obj, this.operation.security);
1297   if(opts.mock === true)
1298     return obj;
1299   else
1300     new SwaggerHttp().execute(obj, opts);
1301 };
1302
1303 Operation.prototype.setContentTypes = function(args, opts) {
1304   // default type
1305   var accepts = 'application/json';
1306   var consumes = args.parameterContentType || 'application/json';
1307   var allDefinedParams = this.parameters;
1308   var definedFormParams = [];
1309   var definedFileParams = [];
1310   var body;
1311   var headers = {};
1312
1313   // get params from the operation and set them in definedFileParams, definedFormParams, headers
1314   var i;
1315   for(i = 0; i < allDefinedParams.length; i++) {
1316     var param = allDefinedParams[i];
1317     if(param.in === 'formData') {
1318       if(param.type === 'file')
1319         definedFileParams.push(param);
1320       else
1321         definedFormParams.push(param);
1322     }
1323     else if(param.in === 'header' && opts) {
1324       var key = param.name;
1325       var headerValue = opts[param.name];
1326       if(typeof opts[param.name] !== 'undefined')
1327         headers[key] = headerValue;
1328     }
1329     else if(param.in === 'body' && typeof args[param.name] !== 'undefined') {
1330       body = args[param.name];
1331     }
1332   }
1333
1334   // if there's a body, need to set the consumes header via requestContentType
1335   if (body && (this.method === 'post' || this.method === 'put' || this.method === 'patch' || this.method === 'delete')) {
1336     if (opts.requestContentType)
1337       consumes = opts.requestContentType;
1338   } else {
1339     // if any form params, content type must be set
1340     if(definedFormParams.length > 0) {
1341       if(opts.requestContentType)           // override if set
1342         consumes = opts.requestContentType;
1343       else if(definedFileParams.length > 0) // if a file, must be multipart/form-data
1344         consumes = 'multipart/form-data';
1345       else                                  // default to x-www-from-urlencoded
1346         consumes = 'application/x-www-form-urlencoded';
1347     }
1348     else if (this.type == 'DELETE')
1349       body = '{}';
1350     else if (this.type != 'DELETE')
1351       consumes = null;
1352   }
1353
1354   if (consumes && this.consumes) {
1355     if (this.consumes.indexOf(consumes) === -1) {
1356       log('server doesn\'t consume ' + consumes + ', try ' + JSON.stringify(this.consumes));
1357     }
1358   }
1359
1360   if (opts.responseContentType) {
1361     accepts = opts.responseContentType;
1362   } else {
1363     accepts = 'application/json';
1364   }
1365   if (accepts && this.produces) {
1366     if (this.produces.indexOf(accepts) === -1) {
1367       log('server can\'t produce ' + accepts);
1368     }
1369   }
1370
1371   if ((consumes && body !== '') || (consumes === 'application/x-www-form-urlencoded'))
1372     headers['Content-Type'] = consumes;
1373   if (accepts)
1374     headers.Accept = accepts;
1375   return headers;
1376 };
1377
1378 Operation.prototype.asCurl = function (args) {
1379   var obj = this.execute(args, {mock: true});
1380   authorizations.apply(obj);
1381   var results = [];
1382   results.push('-X ' + this.method.toUpperCase());
1383   if (obj.headers) {
1384     var key;
1385     for (key in obj.headers)
1386       results.push('--header "' + key + ': ' + obj.headers[key] + '"');
1387   }
1388   if(obj.body) {
1389     var body;
1390     if(typeof obj.body === 'object')
1391       body = JSON.stringify(obj.body);
1392     else
1393       body = obj.body;
1394     results.push('-d "' + body.replace(/"/g, '\\"') + '"');
1395   }
1396   return 'curl ' + (results.join(' ')) + ' "' + obj.url + '"';
1397 };
1398
1399 Operation.prototype.encodePathCollection = function(type, name, value) {
1400   var encoded = '';
1401   var i;
1402   var separator = '';
1403   if(type === 'ssv')
1404     separator = '%20';
1405   else if(type === 'tsv')
1406     separator = '\\t';
1407   else if(type === 'pipes')
1408     separator = '|';
1409   else
1410     separator = ',';
1411
1412   for(i = 0; i < value.length; i++) {
1413     if(i === 0)
1414       encoded = this.encodeQueryParam(value[i]);
1415     else
1416       encoded += separator + this.encodeQueryParam(value[i]);
1417   }
1418   return encoded;
1419 };
1420
1421 Operation.prototype.encodeQueryCollection = function(type, name, value) {
1422   var encoded = '';
1423   var i;
1424   if(type === 'default' || type === 'multi') {
1425     for(i = 0; i < value.length; i++) {
1426       if(i > 0) encoded += '&';
1427       encoded += this.encodeQueryParam(name) + '=' + this.encodeQueryParam(value[i]);
1428     }
1429   }
1430   else {
1431     var separator = '';
1432     if(type === 'csv')
1433       separator = ',';
1434     else if(type === 'ssv')
1435       separator = '%20';
1436     else if(type === 'tsv')
1437       separator = '\\t';
1438     else if(type === 'pipes')
1439       separator = '|';
1440     else if(type === 'brackets') {
1441       for(i = 0; i < value.length; i++) {
1442         if(i !== 0)
1443           encoded += '&';
1444         encoded += this.encodeQueryParam(name) + '[]=' + this.encodeQueryParam(value[i]);
1445       }
1446     }
1447     if(separator !== '') {
1448       for(i = 0; i < value.length; i++) {
1449         if(i === 0)
1450           encoded = this.encodeQueryParam(name) + '=' + this.encodeQueryParam(value[i]);
1451         else
1452           encoded += separator + this.encodeQueryParam(value[i]);
1453       }
1454     }
1455   }
1456   return encoded;
1457 };
1458
1459 Operation.prototype.encodeQueryParam = function(arg) {
1460   return encodeURIComponent(arg);
1461 };
1462
1463 /**
1464  * TODO revisit, might not want to leave '/'
1465  **/
1466 Operation.prototype.encodePathParam = function(pathParam) {
1467   var encParts, part, parts, i, len;
1468   pathParam = pathParam.toString();
1469   if (pathParam.indexOf('/') === -1) {
1470     return encodeURIComponent(pathParam);
1471   } else {
1472     parts = pathParam.split('/');
1473     encParts = [];
1474     for (i = 0, len = parts.length; i < len; i++) {
1475       encParts.push(encodeURIComponent(parts[i]));
1476     }
1477     return encParts.join('/');
1478   }
1479 };
1480
1481 var Model = function(name, definition) {
1482   this.name = name;
1483   this.definition = definition || {};
1484   this.properties = [];
1485   var requiredFields = definition.required || [];
1486   if(definition.type === 'array') {
1487     var out = new ArrayModel(definition);
1488     return out;
1489   }
1490   var key;
1491   var props = definition.properties;
1492   if(props) {
1493     for(key in props) {
1494       var required = false;
1495       var property = props[key];
1496       if(requiredFields.indexOf(key) >= 0)
1497         required = true;
1498       this.properties.push(new Property(key, property, required));
1499     }
1500   }
1501 };
1502
1503 Model.prototype.createJSONSample = function(modelsToIgnore) {
1504   var i, result = {}, representations = {};
1505   modelsToIgnore = (modelsToIgnore||{});
1506   modelsToIgnore[this.name] = this;
1507   for (i = 0; i < this.properties.length; i++) {
1508     prop = this.properties[i];
1509     var sample = prop.getSampleValue(modelsToIgnore, representations);
1510     result[prop.name] = sample;
1511   }
1512   delete modelsToIgnore[this.name];
1513   return result;
1514 };
1515
1516 Model.prototype.getSampleValue = function(modelsToIgnore) {
1517   var i, obj = {}, representations = {};
1518   for(i = 0; i < this.properties.length; i++ ) {
1519     var property = this.properties[i];
1520     obj[property.name] = property.sampleValue(false, modelsToIgnore, representations);
1521   }
1522   return obj;
1523 };
1524
1525 Model.prototype.getMockSignature = function(modelsToIgnore) {
1526   var i, prop, propertiesStr = [];
1527   for (i = 0; i < this.properties.length; i++) {
1528     prop = this.properties[i];
1529     propertiesStr.push(prop.toString());
1530   }
1531   var strong = '<span class="strong">';
1532   var stronger = '<span class="stronger">';
1533   var strongClose = '</span>';
1534   var classOpen = strong + this.name + ' {' + strongClose;
1535   var classClose = strong + '}' + strongClose;
1536   var returnVal = classOpen + '<div>' + propertiesStr.join(',</div><div>') + '</div>' + classClose;
1537   if (!modelsToIgnore)
1538     modelsToIgnore = {};
1539
1540   modelsToIgnore[this.name] = this;
1541   for (i = 0; i < this.properties.length; i++) {
1542     prop = this.properties[i];
1543     var ref = prop.$ref;
1544     var model = models[ref];
1545     if (model && typeof modelsToIgnore[model.name] === 'undefined') {
1546       returnVal = returnVal + ('<br>' + model.getMockSignature(modelsToIgnore));
1547     }
1548   }
1549   return returnVal;
1550 };
1551
1552 var Property = function(name, obj, required) {
1553   this.schema = obj;
1554   this.required = required;
1555   if(obj.$ref)
1556     this.$ref = simpleRef(obj.$ref);
1557   else if (obj.type === 'array' && obj.items) {
1558     if(obj.items.$ref)
1559       this.$ref = simpleRef(obj.items.$ref);
1560     else
1561       obj = obj.items;
1562   }
1563   this.name = name;
1564   this.description = obj.description;
1565   this.obj = obj;
1566   this.optional = true;
1567   this.optional = !required;
1568   this.default = obj.default || null;
1569   this.example = obj.example !== undefined ? obj.example : null;
1570   this.collectionFormat = obj.collectionFormat || null;
1571   this.maximum = obj.maximum || null;
1572   this.exclusiveMaximum = obj.exclusiveMaximum || null;
1573   this.minimum = obj.minimum || null;
1574   this.exclusiveMinimum = obj.exclusiveMinimum || null;
1575   this.maxLength = obj.maxLength || null;
1576   this.minLength = obj.minLength || null;
1577   this.pattern = obj.pattern || null;
1578   this.maxItems = obj.maxItems || null;
1579   this.minItems = obj.minItems || null;
1580   this.uniqueItems = obj.uniqueItems || null;
1581   this['enum'] = obj['enum'] || null;
1582   this.multipleOf = obj.multipleOf || null;
1583 };
1584
1585 Property.prototype.getSampleValue = function (modelsToIgnore, representations) {
1586   return this.sampleValue(false, modelsToIgnore, representations);
1587 };
1588
1589 Property.prototype.isArray = function () {
1590   var schema = this.schema;
1591   if(schema.type === 'array')
1592     return true;
1593   else
1594     return false;
1595 };
1596
1597 Property.prototype.sampleValue = function(isArray, ignoredModels, representations) {
1598   isArray = (isArray || this.isArray());
1599   ignoredModels = (ignoredModels || {});
1600   // representations = (representations || {});
1601
1602   var type = getStringSignature(this.obj, true);
1603   var output;
1604
1605   if(this.$ref) {
1606     var refModelName = simpleRef(this.$ref);
1607     var refModel = models[refModelName];
1608     if(typeof representations[type] !== 'undefined') {
1609       return representations[type];
1610     }
1611     else
1612
1613     if(refModel && typeof ignoredModels[type] === 'undefined') {
1614       ignoredModels[type] = this;
1615       output = refModel.getSampleValue(ignoredModels, representations);
1616       representations[type] = output;
1617     }
1618     else {
1619       output = (representations[type] || refModelName);
1620     }
1621   }
1622   else if(this.example)
1623     output = this.example;
1624   else if(this.default)
1625     output = this.default;
1626   else if(type === 'date-time')
1627     output = new Date().toISOString();
1628   else if(type === 'date')
1629     output = new Date().toISOString().split("T")[0];
1630   else if(type === 'string')
1631     output = 'string';
1632   else if(type === 'integer')
1633     output = 0;
1634   else if(type === 'long')
1635     output = 0;
1636   else if(type === 'float')
1637     output = 0.0;
1638   else if(type === 'double')
1639     output = 0.0;
1640   else if(type === 'boolean')
1641     output = true;
1642   else
1643     output = {};
1644   ignoredModels[type] = output;
1645   if(isArray)
1646     return [output];
1647   else
1648     return output;
1649 };
1650
1651 getStringSignature = function(obj, baseComponent) {
1652   var str = '';
1653   if(typeof obj.$ref !== 'undefined')
1654     str += simpleRef(obj.$ref);
1655   else if(typeof obj.type === 'undefined')
1656     str += 'object';
1657   else if(obj.type === 'array') {
1658     if(baseComponent)
1659       str += getStringSignature((obj.items || obj.$ref || {}));
1660     else {
1661       str += 'Array[';
1662       str += getStringSignature((obj.items || obj.$ref || {}));
1663       str += ']';
1664     }
1665   }
1666   else if(obj.type === 'integer' && obj.format === 'int32')
1667     str += 'integer';
1668   else if(obj.type === 'integer' && obj.format === 'int64')
1669     str += 'long';
1670   else if(obj.type === 'integer' && typeof obj.format === 'undefined')
1671     str += 'long';
1672   else if(obj.type === 'string' && obj.format === 'date-time')
1673     str += 'date-time';
1674   else if(obj.type === 'string' && obj.format === 'date')
1675     str += 'date';
1676   else if(obj.type === 'string' && typeof obj.format === 'undefined')
1677     str += 'string';
1678   else if(obj.type === 'number' && obj.format === 'float')
1679     str += 'float';
1680   else if(obj.type === 'number' && obj.format === 'double')
1681     str += 'double';
1682   else if(obj.type === 'number' && typeof obj.format === 'undefined')
1683     str += 'double';
1684   else if(obj.type === 'boolean')
1685     str += 'boolean';
1686   else if(obj.$ref)
1687     str += simpleRef(obj.$ref);
1688   else
1689     str += obj.type;
1690   return str;
1691 };
1692
1693 simpleRef = function(name) {
1694   if(typeof name === 'undefined')
1695     return null;
1696   if(name.indexOf("#/definitions/") === 0)
1697     return name.substring('#/definitions/'.length);
1698   else
1699     return name;
1700 };
1701
1702 Property.prototype.toString = function() {
1703   var str = getStringSignature(this.obj);
1704   if(str !== '') {
1705     str = '<span class="propName ' + this.required + '">' + this.name + '</span> (<span class="propType">' + str + '</span>';
1706     if(!this.required)
1707       str += ', <span class="propOptKey">optional</span>';
1708     str += ')';
1709   }
1710   else
1711     str = this.name + ' (' + JSON.stringify(this.obj) + ')';
1712
1713   if(typeof this.description !== 'undefined')
1714     str += ': ' + this.description;
1715
1716   if (this['enum']) {
1717     str += ' = <span class="propVals">[\'' + this['enum'].join('\' or \'') + '\']</span>';
1718   }
1719   if (this.descr) {
1720     str += ': <span class="propDesc">' + this.descr + '</span>';
1721   }
1722
1723
1724   var options = ''; 
1725   var isArray = this.schema.type === 'array';
1726   var type;
1727
1728   if(isArray) {
1729     if(this.schema.items)
1730       type = this.schema.items.type;
1731     else
1732       type = '';
1733   }
1734   else {
1735     type = this.schema.type;
1736   }
1737
1738   if (this.default)
1739     options += optionHtml('Default', this.default);
1740
1741   switch (type) {
1742     case 'string':
1743       if (this.minLength)
1744         options += optionHtml('Min. Length', this.minLength);
1745       if (this.maxLength)
1746         options += optionHtml('Max. Length', this.maxLength);
1747       if (this.pattern)
1748         options += optionHtml('Reg. Exp.', this.pattern);
1749       break;
1750     case 'integer':
1751     case 'number':
1752       if (this.minimum)
1753         options += optionHtml('Min. Value', this.minimum);
1754       if (this.exclusiveMinimum)
1755         options += optionHtml('Exclusive Min.', "true");
1756       if (this.maximum)
1757         options += optionHtml('Max. Value', this.maximum);
1758       if (this.exclusiveMaximum)
1759         options += optionHtml('Exclusive Max.', "true");
1760       if (this.multipleOf)
1761         options += optionHtml('Multiple Of', this.multipleOf);
1762       break;
1763   }
1764
1765   if (isArray) {
1766     if (this.minItems)
1767       options += optionHtml('Min. Items', this.minItems);
1768     if (this.maxItems)
1769       options += optionHtml('Max. Items', this.maxItems);
1770     if (this.uniqueItems)
1771       options += optionHtml('Unique Items', "true");
1772     if (this.collectionFormat)
1773       options += optionHtml('Coll. Format', this.collectionFormat);
1774   }
1775
1776   if (this['enum']) {
1777     var enumString;
1778
1779     if (type === 'number' || type === 'integer')
1780       enumString = this['enum'].join(', ');
1781     else {
1782       enumString = '"' + this['enum'].join('", "') + '"';
1783     }
1784
1785     options += optionHtml('Enum', enumString);
1786   }     
1787
1788   if (options.length > 0)
1789     str = '<span class="propWrap">' + str + '<table class="optionsWrapper"><tr><th colspan="2">' + this.name + '</th></tr>' + options + '</table></span>';
1790   
1791   return str;
1792 };
1793
1794 optionHtml = function(label, value) {
1795   return '<tr><td class="optionName">' + label + ':</td><td>' + value + '</td></tr>';
1796 };
1797
1798 typeFromJsonSchema = function(type, format) {
1799   var str;
1800   if(type === 'integer' && format === 'int32')
1801     str = 'integer';
1802   else if(type === 'integer' && format === 'int64')
1803     str = 'long';
1804   else if(type === 'integer' && typeof format === 'undefined')
1805     str = 'long';
1806   else if(type === 'string' && format === 'date-time')
1807     str = 'date-time';
1808   else if(type === 'string' && format === 'date')
1809     str = 'date';
1810   else if(type === 'number' && format === 'float')
1811     str = 'float';
1812   else if(type === 'number' && format === 'double')
1813     str = 'double';
1814   else if(type === 'number' && typeof format === 'undefined')
1815     str = 'double';
1816   else if(type === 'boolean')
1817     str = 'boolean';
1818   else if(type === 'string')
1819     str = 'string';
1820
1821   return str;
1822 };
1823
1824 var sampleModels = {};
1825 var cookies = {};
1826 var models = {};
1827
1828 SwaggerClient.prototype.buildFrom1_2Spec = function (response) {
1829   if (response.apiVersion !== null) {
1830     this.apiVersion = response.apiVersion;
1831   }
1832   this.apis = {};
1833   this.apisArray = [];
1834   this.consumes = response.consumes;
1835   this.produces = response.produces;
1836   this.authSchemes = response.authorizations;
1837   this.info = this.convertInfo(response.info);
1838
1839   var isApi = false, i, res;
1840   for (i = 0; i < response.apis.length; i++) {
1841     var api = response.apis[i];
1842     if (api.operations) {
1843       var j;
1844       for (j = 0; j < api.operations.length; j++) {
1845         operation = api.operations[j];
1846         isApi = true;
1847       }
1848     }
1849   }
1850   if (response.basePath)
1851     this.basePath = response.basePath;
1852   else if (this.url.indexOf('?') > 0)
1853     this.basePath = this.url.substring(0, this.url.lastIndexOf('?'));
1854   else
1855     this.basePath = this.url;
1856
1857   if (isApi) {
1858     var newName = response.resourcePath.replace(/\//g, '');
1859     this.resourcePath = response.resourcePath;
1860     res = new SwaggerResource(response, this);
1861     this.apis[newName] = res;
1862     this.apisArray.push(res);
1863     this.finish();
1864   } else {
1865     var k;
1866     this.expectedResourceCount = response.apis.length;
1867     for (k = 0; k < response.apis.length; k++) {
1868       var resource = response.apis[k];
1869       res = new SwaggerResource(resource, this);
1870       this.apis[res.name] = res;
1871       this.apisArray.push(res);
1872     }
1873   }
1874   this.isValid = true;
1875   return this;
1876 };
1877
1878 SwaggerClient.prototype.finish = function() {
1879   if (typeof this.success === 'function') {
1880     this.isValid = true;
1881     this.ready = true;
1882     this.isBuilt = true;
1883     this.selfReflect();
1884     this.success();
1885   }  
1886 };
1887
1888 SwaggerClient.prototype.buildFrom1_1Spec = function (response) {
1889   log('This API is using a deprecated version of Swagger!  Please see http://github.com/wordnik/swagger-core/wiki for more info');
1890   if (response.apiVersion !== null)
1891     this.apiVersion = response.apiVersion;
1892   this.apis = {};
1893   this.apisArray = [];
1894   this.produces = response.produces;
1895   this.info = this.convertInfo(response.info);
1896   var isApi = false, res;
1897   for (var i = 0; i < response.apis.length; i++) {
1898     var api = response.apis[i];
1899     if (api.operations) {
1900       for (var j = 0; j < api.operations.length; j++) {
1901         operation = api.operations[j];
1902         isApi = true;
1903       }
1904     }
1905   }
1906   if (response.basePath) {
1907     this.basePath = response.basePath;
1908   } else if (this.url.indexOf('?') > 0) {
1909     this.basePath = this.url.substring(0, this.url.lastIndexOf('?'));
1910   } else {
1911     this.basePath = this.url;
1912   }
1913   if (isApi) {
1914     var newName = response.resourcePath.replace(/\//g, '');
1915     this.resourcePath = response.resourcePath;
1916     res = new SwaggerResource(response, this);
1917     this.apis[newName] = res;
1918     this.apisArray.push(res);
1919     this.finish();
1920   } else {
1921     this.expectedResourceCount = response.apis.length;
1922     for (k = 0; k < response.apis.length; k++) {
1923       resource = response.apis[k];
1924       res = new SwaggerResource(resource, this);
1925       this.apis[res.name] = res;
1926       this.apisArray.push(res);
1927     }
1928   }
1929   this.isValid = true;
1930   return this;
1931 };
1932
1933 SwaggerClient.prototype.convertInfo = function (resp) {
1934   if(typeof resp == 'object') {
1935     var info = {};
1936
1937     info.title = resp.title;
1938     info.description = resp.description;
1939     info.termsOfService = resp.termsOfServiceUrl;
1940     info.contact = {};
1941     info.contact.name = resp.contact;
1942     info.license = {};
1943     info.license.name = resp.license;
1944     info.license.url = resp.licenseUrl;
1945
1946     return info;
1947   }
1948 };
1949
1950 SwaggerClient.prototype.selfReflect = function () {
1951   var resource, tag, ref;
1952   if (this.apis === null) {
1953     return false;
1954   }
1955   ref = this.apis;
1956   for (tag in ref) {
1957     api = ref[tag];
1958     if (api.ready === null) {
1959       return false;
1960     }
1961     this[tag] = api;
1962     this[tag].help = __bind(api.help, api);
1963   }
1964   this.setConsolidatedModels();
1965   this.ready = true;
1966 };
1967
1968 SwaggerClient.prototype.setConsolidatedModels = function () {
1969   var model, modelName, resource, resource_name, i, apis, models, results;
1970   this.models = {};
1971   apis = this.apis;
1972   for (resource_name in apis) {
1973     resource = apis[resource_name];
1974     for (modelName in resource.models) {
1975       if (typeof this.models[modelName] === 'undefined') {
1976         this.models[modelName] = resource.models[modelName];
1977         this.modelsArray.push(resource.models[modelName]);
1978       }
1979     }
1980   }
1981   models = this.modelsArray;
1982   results = [];
1983   for (i = 0; i < models.length; i++) {
1984     model = models[i];
1985     results.push(model.setReferencedModels(this.models));
1986   }
1987   return results;
1988 };
1989
1990 var SwaggerResource = function (resourceObj, api) {
1991   var _this = this;
1992   this.api = api;
1993   this.swaggerRequstHeaders = api.swaggerRequstHeaders;
1994   this.path = (typeof this.api.resourcePath === 'string') ? this.api.resourcePath : resourceObj.path;
1995   this.description = resourceObj.description;
1996   this.authorizations = (resourceObj.authorizations || {});
1997
1998   var parts = this.path.split('/');
1999   this.name = parts[parts.length - 1].replace('.{format}', '');
2000   this.basePath = this.api.basePath;
2001   this.operations = {};
2002   this.operationsArray = [];
2003   this.modelsArray = [];
2004   this.models = api.models || {};
2005   this.rawModels = {};
2006   this.useJQuery = (typeof api.useJQuery !== 'undefined') ? api.useJQuery : null;
2007
2008   if ((resourceObj.apis) && this.api.resourcePath) {
2009     this.addApiDeclaration(resourceObj);
2010   } else {
2011     if (typeof this.path === 'undefined') {
2012       this.api.fail('SwaggerResources must have a path.');
2013     }
2014     if (this.path.substring(0, 4) === 'http') {
2015       this.url = this.path.replace('{format}', 'json');
2016     } else {
2017       this.url = this.api.basePath + this.path.replace('{format}', 'json');
2018     }
2019     this.api.progress('fetching resource ' + this.name + ': ' + this.url);
2020     var obj = {
2021       url: this.url,
2022       method: 'GET',
2023       useJQuery: this.useJQuery,
2024       headers: {
2025         accept: this.swaggerRequstHeaders
2026       },
2027       on: {
2028         response: function (resp) {
2029           var responseObj = resp.obj || JSON.parse(resp.data);
2030           _this.api.resourceCount += 1;
2031           return _this.addApiDeclaration(responseObj);
2032         },
2033         error: function (response) {
2034           _this.api.resourceCount += 1;
2035           return _this.api.fail('Unable to read api \'' +
2036           _this.name + '\' from path ' + _this.url + ' (server returned ' + response.statusText + ')');
2037         }
2038       }
2039     };
2040     var e = typeof window !== 'undefined' ? window : exports;
2041     e.authorizations.apply(obj);
2042     new SwaggerHttp().execute(obj);
2043   }
2044 };
2045
2046 SwaggerResource.prototype.help = function (dontPrint) {
2047   var i;
2048   var output = 'operations for the "' + this.name + '" tag';
2049   for(i = 0; i < this.operationsArray.length; i++) {
2050     var api = this.operationsArray[i];
2051     output += '\n  * ' + api.nickname + ': ' + api.description;
2052   }
2053   if(dontPrint)
2054     return output;
2055   else {
2056     log(output);
2057     return output;
2058   }
2059 };
2060
2061 SwaggerResource.prototype.getAbsoluteBasePath = function (relativeBasePath) {
2062   var pos, url;
2063   url = this.api.basePath;
2064   pos = url.lastIndexOf(relativeBasePath);
2065   var parts = url.split('/');
2066   var rootUrl = parts[0] + '//' + parts[2];
2067
2068   if (relativeBasePath.indexOf('http') === 0)
2069     return relativeBasePath;
2070   if (relativeBasePath === '/')
2071     return rootUrl;
2072   if (relativeBasePath.substring(0, 1) == '/') {
2073     // use root + relative
2074     return rootUrl + relativeBasePath;
2075   }
2076   else {
2077     pos = this.basePath.lastIndexOf('/');
2078     var base = this.basePath.substring(0, pos);
2079     if (base.substring(base.length - 1) == '/')
2080       return base + relativeBasePath;
2081     else
2082       return base + '/' + relativeBasePath;
2083   }
2084 };
2085
2086 SwaggerResource.prototype.addApiDeclaration = function (response) {
2087   if (typeof response.produces === 'string')
2088     this.produces = response.produces;
2089   if (typeof response.consumes === 'string')
2090     this.consumes = response.consumes;
2091   if ((typeof response.basePath === 'string') && response.basePath.replace(/\s/g, '').length > 0)
2092     this.basePath = response.basePath.indexOf('http') === -1 ? this.getAbsoluteBasePath(response.basePath) : response.basePath;
2093   this.resourcePath = response.resourcePath;
2094   this.addModels(response.models);
2095   if (response.apis) {
2096     for (var i = 0 ; i < response.apis.length; i++) {
2097       var endpoint = response.apis[i];
2098       this.addOperations(endpoint.path, endpoint.operations, response.consumes, response.produces);
2099     }
2100   }
2101   this.api[this.name] = this;
2102   this.ready = true;
2103   if(this.api.resourceCount === this.api.expectedResourceCount)
2104     this.api.finish();
2105   return this;
2106 };
2107
2108 SwaggerResource.prototype.addModels = function (models) {
2109   if (typeof models === 'object') {
2110     var modelName;
2111     for (modelName in models) {
2112       if (typeof this.models[modelName] === 'undefined') {
2113         var swaggerModel = new SwaggerModel(modelName, models[modelName]);
2114         this.modelsArray.push(swaggerModel);
2115         this.models[modelName] = swaggerModel;
2116         this.rawModels[modelName] = models[modelName];
2117       }
2118     }
2119     var output = [];
2120     for (var i = 0; i < this.modelsArray.length; i++) {
2121       var model = this.modelsArray[i];
2122       output.push(model.setReferencedModels(this.models));
2123     }
2124     return output;
2125   }
2126 };
2127
2128 SwaggerResource.prototype.addOperations = function (resource_path, ops, consumes, produces) {
2129   if (ops) {
2130     var output = [];
2131     for (var i = 0; i < ops.length; i++) {
2132       var o = ops[i];
2133       consumes = this.consumes;
2134       produces = this.produces;
2135       if (typeof o.consumes !== 'undefined')
2136         consumes = o.consumes;
2137       else
2138         consumes = this.consumes;
2139
2140       if (typeof o.produces !== 'undefined')
2141         produces = o.produces;
2142       else
2143         produces = this.produces;
2144       var type = (o.type || o.responseClass);
2145
2146       if (type === 'array') {
2147         ref = null;
2148         if (o.items)
2149           ref = o.items.type || o.items.$ref;
2150         type = 'array[' + ref + ']';
2151       }
2152       var responseMessages = o.responseMessages;
2153       var method = o.method;
2154       if (o.httpMethod) {
2155         method = o.httpMethod;
2156       }
2157       if (o.supportedContentTypes) {
2158         consumes = o.supportedContentTypes;
2159       }
2160       if (o.errorResponses) {
2161         responseMessages = o.errorResponses;
2162         for (var j = 0; j < responseMessages.length; j++) {
2163           r = responseMessages[j];
2164           r.message = r.reason;
2165           r.reason = null;
2166         }
2167       }
2168       o.nickname = this.sanitize(o.nickname);
2169       var op = new SwaggerOperation(o.nickname,
2170           resource_path,
2171           method,
2172           o.parameters,
2173           o.summary,
2174           o.notes,
2175           type,
2176           responseMessages, 
2177           this, 
2178           consumes, 
2179           produces, 
2180           o.authorizations, 
2181           o.deprecated);
2182
2183       this.operations[op.nickname] = op;
2184       output.push(this.operationsArray.push(op));
2185     }
2186     return output;
2187   }
2188 };
2189
2190 SwaggerResource.prototype.sanitize = function (nickname) {
2191   var op;
2192   op = nickname.replace(/[\s!@#$%^&*()_+=\[{\]};:<>|.\/?,\\'""-]/g, '_');
2193   op = op.replace(/((_){2,})/g, '_');
2194   op = op.replace(/^(_)*/g, '');
2195   op = op.replace(/([_])*$/g, '');
2196   return op;
2197 };
2198
2199 var SwaggerModel = function (modelName, obj) {
2200   this.name = typeof obj.id !== 'undefined' ? obj.id : modelName;
2201   this.properties = [];
2202   var propertyName;
2203   for (propertyName in obj.properties) {
2204     if (obj.required) {
2205       var value;
2206       for (value in obj.required) {
2207         if (propertyName === obj.required[value]) {
2208           obj.properties[propertyName].required = true;
2209         }
2210       }
2211     }
2212     var prop = new SwaggerModelProperty(propertyName, obj.properties[propertyName], this);
2213     this.properties.push(prop);
2214   }
2215 };
2216
2217 SwaggerModel.prototype.setReferencedModels = function (allModels) {
2218   var results = [];
2219   for (var i = 0; i < this.properties.length; i++) {
2220     var property = this.properties[i];
2221     var type = property.type || property.dataType;
2222     if (allModels[type])
2223       results.push(property.refModel = allModels[type]);
2224     else if ((property.refDataType) && (allModels[property.refDataType]))
2225       results.push(property.refModel = allModels[property.refDataType]);
2226     else
2227       results.push(void 0);
2228   }
2229   return results;
2230 };
2231
2232 SwaggerModel.prototype.getMockSignature = function (modelsToIgnore) {
2233   var i, prop, propertiesStr = [];
2234   for (i = 0; i < this.properties.length; i++) {
2235     prop = this.properties[i];
2236     propertiesStr.push(prop.toString());
2237   }
2238
2239   var strong = '<span class="strong">';
2240   var strongClose = '</span>';
2241   var classOpen = strong + this.name + ' {' + strongClose;
2242   var classClose = strong + '}' + strongClose;
2243   var returnVal = classOpen + '<div>' + propertiesStr.join(',</div><div>') + '</div>' + classClose;
2244   if (!modelsToIgnore)
2245     modelsToIgnore = [];
2246   modelsToIgnore.push(this.name);
2247
2248   for (i = 0; i < this.properties.length; i++) {
2249     prop = this.properties[i];
2250     if ((prop.refModel) && modelsToIgnore.indexOf(prop.refModel.name) === -1) {
2251       returnVal = returnVal + ('<br>' + prop.refModel.getMockSignature(modelsToIgnore));
2252     }
2253   }
2254   return returnVal;
2255 };
2256
2257 SwaggerModel.prototype.createJSONSample = function (modelsToIgnore) {
2258   if (sampleModels[this.name]) {
2259     return sampleModels[this.name];
2260   }
2261   else {
2262     var result = {};
2263     modelsToIgnore = (modelsToIgnore || []);
2264     modelsToIgnore.push(this.name);
2265     for (var i = 0; i < this.properties.length; i++) {
2266       var prop = this.properties[i];
2267       result[prop.name] = prop.getSampleValue(modelsToIgnore);
2268     }
2269     modelsToIgnore.pop(this.name);
2270     return result;
2271   }
2272 };
2273
2274 var SwaggerModelProperty = function (name, obj, model) {
2275   this.name = name;
2276   this.dataType = obj.type || obj.dataType || obj.$ref;
2277   this.isCollection = this.dataType && (this.dataType.toLowerCase() === 'array' || this.dataType.toLowerCase() === 'list' || this.dataType.toLowerCase() === 'set');
2278   this.descr = obj.description;
2279   this.required = obj.required;
2280   this.defaultValue = applyModelPropertyMacro(obj, model);
2281   if (obj.items) {
2282     if (obj.items.type) {
2283       this.refDataType = obj.items.type;
2284     }
2285     if (obj.items.$ref) {
2286       this.refDataType = obj.items.$ref;
2287     }
2288   }
2289   this.dataTypeWithRef = this.refDataType ? (this.dataType + '[' + this.refDataType + ']') : this.dataType;
2290   if (obj.allowableValues) {
2291     this.valueType = obj.allowableValues.valueType;
2292     this.values = obj.allowableValues.values;
2293     if (this.values) {
2294       this.valuesString = '\'' + this.values.join('\' or \'') + '\'';
2295     }
2296   }
2297   if (obj['enum']) {
2298     this.valueType = 'string';
2299     this.values = obj['enum'];
2300     if (this.values) {
2301       this.valueString = '\'' + this.values.join('\' or \'') + '\'';
2302     }
2303   }
2304 };
2305
2306 SwaggerModelProperty.prototype.getSampleValue = function (modelsToIgnore) {
2307   var result;
2308   if ((this.refModel) && (modelsToIgnore.indexOf(this.refModel.name) === -1)) {
2309     result = this.refModel.createJSONSample(modelsToIgnore);
2310   } else {
2311     if (this.isCollection) {
2312       result = this.toSampleValue(this.refDataType);
2313     } else {
2314       result = this.toSampleValue(this.dataType);
2315     }
2316   }
2317   if (this.isCollection) {
2318     return [result];
2319   } else {
2320     return result;
2321   }
2322 };
2323
2324 SwaggerModelProperty.prototype.toSampleValue = function (value) {
2325   var result;
2326   if ((typeof this.defaultValue !== 'undefined') && this.defaultValue) {
2327     result = this.defaultValue;
2328   } else if (value === 'integer') {
2329     result = 0;
2330   } else if (value === 'boolean') {
2331     result = false;
2332   } else if (value === 'double' || value === 'number') {
2333     result = 0.0;
2334   } else if (value === 'string') {
2335     result = '';
2336   } else {
2337     result = value;
2338   }
2339   return result;
2340 };
2341
2342 SwaggerModelProperty.prototype.toString = function () {
2343   var req = this.required ? 'propReq' : 'propOpt';
2344   var str = '<span class="propName ' + req + '">' + this.name + '</span> (<span class="propType">' + this.dataTypeWithRef + '</span>';
2345   if (!this.required) {
2346     str += ', <span class="propOptKey">optional</span>';
2347   }
2348   str += ')';
2349   if (this.values) {
2350     str += ' = <span class="propVals">[\'' + this.values.join('\' or \'') + '\']</span>';
2351   }
2352   if (this.descr) {
2353     str += ': <span class="propDesc">' + this.descr + '</span>';
2354   }
2355   return str;
2356 };
2357
2358 var SwaggerOperation = function (nickname, path, method, parameters, summary, notes, type, responseMessages, resource, consumes, produces, authorizations, deprecated) {
2359   var _this = this;
2360
2361   var errors = [];
2362   this.nickname = (nickname || errors.push('SwaggerOperations must have a nickname.'));
2363   this.path = (path || errors.push('SwaggerOperation ' + nickname + ' is missing path.'));
2364   this.method = (method || errors.push('SwaggerOperation ' + nickname + ' is missing method.'));
2365   this.parameters = parameters ? parameters : [];
2366   this.summary = summary;
2367   this.notes = notes;
2368   this.type = type;
2369   this.responseMessages = (responseMessages || []);
2370   this.resource = (resource || errors.push('Resource is required'));
2371   this.consumes = consumes;
2372   this.produces = produces;
2373   this.authorizations = typeof authorizations !== 'undefined' ? authorizations : resource.authorizations;
2374   this.deprecated = deprecated;
2375   this['do'] = __bind(this['do'], this);
2376
2377
2378   if(typeof this.deprecated === 'string') {
2379     switch(this.deprecated.toLowerCase()) {
2380       case 'true': case 'yes': case '1': {
2381         this.deprecated = true;
2382         break;
2383       }
2384       case 'false': case 'no': case '0': case null: {
2385         this.deprecated = false;
2386         break;
2387       }
2388       default: this.deprecated = Boolean(this.deprecated);
2389     }
2390   }
2391
2392   if (errors.length > 0) {
2393     console.error('SwaggerOperation errors', errors, arguments);
2394     this.resource.api.fail(errors);
2395   }
2396
2397   this.path = this.path.replace('{format}', 'json');
2398   this.method = this.method.toLowerCase();
2399   this.isGetMethod = this.method === 'get';
2400
2401   var i, j, v;
2402   this.resourceName = this.resource.name;
2403   if (typeof this.type !== 'undefined' && this.type === 'void')
2404     this.type = null;
2405   else {
2406     this.responseClassSignature = this.getSignature(this.type, this.resource.models);
2407     this.responseSampleJSON = this.getSampleJSON(this.type, this.resource.models);
2408   }
2409
2410   for (i = 0; i < this.parameters.length; i++) {
2411     var param = this.parameters[i];
2412     // might take this away
2413     param.name = param.name || param.type || param.dataType;
2414     // for 1.1 compatibility
2415     type = param.type || param.dataType;
2416     if (type === 'array') {
2417       type = 'array[' + (param.items.$ref ? param.items.$ref : param.items.type) + ']';
2418     }
2419     param.type = type;
2420
2421     if (type && type.toLowerCase() === 'boolean') {
2422       param.allowableValues = {};
2423       param.allowableValues.values = ['true', 'false'];
2424     }
2425     param.signature = this.getSignature(type, this.resource.models);
2426     param.sampleJSON = this.getSampleJSON(type, this.resource.models);
2427
2428     var enumValue = param['enum'];
2429     if (typeof enumValue !== 'undefined') {
2430       param.isList = true;
2431       param.allowableValues = {};
2432       param.allowableValues.descriptiveValues = [];
2433
2434       for (j = 0; j < enumValue.length; j++) {
2435         v = enumValue[j];
2436         if (param.defaultValue) {
2437           param.allowableValues.descriptiveValues.push({
2438             value: String(v),
2439             isDefault: (v === param.defaultValue)
2440           });
2441         }
2442         else {
2443           param.allowableValues.descriptiveValues.push({
2444             value: String(v),
2445             isDefault: false
2446           });
2447         }
2448       }
2449     }
2450     else if (param.allowableValues) {
2451       if (param.allowableValues.valueType === 'RANGE')
2452         param.isRange = true;
2453       else
2454         param.isList = true;
2455       if (param.allowableValues) {
2456         param.allowableValues.descriptiveValues = [];
2457         if (param.allowableValues.values) {
2458           for (j = 0; j < param.allowableValues.values.length; j++) {
2459             v = param.allowableValues.values[j];
2460             if (param.defaultValue !== null) {
2461               param.allowableValues.descriptiveValues.push({
2462                 value: String(v),
2463                 isDefault: (v === param.defaultValue)
2464               });
2465             }
2466             else {
2467               param.allowableValues.descriptiveValues.push({
2468                 value: String(v),
2469                 isDefault: false
2470               });
2471             }
2472           }
2473         }
2474       }
2475     }
2476     param.defaultValue = applyParameterMacro(this, param);
2477   }
2478   var defaultSuccessCallback = this.resource.api.defaultSuccessCallback || null;
2479   var defaultErrorCallback = this.resource.api.defaultErrorCallback || null;
2480
2481   this.resource[this.nickname] = function (args, opts, callback, error) {
2482     var arg1, arg2, arg3, arg4;
2483     if(typeof args === 'function') {  // right shift 3
2484       arg1 = {}; arg2 = {}; arg3 = args; arg4 = opts;
2485     }
2486     else if(typeof args === 'object' && typeof opts === 'function') { // right shift 2
2487       arg1 = args; arg2 = {}; arg3 = opts; arg4 = callback;
2488     }
2489     else {
2490       arg1 = args; arg2 = opts; arg3 = callback; arg4 = error;
2491     }
2492     return _this['do'](arg1 || {}, arg2 || {}, arg3 || defaultSuccessCallback, arg4 || defaultErrorCallback);
2493   };
2494
2495   this.resource[this.nickname].help = function (dontPrint) {
2496     return _this.help(dontPrint);
2497   };
2498   this.resource[this.nickname].asCurl = function (args) {
2499     return _this.asCurl(args);
2500   };
2501 };
2502
2503 SwaggerOperation.prototype.isListType = function (type) {
2504   if (type && type.indexOf('[') >= 0) {
2505     return type.substring(type.indexOf('[') + 1, type.indexOf(']'));
2506   } else {
2507     return void 0;
2508   }
2509 };
2510
2511 SwaggerOperation.prototype.getSignature = function (type, models) {
2512   var isPrimitive, listType;
2513   listType = this.isListType(type);
2514   isPrimitive = ((typeof listType !== 'undefined') && models[listType]) || (typeof models[type] !== 'undefined') ? false : true;
2515   if (isPrimitive) {
2516     return type;
2517   } else {
2518     if (typeof listType !== 'undefined') {
2519       return models[listType].getMockSignature();
2520     } else {
2521       return models[type].getMockSignature();
2522     }
2523   }
2524 };
2525
2526 SwaggerOperation.prototype.getSampleJSON = function (type, models) {
2527   var isPrimitive, listType, val;
2528   listType = this.isListType(type);
2529   isPrimitive = ((typeof listType !== 'undefined') && models[listType]) || (typeof models[type] !== 'undefined') ? false : true;
2530   val = isPrimitive ? void 0 : (listType ? models[listType].createJSONSample() : models[type].createJSONSample());
2531   if (val) {
2532     val = listType ? [val] : val;
2533     if (typeof val == 'string')
2534       return val;
2535     else if (typeof val === 'object') {
2536       var t = val;
2537       if (val instanceof Array && val.length > 0) {
2538         t = val[0];
2539       }
2540       if (t.nodeName) {
2541         var xmlString = new XMLSerializer().serializeToString(t);
2542         return this.formatXml(xmlString);
2543       }
2544       else
2545         return JSON.stringify(val, null, 2);
2546     }
2547     else
2548       return val;
2549   }
2550 };
2551
2552 SwaggerOperation.prototype['do'] = function (args, opts, callback, error) {
2553   var key, param, params, possibleParams = [], req, value;
2554
2555   if (typeof error !== 'function') {
2556     error = function (xhr, textStatus, error) {
2557       return log(xhr, textStatus, error);
2558     };
2559   }
2560
2561   if (typeof callback !== 'function') {
2562     callback = function (response) {
2563       var content;
2564       content = null;
2565       if (response !== null) {
2566         content = response.data;
2567       } else {
2568         content = 'no data';
2569       }
2570       return log('default callback: ' + content);
2571     };
2572   }
2573
2574   params = {};
2575   params.headers = [];
2576   if (args.headers) {
2577     params.headers = args.headers;
2578     delete args.headers;
2579   }
2580   // allow override from the opts
2581   if(opts && opts.responseContentType) {
2582     params.headers['Content-Type'] = opts.responseContentType;
2583   }
2584   if(opts && opts.requestContentType) {
2585     params.headers.Accept = opts.requestContentType;
2586   }
2587
2588   for (var i = 0; i < this.parameters.length; i++) {
2589     param = this.parameters[i];
2590     if (param.paramType === 'header') {
2591       if (typeof args[param.name] !== 'undefined')
2592         params.headers[param.name] = args[param.name];
2593     }
2594     else if (param.paramType === 'form' || param.paramType.toLowerCase() === 'file')
2595       possibleParams.push(param);
2596     else if (param.paramType === 'body' && param.name !== 'body' && typeof args[param.name] !== 'undefined') {
2597       if (args.body) {
2598         throw new Error('Saw two body params in an API listing; expecting a max of one.');
2599       }
2600       args.body = args[param.name];
2601     }
2602   }
2603
2604   if (typeof args.body !== 'undefined') {
2605     params.body = args.body;
2606     delete args.body;
2607   }
2608
2609   if (possibleParams) {
2610     for (key in possibleParams) {
2611       value = possibleParams[key];
2612       if (args[value.name]) {
2613         params[value.name] = args[value.name];
2614       }
2615     }
2616   }
2617
2618   req = new SwaggerRequest(this.method, this.urlify(args), params, opts, callback, error, this);
2619   if (opts.mock) {
2620     return req;
2621   } else {
2622     return true;
2623   }
2624 };
2625
2626 SwaggerOperation.prototype.pathJson = function () {
2627   return this.path.replace('{format}', 'json');
2628 };
2629
2630 SwaggerOperation.prototype.pathXml = function () {
2631   return this.path.replace('{format}', 'xml');
2632 };
2633
2634 SwaggerOperation.prototype.encodePathParam = function (pathParam) {
2635   var encParts, part, parts, _i, _len;
2636   pathParam = pathParam.toString();
2637   if (pathParam.indexOf('/') === -1) {
2638     return encodeURIComponent(pathParam);
2639   } else {
2640     parts = pathParam.split('/');
2641     encParts = [];
2642     for (_i = 0, _len = parts.length; _i < _len; _i++) {
2643       part = parts[_i];
2644       encParts.push(encodeURIComponent(part));
2645     }
2646     return encParts.join('/');
2647   }
2648 };
2649
2650 SwaggerOperation.prototype.urlify = function (args) {
2651   var i, j, param, url;
2652   // ensure no double slashing...
2653   if(this.resource.basePath.length > 1 && this.resource.basePath.slice(-1) === '/' && this.pathJson().charAt(0) === '/')
2654     url = this.resource.basePath + this.pathJson().substring(1);
2655   else
2656     url = this.resource.basePath + this.pathJson();
2657   var params = this.parameters;
2658   for (i = 0; i < params.length; i++) {
2659     param = params[i];
2660     if (param.paramType === 'path') {
2661       if (typeof args[param.name] !== 'undefined') {
2662         // apply path params and remove from args
2663         var reg = new RegExp('\\{\\s*?' + param.name + '[^\\{\\}\\/]*(?:\\{.*?\\}[^\\{\\}\\/]*)*\\}(?=(\\/?|$))', 'gi');
2664         url = url.replace(reg, this.encodePathParam(args[param.name]));
2665         delete args[param.name];
2666       }
2667       else
2668         throw '' + param.name + ' is a required path param.';
2669     }
2670   }
2671
2672   var queryParams = '';
2673   for (i = 0; i < params.length; i++) {
2674     param = params[i];
2675     if(param.paramType === 'query') {
2676       if (queryParams !== '')
2677         queryParams += '&';    
2678       if (Array.isArray(param)) {
2679         var output = '';   
2680         for(j = 0; j < param.length; j++) {    
2681           if(j > 0)    
2682             output += ',';   
2683           output += encodeURIComponent(param[j]);    
2684         }    
2685         queryParams += encodeURIComponent(param.name) + '=' + output;    
2686       }
2687       else {
2688         if (typeof args[param.name] !== 'undefined') {
2689           queryParams += encodeURIComponent(param.name) + '=' + encodeURIComponent(args[param.name]);
2690         } else {
2691           if (param.required)
2692             throw '' + param.name + ' is a required query param.';
2693         }
2694       }
2695     }
2696   }
2697   if ((queryParams) && queryParams.length > 0)
2698     url += '?' + queryParams;
2699   return url;
2700 };
2701
2702 SwaggerOperation.prototype.supportHeaderParams = function () {
2703   return this.resource.api.supportHeaderParams;
2704 };
2705
2706 SwaggerOperation.prototype.supportedSubmitMethods = function () {
2707   return this.resource.api.supportedSubmitMethods;
2708 };
2709
2710 SwaggerOperation.prototype.getQueryParams = function (args) {
2711   return this.getMatchingParams(['query'], args);
2712 };
2713
2714 SwaggerOperation.prototype.getHeaderParams = function (args) {
2715   return this.getMatchingParams(['header'], args);
2716 };
2717
2718 SwaggerOperation.prototype.getMatchingParams = function (paramTypes, args) {
2719   var matchingParams = {};
2720   var params = this.parameters;
2721   for (var i = 0; i < params.length; i++) {
2722     param = params[i];
2723     if (args && args[param.name])
2724       matchingParams[param.name] = args[param.name];
2725   }
2726   var headers = this.resource.api.headers;
2727   var name;
2728   for (name in headers) {
2729     var value = headers[name];
2730     matchingParams[name] = value;
2731   }
2732   return matchingParams;
2733 };
2734
2735 SwaggerOperation.prototype.help = function (dontPrint) {
2736   var msg = this.nickname + ': ' + this.summary;
2737   var params = this.parameters;
2738   for (var i = 0; i < params.length; i++) {
2739     var param = params[i];
2740     msg += '\n* ' + param.name + (param.required ? ' (required)' : '') + " - " + param.description;
2741   }
2742   if(dontPrint)
2743     return msg;
2744   else {
2745     console.log(msg);
2746     return msg;
2747   }
2748 };
2749
2750 SwaggerOperation.prototype.asCurl = function (args) {
2751   var results = [];
2752   var i;
2753
2754   var headers = SwaggerRequest.prototype.setHeaders(args, {}, this);    
2755   for(i = 0; i < this.parameters.length; i++) {
2756     var param = this.parameters[i];
2757     if(param.paramType && param.paramType === 'header' && args[param.name]) {
2758       headers[param.name] = args[param.name];
2759     }
2760   }
2761
2762   var key;
2763   for (key in headers) {
2764     results.push('--header "' + key + ': ' + headers[key] + '"');
2765   }
2766   return 'curl ' + (results.join(' ')) + ' ' + this.urlify(args);
2767 };
2768
2769 SwaggerOperation.prototype.formatXml = function (xml) {
2770   var contexp, formatted, indent, lastType, lines, ln, pad, reg, transitions, wsexp, _fn, _i, _len;
2771   reg = /(>)(<)(\/*)/g;
2772   wsexp = /[ ]*(.*)[ ]+\n/g;
2773   contexp = /(<.+>)(.+\n)/g;
2774   xml = xml.replace(reg, '$1\n$2$3').replace(wsexp, '$1\n').replace(contexp, '$1\n$2');
2775   pad = 0;
2776   formatted = '';
2777   lines = xml.split('\n');
2778   indent = 0;
2779   lastType = 'other';
2780   transitions = {
2781     'single->single': 0,
2782     'single->closing': -1,
2783     'single->opening': 0,
2784     'single->other': 0,
2785     'closing->single': 0,
2786     'closing->closing': -1,
2787     'closing->opening': 0,
2788     'closing->other': 0,
2789     'opening->single': 1,
2790     'opening->closing': 0,
2791     'opening->opening': 1,
2792     'opening->other': 1,
2793     'other->single': 0,
2794     'other->closing': -1,
2795     'other->opening': 0,
2796     'other->other': 0
2797   };
2798   _fn = function (ln) {
2799     var fromTo, j, key, padding, type, types, value;
2800     types = {
2801       single: Boolean(ln.match(/<.+\/>/)),
2802       closing: Boolean(ln.match(/<\/.+>/)),
2803       opening: Boolean(ln.match(/<[^!?].*>/))
2804     };
2805     type = ((function () {
2806       var _results;
2807       _results = [];
2808       for (key in types) {
2809         value = types[key];
2810         if (value) {
2811           _results.push(key);
2812         }
2813       }
2814       return _results;
2815     })())[0];
2816     type = type === void 0 ? 'other' : type;
2817     fromTo = lastType + '->' + type;
2818     lastType = type;
2819     padding = '';
2820     indent += transitions[fromTo];
2821     padding = ((function () {
2822       var _j, _ref5, _results;
2823       _results = [];
2824       for (j = _j = 0, _ref5 = indent; 0 <= _ref5 ? _j < _ref5 : _j > _ref5; j = 0 <= _ref5 ? ++_j : --_j) {
2825         _results.push('  ');
2826       }
2827       return _results;
2828     })()).join('');
2829     if (fromTo === 'opening->closing') {
2830       formatted = formatted.substr(0, formatted.length - 1) + ln + '\n';
2831     } else {
2832       formatted += padding + ln + '\n';
2833     }
2834   };
2835   for (_i = 0, _len = lines.length; _i < _len; _i++) {
2836     ln = lines[_i];
2837     _fn(ln);
2838   }
2839   return formatted;
2840 };
2841
2842 var SwaggerRequest = function (type, url, params, opts, successCallback, errorCallback, operation, execution) {
2843   var _this = this;
2844   var errors = [];
2845
2846   this.useJQuery = (typeof operation.resource.useJQuery !== 'undefined' ? operation.resource.useJQuery : null);
2847   this.type = (type || errors.push('SwaggerRequest type is required (get/post/put/delete/patch/options).'));
2848   this.url = (url || errors.push('SwaggerRequest url is required.'));
2849   this.params = params;
2850   this.opts = opts;
2851   this.successCallback = (successCallback || errors.push('SwaggerRequest successCallback is required.'));
2852   this.errorCallback = (errorCallback || errors.push('SwaggerRequest error callback is required.'));
2853   this.operation = (operation || errors.push('SwaggerRequest operation is required.'));
2854   this.execution = execution;
2855   this.headers = (params.headers || {});
2856
2857   if (errors.length > 0) {
2858     throw errors;
2859   }
2860
2861   this.type = this.type.toUpperCase();
2862
2863   // set request, response content type headers
2864   var headers = this.setHeaders(params, opts, this.operation);
2865   var body = params.body;
2866
2867   // encode the body for form submits
2868   if (headers['Content-Type']) {
2869     var key, value, values = {}, i;
2870     var operationParams = this.operation.parameters;
2871     for (i = 0; i < operationParams.length; i++) {
2872       var param = operationParams[i];
2873       if (param.paramType === 'form')
2874         values[param.name] = param;
2875     }
2876
2877     if (headers['Content-Type'].indexOf('application/x-www-form-urlencoded') === 0) {
2878       var encoded = '';
2879       for (key in values) {
2880         value = this.params[key];
2881         if (typeof value !== 'undefined') {
2882           if (encoded !== '')
2883             encoded += '&';
2884           encoded += encodeURIComponent(key) + '=' + encodeURIComponent(value);
2885         }
2886       }
2887       body = encoded;
2888     }
2889     else if (headers['Content-Type'].indexOf('multipart/form-data') === 0) {
2890       // encode the body for form submits
2891       var data = '';
2892       var boundary = '----SwaggerFormBoundary' + Date.now();
2893       for (key in values) {
2894         value = this.params[key];
2895         if (typeof value !== 'undefined') {
2896           data += '--' + boundary + '\n';
2897           data += 'Content-Disposition: form-data; name="' + key + '"';
2898           data += '\n\n';
2899           data += value + '\n';
2900         }
2901       }
2902       data += '--' + boundary + '--\n';
2903       headers['Content-Type'] = 'multipart/form-data; boundary=' + boundary;
2904       body = data;
2905     }
2906   }
2907
2908   var obj;
2909   if (!((this.headers) && (this.headers.mock))) {
2910     obj = {
2911       url: this.url,
2912       method: this.type,
2913       headers: headers,
2914       body: body,
2915       useJQuery: this.useJQuery,
2916       on: {
2917         error: function (response) {
2918           return _this.errorCallback(response, _this.opts.parent);
2919         },
2920         redirect: function (response) {
2921           return _this.successCallback(response, _this.opts.parent);
2922         },
2923         307: function (response) {
2924           return _this.successCallback(response, _this.opts.parent);
2925         },
2926         response: function (response) {
2927           return _this.successCallback(response, _this.opts.parent);
2928         }
2929       }
2930     };
2931
2932     var status = false;
2933     if (this.operation.resource && this.operation.resource.api && this.operation.resource.api.clientAuthorizations) {
2934       // Get the client authorizations from the resource declaration
2935       status = this.operation.resource.api.clientAuthorizations.apply(obj, this.operation.authorizations);
2936     } else {
2937       // Get the client authorization from the default authorization declaration
2938       var e;
2939       if (typeof window !== 'undefined') {
2940         e = window;
2941       } else {
2942         e = exports;
2943       }
2944       status = e.authorizations.apply(obj, this.operation.authorizations);
2945     }
2946
2947     if (!opts.mock) {
2948       if (status !== false) {
2949         new SwaggerHttp().execute(obj);
2950       } else {
2951         obj.canceled = true;
2952       }
2953     } else {
2954       return obj;
2955     }
2956   }
2957   return obj;
2958 };
2959
2960 SwaggerRequest.prototype.setHeaders = function (params, opts, operation) {
2961   // default type
2962   var accepts = opts.responseContentType || 'application/json';
2963   var consumes = opts.requestContentType || 'application/json';
2964
2965   var allDefinedParams = operation.parameters;
2966   var definedFormParams = [];
2967   var definedFileParams = [];
2968   var body = params.body;
2969   var headers = {};
2970
2971   // get params from the operation and set them in definedFileParams, definedFormParams, headers
2972   var i;
2973   for (i = 0; i < allDefinedParams.length; i++) {
2974     var param = allDefinedParams[i];
2975     if (param.paramType === 'form')
2976       definedFormParams.push(param);
2977     else if (param.paramType === 'file')
2978       definedFileParams.push(param);
2979     else if (param.paramType === 'header' && this.params.headers) {
2980       var key = param.name;
2981       var headerValue = this.params.headers[param.name];
2982       if (typeof this.params.headers[param.name] !== 'undefined')
2983         headers[key] = headerValue;
2984     }
2985   }
2986
2987   // if there's a body, need to set the accepts header via requestContentType
2988   if (body && (this.type === 'POST' || this.type === 'PUT' || this.type === 'PATCH' || this.type === 'DELETE')) {
2989     if (this.opts.requestContentType)
2990       consumes = this.opts.requestContentType;
2991   } else {
2992     // if any form params, content type must be set
2993     if (definedFormParams.length > 0) {
2994       if (definedFileParams.length > 0)
2995         consumes = 'multipart/form-data';
2996       else
2997         consumes = 'application/x-www-form-urlencoded';
2998     }
2999     else if (this.type === 'DELETE')
3000       body = '{}';
3001     else if (this.type != 'DELETE')
3002       consumes = null;
3003   }
3004
3005   if (consumes && this.operation.consumes) {
3006     if (this.operation.consumes.indexOf(consumes) === -1) {
3007       log('server doesn\'t consume ' + consumes + ', try ' + JSON.stringify(this.operation.consumes));
3008     }
3009   }
3010
3011   if (this.opts && this.opts.responseContentType) {
3012     accepts = this.opts.responseContentType;
3013   } else {
3014     accepts = 'application/json';
3015   }
3016   if (accepts && operation.produces) {
3017     if (operation.produces.indexOf(accepts) === -1) {
3018       log('server can\'t produce ' + accepts);
3019     }
3020   }
3021
3022   if ((consumes && body !== '') || (consumes === 'application/x-www-form-urlencoded'))
3023     headers['Content-Type'] = consumes;
3024   if (accepts)
3025     headers.Accept = accepts;
3026   return headers;
3027 };
3028
3029 /**
3030  * SwaggerHttp is a wrapper for executing requests
3031  */
3032 var SwaggerHttp = function() {};
3033
3034 SwaggerHttp.prototype.execute = function(obj, opts) {
3035   if(obj && (typeof obj.useJQuery === 'boolean'))
3036     this.useJQuery = obj.useJQuery;
3037   else
3038     this.useJQuery = this.isIE8();
3039
3040   if(obj && typeof obj.body === 'object') {
3041     if(obj.body.type && obj.body.type !== 'formData')
3042       obj.body = JSON.stringify(obj.body);
3043     else {
3044       obj.contentType = false;
3045       obj.processData = false;
3046       // delete obj.cache;
3047       delete obj.headers['Content-Type'];
3048     }
3049   }
3050
3051   if(this.useJQuery)
3052     return new JQueryHttpClient(opts).execute(obj);
3053   else
3054     return new ShredHttpClient(opts).execute(obj);
3055 };
3056
3057 SwaggerHttp.prototype.isIE8 = function() {
3058   var detectedIE = false;
3059   if (typeof navigator !== 'undefined' && navigator.userAgent) {
3060     nav = navigator.userAgent.toLowerCase();
3061     if (nav.indexOf('msie') !== -1) {
3062       var version = parseInt(nav.split('msie')[1]);
3063       if (version <= 8) {
3064         detectedIE = true;
3065       }
3066     }
3067   }
3068   return detectedIE;
3069 };
3070
3071 /*
3072  * JQueryHttpClient lets a browser take advantage of JQuery's cross-browser magic.
3073  * NOTE: when jQuery is available it will export both '$' and 'jQuery' to the global space.
3074  *       Since we are using closures here we need to alias it for internal use.
3075  */
3076 var JQueryHttpClient = function(options) {
3077   "use strict";
3078   if(!jQuery){
3079     var jQuery = window.jQuery;
3080   }
3081 };
3082
3083 JQueryHttpClient.prototype.execute = function(obj) {
3084   var cb = obj.on;
3085   var request = obj;
3086
3087   obj.type = obj.method;
3088   obj.cache = false;
3089   delete obj.useJQuery;
3090
3091   /*
3092   obj.beforeSend = function(xhr) {
3093     var key, results;
3094     if (obj.headers) {
3095       results = [];
3096       for (key in obj.headers) {
3097         if (key.toLowerCase() === "content-type") {
3098           results.push(obj.contentType = obj.headers[key]);
3099         } else if (key.toLowerCase() === "accept") {
3100           results.push(obj.accepts = obj.headers[key]);
3101         } else {
3102           results.push(xhr.setRequestHeader(key, obj.headers[key]));
3103         }
3104       }
3105       return results;
3106     }
3107   };*/
3108
3109   obj.data = obj.body;
3110   delete obj.body;
3111   obj.complete = function(response, textStatus, opts) {
3112     var headers = {},
3113       headerArray = response.getAllResponseHeaders().split("\n");
3114
3115     for(var i = 0; i < headerArray.length; i++) {
3116       var toSplit = headerArray[i].trim();
3117       if(toSplit.length === 0)
3118         continue;
3119       var separator = toSplit.indexOf(":");
3120       if(separator === -1) {
3121         // Name but no value in the header
3122         headers[toSplit] = null;
3123         continue;
3124       }
3125       var name = toSplit.substring(0, separator).trim(),
3126         value = toSplit.substring(separator + 1).trim();
3127       headers[name] = value;
3128     }
3129
3130     var out = {
3131       url: request.url,
3132       method: request.method,
3133       status: response.status,
3134       statusText: response.statusText,
3135       data: response.responseText,
3136       headers: headers
3137     };
3138
3139     var contentType = (headers["content-type"]||headers["Content-Type"]||null);
3140     if(contentType) {
3141       if(contentType.indexOf("application/json") === 0 || contentType.indexOf("+json") > 0) {
3142         try {
3143           out.obj = response.responseJSON || JSON.parse(out.data) || {};
3144         } catch (ex) {
3145           // do not set out.obj
3146           log("unable to parse JSON content");
3147         }
3148       }
3149     }
3150
3151     if(response.status >= 200 && response.status < 300)
3152       cb.response(out);
3153     else if(response.status === 0 || (response.status >= 400 && response.status < 599))
3154       cb.error(out);
3155     else
3156       return cb.response(out);
3157   };
3158
3159   jQuery.support.cors = true;
3160   return jQuery.ajax(obj);
3161 };
3162
3163 /*
3164  * ShredHttpClient is a light-weight, node or browser HTTP client
3165  */
3166 var ShredHttpClient = function(opts) {
3167   this.opts = (opts||{});
3168   this.isInitialized = false;
3169
3170   var identity, toString;
3171
3172   if (typeof window !== 'undefined') {
3173     this.Shred = require("./shred");
3174     this.content = require("./shred/content");
3175   }
3176   else
3177     this.Shred = require("shred");
3178   this.shred = new this.Shred(opts);
3179 };
3180
3181 ShredHttpClient.prototype.initShred = function () {
3182   this.isInitialized = true;
3183   this.registerProcessors(this.shred);
3184 };
3185
3186 ShredHttpClient.prototype.registerProcessors = function(shred) {
3187   var identity = function(x) {
3188     return x;
3189   };
3190   var toString = function(x) {
3191     return x.toString();
3192   };
3193
3194   if (typeof window !== 'undefined') {
3195     this.content.registerProcessor(["application/json; charset=utf-8", "application/json", "json"], {
3196       parser: identity,
3197       stringify: toString
3198     });
3199   } else {
3200     this.Shred.registerProcessor(["application/json; charset=utf-8", "application/json", "json"], {
3201       parser: identity,
3202       stringify: toString
3203     });
3204   }
3205 };
3206
3207 ShredHttpClient.prototype.execute = function(obj) {
3208   if(!this.isInitialized)
3209     this.initShred();
3210
3211   var cb = obj.on, res;
3212   var transform = function(response) {
3213     var out = {
3214       headers: response._headers,
3215       url: response.request.url,
3216       method: response.request.method,
3217       status: response.status,
3218       data: response.content.data
3219     };
3220
3221     var headers = response._headers.normalized || response._headers;
3222     var contentType = (headers["content-type"]||headers["Content-Type"]||null);
3223
3224     if(contentType) {
3225       if(contentType.indexOf("application/json") === 0 || contentType.indexOf("+json") > 0) {
3226         if(response.content.data && response.content.data !== "")
3227           try{
3228             out.obj = JSON.parse(response.content.data);
3229           }
3230           catch (e) {
3231             // unable to parse
3232           }
3233         else
3234           out.obj = {};
3235       }
3236     }
3237     return out;
3238   };
3239
3240   // Transform an error into a usable response-like object
3241   var transformError = function (error) {
3242     var out = {
3243       // Default to a status of 0 - The client will treat this as a generic permissions sort of error
3244       status: 0,
3245       data: error.message || error
3246     };
3247
3248     if (error.code) {
3249       out.obj = error;
3250
3251       if (error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED') {
3252         // We can tell the client that this should be treated as a missing resource and not as a permissions thing
3253         out.status = 404;
3254       }
3255     }
3256     return out;
3257   };
3258
3259   res = {
3260     error: function (response) {
3261       if (obj)
3262         return cb.error(transform(response));
3263     },
3264     // Catch the Shred error raised when the request errors as it is made (i.e. No Response is coming)
3265     request_error: function (err) {
3266       if (obj)
3267         return cb.error(transformError(err));
3268     },
3269     response: function (response) {
3270       if (obj) {
3271         return cb.response(transform(response));
3272       }
3273     }
3274   };
3275   if (obj) {
3276     obj.on = res;
3277   }
3278   return this.shred.request(obj);
3279 };
3280
3281
3282 var e = (typeof window !== 'undefined' ? window : exports);
3283
3284 e.authorizations = authorizations = new SwaggerAuthorizations();
3285 e.ApiKeyAuthorization = ApiKeyAuthorization;
3286 e.PasswordAuthorization = PasswordAuthorization;
3287 e.CookieAuthorization = CookieAuthorization;
3288 e.SwaggerClient = SwaggerClient;
3289 e.SwaggerApi = SwaggerClient;
3290 e.Operation = Operation;
3291 e.Model = Model;
3292 e.addModel = addModel;
3293 e.Resolver = Resolver;
3294 })();