github.com/kaptinlin/jsonschema@v0.4.6/result.go (about)

     1  package jsonschema
     2  
     3  import "github.com/kaptinlin/go-i18n"
     4  
     5  type EvaluationError struct {
     6  	Keyword string                 `json:"keyword"`
     7  	Code    string                 `json:"code"`
     8  	Message string                 `json:"message"`
     9  	Params  map[string]interface{} `json:"params"`
    10  }
    11  
    12  func NewEvaluationError(keyword string, code string, message string, params ...map[string]interface{}) *EvaluationError {
    13  	if len(params) > 0 {
    14  		return &EvaluationError{
    15  			Keyword: keyword,
    16  			Code:    code,
    17  			Message: message,
    18  			Params:  params[0],
    19  		}
    20  	} else {
    21  		return &EvaluationError{
    22  			Keyword: keyword,
    23  			Code:    code,
    24  			Message: message,
    25  		}
    26  	}
    27  }
    28  
    29  func (e *EvaluationError) Error() string {
    30  	return replace(e.Message, e.Params)
    31  }
    32  
    33  func (e *EvaluationError) Localize(localizer *i18n.Localizer) string {
    34  	if localizer != nil {
    35  		return localizer.Get(e.Code, i18n.Vars(e.Params))
    36  	} else {
    37  		return e.Error()
    38  	}
    39  }
    40  
    41  type Flag struct {
    42  	Valid bool `json:"valid"`
    43  }
    44  
    45  type List struct {
    46  	Valid            bool                   `json:"valid"`
    47  	EvaluationPath   string                 `json:"evaluationPath"`
    48  	SchemaLocation   string                 `json:"schemaLocation"`
    49  	InstanceLocation string                 `json:"instanceLocation"`
    50  	Annotations      map[string]interface{} `json:"annotations,omitempty"`
    51  	Errors           map[string]string      `json:"errors,omitempty"`
    52  	Details          []List                 `json:"details,omitempty"`
    53  }
    54  
    55  type EvaluationResult struct {
    56  	schema           *Schema                     `json:"-"`
    57  	Valid            bool                        `json:"valid"`
    58  	EvaluationPath   string                      `json:"evaluationPath"`
    59  	SchemaLocation   string                      `json:"schemaLocation"`
    60  	InstanceLocation string                      `json:"instanceLocation"`
    61  	Annotations      map[string]interface{}      `json:"annotations,omitempty"`
    62  	Errors           map[string]*EvaluationError `json:"errors,omitempty"` // Store error messages here
    63  	Details          []*EvaluationResult         `json:"details,omitempty"`
    64  }
    65  
    66  func NewEvaluationResult(schema *Schema) *EvaluationResult {
    67  	e := &EvaluationResult{
    68  		schema: schema,
    69  		Valid:  true,
    70  	}
    71  	//nolint:errcheck
    72  	e.CollectAnnotations()
    73  
    74  	return e
    75  }
    76  
    77  func (e *EvaluationResult) SetEvaluationPath(evaluationPath string) *EvaluationResult {
    78  	e.EvaluationPath = evaluationPath
    79  
    80  	return e
    81  }
    82  
    83  func (e *EvaluationResult) Error() string {
    84  	return "evaluation failed"
    85  }
    86  
    87  func (e *EvaluationResult) SetSchemaLocation(location string) *EvaluationResult {
    88  	e.SchemaLocation = location
    89  
    90  	return e
    91  }
    92  
    93  func (e *EvaluationResult) SetInstanceLocation(instanceLocation string) *EvaluationResult {
    94  	e.InstanceLocation = instanceLocation
    95  
    96  	return e
    97  }
    98  
    99  func (e *EvaluationResult) SetInvalid() *EvaluationResult {
   100  	e.Valid = false
   101  
   102  	return e
   103  }
   104  
   105  func (e *EvaluationResult) IsValid() bool {
   106  	return e.Valid
   107  }
   108  
   109  func (e *EvaluationResult) AddError(err *EvaluationError) *EvaluationResult {
   110  	if e.Errors == nil {
   111  		e.Errors = make(map[string]*EvaluationError)
   112  	}
   113  
   114  	if e.Valid {
   115  		e.Valid = false
   116  	}
   117  
   118  	e.Errors[err.Keyword] = err
   119  	return e
   120  }
   121  
   122  func (e *EvaluationResult) AddDetail(detail *EvaluationResult) *EvaluationResult {
   123  	if e.Details == nil {
   124  		e.Details = make([]*EvaluationResult, 0)
   125  	}
   126  
   127  	e.Details = append(e.Details, detail)
   128  	return e
   129  }
   130  
   131  func (e *EvaluationResult) AddAnnotation(keyword string, annotation interface{}) *EvaluationResult {
   132  	if e.Annotations == nil {
   133  		e.Annotations = make(map[string]interface{})
   134  	}
   135  
   136  	e.Annotations[keyword] = annotation
   137  	return e
   138  }
   139  
   140  func (e *EvaluationResult) CollectAnnotations() *EvaluationResult {
   141  	if e.Annotations == nil {
   142  		e.Annotations = make(map[string]interface{})
   143  	}
   144  
   145  	if e.schema.Title != nil {
   146  		e.Annotations["title"] = e.schema.Title
   147  	}
   148  	if e.schema.Description != nil {
   149  		e.Annotations["description"] = e.schema.Description
   150  	}
   151  	if e.schema.Default != nil {
   152  		e.Annotations["default"] = e.schema.Default
   153  	}
   154  	if e.schema.Deprecated != nil {
   155  		e.Annotations["deprecated"] = e.schema.Deprecated
   156  	}
   157  	if e.schema.ReadOnly != nil {
   158  		e.Annotations["readOnly"] = e.schema.ReadOnly
   159  	}
   160  	if e.schema.WriteOnly != nil {
   161  		e.Annotations["writeOnly"] = e.schema.WriteOnly
   162  	}
   163  	if e.schema.Examples != nil {
   164  		e.Annotations["examples"] = e.schema.Examples
   165  	}
   166  
   167  	return e
   168  }
   169  
   170  // Converts EvaluationResult to a simple Flag struct
   171  func (e *EvaluationResult) ToFlag() *Flag {
   172  	return &Flag{
   173  		Valid: e.Valid,
   174  	}
   175  }
   176  
   177  // ToList converts the evaluation results into a list format with optional hierarchy
   178  // includeHierarchy is variadic; if not provided, it defaults to true
   179  func (e *EvaluationResult) ToList(includeHierarchy ...bool) *List {
   180  	// Set default value for includeHierarchy to true
   181  	hierarchyIncluded := true
   182  	if len(includeHierarchy) > 0 {
   183  		hierarchyIncluded = includeHierarchy[0]
   184  	}
   185  
   186  	return e.ToLocalizeList(nil, hierarchyIncluded)
   187  }
   188  
   189  // ToLocalizeList converts the evaluation results into a list format with optional hierarchy with localization
   190  // includeHierarchy is variadic; if not provided, it defaults to true
   191  func (e *EvaluationResult) ToLocalizeList(localizer *i18n.Localizer, includeHierarchy ...bool) *List {
   192  	// Set default value for includeHierarchy to true
   193  	hierarchyIncluded := true
   194  	if len(includeHierarchy) > 0 {
   195  		hierarchyIncluded = includeHierarchy[0]
   196  	}
   197  
   198  	list := &List{
   199  		Valid:            e.Valid,
   200  		EvaluationPath:   e.EvaluationPath,
   201  		SchemaLocation:   e.SchemaLocation,
   202  		InstanceLocation: e.InstanceLocation,
   203  		Annotations:      e.Annotations,
   204  		Errors:           e.convertErrors(localizer),
   205  		Details:          make([]List, 0),
   206  	}
   207  
   208  	if hierarchyIncluded {
   209  		for _, detail := range e.Details {
   210  			childList := detail.ToLocalizeList(localizer, true) // recursively include hierarchy
   211  			list.Details = append(list.Details, *childList)
   212  		}
   213  	} else {
   214  		e.flattenDetailsToList(localizer, list, e.Details) // flat structure
   215  	}
   216  
   217  	return list
   218  }
   219  
   220  func (e *EvaluationResult) flattenDetailsToList(localizer *i18n.Localizer, list *List, details []*EvaluationResult) {
   221  	for _, detail := range details {
   222  		flatDetail := List{
   223  			Valid:            detail.Valid,
   224  			EvaluationPath:   detail.EvaluationPath,
   225  			SchemaLocation:   detail.SchemaLocation,
   226  			InstanceLocation: detail.InstanceLocation,
   227  			Annotations:      detail.Annotations,
   228  			Errors:           detail.convertErrors(localizer),
   229  		}
   230  		list.Details = append(list.Details, flatDetail)
   231  
   232  		if len(detail.Details) > 0 {
   233  			e.flattenDetailsToList(localizer, list, detail.Details)
   234  		}
   235  	}
   236  }
   237  
   238  func (e *EvaluationResult) convertErrors(localizer *i18n.Localizer) map[string]string {
   239  	errors := make(map[string]string)
   240  	for key, err := range e.Errors {
   241  		if localizer != nil {
   242  			errors[key] = err.Localize(localizer)
   243  		} else {
   244  			errors[key] = err.Error()
   245  		}
   246  	}
   247  	return errors
   248  }