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