func (service *ServiceModel) AddHandler(handler *RESTHandler) {
	if service.Handlers == nil {
		service.Handlers = []*RESTHandler{}
	}
	service.Handlers = append(service.Handlers, handler)
}
AddHandler adds handler to this ServiceModel.
package gomodel
import (
	"fmt"
	"regexp"
	"sort"
	"strings"
	"github.com/googleapis/gapic-showcase/util/genrest/errorhandling"
	"github.com/googleapis/gapic-showcase/util/genrest/internal/pbinfo"
	"github.com/googleapis/gapic-showcase/util/genrest/resttools"
)
type Model struct {
	errorhandling.Accumulator
	Service []*ServiceModel
}
func (gm *Model) Add(service *ServiceModel) {
	gm.Service = append(gm.Service, service)
}
func (gm *Model) String() string {
	shimStrings := make([]string, len(gm.Service))
	for idx, shim := range gm.Service {
		shimStrings[idx] = shim.String()
	}
	sep := "----------------------------------------"
	return fmt.Sprintf("GoModel\n%s\n%s", sep, strings.Join(shimStrings, "\n"+sep+"\n"))
}
func (gm *Model) CheckConsistency() {
	reBodyField := regexp.MustCompile(resttools.RegexField)
	allHandlers := []*RESTHandler{}
	for _, service := range gm.Service {
		allHandlers = append(allHandlers, service.Handlers...)
	}
	for first, firstHandler := range allHandlers {
		if len(firstHandler.RequestBodyFieldProtoName) > 0 && firstHandler.RequestBodyFieldProtoName != "*" {
			if reBodyField.FindStringIndex(firstHandler.RequestBodyFieldProtoName) == nil {
				gm.AccumulateError(fmt.Errorf("bad syntax in body field spec %q", firstHandler.RequestBodyFieldProtoName))
			}
		}
		if _, nestedVariables := firstHandler.PathTemplate.HasVariables(); nestedVariables {
			gm.AccumulateError(fmt.Errorf("pattern %q specifies nested variables, which are not allowed as per https://cloud.google.com/endpoints/docs/grpc-service-config/reference/rpc/google.api#path-template-syntax", firstHandler.URIPattern))
		}
		for _, secondHandler := range allHandlers[first+1:] {
			if firstHandler.HTTPMethod != secondHandler.HTTPMethod {
				continue
			}
			fullMatch, ambiguousPattern, err := FindValuesMatching(firstHandler.PathTemplate, secondHandler.PathTemplate)
			if err != nil {
				gm.AccumulateError(fmt.Errorf("matching patterns %q and %q (constructed %q): %s", firstHandler, secondHandler, ambiguousPattern, err))
				continue
			}
			if !fullMatch {
				continue
			}
			gm.AccumulateError(fmt.Errorf("pattern %q matches both\n   %s and\n   %s\n\n", ambiguousPattern, firstHandler, secondHandler))
		}
	}
}
type ServiceModel struct {
	ProtoPath string
	ShortName string
	Imports map[string]*pbinfo.ImportSpec
	Handlers []*RESTHandler
}
func (service *ServiceModel) FullName() string {
	return fmt.Sprintf("%q (%s)", service.ShortName, service.ProtoPath)
}
func (service *ServiceModel) String() string {
	importStrings := make([]string, 0, len(service.Imports))
	for path, spec := range service.Imports {
		importStrings = append(importStrings, fmt.Sprintf("%s: %q %q", spec.Name, spec.Path, path))
	}
	sort.Strings(importStrings)
	handlerStrings := make([]string, len(service.Handlers))
	for idx, handler := range service.Handlers {
		handlerStrings[idx] = handler.String()
	}
	sort.Strings(handlerStrings)
	return fmt.Sprintf("Shim %s\n  Imports:\n    %s\n  Handlers (%d):\n    %s",
		service.FullName(),
		strings.Join(importStrings, "\n    "),
		len(handlerStrings),
		strings.Join(handlerStrings, "\n    "))
}