func AssociateControllerWithPath(path string, controller Controller) {
	pathElementList := strings.Split(strings.Trim(path, "/"), "/")
	newPathElementList := []string{}
	for _, pathElement := range pathElementList {
		if pathElement[:1] == ":" {
			newPathElementList = append(newPathElementList, "[^/]+")
		} else {
			newPathElementList = append(newPathElementList, pathElement)
		}
	}
	newPath := fmt.Sprintf("^%s$", strings.Join(newPathElementList, "/"))
	if oldPair, exists := pathControllerMap[newPath]; exists {
		if oldPair.controller != controller {
			logging.Logger().Criticalf("path %s is already mapped to another controller", newPath)
			os.Exit(1)
		}
	}
	newRegExp, err := regexp.Compile(newPath)
	if err != nil {
		logging.Logger().Critical(err.Error())
		os.Exit(1)
	}
	pathControllerMap[newPath] = &regExpControllerPair{
		regExp:     newRegExp,
		controller: controller,
	}
}
AssociateControllerWithPath associates a path and a controller
package extension
import (
	"fmt"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strings"
	"github.com/gin-gonic/gin"
	"github.com/qb0C80aE/clay/logging"
)
type regExpControllerPair struct {
	regExp     *regexp.Regexp
	controller Controller
}
var controllerList = []Controller{}
var pathControllerMap = map[string]*regExpControllerPair{}
var routerGroupMap = map[string]*gin.RouterGroup{}
const (
	MethodGet     = 1
	MethodPost    = 2
	MethodPut     = 3
	MethodDelete  = 4
	MethodPatch   = 5
	MethodOptions = 6
)
const (
	URLSingle = 1
	URLMulti  = 2
)
const (
	AcceptJSON     = "application/json"
	AcceptXYAML    = "application/x-yaml"
	AcceptTextYAML = "text/yaml"
	AcceptAll      = "*/*"
)
const (
	AcceptCharsetUTF8 = "utf-8"
)
const (
	ContentTypeJSON              = "application/json"
	ContentTypeXYAML             = "application/x-yaml"
	ContentTypeTextYAML          = "text/yaml"
	ContentTypeMultipartFormData = "multipart/form-data"
	ContentTypeOctetStream       = "application/octet-stream"
)
var methodStringMap = map[int]string{
	MethodGet:     http.MethodGet,
	MethodPost:    http.MethodPost,
	MethodPut:     http.MethodPut,
	MethodDelete:  http.MethodDelete,
	MethodPatch:   http.MethodPatch,
	MethodOptions: http.MethodOptions,
}
var methodIntMap = map[string]int{
	http.MethodGet:     MethodGet,
	http.MethodPost:    MethodPost,
	http.MethodPut:     MethodPut,
	http.MethodDelete:  MethodDelete,
	http.MethodPatch:   MethodPatch,
	http.MethodOptions: MethodOptions,
}
type Controller interface {
	GetModel() Model
	GetResourceName() (string, error)
	GetResourceSingleURL() (string, error)
	GetResourceMultiURL() (string, error)
	GetRouteMap() map[int]map[int]gin.HandlerFunc
}
type Binder interface {
	Bind(c *gin.Context, resourceName string) (interface{}, error)
}
type QueryCustomizer interface {
	GetQueries(c *gin.Context) url.Values
}
type OutputHandler interface {
	OutputError(c *gin.Context, code int, err error)
	OutputGetSingle(c *gin.Context, code int, result interface{}, fields map[string]interface{})
	OutputGetMulti(c *gin.Context, code int, result interface{}, total int, countBeforePagination int, fields map[string]interface{})
	OutputCreate(c *gin.Context, code int, result interface{})
	OutputUpdate(c *gin.Context, code int, result interface{})
	OutputDelete(c *gin.Context, code int)
	OutputPatch(c *gin.Context, code int, result interface{})
	OutputGetOptions(c *gin.Context, code int)
}
func LookUpMethodName(method int) string {
	return methodStringMap[method]
}
func LookUpMethodInt(method string) int {
	return methodIntMap[method]
}
func RegisterController(controller Controller) {
	controllerList = append(controllerList, controller)
}
func GetRegisteredControllerList() []Controller {
	result := []Controller{}
	result = append(result, controllerList...)
	return result
}