Open Lighting Architecture  0.9.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JsonSchema.h
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15  *
16  * JsonSchema.h
17  * A Json Schema, see json-schema.org
18  * Copyright (C) 2014 Simon Newton
19  */
20 
29 #ifndef INCLUDE_OLA_WEB_JSONSCHEMA_H_
30 #define INCLUDE_OLA_WEB_JSONSCHEMA_H_
31 
32 #include <ola/base/Macro.h>
33 #include <ola/stl/STLUtils.h>
34 #include <ola/web/Json.h>
35 #include <ola/web/JsonTypes.h>
36 #include <deque>
37 #include <map>
38 #include <memory>
39 #include <set>
40 #include <string>
41 #include <vector>
42 
43 namespace ola {
44 namespace web {
45 
51 class SchemaDefinitions;
52 
57  public:
61  typedef std::vector<ValidatorInterface*> ValidatorList;
62 
63  virtual ~ValidatorInterface() {}
64 
68  virtual bool IsValid() const = 0;
69 
70  // Do we need a "GetError" here?
71 
77  virtual JsonObject* GetSchema() const = 0;
78 
82  virtual void SetSchema(const std::string &schema) = 0;
83 
87  virtual void SetId(const std::string &id) = 0;
88 
92  virtual void SetTitle(const std::string &title) = 0;
93 
97  virtual void SetDescription(const std::string &title) = 0;
98 
104  virtual void SetDefaultValue(const JsonValue *value) = 0;
105 
114  virtual const JsonValue *GetDefaultValue() const = 0;
115 };
116 
122  protected:
123  explicit BaseValidator(JsonType type)
124  : m_is_valid(true),
125  m_type(type) {
126  }
127 
128  public:
129  virtual ~BaseValidator();
130 
131  virtual bool IsValid() const { return m_is_valid; }
132 
133  virtual void Visit(const JsonString&) {
134  m_is_valid = false;
135  }
136 
137  virtual void Visit(const JsonBool&) {
138  m_is_valid = false;
139  }
140 
141  virtual void Visit(const JsonNull&) {
142  m_is_valid = false;
143  }
144 
145  virtual void Visit(const JsonRawValue&) {
146  m_is_valid = false;
147  }
148 
149  virtual void Visit(const JsonObject&) {
150  m_is_valid = false;
151  }
152 
153  virtual void Visit(const JsonArray&) {
154  m_is_valid = false;
155  }
156 
157  virtual void Visit(const JsonUInt&) {
158  m_is_valid = false;
159  }
160 
161  virtual void Visit(const JsonUInt64&) {
162  m_is_valid = false;
163  }
164 
165  virtual void Visit(const JsonInt&) {
166  m_is_valid = false;
167  }
168 
169  virtual void Visit(const JsonInt64&) {
170  m_is_valid = false;
171  }
172 
173  virtual void Visit(const JsonDouble&) {
174  m_is_valid = false;
175  }
176 
177  virtual JsonObject* GetSchema() const;
178 
182  void SetSchema(const std::string &schema);
183 
187  void SetId(const std::string &id);
188 
192  void SetTitle(const std::string &title);
193 
197  void SetDescription(const std::string &title);
198 
203  void SetDefaultValue(const JsonValue *value);
204 
209  const JsonValue *GetDefaultValue() const;
210 
215  void AddEnumValue(const JsonValue *value);
216 
217  protected:
218  bool m_is_valid;
219  JsonType m_type;
220  std::string m_schema;
221  std::string m_id;
222  std::string m_title;
223  std::string m_description;
224  std::auto_ptr<const JsonValue> m_default_value;
225  std::vector<const JsonValue*> m_enums;
226 
227  bool CheckEnums(const JsonValue &value);
228 
229  // Child classes can hook in here to extend the schema.
230  virtual void ExtendSchema(JsonObject *schema) const {
231  (void) schema;
232  }
233 };
234 
240  public:
242 
243  bool IsValid() const { return true; }
244 };
245 
250  public:
256  ReferenceValidator(const SchemaDefinitions *definitions,
257  const std::string &schema);
258 
259  bool IsValid() const;
260 
261  void Visit(const JsonString &value);
262  void Visit(const JsonBool &value);
263  void Visit(const JsonNull &value);
264  void Visit(const JsonRawValue &value);
265  void Visit(const JsonObject &value);
266  void Visit(const JsonArray &value);
267  void Visit(const JsonUInt &value);
268  void Visit(const JsonUInt64 &value);
269  void Visit(const JsonInt &value);
270  void Visit(const JsonInt64 &value);
271  void Visit(const JsonDouble &value);
272 
273  JsonObject* GetSchema() const;
274 
275  void SetSchema(const std::string &schema);
276  void SetId(const std::string &id);
277  void SetTitle(const std::string &title);
278  void SetDescription(const std::string &title);
279  void SetDefaultValue(const JsonValue *value);
280  const JsonValue *GetDefaultValue() const;
281 
282  private:
283  const SchemaDefinitions *m_definitions;
284  const std::string m_schema;
285  ValidatorInterface *m_validator;
286 
287  template <typename T>
288  void Validate(const T &value);
289 };
290 
295  public:
296  struct Options {
297  Options()
298  : min_length(0),
299  max_length(-1) {
300  }
301 
302  unsigned int min_length;
303  int max_length;
304  // Formats & Regexes aren't supported.
305  // std::string pattern
306  // std::string format
307  };
308 
309  explicit StringValidator(const Options &options)
311  m_options(options) {
312  }
313 
314  void Visit(const JsonString &str);
315 
316  private:
317  const Options m_options;
318 
319  void ExtendSchema(JsonObject *schema) const;
320 
321  DISALLOW_COPY_AND_ASSIGN(StringValidator);
322 };
323 
327 class BoolValidator : public BaseValidator {
328  public:
330 
331  void Visit(const JsonBool &value) { m_is_valid = CheckEnums(value); }
332 
333  private:
334  DISALLOW_COPY_AND_ASSIGN(BoolValidator);
335 };
336 
340 class NullValidator : public BaseValidator {
341  public:
343 
344  void Visit(const JsonNull &value) { m_is_valid = CheckEnums(value); }
345 
346  private:
347  DISALLOW_COPY_AND_ASSIGN(NullValidator);
348 };
349 
355  public:
356  virtual ~NumberConstraint() {}
357 
358  virtual bool IsValid(const JsonNumber &value) = 0;
359 
360  virtual void ExtendSchema(JsonObject *schema) const = 0;
361 };
362 
367  public:
368  explicit MultipleOfConstraint(const JsonNumber *value)
369  : m_multiple_of(value) {
370  }
371 
372  bool IsValid(const JsonNumber &value) {
373  return value.MultipleOf(*m_multiple_of);
374  }
375 
376  void ExtendSchema(JsonObject *schema) const {
377  schema->AddValue("multipleOf", m_multiple_of->Clone());
378  }
379 
380  private:
381  std::auto_ptr<const JsonNumber> m_multiple_of;
382 };
383 
388  public:
394  MaximumConstraint(const JsonNumber *limit, bool is_exclusive)
395  : m_limit(limit),
396  m_has_exclusive(true),
397  m_is_exclusive(is_exclusive) {
398  }
399 
404  explicit MaximumConstraint(const JsonNumber *limit)
405  : m_limit(limit),
406  m_has_exclusive(false) {
407  }
408 
409  bool IsValid(const JsonNumber &value) {
410  return (m_has_exclusive && m_is_exclusive) ? value < *m_limit
411  : value <= *m_limit;
412  }
413 
414  void ExtendSchema(JsonObject *schema) const {
415  schema->AddValue("maximum", m_limit->Clone());
416  if (m_has_exclusive) {
417  schema->Add("exclusiveMaximum", m_is_exclusive);
418  }
419  }
420 
421  private:
422  std::auto_ptr<const JsonNumber> m_limit;
423  bool m_has_exclusive, m_is_exclusive;
424 };
425 
430  public:
436  MinimumConstraint(const JsonNumber *limit, bool is_exclusive)
437  : m_limit(limit),
438  m_has_exclusive(true),
439  m_is_exclusive(is_exclusive) {
440  }
441 
446  explicit MinimumConstraint(const JsonNumber *limit)
447  : m_limit(limit),
448  m_has_exclusive(false) {
449  }
450 
451  bool IsValid(const JsonNumber &value) {
452  return (m_has_exclusive && m_is_exclusive) ? value > *m_limit
453  : value >= *m_limit;
454  }
455 
456  void ExtendSchema(JsonObject *schema) const {
457  schema->AddValue("minimum", m_limit->Clone());
458  if (m_has_exclusive) {
459  schema->Add("exclusiveMinimum", m_is_exclusive);
460  }
461  }
462 
463  private:
464  std::auto_ptr<const JsonNumber> m_limit;
465  bool m_has_exclusive, m_is_exclusive;
466 };
467 
472  public:
474  virtual ~IntegerValidator();
475 
480  void AddConstraint(NumberConstraint *constraint);
481 
482  void Visit(const JsonUInt&);
483  void Visit(const JsonInt&);
484  void Visit(const JsonUInt64&);
485  void Visit(const JsonInt64&);
486  virtual void Visit(const JsonDouble&);
487 
488  protected:
489  explicit IntegerValidator(JsonType type) : BaseValidator(type) {}
490 
491  void CheckValue(const JsonNumber &value);
492 
493  private:
494  std::vector<NumberConstraint*> m_constraints;
495 
496  void ExtendSchema(JsonObject *schema) const;
497 
498  DISALLOW_COPY_AND_ASSIGN(IntegerValidator);
499 };
500 
501 
508  public:
510 
511  void Visit(const JsonDouble&);
512 
513  private:
514  DISALLOW_COPY_AND_ASSIGN(NumberValidator);
515 };
516 
525  public:
526  struct Options {
527  Options()
528  : max_properties(-1),
529  min_properties(0),
530  has_required_properties(false),
531  has_allow_additional_properties(false) {
532  }
533 
534  void SetRequiredProperties(
535  const std::set<std::string> &required_properties_arg) {
536  required_properties = required_properties_arg;
537  has_required_properties = true;
538  }
539 
540  void SetAdditionalProperties(bool allow_additional) {
541  has_allow_additional_properties = true;
542  allow_additional_properties = allow_additional;
543  }
544 
545  int max_properties;
546  unsigned int min_properties;
547  bool has_required_properties;
548  std::set<std::string> required_properties;
549  bool has_allow_additional_properties;
550  bool allow_additional_properties;
551  };
552 
553  explicit ObjectValidator(const Options &options);
554  ~ObjectValidator();
555 
561  void AddValidator(const std::string &property, ValidatorInterface *validator);
562 
568 
578  void AddSchemaDependency(const std::string &property,
579  ValidatorInterface *validator);
580 
590  void AddPropertyDependency(const std::string &property,
591  const std::set<std::string> &properties);
592 
593  void Visit(const JsonObject &obj);
594 
595  void VisitProperty(const std::string &property, const JsonValue &value);
596 
597  private:
598  typedef std::set<std::string> StringSet;
599  typedef std::map<std::string, ValidatorInterface*> PropertyValidators;
600  typedef std::map<std::string, ValidatorInterface*> SchemaDependencies;
601  typedef std::map<std::string, StringSet> PropertyDependencies;
602 
603  const Options m_options;
604 
605  PropertyValidators m_property_validators;
606  std::auto_ptr<ValidatorInterface> m_additional_property_validator;
607  PropertyDependencies m_property_dependencies;
608  SchemaDependencies m_schema_dependencies;
609 
610  StringSet m_seen_properties;
611 
612  void ExtendSchema(JsonObject *schema) const;
613 
614  DISALLOW_COPY_AND_ASSIGN(ObjectValidator);
615 };
616 
621  public:
626  class Items {
627  public:
628  explicit Items(ValidatorInterface *validator)
629  : m_validator(validator) {
630  }
631 
632  explicit Items(ValidatorList *validators)
633  : m_validator(NULL),
634  m_validator_list(*validators) {
635  }
636 
637  ~Items() {
638  STLDeleteElements(&m_validator_list);
639  }
640 
641  ValidatorInterface* Validator() const { return m_validator.get(); }
642  const ValidatorList& Validators() const { return m_validator_list; }
643 
644  private:
645  std::auto_ptr<ValidatorInterface> m_validator;
646  ValidatorList m_validator_list;
647 
648  DISALLOW_COPY_AND_ASSIGN(Items);
649  };
650 
655  public:
656  explicit AdditionalItems(bool allow_additional)
657  : m_allowed(allow_additional),
658  m_validator(NULL) {
659  }
660 
661  explicit AdditionalItems(ValidatorInterface *validator)
662  : m_allowed(true),
663  m_validator(validator) {
664  }
665 
666  ValidatorInterface* Validator() const { return m_validator.get(); }
667  bool AllowAdditional() const { return m_allowed; }
668 
669  private:
670  bool m_allowed;
671  std::auto_ptr<ValidatorInterface> m_validator;
672 
673  DISALLOW_COPY_AND_ASSIGN(AdditionalItems);
674  };
675 
676  struct Options {
677  Options()
678  : max_items(-1),
679  min_items(0),
680  unique_items(false) {
681  }
682 
683  int max_items;
684  unsigned int min_items;
685  bool unique_items;
686  };
687 
695  ArrayValidator(Items *items, AdditionalItems *additional_items,
696  const Options &options);
697 
698  ~ArrayValidator();
699 
700  void Visit(const JsonArray &array);
701 
702  private:
703  typedef std::deque<ValidatorInterface*> ValidatorQueue;
704 
705  const std::auto_ptr<Items> m_items;
706  const std::auto_ptr<AdditionalItems> m_additional_items;
707  const Options m_options;
708 
709  // This is used if items is missing, or if additionalItems is true.
710  std::auto_ptr<WildcardValidator> m_wildcard_validator;
711 
712  class ArrayElementValidator : public BaseValidator {
713  public:
714  ArrayElementValidator(const ValidatorList &validators,
715  ValidatorInterface *default_validator);
716 
717  void Visit(const JsonString&);
718  void Visit(const JsonBool&);
719  void Visit(const JsonNull&);
720  void Visit(const JsonRawValue&);
721  void Visit(const JsonObject&);
722  void Visit(const JsonArray &array);
723  void Visit(const JsonUInt&);
724  void Visit(const JsonUInt64&);
725  void Visit(const JsonInt&);
726  void Visit(const JsonInt64&);
727  void Visit(const JsonDouble&);
728 
729  private:
730  ValidatorQueue m_item_validators;
731  ValidatorInterface *m_default_validator;
732 
733  template <typename T>
734  void ValidateItem(const T &item);
735 
736  DISALLOW_COPY_AND_ASSIGN(ArrayElementValidator);
737  };
738 
739  void ExtendSchema(JsonObject *schema) const;
740  ArrayElementValidator* ConstructElementValidator() const;
741 
742  DISALLOW_COPY_AND_ASSIGN(ArrayValidator);
743 };
744 
745 
751  public:
758  ConjunctionValidator(const std::string &keyword, ValidatorList *validators);
759  virtual ~ConjunctionValidator();
760 
761  void Visit(const JsonString &value) {
762  Validate(value);
763  }
764 
765  void Visit(const JsonBool &value) {
766  Validate(value);
767  }
768 
769  void Visit(const JsonNull &value) {
770  Validate(value);
771  }
772 
773  void Visit(const JsonRawValue &value) {
774  Validate(value);
775  }
776 
777  void Visit(const JsonObject &value) {
778  Validate(value);
779  }
780 
781  void Visit(const JsonArray &value) {
782  Validate(value);
783  }
784 
785  void Visit(const JsonUInt &value) {
786  Validate(value);
787  }
788 
789  void Visit(const JsonUInt64 &value) {
790  Validate(value);
791  }
792 
793  void Visit(const JsonInt &value) {
794  Validate(value);
795  }
796 
797  void Visit(const JsonInt64 &value) {
798  Validate(value);
799  }
800 
801  void Visit(const JsonDouble &value) {
802  Validate(value);
803  }
804 
805  protected:
806  std::string m_keyword;
807  ValidatorList m_validators;
808 
809  void ExtendSchema(JsonObject *schema) const;
810 
811  virtual void Validate(const JsonValue &value) = 0;
812 };
813 
818  public:
824  explicit AllOfValidator(ValidatorList *validators)
825  : ConjunctionValidator("allOf", validators) {
826  }
827 
828  protected:
829  void Validate(const JsonValue &value);
830 
831  private:
832  DISALLOW_COPY_AND_ASSIGN(AllOfValidator);
833 };
834 
840  public:
846  explicit AnyOfValidator(ValidatorList *validators)
847  : ConjunctionValidator("anyOf", validators) {
848  }
849 
850  protected:
851  void Validate(const JsonValue &value);
852 
853  private:
854  DISALLOW_COPY_AND_ASSIGN(AnyOfValidator);
855 };
856 
862  public:
868  explicit OneOfValidator(ValidatorList *validators)
869  : ConjunctionValidator("oneOf", validators) {
870  }
871 
872  protected:
873  void Validate(const JsonValue &value);
874 
875  private:
876  DISALLOW_COPY_AND_ASSIGN(OneOfValidator);
877 };
878 
882 class NotValidator : public BaseValidator {
883  public:
884  explicit NotValidator(ValidatorInterface *validator)
886  m_validator(validator) {
887  }
888 
889  void Visit(const JsonString &value) {
890  Validate(value);
891  }
892 
893  void Visit(const JsonBool &value) {
894  Validate(value);
895  }
896 
897  void Visit(const JsonNull &value) {
898  Validate(value);
899  }
900 
901  void Visit(const JsonRawValue &value) {
902  Validate(value);
903  }
904 
905  void Visit(const JsonObject &value) {
906  Validate(value);
907  }
908 
909  void Visit(const JsonArray &value) {
910  Validate(value);
911  }
912 
913  void Visit(const JsonUInt &value) {
914  Validate(value);
915  }
916 
917  void Visit(const JsonUInt64 &value) {
918  Validate(value);
919  }
920 
921  void Visit(const JsonInt &value) {
922  Validate(value);
923  }
924 
925  void Visit(const JsonInt64 &value) {
926  Validate(value);
927  }
928 
929  void Visit(const JsonDouble &value) {
930  Validate(value);
931  }
932 
933  private:
934  std::auto_ptr<ValidatorInterface> m_validator;
935 
936  void Validate(const JsonValue &value);
937 
938  void ExtendSchema(JsonObject *schema) const;
939 
940  DISALLOW_COPY_AND_ASSIGN(NotValidator);
941 };
942 
944  public:
945  SchemaDefinitions() {}
947 
948  void Add(const std::string &schema_name, ValidatorInterface *validator);
949  ValidatorInterface *Lookup(const std::string &schema_name) const;
950 
951  void AddToJsonObject(JsonObject *json) const;
952 
953  bool HasDefinitions() const { return !m_validators.empty(); }
954 
955  private:
956  typedef std::map<std::string, ValidatorInterface*> SchemaMap;
957 
958  SchemaMap m_validators;
959 
960  DISALLOW_COPY_AND_ASSIGN(SchemaDefinitions);
961 };
962 
963 
967 class JsonSchema {
968  public:
969  ~JsonSchema() {}
970 
971  /*
972  * @brief The URI which defines which version of the schema this is.
973  */
974  std::string SchemaURI() const;
975 
979  bool IsValid(const JsonValue &value);
980 
984  const JsonObject* AsJson() const;
985 
990  static JsonSchema* FromString(const std::string& schema_string,
991  std::string *error);
992 
993  private:
994  std::string m_schema_uri;
995  std::auto_ptr<ValidatorInterface> m_root_validator;
996  std::auto_ptr<SchemaDefinitions> m_schema_defs;
997 
998  JsonSchema(const std::string &schema_url,
999  ValidatorInterface *root_validator,
1000  SchemaDefinitions *schema_defs);
1001 
1002  DISALLOW_COPY_AND_ASSIGN(JsonSchema);
1003 };
1004 
1006 } // namespace web
1007 } // namespace ola
1008 #endif // INCLUDE_OLA_WEB_JSONSCHEMA_H_