1 /**
2  * Orthanc - A Lightweight, RESTful DICOM Store
3  * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4  * Department, University Hospital of Liege, Belgium
5  * Copyright (C) 2017-2021 Osimis S.A., Belgium
6  *
7  * This program is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation, either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program. If not, see
19  * <http://www.gnu.org/licenses/>.
20  **/
21 
22 
23 #pragma once
24 
25 #include "../Enumerations.h"
26 
27 #include <boost/noncopyable.hpp>
28 #include <json/value.h>
29 
30 #include <map>
31 #include <set>
32 
33 namespace Orthanc
34 {
35   class RestApiCallDocumentation : public boost::noncopyable
36   {
37   public:
38     enum Type
39     {
40       Type_Unknown,
41       Type_Text,
42       Type_String,
43       Type_Number,
44       Type_Boolean,
45       Type_JsonListOfStrings,
46       Type_JsonListOfObjects,
47       Type_JsonObject
48     };
49 
50   private:
51     class Parameter
52     {
53     private:
54       Type         type_;
55       std::string  description_;
56       bool         required_;
57 
58     public:
Parameter()59       Parameter() :
60         type_(Type_Unknown),
61         required_(false)
62       {
63       }
64 
Parameter(Type type,const std::string & description,bool required)65       Parameter(Type type,
66                 const std::string& description,
67                 bool required) :
68         type_(type),
69         description_(description),
70         required_(required)
71       {
72       }
73 
GetType()74       Type GetType() const
75       {
76         return type_;
77       }
78 
GetDescription()79       const std::string& GetDescription() const
80       {
81         return description_;
82       }
83 
IsRequired()84       bool IsRequired() const
85       {
86         return required_;
87       }
88     };
89 
90     typedef std::map<std::string, Parameter>  Parameters;
91     typedef std::map<MimeType, std::string>   AllowedTypes;
92 
93     HttpMethod    method_;
94     std::string   tag_;
95     std::string   summary_;
96     std::string   description_;
97     Parameters    uriArguments_;
98     Parameters    httpHeaders_;
99     Parameters    getArguments_;
100     AllowedTypes  requestTypes_;
101     Parameters    requestFields_;  // For JSON request
102     AllowedTypes  answerTypes_;
103     Parameters    answerFields_;  // Only if JSON object
104     std::string   answerDescription_;
105     Parameters    answerHeaders_;
106     bool          hasSampleText_;
107     std::string   sampleText_;
108     Json::Value   sampleJson_;
109     bool          deprecated_;
110 
111   public:
RestApiCallDocumentation(HttpMethod method)112     explicit RestApiCallDocumentation(HttpMethod method) :
113       method_(method),
114       hasSampleText_(false),
115       sampleJson_(Json::nullValue),
116       deprecated_(false)
117     {
118     }
119 
SetTag(const std::string & tag)120     RestApiCallDocumentation& SetTag(const std::string& tag)
121     {
122       tag_ = tag;
123       return *this;
124     }
125 
SetSummary(const std::string & summary)126     RestApiCallDocumentation& SetSummary(const std::string& summary)
127     {
128       summary_ = summary;
129       return *this;
130     }
131 
SetDescription(const std::string & description)132     RestApiCallDocumentation& SetDescription(const std::string& description)
133     {
134       description_ = description;
135       return *this;
136     }
137 
138     RestApiCallDocumentation& AddRequestType(MimeType mime,
139                                              const std::string& description);
140 
141     RestApiCallDocumentation& SetRequestField(const std::string& name,
142                                               Type type,
143                                               const std::string& description,
144                                               bool required);
145 
146     RestApiCallDocumentation& AddAnswerType(MimeType type,
147                                             const std::string& description);
148 
149     RestApiCallDocumentation& SetUriArgument(const std::string& name,
150                                              Type type,
151                                              const std::string& description);
152 
SetUriArgument(const std::string & name,const std::string & description)153     RestApiCallDocumentation& SetUriArgument(const std::string& name,
154                                              const std::string& description)
155     {
156       return SetUriArgument(name, Type_String, description);
157     }
158 
HasUriArgument(const std::string & name)159     bool HasUriArgument(const std::string& name) const
160     {
161       return (uriArguments_.find(name) != uriArguments_.end());
162     }
163 
164     RestApiCallDocumentation& SetHttpHeader(const std::string& name,
165                                             const std::string& description);
166 
167     RestApiCallDocumentation& SetHttpGetArgument(const std::string& name,
168                                                  Type type,
169                                                  const std::string& description,
170                                                  bool required);
171 
172     RestApiCallDocumentation& SetAnswerField(const std::string& name,
173                                              Type type,
174                                              const std::string& description);
175 
176     RestApiCallDocumentation& SetAnswerHeader(const std::string& name,
177                                               const std::string& description);
178 
179     void SetHttpGetSample(const std::string& url,
180                           bool isJson);
181 
182     void SetTruncatedJsonHttpGetSample(const std::string& url,
183                                        size_t size);
184 
SetSample(const Json::Value & sample)185     void SetSample(const Json::Value& sample)
186     {
187       sampleJson_ = sample;
188     }
189 
190     bool FormatOpenApi(Json::Value& target,
191                        const std::set<std::string>& expectedUriArguments,
192                        const std::string& uri /* only used in logs */) const;
193 
HasSummary()194     bool HasSummary() const
195     {
196       return !summary_.empty();
197     }
198 
GetSummary()199     const std::string& GetSummary() const
200     {
201       return summary_;
202     }
203 
GetTag()204     const std::string& GetTag() const
205     {
206       return tag_;
207     }
208 
SetDeprecated()209     RestApiCallDocumentation& SetDeprecated()
210     {
211       deprecated_ = true;
212       return *this;
213     }
214 
IsDeprecated()215     bool IsDeprecated() const
216     {
217       return deprecated_;
218     }
219   };
220 }
221