func (r *attrFactory) NewQualifier(objType *exprpb.Type,
	qualID int64,
	val interface{}) (Qualifier, error) {
	str, isStr := val.(string)
	if isStr && objType != nil && objType.GetMessageType() != "" {
		ft, found := r.provider.FindFieldType(objType.GetMessageType(), str)
		if found && ft.IsSet != nil && ft.GetFrom != nil {
			return &fieldQualifier{
				id:        qualID,
				Name:      str,
				FieldType: ft,
				adapter:   r.adapter,
			}, nil
		}
	}
	return newQualifier(r.adapter, qualID, val)
}
NewQualifier is an implementation of the AttributeFactory interface.
package interpreter
import (
	"errors"
	"fmt"
	"math"
	"github.com/google/cel-go/common/containers"
	"github.com/google/cel-go/common/types"
	"github.com/google/cel-go/common/types/ref"
	"github.com/google/cel-go/common/types/traits"
	exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
)
type AttributeFactory interface {
	AbsoluteAttribute(id int64, names ...string) NamespacedAttribute
	ConditionalAttribute(id int64, expr Interpretable, t, f Attribute) Attribute
	MaybeAttribute(id int64, name string) Attribute
	RelativeAttribute(id int64, operand Interpretable) Attribute
	NewQualifier(objType *exprpb.Type, qualID int64, val interface{}) (Qualifier, error)
}
type Qualifier interface {
	ID() int64
	Qualify(vars Activation, obj interface{}) (interface{}, error)
}
type ConstantQualifier interface {
	Qualifier
	Value() ref.Val
}
type Attribute interface {
	Qualifier
	AddQualifier(Qualifier) (Attribute, error)
	Resolve(Activation) (interface{}, error)
}
type NamespacedAttribute interface {
	Attribute
	CandidateVariableNames() []string
	Qualifiers() []Qualifier
	TryResolve(Activation) (interface{}, bool, error)
}
func NewAttributeFactory(cont *containers.Container,
	a ref.TypeAdapter,
	p ref.TypeProvider) AttributeFactory {
	return &attrFactory{
		container: cont,
		adapter:   a,
		provider:  p,
	}
}
type attrFactory struct {
	container *containers.Container
	adapter   ref.TypeAdapter
	provider  ref.TypeProvider
}
func (r *attrFactory) AbsoluteAttribute(id int64, names ...string) NamespacedAttribute {
	return &absoluteAttribute{
		id:             id,
		namespaceNames: names,
		qualifiers:     []Qualifier{},
		adapter:        r.adapter,
		provider:       r.provider,
		fac:            r,
	}
}
func (r *attrFactory) ConditionalAttribute(id int64, expr Interpretable, t, f Attribute) Attribute {
	return &conditionalAttribute{
		id:      id,
		expr:    expr,
		truthy:  t,
		falsy:   f,
		adapter: r.adapter,
		fac:     r,
	}
}
func (r *attrFactory) MaybeAttribute(id int64, name string) Attribute {
	return &maybeAttribute{
		id: id,
		attrs: []NamespacedAttribute{
			r.AbsoluteAttribute(id, r.container.ResolveCandidateNames(name)...),
		},
		adapter:  r.adapter,
		provider: r.provider,
		fac:      r,
	}
}
func (r *attrFactory) RelativeAttribute(id int64, operand Interpretable) Attribute {
	return &relativeAttribute{
		id:         id,
		operand:    operand,
		qualifiers: []Qualifier{},
		adapter:    r.adapter,
		fac:        r,
	}
}