github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/cloudlets/v3/match_rule.go (about)

     1  package v3
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/edgegriderr"
     9  
    10  	validation "github.com/go-ozzo/ozzo-validation/v4"
    11  )
    12  
    13  type (
    14  	// MatchRule is base interface for MatchRuleXX
    15  	MatchRule interface {
    16  		// cloudletType is a private method to ensure that only match rules for supported cloudlets can be used
    17  		cloudletType() string
    18  		Validate() error
    19  	}
    20  
    21  	// MatchRules is an array of *MatchRuleXX depending on the cloudletId (9 or 0) of the policy
    22  	MatchRules []MatchRule
    23  
    24  	// MatchRuleAP represents an API Prioritization (AP) match rule resource for create or update
    25  	MatchRuleAP struct {
    26  		Name               string            `json:"name,omitempty"`
    27  		Type               MatchRuleType     `json:"type,omitempty"`
    28  		Start              int64             `json:"start,omitempty"`
    29  		End                int64             `json:"end,omitempty"`
    30  		ID                 int64             `json:"id,omitempty"`
    31  		Matches            []MatchCriteriaAP `json:"matches,omitempty"`
    32  		MatchURL           string            `json:"matchURL,omitempty"`
    33  		PassThroughPercent *float64          `json:"passThroughPercent"`
    34  		Disabled           bool              `json:"disabled,omitempty"`
    35  	}
    36  
    37  	// MatchRuleAS represents an Application Segmentation (AS) match rule resource for create or update resource
    38  	MatchRuleAS struct {
    39  		Name            string            `json:"name,omitempty"`
    40  		Type            MatchRuleType     `json:"type,omitempty"`
    41  		Start           int64             `json:"start,omitempty"`
    42  		End             int64             `json:"end,omitempty"`
    43  		ID              int64             `json:"id,omitempty"`
    44  		Matches         []MatchCriteriaAS `json:"matches,omitempty"`
    45  		MatchURL        string            `json:"matchURL,omitempty"`
    46  		ForwardSettings ForwardSettingsAS `json:"forwardSettings"`
    47  		Disabled        bool              `json:"disabled,omitempty"`
    48  	}
    49  
    50  	// ForwardSettingsAS represents forward settings for an Application Segmentation (AS)
    51  	ForwardSettingsAS struct {
    52  		PathAndQS              string `json:"pathAndQS,omitempty"`
    53  		UseIncomingQueryString bool   `json:"useIncomingQueryString,omitempty"`
    54  		OriginID               string `json:"originId,omitempty"`
    55  	}
    56  
    57  	// MatchRulePR represents a Phased Release (PR aka CD) match rule resource for create or update resource
    58  	MatchRulePR struct {
    59  		Name            string            `json:"name,omitempty"`
    60  		Type            MatchRuleType     `json:"type,omitempty"`
    61  		Start           int64             `json:"start,omitempty"`
    62  		End             int64             `json:"end,omitempty"`
    63  		ID              int64             `json:"id,omitempty"`
    64  		Matches         []MatchCriteriaPR `json:"matches,omitempty"`
    65  		MatchURL        string            `json:"matchURL,omitempty"`
    66  		ForwardSettings ForwardSettingsPR `json:"forwardSettings"`
    67  		Disabled        bool              `json:"disabled,omitempty"`
    68  		MatchesAlways   bool              `json:"matchesAlways,omitempty"`
    69  	}
    70  
    71  	// ForwardSettingsPR represents forward settings for a Phased Release (PR aka CD)
    72  	ForwardSettingsPR struct {
    73  		OriginID string `json:"originId"`
    74  		Percent  int    `json:"percent"`
    75  	}
    76  
    77  	// MatchRuleER represents an Edge Redirector (ER) match rule resource for create or update resource
    78  	MatchRuleER struct {
    79  		Name                     string            `json:"name,omitempty"`
    80  		Type                     MatchRuleType     `json:"type,omitempty"`
    81  		Start                    int64             `json:"start,omitempty"`
    82  		End                      int64             `json:"end,omitempty"`
    83  		ID                       int64             `json:"id,omitempty"`
    84  		Matches                  []MatchCriteriaER `json:"matches,omitempty"`
    85  		MatchesAlways            bool              `json:"matchesAlways,omitempty"`
    86  		UseRelativeURL           string            `json:"useRelativeUrl,omitempty"`
    87  		StatusCode               int               `json:"statusCode"`
    88  		RedirectURL              string            `json:"redirectURL"`
    89  		MatchURL                 string            `json:"matchURL,omitempty"`
    90  		UseIncomingQueryString   bool              `json:"useIncomingQueryString"`
    91  		UseIncomingSchemeAndHost bool              `json:"useIncomingSchemeAndHost"`
    92  		Disabled                 bool              `json:"disabled,omitempty"`
    93  	}
    94  
    95  	// MatchRuleFR represents a Forward Rewrite (FR) match rule resource for create or update resource
    96  	MatchRuleFR struct {
    97  		Name            string            `json:"name,omitempty"`
    98  		Type            MatchRuleType     `json:"type,omitempty"`
    99  		Start           int64             `json:"start,omitempty"`
   100  		End             int64             `json:"end,omitempty"`
   101  		ID              int64             `json:"id,omitempty"`
   102  		Matches         []MatchCriteriaFR `json:"matches,omitempty"`
   103  		MatchURL        string            `json:"matchURL,omitempty"`
   104  		ForwardSettings ForwardSettingsFR `json:"forwardSettings"`
   105  		Disabled        bool              `json:"disabled,omitempty"`
   106  	}
   107  
   108  	// ForwardSettingsFR represents forward settings for a Forward Rewrite (FR)
   109  	ForwardSettingsFR struct {
   110  		PathAndQS              string `json:"pathAndQS,omitempty"`
   111  		UseIncomingQueryString bool   `json:"useIncomingQueryString,omitempty"`
   112  		OriginID               string `json:"originId,omitempty"`
   113  	}
   114  
   115  	// MatchRuleRC represents a Request Control (RC aka IG) match rule resource for create or update resource
   116  	MatchRuleRC struct {
   117  		Name          string            `json:"name,omitempty"`
   118  		Type          MatchRuleType     `json:"type,omitempty"`
   119  		Start         int64             `json:"start,omitempty"`
   120  		End           int64             `json:"end,omitempty"`
   121  		ID            int64             `json:"id,omitempty"`
   122  		Matches       []MatchCriteriaRC `json:"matches,omitempty"`
   123  		MatchesAlways bool              `json:"matchesAlways,omitempty"`
   124  		AllowDeny     AllowDeny         `json:"allowDeny"`
   125  		Disabled      bool              `json:"disabled,omitempty"`
   126  	}
   127  
   128  	// MatchCriteria represents a match criteria resource for match rule for cloudlet
   129  	MatchCriteria struct {
   130  		MatchType        string        `json:"matchType,omitempty"`
   131  		MatchValue       string        `json:"matchValue,omitempty"`
   132  		MatchOperator    MatchOperator `json:"matchOperator,omitempty"`
   133  		CaseSensitive    bool          `json:"caseSensitive"`
   134  		Negate           bool          `json:"negate"`
   135  		CheckIPs         CheckIPs      `json:"checkIPs,omitempty"`
   136  		ObjectMatchValue interface{}   `json:"objectMatchValue,omitempty"`
   137  	}
   138  
   139  	// MatchCriteriaAP represents a match criteria resource for match rule for cloudlet API Prioritization (AP)
   140  	// ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple
   141  	MatchCriteriaAP MatchCriteria
   142  
   143  	// MatchCriteriaAS represents a match criteria resource for match rule for cloudlet Application Segmentation (AS)
   144  	// ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple or ObjectMatchValueRange
   145  	MatchCriteriaAS MatchCriteria
   146  
   147  	// MatchCriteriaPR represents a match criteria resource for match rule for cloudlet Phased Release (PR aka CD)
   148  	// ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple
   149  	MatchCriteriaPR MatchCriteria
   150  
   151  	// MatchCriteriaER represents a match criteria resource for match rule for cloudlet Edge Redirector (ER)
   152  	// ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple
   153  	MatchCriteriaER MatchCriteria
   154  
   155  	// MatchCriteriaFR represents a match criteria resource for match rule for cloudlet Forward Rewrite (FR)
   156  	// ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple
   157  	MatchCriteriaFR MatchCriteria
   158  
   159  	// MatchCriteriaRC represents a match criteria resource for match rule for cloudlet Request Control (RC aka IG)
   160  	// ObjectMatchValue can contain ObjectMatchValueObject or ObjectMatchValueSimple
   161  	MatchCriteriaRC MatchCriteria
   162  
   163  	// ObjectMatchValueObject represents an object match value resource for match criteria of type object
   164  	ObjectMatchValueObject struct {
   165  		Name              string                     `json:"name"`
   166  		Type              ObjectMatchValueObjectType `json:"type"`
   167  		NameCaseSensitive bool                       `json:"nameCaseSensitive"`
   168  		NameHasWildcard   bool                       `json:"nameHasWildcard"`
   169  		Options           *Options                   `json:"options,omitempty"`
   170  	}
   171  
   172  	// ObjectMatchValueSimple represents an object match value resource for match criteria of type simple
   173  	ObjectMatchValueSimple struct {
   174  		Type  ObjectMatchValueSimpleType `json:"type"`
   175  		Value []string                   `json:"value,omitempty"`
   176  	}
   177  
   178  	// ObjectMatchValueRange represents an object match value resource for match criteria of type range
   179  	ObjectMatchValueRange struct {
   180  		Type  ObjectMatchValueRangeType `json:"type"`
   181  		Value []int64                   `json:"value,omitempty"`
   182  	}
   183  
   184  	// Options represents an option resource for ObjectMatchValueObject
   185  	Options struct {
   186  		Value              []string `json:"value,omitempty"`
   187  		ValueHasWildcard   bool     `json:"valueHasWildcard,omitempty"`
   188  		ValueCaseSensitive bool     `json:"valueCaseSensitive,omitempty"`
   189  		ValueEscaped       bool     `json:"valueEscaped,omitempty"`
   190  	}
   191  
   192  	//MatchRuleType enum type
   193  	MatchRuleType string
   194  	// MatchRuleFormat enum type
   195  	MatchRuleFormat string
   196  	// MatchOperator enum type
   197  	MatchOperator string
   198  	// AllowDeny enum type
   199  	AllowDeny string
   200  	// CheckIPs enum type
   201  	CheckIPs string
   202  	// ObjectMatchValueRangeType enum type
   203  	ObjectMatchValueRangeType string
   204  	// ObjectMatchValueSimpleType enum type
   205  	ObjectMatchValueSimpleType string
   206  	// ObjectMatchValueObjectType enum type
   207  	ObjectMatchValueObjectType string
   208  )
   209  
   210  const (
   211  	// MatchRuleTypeAP represents rule type for API Prioritization (AP) cloudlets
   212  	MatchRuleTypeAP MatchRuleType = "apMatchRule"
   213  	// MatchRuleTypeAS represents rule type for Application Segmentation (AS) cloudlets
   214  	MatchRuleTypeAS MatchRuleType = "asMatchRule"
   215  	// MatchRuleTypePR represents rule type for Phased Release (PR aka CD) cloudlets
   216  	MatchRuleTypePR MatchRuleType = "cdMatchRule"
   217  	// MatchRuleTypeER represents rule type for Edge Redirector (ER) cloudlets
   218  	MatchRuleTypeER MatchRuleType = "erMatchRule"
   219  	// MatchRuleTypeFR represents rule type for Forward Rewrite (FR) cloudlets
   220  	MatchRuleTypeFR MatchRuleType = "frMatchRule"
   221  	// MatchRuleTypeRC represents rule type for Request Control (RC aka IG) cloudlets
   222  	MatchRuleTypeRC MatchRuleType = "igMatchRule"
   223  	// MatchRuleTypeVP represents rule type for Visitor Prioritization (VP) cloudlets
   224  	MatchRuleTypeVP MatchRuleType = "vpMatchRule"
   225  )
   226  
   227  const (
   228  	// MatchRuleFormat10 represents default match rule format
   229  	MatchRuleFormat10 MatchRuleFormat = "1.0"
   230  )
   231  
   232  const (
   233  	// MatchOperatorContains represents contains operator
   234  	MatchOperatorContains MatchOperator = "contains"
   235  	// MatchOperatorExists represents exists operator
   236  	MatchOperatorExists MatchOperator = "exists"
   237  	// MatchOperatorEquals represents equals operator
   238  	MatchOperatorEquals MatchOperator = "equals"
   239  )
   240  
   241  const (
   242  	// Allow represents allow option
   243  	Allow AllowDeny = "allow"
   244  	// Deny represents deny option
   245  	Deny AllowDeny = "deny"
   246  	// DenyBranded represents denybranded option
   247  	DenyBranded AllowDeny = "denybranded"
   248  )
   249  
   250  const (
   251  	// CheckIPsConnectingIP represents connecting ip option
   252  	CheckIPsConnectingIP CheckIPs = "CONNECTING_IP"
   253  	// CheckIPsXFFHeaders represents xff headers option
   254  	CheckIPsXFFHeaders CheckIPs = "XFF_HEADERS"
   255  	// CheckIPsConnectingIPXFFHeaders represents connecting ip + xff headers option
   256  	CheckIPsConnectingIPXFFHeaders CheckIPs = "CONNECTING_IP XFF_HEADERS"
   257  )
   258  
   259  const (
   260  	// Range represents range option
   261  	Range ObjectMatchValueRangeType = "range"
   262  	// Simple represents simple option
   263  	Simple ObjectMatchValueSimpleType = "simple"
   264  	// Object represents object option
   265  	Object ObjectMatchValueObjectType = "object"
   266  )
   267  
   268  var (
   269  	// ErrUnmarshallMatchCriteriaAP is returned when unmarshalling of MatchCriteriaAP fails
   270  	ErrUnmarshallMatchCriteriaAP = errors.New("unmarshalling MatchCriteriaAP")
   271  	// ErrUnmarshallMatchCriteriaAS is returned when unmarshalling of MatchCriteriaAS fails
   272  	ErrUnmarshallMatchCriteriaAS = errors.New("unmarshalling MatchCriteriaAS")
   273  	// ErrUnmarshallMatchCriteriaPR is returned when unmarshalling of MatchCriteriaPR fails
   274  	ErrUnmarshallMatchCriteriaPR = errors.New("unmarshalling MatchCriteriaPR")
   275  	// ErrUnmarshallMatchCriteriaER is returned when unmarshalling of MatchCriteriaER fails
   276  	ErrUnmarshallMatchCriteriaER = errors.New("unmarshalling MatchCriteriaER")
   277  	// ErrUnmarshallMatchCriteriaFR is returned when unmarshalling of MatchCriteriaFR fails
   278  	ErrUnmarshallMatchCriteriaFR = errors.New("unmarshalling MatchCriteriaFR")
   279  	// ErrUnmarshallMatchCriteriaRC is returned when unmarshalling of MatchCriteriaRC fails
   280  	ErrUnmarshallMatchCriteriaRC = errors.New("unmarshalling MatchCriteriaRC")
   281  	// ErrUnmarshallMatchCriteriaVP is returned when unmarshalling of MatchCriteriaVP fails
   282  	ErrUnmarshallMatchCriteriaVP = errors.New("unmarshalling MatchCriteriaVP")
   283  	// ErrUnmarshallMatchRules is returned when unmarshalling of MatchRules fails
   284  	ErrUnmarshallMatchRules = errors.New("unmarshalling MatchRules")
   285  )
   286  
   287  // matchRuleHandlers contains mapping between name of the type for MatchRule and its implementation
   288  // It makes the UnmarshalJSON more compact and easier to support more cloudlet types
   289  var matchRuleHandlers = map[string]func() MatchRule{
   290  	"apMatchRule": func() MatchRule { return &MatchRuleAP{} },
   291  	"asMatchRule": func() MatchRule { return &MatchRuleAS{} },
   292  	"cdMatchRule": func() MatchRule { return &MatchRulePR{} },
   293  	"erMatchRule": func() MatchRule { return &MatchRuleER{} },
   294  	"frMatchRule": func() MatchRule { return &MatchRuleFR{} },
   295  	"igMatchRule": func() MatchRule { return &MatchRuleRC{} },
   296  }
   297  
   298  // objectOrRangeOrSimpleMatchValueHandlers contains mapping between name of the type for ObjectMatchValue and its implementation
   299  // It makes the UnmarshalJSON more compact and easier to support more types
   300  var objectOrRangeOrSimpleMatchValueHandlers = map[string]func() interface{}{
   301  	"object": func() interface{} { return &ObjectMatchValueObject{} },
   302  	"range":  func() interface{} { return &ObjectMatchValueRange{} },
   303  	"simple": func() interface{} { return &ObjectMatchValueSimple{} },
   304  }
   305  
   306  // simpleObjectMatchValueHandlers contains mapping between name of the types (simple or object) for ObjectMatchValue and their implementations
   307  // It makes the UnmarshalJSON more compact and easier to support more types
   308  var simpleObjectMatchValueHandlers = map[string]func() interface{}{
   309  	"object": func() interface{} { return &ObjectMatchValueObject{} },
   310  	"simple": func() interface{} { return &ObjectMatchValueSimple{} },
   311  }
   312  
   313  // Validate validates MatchRules
   314  func (m MatchRules) Validate() error {
   315  	type matchRules MatchRules
   316  
   317  	errs := validation.Errors{
   318  		"MatchRules": validation.Validate(matchRules(m), validation.Length(0, 5000)),
   319  	}
   320  	return edgegriderr.ParseValidationErrors(errs)
   321  }
   322  
   323  // Validate validates MatchRuleAP
   324  func (m MatchRuleAP) Validate() error {
   325  	return validation.Errors{
   326  		"Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypeAP).Error(
   327  			fmt.Sprintf("value '%s' is invalid. Must be: 'apMatchRule'", (&m).Type))),
   328  		"Name":               validation.Validate(m.Name, validation.Length(0, 8192)),
   329  		"Start":              validation.Validate(m.Start, validation.Min(0)),
   330  		"End":                validation.Validate(m.End, validation.Min(0)),
   331  		"MatchURL":           validation.Validate(m.MatchURL, validation.Length(0, 8192)),
   332  		"PassThroughPercent": validation.Validate(m.PassThroughPercent, validation.By(passThroughPercentValidation)),
   333  		"Matches":            validation.Validate(m.Matches),
   334  	}.Filter()
   335  }
   336  
   337  // Validate validates MatchRuleAS
   338  func (m MatchRuleAS) Validate() error {
   339  	return validation.Errors{
   340  		"Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypeAS).Error(
   341  			fmt.Sprintf("value '%s' is invalid. Must be: 'asMatchRule'", (&m).Type))),
   342  		"Name":                      validation.Validate(m.Name, validation.Length(0, 8192)),
   343  		"Start":                     validation.Validate(m.Start, validation.Min(0)),
   344  		"End":                       validation.Validate(m.End, validation.Min(0)),
   345  		"MatchURL":                  validation.Validate(m.MatchURL, validation.Length(0, 8192)),
   346  		"Matches":                   validation.Validate(m.Matches),
   347  		"ForwardSettings":           validation.Validate(m.ForwardSettings, validation.Required),
   348  		"ForwardSettings.PathAndQS": validation.Validate(m.ForwardSettings.PathAndQS, validation.Length(1, 8192)),
   349  		"ForwardSettings.OriginID":  validation.Validate(m.ForwardSettings.OriginID, validation.Length(0, 8192)),
   350  	}.Filter()
   351  }
   352  
   353  // Validate validates MatchRulePR
   354  func (m MatchRulePR) Validate() error {
   355  	return validation.Errors{
   356  		"Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypePR).Error(
   357  			fmt.Sprintf("value '%s' is invalid. Must be: 'cdMatchRule'", (&m).Type))),
   358  		"Name":                     validation.Validate(m.Name, validation.Length(0, 8192)),
   359  		"Start":                    validation.Validate(m.Start, validation.Min(0)),
   360  		"End":                      validation.Validate(m.End, validation.Min(0)),
   361  		"MatchURL":                 validation.Validate(m.MatchURL, validation.Length(0, 8192)),
   362  		"ForwardSettings":          validation.Validate(m.ForwardSettings, validation.Required),
   363  		"ForwardSettings.OriginID": validation.Validate(m.ForwardSettings.OriginID, validation.Required, validation.Length(0, 8192)),
   364  		"ForwardSettings.Percent":  validation.Validate(m.ForwardSettings.Percent, validation.Required, validation.Min(1), validation.Max(100)),
   365  		"Matches":                  validation.Validate(m.Matches),
   366  		"Matches/MatchesAlways":    validation.Validate(len(m.Matches), validation.When(m.MatchesAlways, validation.Empty.Error("only one of [ \"Matches\", \"MatchesAlways\" ] can be specified"))),
   367  	}.Filter()
   368  }
   369  
   370  // Validate validates MatchRuleER
   371  func (m MatchRuleER) Validate() error {
   372  	return validation.Errors{
   373  		"Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypeER).Error(
   374  			fmt.Sprintf("value '%s' is invalid. Must be: 'erMatchRule'", (&m).Type))),
   375  		"Name":        validation.Validate(m.Name, validation.Length(0, 8192)),
   376  		"Start":       validation.Validate(m.Start, validation.Min(0)),
   377  		"End":         validation.Validate(m.End, validation.Min(0)),
   378  		"MatchURL":    validation.Validate(m.MatchURL, validation.Length(0, 8192)),
   379  		"RedirectURL": validation.Validate(m.RedirectURL, validation.Required, validation.Length(1, 8192)),
   380  		"UseRelativeURL": validation.Validate(m.UseRelativeURL, validation.In("none", "copy_scheme_hostname", "relative_url").Error(
   381  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'none', 'copy_scheme_hostname', 'relative_url' or '' (empty)", (&m).UseRelativeURL))),
   382  		"StatusCode": validation.Validate(m.StatusCode, validation.Required, validation.In(301, 302, 303, 307, 308).Error(
   383  			fmt.Sprintf("value '%d' is invalid. Must be one of: 301, 302, 303, 307 or 308", (&m).StatusCode))),
   384  		"Matches":               validation.Validate(m.Matches),
   385  		"Matches/MatchesAlways": validation.Validate(len(m.Matches), validation.When(m.MatchesAlways, validation.Empty.Error("only one of [ \"Matches\", \"MatchesAlways\" ] can be specified"))),
   386  	}.Filter()
   387  }
   388  
   389  // Validate validates MatchRuleFR
   390  func (m MatchRuleFR) Validate() error {
   391  	return validation.Errors{
   392  		"Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypeFR).Error(
   393  			fmt.Sprintf("value '%s' is invalid. Must be: 'frMatchRule'", (&m).Type))),
   394  		"Name":                      validation.Validate(m.Name, validation.Length(0, 8192)),
   395  		"Start":                     validation.Validate(m.Start, validation.Min(0)),
   396  		"End":                       validation.Validate(m.End, validation.Min(0)),
   397  		"MatchURL":                  validation.Validate(m.MatchURL, validation.Length(0, 8192)),
   398  		"Matches":                   validation.Validate(m.Matches),
   399  		"ForwardSettings":           validation.Validate(m.ForwardSettings, validation.Required),
   400  		"ForwardSettings.PathAndQS": validation.Validate(m.ForwardSettings.PathAndQS, validation.Length(1, 8192)),
   401  		"ForwardSettings.OriginID":  validation.Validate(m.ForwardSettings.OriginID, validation.Length(0, 8192)),
   402  	}.Filter()
   403  }
   404  
   405  // Validate validates MatchRuleRC
   406  func (m MatchRuleRC) Validate() error {
   407  	return validation.Errors{
   408  		"Type": validation.Validate(m.Type, validation.Required, validation.In(MatchRuleTypeRC).Error(
   409  			fmt.Sprintf("value '%s' is invalid. Must be: 'igMatchRule'", (&m).Type))),
   410  		"Name":                  validation.Validate(m.Name, validation.Length(0, 8192)),
   411  		"Start":                 validation.Validate(m.Start, validation.Min(0)),
   412  		"End":                   validation.Validate(m.End, validation.Min(0)),
   413  		"Matches":               validation.Validate(m.Matches),
   414  		"Matches/MatchesAlways": validation.Validate(len(m.Matches), validation.When(m.MatchesAlways, validation.Empty.Error("only one of [ \"Matches\", \"MatchesAlways\" ] can be specified"))),
   415  		"AllowDeny": validation.Validate(m.AllowDeny, validation.Required, validation.In(Allow, Deny, DenyBranded).Error(
   416  			fmt.Sprintf("value '%s' is invalid. Must be one of: '%s', '%s' or '%s'", (&m).AllowDeny, Allow, Deny, DenyBranded),
   417  		)),
   418  	}.Filter()
   419  }
   420  
   421  // Validate validates MatchCriteriaAP
   422  func (m MatchCriteriaAP) Validate() error {
   423  	return validation.Errors{
   424  		"MatchType": validation.Validate(m.MatchType, validation.In(
   425  			"header", "hostname", "path", "extension", "query", "cookie", "deviceCharacteristics", "clientip",
   426  			"continent", "countrycode", "regioncode", "protocol", "method", "proxy").Error(
   427  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'cookie', "+
   428  				"'deviceCharacteristics', 'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy'", (&m).MatchType))),
   429  		"MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"),
   430  			validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")),
   431  		"MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error(
   432  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))),
   433  		"CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error(
   434  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))),
   435  		"ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"),
   436  			validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrObjectValidation)),
   437  	}.Filter()
   438  }
   439  
   440  // Validate validates MatchCriteriaAS
   441  func (m MatchCriteriaAS) Validate() error {
   442  	return validation.Errors{
   443  		"MatchType": validation.Validate(m.MatchType, validation.In("header", "hostname", "path", "extension", "query", "range",
   444  			"regex", "cookie", "deviceCharacteristics", "clientip", "continent", "countrycode", "regioncode", "protocol", "method", "proxy").Error(
   445  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'range', "+
   446  				"'regex', 'cookie', 'deviceCharacteristics', 'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy'", (&m).MatchType))),
   447  		"MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"),
   448  			validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")),
   449  		"MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error(
   450  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))),
   451  		"CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error(
   452  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))),
   453  		"ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"),
   454  			validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrRangeOrObjectValidation)),
   455  	}.Filter()
   456  }
   457  
   458  // Validate validates MatchCriteriaPR
   459  func (m MatchCriteriaPR) Validate() error {
   460  	return validation.Errors{
   461  		"MatchType": validation.Validate(m.MatchType, validation.In("header", "hostname", "path", "extension",
   462  			"query", "cookie", "deviceCharacteristics", "clientip", "continent", "countrycode", "regioncode", "protocol",
   463  			"method", "proxy").Error(
   464  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'cookie', "+
   465  				"'deviceCharacteristics', 'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy'", (&m).MatchType))),
   466  		"MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"),
   467  			validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")),
   468  		"MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error(
   469  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))),
   470  		"CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error(
   471  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))),
   472  		"ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"),
   473  			validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrObjectValidation)),
   474  	}.Filter()
   475  }
   476  
   477  // Validate validates MatchCriteriaER
   478  func (m MatchCriteriaER) Validate() error {
   479  	return validation.Errors{
   480  		"MatchType": validation.Validate(m.MatchType, validation.In("header", "hostname", "path", "extension", "query",
   481  			"regex", "cookie", "deviceCharacteristics", "clientip", "continent", "countrycode", "regioncode", "protocol", "method", "proxy").Error(
   482  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'regex', 'cookie', "+
   483  				"'deviceCharacteristics', 'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy' or '' (empty)", (&m).MatchType))),
   484  		"MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"),
   485  			validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")),
   486  		"MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error(
   487  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))),
   488  		"CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error(
   489  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))),
   490  		"ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"),
   491  			validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrObjectValidation)),
   492  	}.Filter()
   493  }
   494  
   495  // Validate validates MatchCriteriaFR
   496  func (m MatchCriteriaFR) Validate() error {
   497  	return validation.Errors{
   498  		"MatchType": validation.Validate(m.MatchType, validation.Required, validation.In("header", "hostname", "path", "extension", "query", "regex",
   499  			"cookie", "deviceCharacteristics", "clientip", "continent", "countrycode", "regioncode", "protocol", "method", "proxy").Error(
   500  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'regex', 'cookie', "+
   501  				"'deviceCharacteristics', 'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy'", (&m).MatchType))),
   502  		"MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"),
   503  			validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")),
   504  		"MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error(
   505  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))),
   506  		"CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error(
   507  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))),
   508  		"ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"),
   509  			validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrObjectValidation)),
   510  	}.Filter()
   511  }
   512  
   513  // Validate validates MatchCriteriaRC
   514  func (m MatchCriteriaRC) Validate() error {
   515  	return validation.Errors{
   516  		"MatchType": validation.Validate(m.MatchType, validation.Required, validation.In("header", "hostname", "path", "extension", "query", "cookie",
   517  			"deviceCharacteristics", "clientip", "continent", "countrycode", "regioncode", "protocol", "method", "proxy").Error(
   518  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'header', 'hostname', 'path', 'extension', 'query', 'cookie', 'deviceCharacteristics', "+
   519  				"'clientip', 'continent', 'countrycode', 'regioncode', 'protocol', 'method', 'proxy'", (&m).MatchType))),
   520  		"MatchValue": validation.Validate(m.MatchValue, validation.Length(1, 8192), validation.Required.When(m.ObjectMatchValue == nil).Error("cannot be blank when ObjectMatchValue is blank"),
   521  			validation.Empty.When(m.ObjectMatchValue != nil).Error("must be blank when ObjectMatchValue is set")),
   522  		"MatchOperator": validation.Validate(m.MatchOperator, validation.In(MatchOperatorContains, MatchOperatorExists, MatchOperatorEquals).Error(
   523  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'contains', 'exists', 'equals' or '' (empty)", (&m).MatchOperator))),
   524  		"CheckIPs": validation.Validate(m.CheckIPs, validation.In(CheckIPsConnectingIP, CheckIPsXFFHeaders, CheckIPsConnectingIPXFFHeaders).Error(
   525  			fmt.Sprintf("value '%s' is invalid. Must be one of: 'CONNECTING_IP', 'XFF_HEADERS', 'CONNECTING_IP XFF_HEADERS' or '' (empty)", (&m).CheckIPs))),
   526  		"ObjectMatchValue": validation.Validate(m.ObjectMatchValue, validation.Required.When(m.MatchValue == "").Error("cannot be blank when MatchValue is blank"),
   527  			validation.Empty.When(m.MatchValue != "").Error("must be blank when MatchValue is set"), validation.By(objectMatchValueSimpleOrObjectValidation)),
   528  	}.Filter()
   529  }
   530  
   531  func objectMatchValueSimpleOrObjectValidation(value interface{}) error {
   532  	if value == nil {
   533  		return nil
   534  	}
   535  	switch value.(type) {
   536  	case *ObjectMatchValueObject, *ObjectMatchValueSimple:
   537  		return nil
   538  	default:
   539  		return fmt.Errorf("type %T is invalid. Must be one of: 'simple' or 'object'", value)
   540  	}
   541  }
   542  
   543  func objectMatchValueSimpleOrRangeOrObjectValidation(value interface{}) error {
   544  	if value == nil {
   545  		return nil
   546  	}
   547  	switch value.(type) {
   548  	case *ObjectMatchValueObject, *ObjectMatchValueSimple, *ObjectMatchValueRange:
   549  		return nil
   550  	default:
   551  		return fmt.Errorf("type %T is invalid. Must be one of: 'simple', 'range' or 'object'", value)
   552  	}
   553  }
   554  
   555  func passThroughPercentValidation(value interface{}) error {
   556  	v, ok := value.(*float64)
   557  	if !ok {
   558  		return fmt.Errorf("type %T is invalid. Must be *float64", value)
   559  	}
   560  	if v == nil {
   561  		return fmt.Errorf("cannot be blank")
   562  	}
   563  	if *v < -1 {
   564  		return fmt.Errorf("must be no less than -1")
   565  	}
   566  	if *v > 100 {
   567  		return fmt.Errorf("must be no greater than 100")
   568  	}
   569  	return nil
   570  }
   571  
   572  // Validate validates ObjectMatchValueRange
   573  func (o ObjectMatchValueRange) Validate() error {
   574  	return validation.Errors{
   575  		"Type": validation.Validate(o.Type, validation.In(Range).Error(
   576  			fmt.Sprintf("value '%s' is invalid. Must be: 'range'", (&o).Type))),
   577  	}.Filter()
   578  }
   579  
   580  // Validate validates ObjectMatchValueSimple
   581  func (o ObjectMatchValueSimple) Validate() error {
   582  	return validation.Errors{
   583  		"Type": validation.Validate(o.Type, validation.In(Simple).Error(
   584  			fmt.Sprintf("value '%s' is invalid. Must be: 'simple'", (&o).Type))),
   585  	}.Filter()
   586  }
   587  
   588  // Validate validates ObjectMatchValueObject
   589  func (o ObjectMatchValueObject) Validate() error {
   590  	return validation.Errors{
   591  		"Name": validation.Validate(o.Name, validation.Required, validation.Length(0, 8192)),
   592  		"Type": validation.Validate(o.Type, validation.Required, validation.In(Object).Error(
   593  			fmt.Sprintf("value '%s' is invalid. Must be: 'object'", (&o).Type))),
   594  	}.Filter()
   595  }
   596  
   597  func (m MatchRuleAP) cloudletType() string {
   598  	return "apMatchRule"
   599  }
   600  
   601  func (m MatchRuleAS) cloudletType() string {
   602  	return "asMatchRule"
   603  }
   604  
   605  func (m MatchRulePR) cloudletType() string {
   606  	return "cdMatchRule"
   607  }
   608  
   609  func (m MatchRuleER) cloudletType() string {
   610  	return "erMatchRule"
   611  }
   612  
   613  func (m MatchRuleFR) cloudletType() string {
   614  	return "frMatchRule"
   615  }
   616  
   617  func (m MatchRuleRC) cloudletType() string {
   618  	return "igMatchRule"
   619  }
   620  
   621  // UnmarshalJSON helps to un-marshall items of MatchRules array as proper instances of or *MatchRuleER
   622  func (m *MatchRules) UnmarshalJSON(b []byte) error {
   623  	data := make([]map[string]interface{}, 0)
   624  	if err := json.Unmarshal(b, &data); err != nil {
   625  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchRules, err)
   626  	}
   627  	for _, matchRule := range data {
   628  		cloudletType, ok := matchRule["type"]
   629  		if !ok {
   630  			return fmt.Errorf("%w: match rule entry should contain 'type' field", ErrUnmarshallMatchRules)
   631  		}
   632  		cloudletTypeName, ok := cloudletType.(string)
   633  		if !ok {
   634  			return fmt.Errorf("%w: 'type' field on match rule entry should be a string", ErrUnmarshallMatchRules)
   635  		}
   636  		byteArr, err := json.Marshal(matchRule)
   637  		if err != nil {
   638  			return fmt.Errorf("%w: %s", ErrUnmarshallMatchRules, err)
   639  		}
   640  
   641  		matchRuleType, ok := matchRuleHandlers[cloudletTypeName]
   642  		if !ok {
   643  			return fmt.Errorf("%w: unsupported match rule type: %s", ErrUnmarshallMatchRules, cloudletTypeName)
   644  		}
   645  		dst := matchRuleType()
   646  		err = json.Unmarshal(byteArr, dst)
   647  		if err != nil {
   648  			return fmt.Errorf("%w: %s", ErrUnmarshallMatchRules, err)
   649  		}
   650  		*m = append(*m, dst)
   651  	}
   652  	return nil
   653  }
   654  
   655  // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaAP as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple
   656  func (m *MatchCriteriaAP) UnmarshalJSON(b []byte) error {
   657  	// matchCriteriaAP is an alias for MatchCriteriaAP for un-marshalling purposes
   658  	type matchCriteriaAP MatchCriteriaAP
   659  
   660  	// populate common attributes using default json unmarshaler using aliased type
   661  	err := json.Unmarshal(b, (*matchCriteriaAP)(m))
   662  	if err != nil {
   663  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAP, err)
   664  	}
   665  	if m.ObjectMatchValue == nil {
   666  		return nil
   667  	}
   668  
   669  	objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue)
   670  	if err != nil {
   671  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAP, err)
   672  	}
   673  
   674  	createObjectMatchValue, ok := simpleObjectMatchValueHandlers[objectMatchValueTypeName]
   675  	if !ok {
   676  		return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaAP, objectMatchValueTypeName)
   677  	}
   678  	convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue())
   679  	if err != nil {
   680  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAP, err)
   681  	}
   682  	m.ObjectMatchValue = convertedObjectMatchValue
   683  
   684  	return nil
   685  }
   686  
   687  // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaAS as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple or *ObjectMatchValueRange
   688  func (m *MatchCriteriaAS) UnmarshalJSON(b []byte) error {
   689  	// matchCriteriaAS is an alias for MatchCriteriaAS for un-marshalling purposes
   690  	type matchCriteriaAS MatchCriteriaAS
   691  
   692  	// populate common attributes using default json unmarshaler using aliased type
   693  	err := json.Unmarshal(b, (*matchCriteriaAS)(m))
   694  	if err != nil {
   695  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAS, err)
   696  	}
   697  	if m.ObjectMatchValue == nil {
   698  		return nil
   699  	}
   700  
   701  	objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue)
   702  	if err != nil {
   703  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAS, err)
   704  	}
   705  
   706  	createObjectMatchValue, ok := objectOrRangeOrSimpleMatchValueHandlers[objectMatchValueTypeName]
   707  	if !ok {
   708  		return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaAS, objectMatchValueTypeName)
   709  	}
   710  	convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue())
   711  	if err != nil {
   712  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaAS, err)
   713  	}
   714  	m.ObjectMatchValue = convertedObjectMatchValue
   715  
   716  	return nil
   717  }
   718  
   719  // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaPR as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple
   720  func (m *MatchCriteriaPR) UnmarshalJSON(b []byte) error {
   721  	// matchCriteriaPR is an alias for MatchCriteriaPR for un-marshalling purposes
   722  	type matchCriteriaPR MatchCriteriaPR
   723  
   724  	// populate common attributes using default json unmarshaler using aliased type
   725  	err := json.Unmarshal(b, (*matchCriteriaPR)(m))
   726  	if err != nil {
   727  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaPR, err)
   728  	}
   729  	if m.ObjectMatchValue == nil {
   730  		return nil
   731  	}
   732  
   733  	objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue)
   734  	if err != nil {
   735  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaPR, err)
   736  	}
   737  
   738  	createObjectMatchValue, ok := simpleObjectMatchValueHandlers[objectMatchValueTypeName]
   739  	if !ok {
   740  		return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaPR, objectMatchValueTypeName)
   741  	}
   742  	convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue())
   743  	if err != nil {
   744  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaPR, err)
   745  	}
   746  	m.ObjectMatchValue = convertedObjectMatchValue
   747  
   748  	return nil
   749  }
   750  
   751  // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaER as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple
   752  func (m *MatchCriteriaER) UnmarshalJSON(b []byte) error {
   753  	// matchCriteriaER is an alias for MatchCriteriaER for un-marshalling purposes
   754  	type matchCriteriaER MatchCriteriaER
   755  
   756  	// populate common attributes using default json unmarshaler using aliased type
   757  	err := json.Unmarshal(b, (*matchCriteriaER)(m))
   758  	if err != nil {
   759  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaER, err)
   760  	}
   761  	if m.ObjectMatchValue == nil {
   762  		return nil
   763  	}
   764  
   765  	objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue)
   766  	if err != nil {
   767  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaER, err)
   768  	}
   769  
   770  	createObjectMatchValue, ok := simpleObjectMatchValueHandlers[objectMatchValueTypeName]
   771  	if !ok {
   772  		return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaER, objectMatchValueTypeName)
   773  	}
   774  	convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue())
   775  	if err != nil {
   776  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaER, err)
   777  	}
   778  	m.ObjectMatchValue = convertedObjectMatchValue
   779  
   780  	return nil
   781  }
   782  
   783  // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaFR as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple
   784  func (m *MatchCriteriaFR) UnmarshalJSON(b []byte) error {
   785  	// matchCriteriaFR is an alias for MatchCriteriaFR for un-marshalling purposes
   786  	type matchCriteriaFR MatchCriteriaFR
   787  
   788  	// populate common attributes using default json unmarshaler using aliased type
   789  	err := json.Unmarshal(b, (*matchCriteriaFR)(m))
   790  	if err != nil {
   791  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaFR, err)
   792  	}
   793  	if m.ObjectMatchValue == nil {
   794  		return nil
   795  	}
   796  
   797  	objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue)
   798  	if err != nil {
   799  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaFR, err)
   800  	}
   801  
   802  	createObjectMatchValue, ok := simpleObjectMatchValueHandlers[objectMatchValueTypeName]
   803  	if !ok {
   804  		return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaFR, objectMatchValueTypeName)
   805  	}
   806  	convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue())
   807  	if err != nil {
   808  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaFR, err)
   809  	}
   810  	m.ObjectMatchValue = convertedObjectMatchValue
   811  
   812  	return nil
   813  }
   814  
   815  // UnmarshalJSON helps to un-marshall field ObjectMatchValue of MatchCriteriaRC as proper instance of *ObjectMatchValueObject or *ObjectMatchValueSimple
   816  func (m *MatchCriteriaRC) UnmarshalJSON(b []byte) error {
   817  	// matchCriteriaRC is an alias for MatchCriteriaRC for un-marshalling purposes
   818  	type matchCriteriaRC MatchCriteriaRC
   819  
   820  	// populate common attributes using default json unmarshaler using aliased type
   821  	err := json.Unmarshal(b, (*matchCriteriaRC)(m))
   822  	if err != nil {
   823  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaRC, err)
   824  	}
   825  	if m.ObjectMatchValue == nil {
   826  		return nil
   827  	}
   828  
   829  	objectMatchValueTypeName, err := getObjectMatchValueType(m.ObjectMatchValue)
   830  	if err != nil {
   831  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaRC, err)
   832  	}
   833  
   834  	createObjectMatchValue, ok := simpleObjectMatchValueHandlers[objectMatchValueTypeName]
   835  	if !ok {
   836  		return fmt.Errorf("%w: objectMatchValue has unexpected type: '%s'", ErrUnmarshallMatchCriteriaRC, objectMatchValueTypeName)
   837  	}
   838  	convertedObjectMatchValue, err := convertObjectMatchValue(m.ObjectMatchValue, createObjectMatchValue())
   839  	if err != nil {
   840  		return fmt.Errorf("%w: %s", ErrUnmarshallMatchCriteriaRC, err)
   841  	}
   842  	m.ObjectMatchValue = convertedObjectMatchValue
   843  
   844  	return nil
   845  }
   846  
   847  func getObjectMatchValueType(omv interface{}) (string, error) {
   848  	objectMatchValueMap, ok := omv.(map[string]interface{})
   849  	if !ok {
   850  		return "", fmt.Errorf("structure of objectMatchValue should be 'map', but was '%T'", omv)
   851  	}
   852  	objectMatchValueType, ok := objectMatchValueMap["type"]
   853  	if !ok {
   854  		return "", fmt.Errorf("objectMatchValue should contain 'type' field")
   855  	}
   856  	objectMatchValueTypeName, ok := objectMatchValueType.(string)
   857  	if !ok {
   858  		return "", fmt.Errorf("'type' should be a string")
   859  	}
   860  	return objectMatchValueTypeName, nil
   861  }
   862  
   863  func convertObjectMatchValue(in, out interface{}) (interface{}, error) {
   864  	marshal, err := json.Marshal(in)
   865  	if err != nil {
   866  		return nil, fmt.Errorf("%s", err)
   867  	}
   868  	err = json.Unmarshal(marshal, out)
   869  	if err != nil {
   870  		return nil, fmt.Errorf("%s", err)
   871  	}
   872  
   873  	return out, nil
   874  }