Open Lighting Architecture  0.9.5
 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  m_is_exclusive(false) {
408  }
409 
410  bool IsValid(const JsonNumber &value) {
411  return (m_has_exclusive && m_is_exclusive) ? value < *m_limit
412  : value <= *m_limit;
413  }
414 
415  void ExtendSchema(JsonObject *schema) const {
416  schema->AddValue("maximum", m_limit->Clone());
417  if (m_has_exclusive) {
418  schema->Add("exclusiveMaximum", m_is_exclusive);
419  }
420  }
421 
422  private:
423  std::auto_ptr<const JsonNumber> m_limit;
424  bool m_has_exclusive, m_is_exclusive;
425 };
426 
431  public:
437  MinimumConstraint(const JsonNumber *limit, bool is_exclusive)
438  : m_limit(limit),
439  m_has_exclusive(true),
440  m_is_exclusive(is_exclusive) {
441  }
442 
447  explicit MinimumConstraint(const JsonNumber *limit)
448  : m_limit(limit),
449  m_has_exclusive(false),
450  m_is_exclusive(false) {
451  }
452 
453  bool IsValid(const JsonNumber &value) {
454  return (m_has_exclusive && m_is_exclusive) ? value > *m_limit
455  : value >= *m_limit;
456  }
457 
458  void ExtendSchema(JsonObject *schema) const {
459  schema->AddValue("minimum", m_limit->Clone());
460  if (m_has_exclusive) {
461  schema->Add("exclusiveMinimum", m_is_exclusive);
462  }
463  }
464 
465  private:
466  std::auto_ptr<const JsonNumber> m_limit;
467  bool m_has_exclusive, m_is_exclusive;
468 };
469 
474  public:
476  virtual ~IntegerValidator();
477 
482  void AddConstraint(NumberConstraint *constraint);
483 
484  void Visit(const JsonUInt&);
485  void Visit(const JsonInt&);
486  void Visit(const JsonUInt64&);
487  void Visit(const JsonInt64&);
488  virtual void Visit(const JsonDouble&);
489 
490  protected:
491  explicit IntegerValidator(JsonType type) : BaseValidator(type) {}
492 
493  void CheckValue(const JsonNumber &value);
494 
495  private:
496  std::vector<NumberConstraint*> m_constraints;
497 
498  void ExtendSchema(JsonObject *schema) const;
499 
500  DISALLOW_COPY_AND_ASSIGN(IntegerValidator);
501 };
502 
503 
510  public:
512 
513  void Visit(const JsonDouble&);
514 
515  private:
516  DISALLOW_COPY_AND_ASSIGN(NumberValidator);
517 };
518 
527  public:
528  struct Options {
529  Options()
530  : max_properties(-1),
531  min_properties(0),
532  has_required_properties(false),
533  has_allow_additional_properties(false),
534  allow_additional_properties(false) {
535  }
536 
537  void SetRequiredProperties(
538  const std::set<std::string> &required_properties_arg) {
539  required_properties = required_properties_arg;
540  has_required_properties = true;
541  }
542 
543  void SetAdditionalProperties(bool allow_additional) {
544  has_allow_additional_properties = true;
545  allow_additional_properties = allow_additional;
546  }
547 
548  int max_properties;
549  unsigned int min_properties;
550  bool has_required_properties;
551  std::set<std::string> required_properties;
552  bool has_allow_additional_properties;
553  bool allow_additional_properties;
554  };
555 
556  explicit ObjectValidator(const Options &options);
557  ~ObjectValidator();
558 
564  void AddValidator(const std::string &property, ValidatorInterface *validator);
565 
571 
581  void AddSchemaDependency(const std::string &property,
582  ValidatorInterface *validator);
583 
593  void AddPropertyDependency(const std::string &property,
594  const std::set<std::string> &properties);
595 
596  void Visit(const JsonObject &obj);
597 
598  void VisitProperty(const std::string &property, const JsonValue &value);
599 
600  private:
601  typedef std::set<std::string> StringSet;
602  typedef std::map<std::string, ValidatorInterface*> PropertyValidators;
603  typedef std::map<std::string, ValidatorInterface*> SchemaDependencies;
604  typedef std::map<std::string, StringSet> PropertyDependencies;
605 
606  const Options m_options;
607 
608  PropertyValidators m_property_validators;
609  std::auto_ptr<ValidatorInterface> m_additional_property_validator;
610  PropertyDependencies m_property_dependencies;
611  SchemaDependencies m_schema_dependencies;
612 
613  StringSet m_seen_properties;
614 
615  void ExtendSchema(JsonObject *schema) const;
616 
617  DISALLOW_COPY_AND_ASSIGN(ObjectValidator);
618 };
619 
624  public:
629  class Items {
630  public:
631  explicit Items(ValidatorInterface *validator)
632  : m_validator(validator) {
633  }
634 
635  explicit Items(ValidatorList *validators)
636  : m_validator(NULL),
637  m_validator_list(*validators) {
638  }
639 
640  ~Items() {
641  STLDeleteElements(&m_validator_list);
642  }
643 
644  ValidatorInterface* Validator() const { return m_validator.get(); }
645  const ValidatorList& Validators() const { return m_validator_list; }
646 
647  private:
648  std::auto_ptr<ValidatorInterface> m_validator;
649  ValidatorList m_validator_list;
650 
651  DISALLOW_COPY_AND_ASSIGN(Items);
652  };
653 
658  public:
659  explicit AdditionalItems(bool allow_additional)
660  : m_allowed(allow_additional),
661  m_validator(NULL) {
662  }
663 
664  explicit AdditionalItems(ValidatorInterface *validator)
665  : m_allowed(true),
666  m_validator(validator) {
667  }
668 
669  ValidatorInterface* Validator() const { return m_validator.get(); }
670  bool AllowAdditional() const { return m_allowed; }
671 
672  private:
673  bool m_allowed;
674  std::auto_ptr<ValidatorInterface> m_validator;
675 
676  DISALLOW_COPY_AND_ASSIGN(AdditionalItems);
677  };
678 
679  struct Options {
680  Options()
681  : max_items(-1),
682  min_items(0),
683  unique_items(false) {
684  }
685 
686  int max_items;
687  unsigned int min_items;
688  bool unique_items;
689  };
690 
698  ArrayValidator(Items *items, AdditionalItems *additional_items,
699  const Options &options);
700 
701  ~ArrayValidator();
702 
703  void Visit(const JsonArray &array);
704 
705  private:
706  typedef std::deque<ValidatorInterface*> ValidatorQueue;
707 
708  const std::auto_ptr<Items> m_items;
709  const std::auto_ptr<AdditionalItems> m_additional_items;
710  const Options m_options;
711 
712  // This is used if items is missing, or if additionalItems is true.
713  std::auto_ptr<WildcardValidator> m_wildcard_validator;
714 
715  class ArrayElementValidator : public BaseValidator {
716  public:
717  ArrayElementValidator(const ValidatorList &validators,
718  ValidatorInterface *default_validator);
719 
720  void Visit(const JsonString&);
721  void Visit(const JsonBool&);
722  void Visit(const JsonNull&);
723  void Visit(const JsonRawValue&);
724  void Visit(const JsonObject&);
725  void Visit(const JsonArray &array);
726  void Visit(const JsonUInt&);
727  void Visit(const JsonUInt64&);
728  void Visit(const JsonInt&);
729  void Visit(const JsonInt64&);
730  void Visit(const JsonDouble&);
731 
732  private:
733  ValidatorQueue m_item_validators;
734  ValidatorInterface *m_default_validator;
735 
736  template <typename T>
737  void ValidateItem(const T &item);
738 
739  DISALLOW_COPY_AND_ASSIGN(ArrayElementValidator);
740  };
741 
742  void ExtendSchema(JsonObject *schema) const;
743  ArrayElementValidator* ConstructElementValidator() const;
744 
745  DISALLOW_COPY_AND_ASSIGN(ArrayValidator);
746 };
747 
748 
754  public:
761  ConjunctionValidator(const std::string &keyword, ValidatorList *validators);
762  virtual ~ConjunctionValidator();
763 
764  void Visit(const JsonString &value) {
765  Validate(value);
766  }
767 
768  void Visit(const JsonBool &value) {
769  Validate(value);
770  }
771 
772  void Visit(const JsonNull &value) {
773  Validate(value);
774  }
775 
776  void Visit(const JsonRawValue &value) {
777  Validate(value);
778  }
779 
780  void Visit(const JsonObject &value) {
781  Validate(value);
782  }
783 
784  void Visit(const JsonArray &value) {
785  Validate(value);
786  }
787 
788  void Visit(const JsonUInt &value) {
789  Validate(value);
790  }
791 
792  void Visit(const JsonUInt64 &value) {
793  Validate(value);
794  }
795 
796  void Visit(const JsonInt &value) {
797  Validate(value);
798  }
799 
800  void Visit(const JsonInt64 &value) {
801  Validate(value);
802  }
803 
804  void Visit(const JsonDouble &value) {
805  Validate(value);
806  }
807 
808  protected:
809  std::string m_keyword;
810  ValidatorList m_validators;
811 
812  void ExtendSchema(JsonObject *schema) const;
813 
814  virtual void Validate(const JsonValue &value) = 0;
815 };
816 
821  public:
827  explicit AllOfValidator(ValidatorList *validators)
828  : ConjunctionValidator("allOf", validators) {
829  }
830 
831  protected:
832  void Validate(const JsonValue &value);
833 
834  private:
835  DISALLOW_COPY_AND_ASSIGN(AllOfValidator);
836 };
837 
843  public:
849  explicit AnyOfValidator(ValidatorList *validators)
850  : ConjunctionValidator("anyOf", validators) {
851  }
852 
853  protected:
854  void Validate(const JsonValue &value);
855 
856  private:
857  DISALLOW_COPY_AND_ASSIGN(AnyOfValidator);
858 };
859 
865  public:
871  explicit OneOfValidator(ValidatorList *validators)
872  : ConjunctionValidator("oneOf", validators) {
873  }
874 
875  protected:
876  void Validate(const JsonValue &value);
877 
878  private:
879  DISALLOW_COPY_AND_ASSIGN(OneOfValidator);
880 };
881 
885 class NotValidator : public BaseValidator {
886  public:
887  explicit NotValidator(ValidatorInterface *validator)
889  m_validator(validator) {
890  }
891 
892  void Visit(const JsonString &value) {
893  Validate(value);
894  }
895 
896  void Visit(const JsonBool &value) {
897  Validate(value);
898  }
899 
900  void Visit(const JsonNull &value) {
901  Validate(value);
902  }
903 
904  void Visit(const JsonRawValue &value) {
905  Validate(value);
906  }
907 
908  void Visit(const JsonObject &value) {
909  Validate(value);
910  }
911 
912  void Visit(const JsonArray &value) {
913  Validate(value);
914  }
915 
916  void Visit(const JsonUInt &value) {
917  Validate(value);
918  }
919 
920  void Visit(const JsonUInt64 &value) {
921  Validate(value);
922  }
923 
924  void Visit(const JsonInt &value) {
925  Validate(value);
926  }
927 
928  void Visit(const JsonInt64 &value) {
929  Validate(value);
930  }
931 
932  void Visit(const JsonDouble &value) {
933  Validate(value);
934  }
935 
936  private:
937  std::auto_ptr<ValidatorInterface> m_validator;
938 
939  void Validate(const JsonValue &value);
940 
941  void ExtendSchema(JsonObject *schema) const;
942 
943  DISALLOW_COPY_AND_ASSIGN(NotValidator);
944 };
945 
947  public:
948  SchemaDefinitions() {}
950 
951  void Add(const std::string &schema_name, ValidatorInterface *validator);
952  ValidatorInterface *Lookup(const std::string &schema_name) const;
953 
954  void AddToJsonObject(JsonObject *json) const;
955 
956  bool HasDefinitions() const { return !m_validators.empty(); }
957 
958  private:
959  typedef std::map<std::string, ValidatorInterface*> SchemaMap;
960 
961  SchemaMap m_validators;
962 
963  DISALLOW_COPY_AND_ASSIGN(SchemaDefinitions);
964 };
965 
966 
970 class JsonSchema {
971  public:
972  ~JsonSchema() {}
973 
974  /*
975  * @brief The URI which defines which version of the schema this is.
976  */
977  std::string SchemaURI() const;
978 
982  bool IsValid(const JsonValue &value);
983 
987  const JsonObject* AsJson() const;
988 
993  static JsonSchema* FromString(const std::string& schema_string,
994  std::string *error);
995 
996  private:
997  std::string m_schema_uri;
998  std::auto_ptr<ValidatorInterface> m_root_validator;
999  std::auto_ptr<SchemaDefinitions> m_schema_defs;
1000 
1001  JsonSchema(const std::string &schema_url,
1002  ValidatorInterface *root_validator,
1003  SchemaDefinitions *schema_defs);
1004 
1005  DISALLOW_COPY_AND_ASSIGN(JsonSchema);
1006 };
1007 
1009 } // namespace web
1010 } // namespace ola
1011 #endif // INCLUDE_OLA_WEB_JSONSCHEMA_H_