text:
package iris

import (
	"bytes"
	"crypto/tls"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/iris-contrib/errors"
	"github.com/iris-contrib/letsencrypt"
	"github.com/iris-contrib/logger"
	"github.com/kataras/iris/config"
	"github.com/kataras/iris/utils"
	"github.com/valyala/fasthttp"
	"github.com/valyala/fasthttp/fasthttpadaptor"
)

const (
	// MethodGet "GET"
	MethodGet = "GET"
	// MethodPost "POST"
	MethodPost = "POST"
	// MethodPut "PUT"
	MethodPut = "PUT"
	// MethodDelete "DELETE"
	MethodDelete = "DELETE"
	// MethodConnect "CONNECT"
	MethodConnect = "CONNECT"
	// MethodHead "HEAD"
	MethodHead = "HEAD"
	// MethodPatch "PATCH"
	MethodPatch = "PATCH"
	// MethodOptions "OPTIONS"
	MethodOptions = "OPTIONS"
	// MethodTrace "TRACE"
	MethodTrace = "TRACE"
)

var (
	// AllMethods "GET", "POST", "PUT", "DELETE", "CONNECT", "HEAD", "PATCH", "OPTIONS", "TRACE"
	AllMethods = [...]string{MethodGet, MethodPost, MethodPut, MethodDelete, MethodConnect, MethodHead, MethodPatch, MethodOptions, MethodTrace}

	/* methods as []byte, these are really used by iris */
	// methodGetBytes "GET"
	methodGetBytes = []byte(MethodGet)
	// methodPostBytes "POST"
	methodPostBytes = []byte(MethodPost)
	// methodPutBytes "PUT"
	methodPutBytes = []byte(MethodPut)
	// methodDeleteBytes "DELETE"
	methodDeleteBytes = []byte(MethodDelete)
	// methodConnectBytes "CONNECT"
	methodConnectBytes = []byte(MethodConnect)
	// methodHeadBytes "HEAD"
	methodHeadBytes = []byte(MethodHead)
	// methodPatchBytes "PATCH"
	methodPatchBytes = []byte(MethodPatch)
	// methodOptionsBytes "OPTIONS"
	methodOptionsBytes = []byte(MethodOptions)
	// methodTraceBytes "TRACE"
	methodTraceBytes = []byte(MethodTrace)
	/* */

)

const (
	// StatusContinue http status '100'
	StatusContinue = 100
	// StatusSwitchingProtocols http status '101'
	StatusSwitchingProtocols = 101

	// StatusOK http status '200'
	StatusOK = 200
	// StatusCreated http status '201'
	StatusCreated = 201
	// StatusAccepted http status '202'
	StatusAccepted = 202
	// StatusNonAuthoritativeInfo http status '203'
	StatusNonAuthoritativeInfo = 203
	// StatusNoContent http status '204'
	StatusNoContent = 204
	// StatusResetContent http status '205'
	StatusResetContent = 205
	// StatusPartialContent http status '206'
	StatusPartialContent = 206

	// StatusMultipleChoices http status '300'
	StatusMultipleChoices = 300
	// StatusMovedPermanently http status '301'
	StatusMovedPermanently = 301
	// StatusFound http status '302'
	StatusFound = 302
	// StatusSeeOther http status '303'
	StatusSeeOther = 303
	// StatusNotModified http status '304'
	StatusNotModified = 304
	// StatusUseProxy http status '305'
	StatusUseProxy = 305
	// StatusTemporaryRedirect http status '307'
	StatusTemporaryRedirect = 307

	// StatusBadRequest http status '400'
	StatusBadRequest = 400
	// StatusUnauthorized http status '401'
	StatusUnauthorized = 401
	// StatusPaymentRequired http status '402'
	StatusPaymentRequired = 402
	// StatusForbidden http status '403'
	StatusForbidden = 403
	// StatusNotFound http status '404'
	StatusNotFound = 404
	// StatusMethodNotAllowed http status '405'
	StatusMethodNotAllowed = 405
	// StatusNotAcceptable http status '406'
	StatusNotAcceptable = 406
	// StatusProxyAuthRequired http status '407'
	StatusProxyAuthRequired = 407
	// StatusRequestTimeout http status '408'
	StatusRequestTimeout = 408
	// StatusConflict http status '409'
	StatusConflict = 409
	// StatusGone http status '410'
	StatusGone = 410
	// StatusLengthRequired http status '411'
	StatusLengthRequired = 411
	// StatusPreconditionFailed http status '412'
	StatusPreconditionFailed = 412
	// StatusRequestEntityTooLarge http status '413'
	StatusRequestEntityTooLarge = 413
	// StatusRequestURITooLong http status '414'
	StatusRequestURITooLong = 414
	// StatusUnsupportedMediaType http status '415'
	StatusUnsupportedMediaType = 415
	// StatusRequestedRangeNotSatisfiable http status '416'
	StatusRequestedRangeNotSatisfiable = 416
	// StatusExpectationFailed http status '417'
	StatusExpectationFailed = 417
	// StatusTeapot http status '418'
	StatusTeapot = 418
	// StatusPreconditionRequired http status '428'
	StatusPreconditionRequired = 428
	// StatusTooManyRequests http status '429'
	StatusTooManyRequests = 429
	// StatusRequestHeaderFieldsTooLarge http status '431'
	StatusRequestHeaderFieldsTooLarge = 431
	// StatusUnavailableForLegalReasons http status '451'
	StatusUnavailableForLegalReasons = 451

	// StatusInternalServerError http status '500'
	StatusInternalServerError = 500
	// StatusNotImplemented http status '501'
	StatusNotImplemented = 501
	// StatusBadGateway http status '502'
	StatusBadGateway = 502
	// StatusServiceUnavailable http status '503'
	StatusServiceUnavailable = 503
	// StatusGatewayTimeout http status '504'
	StatusGatewayTimeout = 504
	// StatusHTTPVersionNotSupported http status '505'
	StatusHTTPVersionNotSupported = 505
	// StatusNetworkAuthenticationRequired http status '511'
	StatusNetworkAuthenticationRequired = 511
)

var statusText = map[int]string{
	StatusContinue:           "Continue",
	StatusSwitchingProtocols: "Switching Protocols",

	StatusOK:                   "OK",
	StatusCreated:              "Created",
	StatusAccepted:             "Accepted",
	StatusNonAuthoritativeInfo: "Non-Authoritative Information",
	StatusNoContent:            "No Content",
	StatusResetContent:         "Reset Content",
	StatusPartialContent:       "Partial Content",

	StatusMultipleChoices:   "Multiple Choices",
	StatusMovedPermanently:  "Moved Permanently",
	StatusFound:             "Found",
	StatusSeeOther:          "See Other",
	StatusNotModified:       "Not Modified",
	StatusUseProxy:          "Use Proxy",
	StatusTemporaryRedirect: "Temporary Redirect",

	StatusBadRequest:                   "Bad Request",
	StatusUnauthorized:                 "Unauthorized",
	StatusPaymentRequired:              "Payment Required",
	StatusForbidden:                    "Forbidden",
	StatusNotFound:                     "Not Found",
	StatusMethodNotAllowed:             "Method Not Allowed",
	StatusNotAcceptable:                "Not Acceptable",
	StatusProxyAuthRequired:            "Proxy Authentication Required",
	StatusRequestTimeout:               "Request Timeout",
	StatusConflict:                     "Conflict",
	StatusGone:                         "Gone",
	StatusLengthRequired:               "Length Required",
	StatusPreconditionFailed:           "Precondition Failed",
	StatusRequestEntityTooLarge:        "Request Entity Too Large",
	StatusRequestURITooLong:            "Request URI Too Long",
	StatusUnsupportedMediaType:         "Unsupported Media Type",
	StatusRequestedRangeNotSatisfiable: "Requested Range Not Satisfiable",
	StatusExpectationFailed:            "Expectation Failed",
	StatusTeapot:                       "I'm a teapot",
	StatusPreconditionRequired:         "Precondition Required",
	StatusTooManyRequests:              "Too Many Requests",
	StatusRequestHeaderFieldsTooLarge:  "Request Header Fields Too Large",
	StatusUnavailableForLegalReasons:   "Unavailable For Legal Reasons",

	StatusInternalServerError:           "Internal Server Error",
	StatusNotImplemented:                "Not Implemented",
	StatusBadGateway:                    "Bad Gateway",
	StatusServiceUnavailable:            "Service Unavailable",
	StatusGatewayTimeout:                "Gateway Timeout",
	StatusHTTPVersionNotSupported:       "HTTP Version Not Supported",
	StatusNetworkAuthenticationRequired: "Network Authentication Required",
}

// StatusText returns a text for the HTTP status code. It returns the empty
// string if the code is unknown.
func StatusText(code int) string {
	return statusText[code]
}

// Errors introduced by server.
var (
	errServerPortAlreadyUsed = errors.New("Server can't run, port is already used")
	errServerAlreadyStarted  = errors.New("Server is already started and listening")
	errServerHandlerMissing  = errors.New("Handler is missing from server, can't start without handler")
	errServerIsClosed        = errors.New("Can't close the server, propably is already closed or never started")
	errServerRemoveUnix      = errors.New("Unexpected error when trying to remove unix socket file. Addr: %s | Trace: %s")
	errServerChmod           = errors.New("Cannot chmod %#o for %q: %s")
)

type (
	// Server the http server
	Server struct {
		*fasthttp.Server
		listener net.Listener
		Config   config.Server
		tls      bool
		mu       sync.Mutex
	}
	// ServerList contains the servers connected to the Iris station
	ServerList struct {
		mux     *serveMux
		servers []*Server
	}
)

// newServer returns a pointer to a Server object, and set it's options if any,  nothing more
func newServer(cfg config.Server) *Server {
	if cfg.Name == "" {
		cfg.Name = config.DefaultServerName
	}
	s := &Server{Server: &fasthttp.Server{Name: cfg.Name}, Config: cfg}
	return s
}

// IsListening returns true if server is listening/started, otherwise false
func (s *Server) IsListening() bool {
	if s == nil {
		return false
	}
	s.mu.Lock()
	defer s.mu.Unlock()
	return s.listener != nil && s.listener.Addr().String() != ""
}

// IsOpened checks if handler is not nil and returns true if not, otherwise false
// this is used to see if a server has opened, use IsListening if you want to see if the server is actually ready to serve connections
func (s *Server) IsOpened() bool {
	if s == nil {
		return false
	}
	return s.Server != nil && s.Server.Handler != nil
}

// IsSecure returns true if server uses TLS, otherwise false
func (s *Server) IsSecure() bool {
	return s.tls || s.Config.AutoTLS // for any case
}

// Listener returns the net.Listener which this server (is) listening to
func (s *Server) Listener() net.Listener {
	return s.listener
}

// Host returns the registered host for the server
func (s *Server) Host() string {
	if s.Config.VListeningAddr != "" {
		return s.Config.VListeningAddr
	}
	return s.Config.ListeningAddr
}

// Port returns the port which server listening for
// if no port given with the ListeningAddr, it returns 80
func (s *Server) Port() int {
	a := s.Host()
	if portIdx := strings.IndexByte(a, ':'); portIdx != -1 {
		p, err := strconv.Atoi(a[portIdx+1:])
		if err != nil {
			if s.Config.AutoTLS {
				return 443
			}
			return 80
		}
		return p
	}
	if s.Config.AutoTLS {
		return 443
	}
	return 80

}

// Scheme returns http:// or https:// if SSL is enabled
func (s *Server) Scheme() string {
	scheme := "http://"
	// we need to be able to take that before(for testing &debugging) and after server's listen
	if s.IsSecure() || (s.Config.CertFile != "" && s.Config.KeyFile != "") || s.Config.AutoTLS {
		scheme = "https://"
	}
	// but if virtual scheme is setted and it differs from the real scheme, return the vscheme
	// the developer should set it correctly, http:// or https:// or anything at the future:P
	vscheme := s.Config.VScheme
	if len(vscheme) > 0 && vscheme != scheme {
		return vscheme
	}

	return scheme
}

// FullHost returns the scheme+host
func (s *Server) FullHost() string {
	return s.Scheme() + s.Host()
}

// Hostname returns the hostname part of the host (host expect port)
func (s *Server) Hostname() string {
	a := s.Host()
	idxPort := strings.IndexByte(a, ':')
	if idxPort > 0 {
		// port exists, (it always exists for Config.ListeningAddr
		return a[0:idxPort] // except the port
	} // but for Config.VListeningAddr the developer maybe doesn't uses the host:port format

	// so, if no port found, then return the Host as it is, it should be something 'mydomain.com'
	return a
}

func (s *Server) listen() error {
	if s.IsListening() {
		return errServerAlreadyStarted.Return()
	}
	listener, err := net.Listen("tcp4", s.Config.ListeningAddr)

	if err != nil {
		return err
	}

	go s.serve(listener) // we don't catch underline errors, we catched all already
	return nil

}

func (s *Server) listenUNIX() error {

	mode := s.Config.Mode
	addr := s.Config.ListeningAddr

	if errOs := os.Remove(addr); errOs != nil && !os.IsNotExist(errOs) {
		return errServerRemoveUnix.Format(s.Config.ListeningAddr, errOs.Error())
	}

	listener, err := net.Listen("unix", addr)

	if err != nil {
		return errServerPortAlreadyUsed.Return()
	}

	if err = os.Chmod(addr, mode); err != nil {
		return errServerChmod.Format(mode, addr, err.Error())
	}

	go s.serve(listener) // we don't catch underline errors, we catched all already
	return nil

}

//Serve just serves a listener, it is a blocking action, plugin.PostListen is not fired here.
func (s *Server) serve(l net.Listener) error {
	s.mu.Lock()
	s.listener = l
	s.mu.Unlock()
	if s.Config.CertFile != "" && s.Config.KeyFile != "" {
		s.tls = true
		return s.Server.ServeTLS(s.listener, s.Config.CertFile, s.Config.KeyFile)
	} else if s.Config.AutoTLS {
		var m letsencrypt.Manager
		if err := m.CacheFile("letsencrypt.cache"); err != nil {
			return err
		}
		tlsConfig := &tls.Config{GetCertificate: m.GetCertificate}

		ln := tls.NewListener(l, tlsConfig)
		s.tls = true
		s.mu.Lock()
		s.listener = ln
		s.mu.Unlock()
	}

	return s.Server.Serve(s.listener)
}

// Open opens/starts/runs/listens (to) the server, listen tls if Cert && Key is registed, listenUNIX if Mode is registed, otherwise listen
func (s *Server) Open(h fasthttp.RequestHandler) error {
	if h == nil {
		return errServerHandlerMissing.Return()
	}

	if s.IsListening() {
		return errServerAlreadyStarted.Return()
	}

	s.Server.MaxRequestBodySize = s.Config.MaxRequestBodySize
	s.Server.ReadBufferSize = s.Config.ReadBufferSize
	s.Server.WriteBufferSize = s.Config.WriteBufferSize
	s.Server.ReadTimeout = s.Config.ReadTimeout
	s.Server.WriteTimeout = s.Config.WriteTimeout
	if s.Config.RedirectTo != "" {
		// override the handler and redirect all requests to this addr
		s.Server.Handler = func(reqCtx *fasthttp.RequestCtx) {
			path := string(reqCtx.Path())
			redirectTo := s.Config.RedirectTo
			if path != "/" {
				redirectTo += "/" + path
			}
			reqCtx.Redirect(redirectTo, StatusMovedPermanently)
		}
	} else {
		s.Server.Handler = h
	}

	if s.Config.Mode > 0 {
		return s.listenUNIX()
	}

	s.Config.ListeningAddr = config.ServerParseAddr(s.Config.ListeningAddr)

	if s.Config.Virtual {
		return nil
	}

	return s.listen()

}

// Close terminates the server
func (s *Server) Close() (err error) {
	if !s.IsListening() {
		return errServerIsClosed.Return()
	}
	err = s.listener.Close()

	return
}

// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
// --------------------------------ServerList implementation-----------------------------
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------

// Add adds a server to the list by its config
// returns the new server
func (s *ServerList) Add(cfg config.Server) *Server {
	srv := newServer(cfg)
	s.servers = append(s.servers, srv)
	return srv
}

// Len returns the size of the server list
func (s *ServerList) Len() int {
	return len(s.servers)
}

// Main returns the main server,
// the last added server is the main server, even if's Virtual
func (s *ServerList) Main() (srv *Server) {
	l := len(s.servers) - 1
	for i := range s.servers {
		if i == l {
			return s.servers[i]
		}
	}
	return nil
}

// Get returns the server by it's registered Address
func (s *ServerList) Get(addr string) (srv *Server) {
	for i := range s.servers {
		srv = s.servers[i]
		if srv.Config.ListeningAddr == addr {
			return
		}
	}
	return
}

// GetAll returns all registered servers
func (s *ServerList) GetAll() []*Server {
	return s.servers
}

// GetByIndex returns a server from the list by it's index
func (s *ServerList) GetByIndex(i int) *Server {
	if len(s.servers) >= i+1 {
		return s.servers[i]
	}
	return nil
}

// Remove deletes a server by it's registered Address
// returns true if something was removed, otherwise returns false
func (s *ServerList) Remove(addr string) bool {
	servers := s.servers
	for i := range servers {
		srv := servers[i]
		if srv.Config.ListeningAddr == addr {
			copy(servers[i:], servers[i+1:])
			servers[len(servers)-1] = nil
			s.servers = servers[:len(servers)-1]
			return true
		}
	}
	return false
}

// CloseAll terminates all listening servers
// returns the first error, if erro happens it continues to closes the rest of the servers
func (s *ServerList) CloseAll() (err error) {
	for i := range s.servers {
		if err == nil {
			err = s.servers[i].Close()
		}
	}
	return
}

// OpenAll starts all servers
// returns the first error happens to one of these servers
// if one server gets error it closes the previous servers and exits from this process
func (s *ServerList) OpenAll(reqHandler fasthttp.RequestHandler) error {
	l := len(s.servers) - 1
	for i := range s.servers {
		if err := s.servers[i].Open(reqHandler); err != nil {
			time.Sleep(2 * time.Second)
			// for any case,
			// we don't care about performance on initialization,
			// we must make sure that the previous servers are running before closing them
			s.CloseAll()
			return err
		}
		if i == l {
			s.mux.setHostname(s.servers[i].Hostname())
		}

	}
	return nil
}

// GetAllOpened returns all opened/started servers
func (s *ServerList) GetAllOpened() (servers []*Server) {
	for i := range s.servers {
		if s.servers[i].IsOpened() {
			servers = append(servers, s.servers[i])
		}
	}
	return
}

// errHandler returns na error with message: 'Passed argument is not func(*Context) neither an object which implements the iris.Handler with Serve(ctx *Context)
// It seems to be a  +type Points to: +pointer.'
var errHandler = errors.New("Passed argument is not func(*Context) neither an object which implements the iris.Handler with Serve(ctx *Context)\n It seems to be a  %T Points to: %v.")

type (
	// Handler the main Iris Handler interface.
	Handler interface {
		Serve(ctx *Context)
	}

	// HandlerFunc type is an adapter to allow the use of
	// ordinary functions as HTTP handlers.  If f is a function
	// with the appropriate signature, HandlerFunc(f) is a
	// Handler that calls f.
	HandlerFunc func(*Context)
	// Middleware is just a slice of Handler []func(c *Context)
	Middleware []Handler

	// HandlerAPI empty interface used for .API
	HandlerAPI interface{}
)

// Serve implements the Handler, is like ServeHTTP but for Iris
func (h HandlerFunc) Serve(ctx *Context) {
	h(ctx)
}

// ToHandler converts an httapi.Handler or http.HandlerFunc to an iris.Handler
func ToHandler(handler interface{}) Handler {
	//this is not the best way to do it, but I dont have any options right now.
	switch handler.(type) {
	case Handler:
		//it's already an iris handler
		return handler.(Handler)
	case http.Handler:
		//it's http.Handler
		h := fasthttpadaptor.NewFastHTTPHandlerFunc(handler.(http.Handler).ServeHTTP)

		return ToHandlerFastHTTP(h)
	case func(http.ResponseWriter, *http.Request):
		//it's http.HandlerFunc
		h := fasthttpadaptor.NewFastHTTPHandlerFunc(handler.(func(http.ResponseWriter, *http.Request)))
		return ToHandlerFastHTTP(h)
	default:
		panic(errHandler.Format(handler, handler))
	}
}

// ToHandlerFunc converts an http.Handler or http.HandlerFunc to an iris.HandlerFunc
func ToHandlerFunc(handler interface{}) HandlerFunc {
	return ToHandler(handler).Serve
}

// ToHandlerFastHTTP converts an fasthttp.RequestHandler to an iris.Handler
func ToHandlerFastHTTP(h fasthttp.RequestHandler) Handler {
	return HandlerFunc((func(ctx *Context) {
		h(ctx.RequestCtx)
	}))
}

// convertToHandlers just make []HandlerFunc to []Handler, although HandlerFunc and Handler are the same
// we need this on some cases we explicit want a interface Handler, it is useless for users.
func convertToHandlers(handlersFn []HandlerFunc) []Handler {
	hlen := len(handlersFn)
	mlist := make([]Handler, hlen)
	for i := 0; i < hlen; i++ {
		mlist[i] = Handler(handlersFn[i])
	}
	return mlist
}

// joinMiddleware uses to create a copy of all middleware and return them in order to use inside the node
func joinMiddleware(middleware1 Middleware, middleware2 Middleware) Middleware {
	nowLen := len(middleware1)
	totalLen := nowLen + len(middleware2)
	// create a new slice of middleware in order to store all handlers, the already handlers(middleware) and the new
	newMiddleware := make(Middleware, totalLen)
	//copy the already middleware to the just created
	copy(newMiddleware, middleware1)
	//start from there we finish, and store the new middleware too
	copy(newMiddleware[nowLen:], middleware2)
	return newMiddleware
}

func profileMiddleware(debugPath string) Middleware {
	htmlMiddleware := HandlerFunc(func(ctx *Context) {
		ctx.SetContentType(contentHTML + "; charset=" + ctx.framework.Config.Charset)
		ctx.Next()
	})
	indexHandler := ToHandlerFunc(pprof.Index)
	cmdlineHandler := ToHandlerFunc(pprof.Cmdline)
	profileHandler := ToHandlerFunc(pprof.Profile)
	symbolHandler := ToHandlerFunc(pprof.Symbol)
	goroutineHandler := ToHandlerFunc(pprof.Handler("goroutine"))
	heapHandler := ToHandlerFunc(pprof.Handler("heap"))
	threadcreateHandler := ToHandlerFunc(pprof.Handler("threadcreate"))
	debugBlockHandler := ToHandlerFunc(pprof.Handler("block"))

	return Middleware{htmlMiddleware, HandlerFunc(func(ctx *Context) {
		action := ctx.Param("action")
		if len(action) > 1 {
			if strings.Contains(action, "cmdline") {
				cmdlineHandler.Serve((ctx))
			} else if strings.Contains(action, "profile") {
				profileHandler.Serve(ctx)
			} else if strings.Contains(action, "symbol") {
				symbolHandler.Serve(ctx)
			} else if strings.Contains(action, "goroutine") {
				goroutineHandler.Serve(ctx)
			} else if strings.Contains(action, "heap") {
				heapHandler.Serve(ctx)
			} else if strings.Contains(action, "threadcreate") {
				threadcreateHandler.Serve(ctx)
			} else if strings.Contains(action, "debug/block") {
				debugBlockHandler.Serve(ctx)
			}
		} else {
			indexHandler.Serve(ctx)
		}
	})}
}

const (
	// parameterStartByte is very used on the node, it's just contains the byte for the ':' rune/char
	parameterStartByte = byte(':')
	// slashByte is just a byte of '/' rune/char
	slashByte = byte('/')
	// slash is just a string of "/"
	slash = "/"
	// matchEverythingByte is just a byte of '*" rune/char
	matchEverythingByte = byte('*')

	isStatic entryCase = iota
	isRoot
	hasParams
	matchEverything
)

type (
	// PathParameter is a struct which contains Key and Value, used for named path parameters
	PathParameter struct {
		Key   string
		Value string
	}

	// PathParameters type for a slice of PathParameter
	// Tt's a slice of PathParameter type, because it's faster than map
	PathParameters []PathParameter

	// entryCase is the type which the type of muxEntryusing in order to determinate what type (parameterized, anything, static...) is the perticular node
	entryCase uint8

	// muxEntry is the node of a tree of the routes,
	// in order to learn how this is working, google 'trie' or watch this lecture: https://www.youtube.com/watch?v=uhAUk63tLRM
	// this method is used by the BSD's kernel also
	muxEntry struct {
		part        string
		entryCase   entryCase
		hasWildNode bool
		tokens      string
		nodes       []*muxEntry
		middleware  Middleware
		precedence  uint64
		paramsLen   uint8
	}
)

var (
	errMuxEntryConflictsWildcard           = errors.New("Router: Path's part: '%s' conflicts with wildcard '%s' in the route path: '%s' !")
	errMuxEntryMiddlewareAlreadyExists     = errors.New("Router: Middleware were already registered for the path: '%s' !")
	errMuxEntryInvalidWildcard             = errors.New("Router: More than one wildcard found in the path part: '%s' in route's path: '%s' !")
	errMuxEntryConflictsExistingWildcard   = errors.New("Router: Wildcard for route path: '%s' conflicts with existing children in route path: '%s' !")
	errMuxEntryWildcardUnnamed             = errors.New("Router: Unnamed wildcard found in path: '%s' !")
	errMuxEntryWildcardInvalidPlace        = errors.New("Router: Wildcard is only allowed at the end of the path, in the route path: '%s' !")
	errMuxEntryWildcardConflictsMiddleware = errors.New("Router: Wildcard  conflicts with existing middleware for the route path: '%s' !")
	errMuxEntryWildcardMissingSlash        = errors.New("Router: No slash(/) were found before wildcard in the route path: '%s' !")
)

// Get returns a value from a key inside this Parameters
// If no parameter with this key given then it returns an empty string
func (params PathParameters) Get(key string) string {
	for _, p := range params {
		if p.Key == key {
			return p.Value
		}
	}
	return ""
}

// String returns a string implementation of all parameters that this PathParameters object keeps
// hasthe form of key1=value1,key2=value2...
func (params PathParameters) String() string {
	var buff bytes.Buffer
	for i := range params {
		buff.WriteString(params[i].Key)
		buff.WriteString("=")
		buff.WriteString(params[i].Value)
		if i < len(params)-1 {
			buff.WriteString(",")
		}

	}
	return buff.String()
}

// ParseParams receives a string and returns PathParameters (slice of PathParameter)
// received string must have this form:  key1=value1,key2=value2...
func ParseParams(str string) PathParameters {
	_paramsstr := strings.Split(str, ",")
	if len(_paramsstr) == 0 {
		return nil
	}

	params := make(PathParameters, 0) // PathParameters{}

	//	for i := 0; i < len(_paramsstr); i++ {
	for i := range _paramsstr {
		idxOfEq := strings.IndexRune(_paramsstr[i], '=')
		if idxOfEq == -1 {
			//error
			return nil
		}

		key := _paramsstr[i][:idxOfEq]
		val := _paramsstr[i][idxOfEq+1:]
		params = append(params, PathParameter{key, val})
	}
	return params
}

// getParamsLen returns the parameters length from a given path
func getParamsLen(path string) uint8 {
	var n uint
	for i := 0; i < len(path); i++ {
		if path[i] != ':' && path[i] != '*' { // ParameterStartByte & MatchEverythingByte
			continue
		}
		n++
	}
	if n >= 255 {
		return 255
	}
	return uint8(n)
}

// add adds a muxEntry to the existing muxEntry or to the tree if no muxEntry has the prefix of
func (e *muxEntry) add(path string, middleware Middleware) error {
	fullPath := path
	e.precedence++
	numParams := getParamsLen(path)

	if len(e.part) > 0 || len(e.nodes) > 0 {
	loop:
		for {
			if numParams > e.paramsLen {
				e.paramsLen = numParams
			}

			i := 0
			max := utils.FindLower(len(path), len(e.part))
			for i < max && path[i] == e.part[i] {
				i++
			}

			if i < len(e.part) {
				node := muxEntry{
					part:        e.part[i:],
					hasWildNode: e.hasWildNode,
					tokens:      e.tokens,
					nodes:       e.nodes,
					middleware:  e.middleware,
					precedence:  e.precedence - 1,
				}

				for i := range node.nodes {
					if node.nodes[i].paramsLen > node.paramsLen {
						node.paramsLen = node.nodes[i].paramsLen
					}
				}

				e.nodes = []*muxEntry{&node}
				e.tokens = string([]byte{e.part[i]})
				e.part = path[:i]
				e.middleware = nil
				e.hasWildNode = false
			}

			if i < len(path) {
				path = path[i:]

				if e.hasWildNode {
					e = e.nodes[0]
					e.precedence++

					if numParams > e.paramsLen {
						e.paramsLen = numParams
					}
					numParams--

					if len(path) >= len(e.part) && e.part == path[:len(e.part)] {

						if len(e.part) >= len(path) || path[len(e.part)] == slashByte {
							continue loop
						}
					}
					return errMuxEntryConflictsWildcard.Format(path, e.part, fullPath)
				}

				c := path[0]

				if e.entryCase == hasParams && c == slashByte && len(e.nodes) == 1 {
					e = e.nodes[0]
					e.precedence++
					continue loop
				}
				for i := range e.tokens {
					if c == e.tokens[i] {
						i = e.precedenceTo(i)
						e = e.nodes[i]
						continue loop
					}
				}

				if c != parameterStartByte && c != matchEverythingByte {

					e.tokens += string([]byte{c})
					node := &muxEntry{
						paramsLen: numParams,
					}
					e.nodes = append(e.nodes, node)
					e.precedenceTo(len(e.tokens) - 1)
					e = node
				}
				e.addNode(numParams, path, fullPath, middleware)
				return nil

			} else if i == len(path) {
				if e.middleware != nil {
					return errMuxEntryMiddlewareAlreadyExists.Format(fullPath)
				}
				e.middleware = middleware
			}
			return nil
		}
	} else {
		e.addNode(numParams, path, fullPath, middleware)
		e.entryCase = isRoot
	}
	return nil
}

// addNode adds a muxEntry as children to other muxEntry
func (e *muxEntry) addNode(numParams uint8, path string, fullPath string, middleware Middleware) error {
	var offset int

	for i, max := 0, len(path); numParams > 0; i++ {
		c := path[i]
		if c != parameterStartByte && c != matchEverythingByte {
			continue
		}

		end := i + 1
		for end < max && path[end] != slashByte {
			switch path[end] {
			case parameterStartByte, matchEverythingByte:
				/*
				   panic("only one wildcard per path segment is allowed, has: '" +
				   	path[i:] + "' in path '" + fullPath + "'")
				*/
				return errMuxEntryInvalidWildcard.Format(path[i:], fullPath)
			default:
				end++
			}
		}

		if len(e.nodes) > 0 {
			return errMuxEntryConflictsExistingWildcard.Format(path[i:end], fullPath)
		}

		if end-i < 2 {
			return errMuxEntryWildcardUnnamed.Format(fullPath)
		}

		if c == parameterStartByte {

			if i > 0 {
				e.part = path[offset:i]
				offset = i
			}

			child := &muxEntry{
				entryCase: hasParams,
				paramsLen: numParams,
			}
			e.nodes = []*muxEntry{child}
			e.hasWildNode = true
			e = child
			e.precedence++
			numParams--

			if end < max {
				e.part = path[offset:end]
				offset = end

				child := &muxEntry{
					paramsLen:  numParams,
					precedence: 1,
				}
				e.nodes = []*muxEntry{child}
				e = child
			}

		} else {
			if end != max || numParams > 1 {
				return errMuxEntryWildcardInvalidPlace.Format(fullPath)
			}

			if len(e.part) > 0 && e.part[len(e.part)-1] == '/' {
				return errMuxEntryWildcardConflictsMiddleware.Format(fullPath)
			}

			i--
			if path[i] != slashByte {
				return errMuxEntryWildcardMissingSlash.Format(fullPath)
			}

			e.part = path[offset:i]

			child := &muxEntry{
				hasWildNode: true,
				entryCase:   matchEverything,
				paramsLen:   1,
			}
			e.nodes = []*muxEntry{child}
			e.tokens = string(path[i])
			e = child
			e.precedence++

			child = &muxEntry{
				part:       path[i:],
				entryCase:  matchEverything,
				paramsLen:  1,
				middleware: middleware,
				precedence: 1,
			}
			e.nodes = []*muxEntry{child}

			return nil
		}
	}

	e.part = path[offset:]
	e.middleware = middleware

	return nil
}

// get is used by the Router, it finds and returns the correct muxEntry for a path
func (e *muxEntry) get(path string, _params PathParameters) (middleware Middleware, params PathParameters, mustRedirect bool) {
	params = _params
loop:
	for {
		if len(path) > len(e.part) {
			if path[:len(e.part)] == e.part {
				path = path[len(e.part):]

				if !e.hasWildNode {
					c := path[0]
					for i := range e.tokens {
						if c == e.tokens[i] {
							e = e.nodes[i]
							continue loop
						}
					}

					mustRedirect = (path == slash && e.middleware != nil)
					return
				}

				e = e.nodes[0]
				switch e.entryCase {
				case hasParams:

					end := 0
					for end < len(path) && path[end] != '/' {
						end++
					}

					if cap(params) < int(e.paramsLen) {
						params = make(PathParameters, 0, e.paramsLen)
					}
					i := len(params)
					params = params[:i+1]
					params[i].Key = e.part[1:]
					params[i].Value = path[:end]

					if end < len(path) {
						if len(e.nodes) > 0 {
							path = path[end:]
							e = e.nodes[0]
							continue loop
						}

						mustRedirect = (len(path) == end+1)
						return
					}

					if middleware = e.middleware; middleware != nil {
						return
					} else if len(e.nodes) == 1 {
						e = e.nodes[0]
						mustRedirect = (e.part == slash && e.middleware != nil)
					}

					return

				case matchEverything:
					if cap(params) < int(e.paramsLen) {
						params = make(PathParameters, 0, e.paramsLen)
					}
					i := len(params)
					params = params[:i+1]
					params[i].Key = e.part[2:]
					params[i].Value = path

					middleware = e.middleware
					return

				default:
					return
				}
			}
		} else if path == e.part {
			if middleware = e.middleware; middleware != nil {
				return
			}

			if path == slash && e.hasWildNode && e.entryCase != isRoot {
				mustRedirect = true
				return
			}

			for i := range e.tokens {
				if e.tokens[i] == slashByte {
					e = e.nodes[i]
					mustRedirect = (len(e.part) == 1 && e.middleware != nil) ||
						(e.entryCase == matchEverything && e.nodes[0].middleware != nil)
					return
				}
			}

			return
		}

		mustRedirect = (path == slash) ||
			(len(e.part) == len(path)+1 && e.part[len(path)] == slashByte &&
				path == e.part[:len(e.part)-1] && e.middleware != nil)
		return
	}
}

// precedenceTo just adds the priority of this muxEntry by an index
func (e *muxEntry) precedenceTo(index int) int {
	e.nodes[index].precedence++
	_precedence := e.nodes[index].precedence

	newindex := index
	for newindex > 0 && e.nodes[newindex-1].precedence < _precedence {
		tmpN := e.nodes[newindex-1]
		e.nodes[newindex-1] = e.nodes[newindex]
		e.nodes[newindex] = tmpN

		newindex--
	}

	if newindex != index {
		e.tokens = e.tokens[:newindex] +
			e.tokens[index:index+1] +
			e.tokens[newindex:index] + e.tokens[index+1:]
	}

	return newindex
}

//
//
//

type (
	// Route contains some useful information about a route
	Route interface {
		// Name returns the name of the route
		Name() string
		// Subdomain returns the subdomain,if any
		Subdomain() string
		// Method returns the http method
		Method() string
		// Path returns the path
		Path() string
		// SetPath changes/sets the path for this route
		SetPath(string)
		// Middleware returns the slice of Handler([]Handler) registed to this route
		Middleware() Middleware
		// SetMiddleware changes/sets the middleware(handler(s)) for this route
		SetMiddleware(Middleware)
	}

	route struct {
		// if no name given then it's the subdomain+path
		name           string
		subdomain      string
		method         []byte
		methodStr      string
		path           string
		middleware     Middleware
		formattedPath  string
		formattedParts int
	}

	bySubdomain []*route
)

// Sorting happens when the mux's request handler initialized
func (s bySubdomain) Len() int {
	return len(s)
}
func (s bySubdomain) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}
func (s bySubdomain) Less(i, j int) bool {
	return len(s[i].Subdomain()) > len(s[j].Subdomain())
}

var _ Route = &route{}

func newRoute(method []byte, subdomain string, path string, middleware Middleware) *route {
	r := &route{name: path + subdomain, method: method, subdomain: subdomain, path: path, middleware: middleware}
	r.formatPath()
	return r
}

func (r *route) formatPath() {
	// we don't care about performance here.
	n1Len := strings.Count(r.path, ":")
	isMatchEverything := len(r.path) > 0 && r.path[len(r.path)-1] == matchEverythingByte
	if n1Len == 0 && !isMatchEverything {
		// its a static
		return
	}
	if n1Len == 0 && isMatchEverything {
		//if we have something like: /mypath/anything/* -> /mypatch/anything/%v
		r.formattedPath = r.path[0:len(r.path)-2] + "%v"
		r.formattedParts++
		return
	}

	tempPath := r.path
	splittedN1 := strings.Split(r.path, "/")

	for _, v := range splittedN1 {
		if len(v) > 0 {
			if v[0] == ':' || v[0] == matchEverythingByte {
				r.formattedParts++
				tempPath = strings.Replace(tempPath, v, "%v", -1) // n1Len, but let it we don't care about performance here.
			}
		}

	}
	r.formattedPath = tempPath
}

func (r *route) setName(newName string) {
	r.name = newName
}

func (r route) Name() string {
	return r.name
}

func (r route) Subdomain() string {
	return r.subdomain
}

func (r route) Method() string {
	if r.methodStr == "" {
		r.methodStr = string(r.method)
	}
	return r.methodStr
}

func (r route) Path() string {
	return r.path
}

func (r *route) SetPath(s string) {
	r.path = s
}

func (r route) Middleware() Middleware {
	return r.middleware
}

func (r *route) SetMiddleware(m Middleware) {
	r.middleware = m
}

// RouteConflicts checks for route's middleware conflicts
func RouteConflicts(r *route, with string) bool {
	for _, h := range r.middleware {
		if m, ok := h.(interface {
			Conflicts() string
		}); ok {
			if c := m.Conflicts(); c == with {
				return true
			}
		}
	}
	return false
}

func (r *route) hasCors() bool {
	return RouteConflicts(r, "httpmethod")
}

const (
	// subdomainIndicator where './' exists in a registed path then it contains subdomain
	subdomainIndicator = "./"
	// dynamicSubdomainIndicator where a registed path starts with '*.' then it contains a dynamic subdomain, if subdomain == "*." then its dynamic
	dynamicSubdomainIndicator = "*."
)

type (
	muxTree struct {
		method []byte
		// subdomain is empty for default-hostname routes,
		// ex: mysubdomain.
		subdomain string
		entry     *muxEntry
		next      *muxTree
	}

	serveMux struct {
		tree    *muxTree
		lookups []*route

		onLookup func(Route)

		api           *muxAPI
		errorHandlers map[int]Handler
		logger        *logger.Logger
		// the main server host's name, ex:  localhost, 127.0.0.1, 0.0.0.0, iris-go.com
		hostname string
		// if any of the trees contains not empty subdomain
		hosts bool
		// if false then searching by unescaped path
		// defaults to true
		escapePath bool
		// if false then the /something it's not the same as /something/
		// defaults to true
		correctPath bool
		mu          sync.Mutex
	}
)

func newServeMux(logger *logger.Logger) *serveMux {
	mux := &serveMux{
		lookups:       make([]*route, 0),
		errorHandlers: make(map[int]Handler, 0),
		hostname:      config.DefaultServerHostname, // these are changing when the server is up
		escapePath:    !config.DefaultDisablePathEscape,
		correctPath:   !config.DefaultDisablePathCorrection,
		logger:        logger,
	}

	return mux
}

func (mux *serveMux) setHostname(h string) {
	mux.hostname = h
}

func (mux *serveMux) setEscapePath(b bool) {
	mux.escapePath = b
}

func (mux *serveMux) setCorrectPath(b bool) {
	mux.correctPath = b
}

// registerError registers a handler to a http status
func (mux *serveMux) registerError(statusCode int, handler Handler) {
	mux.mu.Lock()
	func(statusCode int, handler Handler) {
		mux.errorHandlers[statusCode] = HandlerFunc(func(ctx *Context) {
			ctx.ResetBody()
			ctx.SetStatusCode(statusCode)
			handler.Serve(ctx)
		})
	}(statusCode, handler)
	mux.mu.Unlock()
}

// fireError fires an error
func (mux *serveMux) fireError(statusCode int, ctx *Context) {
	mux.mu.Lock()
	errHandler := mux.errorHandlers[statusCode]
	if errHandler == nil {
		errHandler = HandlerFunc(func(ctx *Context) {
			ctx.ResetBody()
			ctx.SetStatusCode(statusCode)
			ctx.SetBodyString(statusText[statusCode])
		})
		mux.errorHandlers[statusCode] = errHandler
	}
	mux.mu.Unlock()

	errHandler.Serve(ctx)
}

func (mux *serveMux) getTree(method []byte, subdomain string) (tree *muxTree) {
	tree = mux.tree
	for tree != nil {
		if bytes.Equal(tree.method, method) && tree.subdomain == subdomain {
			return
		}
		tree = tree.next
	}
	// tree is nil here, return that.
	return
}

func (mux *serveMux) register(method []byte, subdomain string, path string, middleware Middleware) *route {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if subdomain != "" {
		mux.hosts = true
	}

	// add to the lookups, it's just a collection of routes information
	lookup := newRoute(method, subdomain, path, middleware)
	if mux.onLookup != nil {
		mux.onLookup(lookup)
	}
	mux.lookups = append(mux.lookups, lookup)

	return lookup

}

// build collects all routes info and adds them to the registry in order to be served from the request handler
// this happens once when server is setting the mux's handler.
func (mux *serveMux) build() {
	mux.tree = nil
	sort.Sort(bySubdomain(mux.lookups))
	for _, r := range mux.lookups {
		// add to the registry tree
		tree := mux.getTree(r.method, r.subdomain)
		if tree == nil {
			//first time we register a route to this method with this domain
			tree = &muxTree{method: r.method, subdomain: r.subdomain, entry: &muxEntry{}, next: nil}
			if mux.tree == nil {
				// it's the first entry
				mux.tree = tree
			} else {
				// find the last tree and make the .next to the tree we created before
				lastTree := mux.tree
				for lastTree != nil {
					if lastTree.next == nil {
						lastTree.next = tree
						break
					}
					lastTree = lastTree.next
				}
			}
		}
		// I decide that it's better to explicit give subdomain and a path to it than registedPath(mysubdomain./something) now its: subdomain: mysubdomain., path: /something
		// we have different tree for each of subdomains, now you can use everything you can use with the normal paths ( before you couldn't set /any/*path)
		if err := tree.entry.add(r.path, r.middleware); err != nil {
			mux.logger.Panic(err.Error())
		}
	}
}

func (mux *serveMux) lookup(routeName string) *route {
	for i := range mux.lookups {
		if r := mux.lookups[i]; r.name == routeName {
			return r
		}
	}
	return nil
}

func (mux *serveMux) Handler() HandlerFunc {

	// initialize the router once
	mux.build()
	// optimize this once once, we could do that: context.RequestPath(mux.escapePath), but we lose some nanoseconds on if :)
	getRequestPath := func(ctx *Context) string {
		return utils.BytesToString(ctx.Path()) //string(ctx.Path()[:]) // a little bit of memory allocation, old method used: BytesToString, If I see the benchmarks get low I will change it back to old, but this way is safer.
	}
	if !mux.escapePath {
		getRequestPath = func(ctx *Context) string { return utils.BytesToString(ctx.RequestCtx.RequestURI()) }
	}

	methodEqual := func(treeMethod []byte, reqMethod []byte) bool {
		return bytes.Equal(treeMethod, reqMethod)
	}

	// check for cors conflicts
	for _, r := range mux.lookups {
		if r.hasCors() {
			methodEqual = func(treeMethod []byte, reqMethod []byte) bool {
				return bytes.Equal(treeMethod, reqMethod) || bytes.Equal(reqMethod, methodOptionsBytes)
			}
			break
		}
	}

	return func(context *Context) {
		routePath := getRequestPath(context)
		tree := mux.tree
		for tree != nil {
			if !methodEqual(tree.method, context.Method()) {
				// we break any CORS OPTIONS method
				// but for performance reasons if user wants http method OPTIONS to be served
				// then must register it with .Options(...)
				tree = tree.next
				continue
			}
			// we have at least one subdomain on the root
			if mux.hosts && tree.subdomain != "" {
				// context.VirtualHost() is a slow method because it makes string.Replaces but user can understand that if subdomain then server will have some nano/or/milleseconds performance cost
				requestHost := context.VirtualHostname()
				if requestHost != mux.hostname {
					// we have a subdomain
					if strings.Index(tree.subdomain, dynamicSubdomainIndicator) != -1 {
					} else {
						// mux.host = iris-go.com:8080, the subdomain for example is api.,
						// so the host must be api.iris-go.com:8080
						if tree.subdomain+mux.hostname != requestHost {
							// go to the next tree, we have a subdomain but it is not the correct
							tree = tree.next
							continue
						}

					}
				} else {
					//("it's subdomain but the request is the same as the listening addr mux.host == requestHost =>" + mux.host + "=" + requestHost + " ____ and tree's subdomain was: " + tree.subdomain)
					tree = tree.next
					continue
				}
			}
			middleware, params, mustRedirect := tree.entry.get(routePath, context.Params) // pass the parameters here for 0 allocation
			if middleware != nil {
				// ok we found the correct route, serve it and exit entirely from here
				context.Params = params
				context.middleware = middleware
				//ctx.Request.Header.SetUserAgentBytes(DefaultUserAgent)
				context.Do()
				return
			} else if mustRedirect && mux.correctPath && !bytes.Equal(context.Method(), methodConnectBytes) {

				reqPath := routePath
				pathLen := len(reqPath)

				if pathLen > 1 {

					if reqPath[pathLen-1] == '/' {
						reqPath = reqPath[:pathLen-1] //remove the last /
					} else {
						//it has path prefix, it doesn't ends with / and it hasn't be found, then just add the slash
						reqPath = reqPath + "/"
					}

					context.Request.URI().SetPath(reqPath)
					urlToRedirect := utils.BytesToString(context.Request.RequestURI())

					context.Redirect(urlToRedirect, StatusMovedPermanently) //	StatusMovedPermanently
					// RFC2616 recommends that a short note "SHOULD" be included in the
					// response because older user agents may not understand 301/307.
					// Shouldn't send the response for POST or HEAD; that leaves GET.
					if bytes.Equal(tree.method, methodGetBytes) {
						note := "<a href=\"" + utils.HTMLEscape(urlToRedirect) + "\">Moved Permanently</a>.\n"
						context.Write(note)
					}
					return
				}
			}
			// not found
			break
		}
		mux.fireError(StatusNotFound, context)
	}
}


text:
package androidx.emoji2.viewsintegration;

import android.annotation.SuppressLint;
import android.text.Editable;

import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.emoji2.text.SpannableBuilder;

/**
 * EditableFactory used to improve editing operations on an EditText.
 *

 * EditText uses DynamicLayout, which attaches to the Spannable instance that is being edited using
 * ChangeWatcher. ChangeWatcher implements SpanWatcher and Textwatcher. Currently every delete/add
 * operation is reported to DynamicLayout, for every span that has changed. For each change,
 * DynamicLayout performs some expensive computations. i.e. if there is 100 EmojiSpans and the first
 * span is deleted, DynamicLayout gets 99 calls about the change of position occurred in the
 * remaining spans. This causes a huge delay in response time.
 *

 * Since "android.text.DynamicLayout$ChangeWatcher" class is not a public class,
 * EmojiEditableFactory checks if the watcher is in the classpath, and if so uses the modified
 * Spannable which reduces the total number of calls to DynamicLayout for operations that affect
 * EmojiSpans.
 *
 * @see SpannableBuilder
 */
final class EmojiEditableFactory extends Editable.Factory {
    private static final Object INSTANCE_LOCK = new Object();
    @GuardedBy("INSTANCE_LOCK")
    private static volatile Editable.Factory sInstance;

    @Nullable private static Class<?> sWatcherClass;

    @SuppressLint("PrivateApi")
    private EmojiEditableFactory() {
        try {
            String className = "android.text.DynamicLayout$ChangeWatcher";
            sWatcherClass = Class.forName(className, false, getClass().getClassLoader());
        } catch (Throwable t) {
            // ignore
        }
    }

    @SuppressWarnings("GuardedBy")
    public static Editable.Factory getInstance() {
        if (sInstance == null) {
            synchronized (INSTANCE_LOCK) {
                if (sInstance == null) {
                    sInstance = new EmojiEditableFactory();
                }
            }
        }
        return sInstance;
    }

    @Override
    public Editable newEditable(@NonNull final CharSequence source) {
        if (sWatcherClass != null) {
            return SpannableBuilder.create(sWatcherClass, source);
        }
        return super.newEditable(source);
    }
}

redpajama_set_name: RedPajamaGithub


text:
/*
 * HomePage Messages
 *
 * This contains all the text for the HomePage component.
 */
import { defineMessages } from 'react-intl';

export default defineMessages({
  home: {
    id: 'simpleapps.components.Header.home',
    defaultMessage: 'Home',
  }
});


text:
var parseHeader = require('../lib/parseHeader');

describe('ParseHeader', function() {

  it('should throw an Error if passed no header type', function() {
    var notDefined = 'Authorization header incorrect (undefined)';
    var justWrong = 'Authorization header incorrect (foo)';
    expect(parseHeader).toThrowError(Error, notDefined);
    expect(function() {parseHeader('foo')}).toThrowError(Error, justWrong);
  });

  it('should return the token part of "Bearer {token}"', function() {
    var parseToken = parseHeader('token');
    expect(parseToken('Bearer foo.bar.token')).toBe('foo.bar.token');
  });

  it('should return the {user,password} for "Basic {base64}"', function() {
    var parseBasic = parseHeader('basic');
    var str = (new Buffer('user:password', 'utf8')).toString('base64');
    var parsed = parseBasic(`Basic ${str}`);
    expect(parsed.user).toBe('user');
    expect(parsed.password).toBe('password');
  });

  it('should return false if header is doesn\'t match type"', function() {
    var parseBasic = parseHeader('basic');
    expect(parseBasic('Bearer foo.bar.token')).toBe(false);
  });

  it('should return false if header or "Basic {base64} is malformed', function() {
    var parseBasic = parseHeader('basic');
    var notBase64 = parseBasic('Basic foo');
    var noString = parseBasic('Basic ');
    var noColon = (new Buffer('pass', 'utf8')).toString('base64');
    var noDelimitingColon = parseBasic(`Basic ${noColon}`);

    var parseToken = parseHeader('token');
    var noToken = parseToken('Bearer ');

    expect(notBase64).toBe(false);
    expect(noString).toBe(false);
    expect(noToken).toBe(false);
    expect(noDelimitingColon).toBe(false);
  });
});


text:
package com.ilivoo.xag.model.core.log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.MessageFormatter;

/**
 * 模块信息, 表示一种日志
 *
 * @author ilivoo
 *
 */
public class ModuleInfo {

	private static final Logger log = LoggerFactory.getLogger(ModuleInfo.class);
	/** 具体模块 */
	private int module;
	/** 模块的子模块 */
	private int subModule;
	/** 记录的消息, 此消息可以根据具体需要进行自行定义 */
	private String message;

	public static ModuleInfo valueOf(ModuleType module, SubModuleType subModule) {
		if (!subModule.getType().equals(module)) {
			String message = MessageFormatter.format("模块[{}]必须是父模块[{}]的子模块", module, subModule).getMessage();
			log.error(message);
		}
		ModuleInfo info = new ModuleInfo();
		info.module = module.getId();
		info.subModule = subModule.getId();
		info.message = subModule.getMessage();
		return info;
	}

	public static ModuleInfo valueOf(ModuleType module, SubModuleType subModule, String message) {
		if (!subModule.getType().equals(module)) {
			String logMessage = MessageFormatter.format("模块[{}]必须是父模块[{}]的子模块", module, subModule).getMessage();
			log.error(logMessage);
		}
		ModuleInfo info = new ModuleInfo();
		info.module = module.getId();
		info.subModule = subModule.getId();
		info.message = message;
		return info;
	}

	public int getModule() {
		return module;
	}

	public void setModule(int module) {
		this.module = module;
	}

	public int getSubModule() {
		return subModule;
	}

	public void setSubModule(int subModule) {
		this.subModule = subModule;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>ClientHandshakeBuilder</title>
<meta name="date" content="2014-07-23">
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Overview

Package

Class

Tree

Deprecated

Index

Help

Prev Class

Next Class

Frames

No Frames

All Classes

Summary:

Nested |

Field |

Constr |

Method

Detail:

Field |

Constr |

Method

org.java_websocket.handshake

Interface ClientHandshakeBuilder

All Superinterfaces:

ClientHandshake, HandshakeBuilder, Handshakedata

All Known Implementing Classes:

HandshakeImpl1Client

public interface ClientHandshakeBuilder
extends HandshakeBuilder, ClientHandshake

Method Summary

Methods

Modifier and Type
Method and Description

void
setResourceDescriptor(java.lang.String resourceDescriptor)

Methods inherited from interface org.java_websocket.handshake.HandshakeBuilder

put, setContent

Methods inherited from interface org.java_websocket.handshake.ClientHandshake

getResourceDescriptor

Methods inherited from interface org.java_websocket.handshake.Handshakedata

getContent, getFieldValue, hasFieldValue, iterateHttpFields

Method Detail

setResourceDescriptor

void setResourceDescriptor(java.lang.String resourceDescriptor)

Overview

Package

Class

Tree

Deprecated

Index

Help

Prev Class

Next Class

Frames

No Frames

All Classes

Summary:

Nested |

Field |

Constr |

Method

Detail:

Field |

Constr |

Method


text:
/**
 * {@link LuceneTestCase}的使用
 * @author zhoujiagen
 */
package com.spike.text.lucene.test;

import org.apache.lucene.util.LuceneTestCase;


text:
package tracker

var DefaultURL = "https://www.pivotaltracker.com"

type Client struct {
	conn connection
}

func NewClient(token string) *Client {
	return &Client{
		conn: newConnection(token),
	}
}

func (c Client) Me() (me Me, err error) {
	request, err := c.conn.CreateRequest("GET", "/me")
	if err != nil {
		return me, err
	}

	_, err = c.conn.Do(request, &me)

	return me, err
}

func (c Client) InProject(projectId int) ProjectClient {
	return ProjectClient{
		id:   projectId,
		conn: c.conn,
	}
}


text:
<?php

declare(strict_types=1);

namespace WordPlate\Tests\Acf\Fields;

use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use WordPlate\Acf\Fields\WysiwygEditor;

class WysiwygEditorTest extends TestCase
{
    public function testType()
    {
        $field = WysiwygEditor::make('Wysiwyg Editor')->toArray();
        $this->assertSame('wysiwyg', $field['type']);
    }

    public function testMediaUpload()
    {
        $field = WysiwygEditor::make('Wysiwyg Editor Media Upload')->mediaUpload(false)->toArray();
        $this->assertFalse($field['media_upload']);
    }

    public function testTabs()
    {
        $field = WysiwygEditor::make('Wysiwyg Editor Tabs')->tabs('visual')->toArray();
        $this->assertSame('visual', $field['tabs']);

        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Invalid argument tabs [test].');

        $field = WysiwygEditor::make('Wysiwyg Editor Inavlid Tabs')->tabs('test')->toArray();
    }

    public function testToolbar()
    {
        $field = WysiwygEditor::make('Wysiwyg Editor Toolbar')->toolbar('basic')->toArray();
        $this->assertSame('basic', $field['toolbar']);
    }
}


text:
package com.ecomhack.riddle.sphere;

import java.lang.reflect.Type;

import com.ecomhack.riddle.sphere.models.AuthResponse;
import com.ecomhack.riddle.sphere.models.Challenge;
import com.ecomhack.riddle.sphere.models.QueryResult;
import com.estimote.sdk.repackaged.gson_v2_3_1.com.google.gson.reflect.TypeToken;

public class SphereChallengeQueryTask extends SphereQueryTask<QueryResult<Challenge>> {
    private static final String TAG = SphereChallengeQueryTask.class.getSimpleName();

    public SphereChallengeQueryTask(AuthResponse authResponse) {
        super(authResponse);
    }

    @Override
    String tag() {
        return TAG;
    }

    @Override
    String endpoint() {
        return "categories";
    }

    @Override
    Type type() {
        return new TypeToken<QueryResult<Challenge>>() {}.getType();
    }

}


text:
package org.apache.camel.processor.aggregate.jdbc;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.support.DefaultExchange;
import org.apache.camel.impl.DefaultExchangeHolder;
import org.apache.camel.util.IOHelper;

/**
 * Adapted from HawtDBCamelCodec
 */
public class JdbcCamelCodec {

    public byte[] marshallExchange(CamelContext camelContext, Exchange exchange, boolean allowSerializedHeaders) throws IOException {
        // use DefaultExchangeHolder to marshal to a serialized object
        DefaultExchangeHolder pe = DefaultExchangeHolder.marshal(exchange, false, allowSerializedHeaders);
        // add the aggregated size and timeout property as the only properties we want to retain
        DefaultExchangeHolder.addProperty(pe, Exchange.AGGREGATED_SIZE, exchange.getProperty(Exchange.AGGREGATED_SIZE, Integer.class));
        DefaultExchangeHolder.addProperty(pe, Exchange.AGGREGATED_TIMEOUT, exchange.getProperty(Exchange.AGGREGATED_TIMEOUT, Long.class));
        // add the aggregated completed by property to retain
        DefaultExchangeHolder.addProperty(pe, Exchange.AGGREGATED_COMPLETED_BY, exchange.getProperty(Exchange.AGGREGATED_COMPLETED_BY, String.class));
        // add the aggregated correlation key property to retain
        DefaultExchangeHolder.addProperty(pe, Exchange.AGGREGATED_CORRELATION_KEY, exchange.getProperty(Exchange.AGGREGATED_CORRELATION_KEY, String.class));
        DefaultExchangeHolder.addProperty(pe, Exchange.AGGREGATED_CORRELATION_KEY, exchange.getProperty(Exchange.AGGREGATED_CORRELATION_KEY, String.class));
        // and a guard property if using the flexible toolbox aggregator
        DefaultExchangeHolder.addProperty(pe, Exchange.AGGREGATED_COLLECTION_GUARD, exchange.getProperty(Exchange.AGGREGATED_COLLECTION_GUARD, String.class));
        // persist the from endpoint as well
        if (exchange.getFromEndpoint() != null) {
            DefaultExchangeHolder.addProperty(pe, "CamelAggregatedFromEndpoint", exchange.getFromEndpoint().getEndpointUri());
        }
        return encode(pe);
    }

    public Exchange unmarshallExchange(CamelContext camelContext, byte[] buffer) throws IOException, ClassNotFoundException {
        DefaultExchangeHolder pe = decode(camelContext, buffer);
        Exchange answer = new DefaultExchange(camelContext);
        DefaultExchangeHolder.unmarshal(answer, pe);
        // restore the from endpoint
        String fromEndpointUri = (String) answer.removeProperty("CamelAggregatedFromEndpoint");
        if (fromEndpointUri != null) {
            Endpoint fromEndpoint = camelContext.hasEndpoint(fromEndpointUri);
            if (fromEndpoint != null) {
                answer.setFromEndpoint(fromEndpoint);
            }
        }
        return answer;
    }

    private byte[] encode(Object object) throws IOException {
        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
        ObjectOutputStream objectOut = new ObjectOutputStream(bytesOut);
        objectOut.writeObject(object);
        objectOut.close();
        byte[] data = bytesOut.toByteArray();
        return data;
    }

    private DefaultExchangeHolder decode(CamelContext camelContext, byte[] dataIn) throws IOException, ClassNotFoundException {
        ByteArrayInputStream bytesIn = new ByteArrayInputStream(dataIn);

        ObjectInputStream objectIn = null;
        Object obj = null;
        try {
            objectIn = new ClassLoadingAwareObjectInputStream(camelContext, bytesIn);
            obj = objectIn.readObject();
        } finally {
            IOHelper.close(objectIn);
        }

        return (DefaultExchangeHolder)obj;
    }

}


text:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace MO.Core.Compiler {

   public class Test {

      public void Show() {
         MessageBox.Show(GetType().FullName);
      }

   }

}


text:
import { DateTime } from 'luxon';

import { EChart } from '@waldur/core/EChart';
import { translate } from '@waldur/i18n';
import { CloseDialogButton } from '@waldur/modal/CloseDialogButton';
import { ModalDialog } from '@waldur/modal/ModalDialog';

import { PlanUsageRowProps } from './types';

const getChartData = (props: PlanUsageRowProps) => ({
  toolbox: {
    show: true,
    showTitle: false,
    feature: {
      saveAsImage: {
        name: `${props.row.plan_name}-${DateTime.now().toISODate()}`,
      },
    },
  },
  series: [
    {
      type: 'pie',
      radius: ['50%', '70%'],
      label: {
        show: true,
        formatter: '{b}: {c}',
      },
      data: [
        {
          name: translate('Usage'),
          value: props.row.usage,
        },
        {
          name: translate('Remaining amount'),
          value: Math.max(0, props.row.limit - props.row.usage),
        },
      ],
    },
  ],
});

export const PlanUsageDialog = (props: { resolve: PlanUsageRowProps }) => (
  <ModalDialog
    title={translate('Plan capacity')}
    footer={<CloseDialogButton />}
  >

      {translate('Provider')}:{' '}
      {props.resolve.row.customer_provider_name}

      {translate('Offering')}:{' '}
      {props.resolve.row.offering_name}

      {translate('Plan')}: {props.resolve.row.plan_name}

    <EChart options={getChartData(props.resolve)} height="300px" />
  </ModalDialog>
);


text:
module Tins
  require 'tins/attempt'
  require 'tins/bijection'
  require 'tins/count_by'
  require 'tins/deep_dup'
  require 'tins/file_binary'
  require 'tins/find'
  require 'tins/generator'
  require 'tins/go'
  require 'tins/hash_symbolize_keys_recursive'
  require 'tins/hash_union'
  require 'tins/limited'
  require 'tins/lines_file'
  require 'tins/memoize'
  require 'tins/minimize'
  require 'tins/module_group'
  require 'tins/null'
  require 'tins/once'
  require 'tins/p'
  require 'tins/partial_application'
  require 'tins/range_plus'
  require 'tins/require_maybe'
  require 'tins/round'
  require 'tins/secure_write'
  require 'tins/shuffle'
  require 'tins/string_camelize'
  require 'tins/string_underscore'
  require 'tins/string_version'
  require 'tins/subhash'
  require 'tins/time_dummy'
  require 'tins/date_dummy'
  require 'tins/date_time_dummy'
  require 'tins/to_proc'
  require 'tins/uniq_by'
  require 'tins/version'
  require 'tins/write'
  require 'tins/extract_last_argument_options'
end
require 'tins/alias'


text:
Meteor.publish("allMarkers",function(){
    return markers.find({},{});
});

Meteor.publish("allMarkerTypes",function(){
    return marker_types.find({},{});
});

Meteor.publish("allGroups",function(){
    return groups.find({},{});
});

Meteor.publish("allMarkerServices",function(){
    return marker_services.find({},{});
});

Meteor.publish("allServices",function(){
    return services.find({},{});
});

/* allow editing of group_codes records so long as owner is current user id

    group codes might look like:

    {
        _id: <mongo_id>,
        group_id : <groups._id>,
        owner : Meteor.userId(),
        hash : (string),
        salt : (string),
        permission : (admin/mod/client)

    }

*/
Meteor.publish("groupCodes",function(){
    return group_codes.find({owner:Meteor.userId()},{});
});

Meteor.publish("publicGroups",function(){
    return groups.find({visibility:'public'});
});
// find all 'public' markers .. i.e.. markers that belong to a public group? should i generate a listing
// of all public groups and look for markers belonging to those? in deps!!!

/*
 stores codes for a user to edit (only their own based on Meteor.userId()
 a record is created in users_group_codes every time a group is subscribed to so long as a refer code record exists and is active.

    term refers to the 'protected passphrase' that is required to grant access...

    Probably run salt on term and compare against hash

    users_group_codes

    {

        _id: <mongo_id>,
        owner: Meteor.userId();
        code_id : group_codes._id,
        term : <string>
    }

*/

Meteor.publish("usersGroupCodes",function(){
    return users_group_codes.find({owner:Meteor.userId()},{});
});

Meteor.startup(function () {
    // Pre fil the markertypes with some default types .. images are stored in /public
    if(marker_types.find({},{}).count() == 0){
        console.log('filling marker types');
        var default_markers = [
            {
                name: 'Other',
                owner : 'sys',
                img : '/Other.png'
            },
            {
                name: 'Clinic',
                owner : 'sys',
                img : '/Clinic.png'
            },
            {
                name: 'Hospital',
                owner : 'sys',
                img : '/Hospital.png'
            },
            {
                name: 'Pharmacy',
                owner : 'sys',
                img : '/Pharmacy.png'
            },
            {
                name: 'Shelter',
                owner : 'sys',
                img : '/Shelter.png'
            }
        ];
        for(var i=0;i<default_markers.length;i++)
            console.log(marker_types.insert(default_markers[i]));

    }
});

// basic function that determines if the user can edit
Meteor.methods({
    canEdit : function(curMarker,theCollection,userId){
    console.log(curMarker + ' , ' + theCollection + ' , ' + userId);
        if(curMarker && theCollection == 'markers'){
            var q = markers.findOne({_id: curMarker, owner: userId });
        }else if(typeof theCollection != 'undefined'){
            if(theCollection == 'groups')
                // use a switch but for now support groups ?
                var q = groups.findOne({_id:curMarker,owner:userId});
        }
        if(q){
            console.log(q);
            return q._id;
        }
        return false;
    }
});


text:
module SagePay
  module Server
    class SignatureVerifier
      def initialize(params, signature_verification_details)

        @params = params
        @signature_verification_details = signature_verification_details
      end

      def calculate_hash
        return nil if @signature_verification_details.nil?

        Digest::MD5.hexdigest(fields_used_in_signature.join).upcase
      end

      private
      def fields_used_in_signature
        [
          @params["VPSTxId"],
          @params["VendorTxCode"],
          @params["Status"],
          @params["TxAuthNo"],
          @signature_verification_details.vendor,
          @params["AVSCV2"],
          @signature_verification_details.security_key,
          @params["AddressResult"],
          @params["PostCodeResult"],
          @params["CV2Result"],
          @params["GiftAid"],
          @params["3DSecureStatus"],
          @params["CAVV"],
          @params["AddressStatus"],
          @params["PayerStatus"],
          @params["CardType"],
          @params["Last4Digits"]
        ]
      end
    end
  end
end


text:
package com.pojos;
// Generated Nov 9, 2013 6:18:21 PM by Hibernate Tools 3.6.0

/**
 * Productinventory generated by hbm2java
 */
public class Productinventory  implements java.io.Serializable {

     private Integer piId;
     private Product product;
     private Integer inventoryCount;
     private Integer backOrder;
     private Integer discontinued;

    public Productinventory() {
    }

    public Productinventory(Product product, Integer inventoryCount, Integer backOrder, Integer discontinued) {
       this.product = product;
       this.inventoryCount = inventoryCount;
       this.backOrder = backOrder;
       this.discontinued = discontinued;
    }

    public Integer getPiId() {
        return this.piId;
    }

    public void setPiId(Integer piId) {
        this.piId = piId;
    }
    public Product getProduct() {
        return this.product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }
    public Integer getInventoryCount() {
        return this.inventoryCount;
    }

    public void setInventoryCount(Integer inventoryCount) {
        this.inventoryCount = inventoryCount;
    }
    public Integer getBackOrder() {
        return this.backOrder;
    }

    public void setBackOrder(Integer backOrder) {
        this.backOrder = backOrder;
    }
    public Integer getDiscontinued() {
        return this.discontinued;
    }

    public void setDiscontinued(Integer discontinued) {
        this.discontinued = discontinued;
    }

}


text:
package org.apereo.cas.mgmt.services.web.factory;

import org.apereo.cas.mgmt.services.web.beans.RegisteredServiceEditBean;
import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
import org.apereo.cas.mgmt.services.web.beans.RegisteredServiceViewBean;

/**
 * Interface for converting {@link RegisteredServiceAttributeReleasePolicy} to/from {@link RegisteredServiceEditBean.ServiceData}.
 *
 * @author Daniel Frett
 * @since 4.2
 */
public interface AttributeReleasePolicyMapper {
    /**
     * Map {@link RegisteredServiceAttributeReleasePolicy} onto the target {@link RegisteredServiceEditBean.ServiceData} data bean.
     *
     * @param policy the source attribute release policy
     * @param bean   the destination data bean
     */
    void mapAttributeReleasePolicy(RegisteredServiceAttributeReleasePolicy policy, RegisteredServiceEditBean.ServiceData bean);

    /**
     * Map {@link RegisteredServiceAttributeReleasePolicy} onto the target {@link RegisteredServiceViewBean} data bean.
     *
     * @param policy the source attribute release policy
     * @param bean   the destination data bean
     */
    void mapAttributeReleasePolicy(RegisteredServiceAttributeReleasePolicy policy, RegisteredServiceViewBean bean);

    /**
     * Create a {@link RegisteredServiceAttributeReleasePolicy} represented by the specified
     * {@link RegisteredServiceEditBean.ServiceData} bean.
     * Return null if a supported {@link RegisteredServiceAttributeReleasePolicy} couldn't be created.
     *
     * @param data a source data bean
     * @return the attribute release policy represented by the specified data bean
     */
    RegisteredServiceAttributeReleasePolicy toAttributeReleasePolicy(RegisteredServiceEditBean.ServiceData data);
}


text:
.. index::
   single: Resource Layer

Resource Layer
==============

We created an abstraction on top of Doctrine, in order to have a consistent and flexible way to manage all the resources. By "resource" we understand every model in the application.
Simplest examples of Sylius resources are "product", "order", "tax_category", "promotion", "user", "shipping_method" and so on...

There are two types of resources in **Sylius**:

* registered by default - their names begin with ``sylius.*`` for example: ``sylius.product``
* custom resources, from your application which have a separate convention. We place them under ``sylius_resource:`` ``resource_name:`` in the ``config.yml``. For these we recommend using the naming convenion of ``app.*`` for instance ``app.my_entity``.

Sylius resource management system lives in the **SyliusResourceBundle** and can be used in any Symfony2 project.

Services
~~~~~~~~

For every resource you have four essential services available:

* Factory
* Manager
* Repository
* Controller

Let us take the "product" resource as an example. By default, it is represented by an object of a class that implements the ``Sylius\Component\Core\Model\ProductInterface``.

Factory
~~~~~~~

The factory service gives you an ability to create new default objects. It can be accessed via the *sylius.factory.product* id (for the Product resource of course).

.. code-block:: php

    <?php

    public function myAction()
    {
        $factory = $this->container->get('sylius.factory.product');

        /** @var ProductInterface $product **/
        $product = $factory->createNew();
    }

.. note::

    Creating resources via this factory method makes the code more testable, and allows you to change the model class easily.

Manager
~~~~~~~

The manager service is just an alias to appropriate Doctrine's `ObjectManager`_ and can be accessed via the *sylius.manager.product* id.
API is exactly the same and you are probably already familiar with it:

.. code-block:: php

    <?php

    public function myAction()
    {
        $manager = $this->container->get('sylius.manager.product');

        // Assuming that the $product1 exists in the database we can perform such operations:
        $manager->remove($product1);

        // If we have created the $product2 using a factory, we can persist it in the database.
        $manager->persist($product2);

        // Before performing a flush, the changes we have made, are not saved. There is only the $product1 in the database.
        $manager->flush(); // Saves changes in the database.

        //After these operations we have only $product2 in the database. The $product1 has been removed.
    }

Repository
~~~~~~~~~~

Repository is defined as a service for every resource and shares the API with standard Doctrine *ObjectRepository*. It contains two additional methods for creating a new object instance and a paginator provider.

The repository service is available via the *sylius.repository.product* id and can be used like all the repositories you have seen before.

.. code-block:: php

    <?php

    public function myAction()
    {
        $repository = $this->container->get('sylius.repository.product');

        $product = $repository->find(4); // Get product with id 4, returns null if not found.
        $product = $repository->findOneBy(['slug' => 'my-super-product']); // Get one product by defined criteria.

        $products = $repository->findAll(); // Load all the products!
        $products = $repository->findBy(['special' => true]); // Find products matching some custom criteria.
    }

Every Sylius repository supports paginating resources. To create a `Pagerfanta instance <https://github.com/whiteoctober/Pagerfanta>`_ use the ``createPaginator`` method:

.. code-block:: php

    <?php

    public function myAction(Request $request)
    {
        $repository = $this->container->get('sylius.repository.product');

        $products = $repository->createPaginator();
        $products->setMaxPerPage(3);
        $products->setCurrentPage($request->query->get('page', 1));

        // Now you can return products to template and iterate over it to get products from current page.
    }

Paginator can be created for a specific criteria and with desired sorting:

.. code-block:: php

    <?php

    public function myAction(Request $request)
    {
        $repository = $this->container->get('sylius.repository.product');

        $products = $repository->createPaginator(['foo' => true], ['createdAt' => 'desc']);
        $products->setMaxPerPage(3);
        $products->setCurrentPage($request->query->get('page', 1));
    }

Controller
~~~~~~~~~~

This service is the most important for every resource and provides a format agnostic CRUD controller with the following actions:

* [GET]      showAction() for getting a single resource
* [GET]      indexAction() for retrieving a collection of resources
* [GET/POST] createAction() for creating new resource
* [GET/PUT]  updateAction() for updating an existing resource
* [DELETE]   deleteAction() for removing an existing resource

As you see, these actions match the common operations in any REST API and yes, they are format agnostic.
This means, all Sylius controllers can serve HTML, JSON or XML, depending on what you request.

Additionally, all these actions are very flexible and allow you to use different templates, forms, repository methods per route.
The bundle is very powerful and allows you to register your own resources as well. To give you some idea of what is possible, here are some examples!

Displaying a resource with a custom template and repository methods:

.. code-block:: yaml

    # routing.yml
    app_product_show:
        path: /products/{slug}
        methods: [GET]
        defaults:
            _controller: sylius.controller.product:showAction
            _sylius:
                template: AppStoreBundle:Product:show.html.twig # Use a custom template.
                repository:
                    method: findForStore # Use a custom repository method.
                    arguments: [$slug] # Pass the slug from the url to the repository.

Creating a product using custom form and a redirection method:

.. code-block:: yaml

    # routing.yml
    app_product_create:
        path: /my-stores/{store}/products/new
        methods: [GET, POST]
        defaults:
            _controller: sylius.controller.product:createAction
            _sylius:
                form: app_user_product # Use this form type!
                template: AppStoreBundle:Product:create.html.twig # Use a custom template.
                factory:
                    method: createForStore # Use a custom factory method to create a product.
                    arguments: [$store] # Pass the store name from the url.
                redirect:
                    route: app_product_index # Redirect the user to his products.
                    parameters: [$store]

All other methods have the same level of flexibility and are documented in the :doc:`Resource Bundle Guide </bundles/SyliusResourceBundle/index>`.

.. _`ObjectManager`: http://www.doctrine-project.org/api/common/2.4/class-Doctrine.Common.Persistence.ObjectManager.html


text:
import copy

import mock
import testtools

from stackalytics.processor import default_data_processor
from stackalytics.processor import normalizer
from tests.unit import test_data

class TestDefaultDataProcessor(testtools.TestCase):
    def setUp(self):
        super(TestDefaultDataProcessor, self).setUp()

        self.get_users = mock.Mock(return_value=[
            test_data.USERS,
        ])

        normalized_data = copy.deepcopy(test_data.DEFAULT_DATA)
        normalizer.normalize_default_data(normalized_data)

    def tearDown(self):
        super(TestDefaultDataProcessor, self).tearDown()

    def test_normalizer(self):
        data = copy.deepcopy(test_data.DEFAULT_DATA)

        normalizer.normalize_default_data(data)

        self.assertIn('releases', data['repos'][0])
        self.assertEqual([], data['repos'][0]['releases'],
                         message='Empty list of releases expected')
        self.assertEqual(0, data['users'][0]['companies'][-1]['end_date'],
                         message='The last company end date should be 0')
        self.assertIn('user_id', data['users'][0])
        self.assertEqual(test_data.USERS[0]['launchpad_id'],
                         data['users'][0]['user_id'],
                         message='User id should be set')

    def test_update_project_list(self):
        with mock.patch('stackalytics.processor.default_data_processor.'
                        '_retrieve_project_list_from_github') as retriever:
            retriever.return_value = [
                {'module': 'nova', 'uri': 'git://github.com/openstack/nova'},
                {'module': 'qa', 'uri': 'git://github.com/openstack/qa'},
            ]
            dd = {
                'repos': [
                    {'module': 'qa', 'uri': 'git://github.com/openstack/qa'},
                ],
                'project_sources': ['any']
            }

            default_data_processor._update_project_list(dd)

            self.assertEqual(2, len(dd['repos']))
            self.assertIn('qa', set([r['module'] for r in dd['repos']]))
            self.assertIn('nova', set([r['module'] for r in dd['repos']]))


text:
/*
 * rosserial Clapper Example
 *
 * This code is a very simple example of the kinds of
 * custom sensors that you can easily set up with rosserial
 * and Mbed.  This code uses a microphone attached to
 * analog pin p20 detect two claps (2 loud sounds).
 * You can use this clapper, for example, to command a robot
 * in the area to come do your bidding.
 */

#include <ros.h>
#include <std_msgs/Empty.h>

#if defined(TARGET_LPC1768)
PinName mic = p20;
#elif defined(TARGET_KL25Z) || defined(TARGET_NUCLEO_F401RE)
PinName mic = A0;
#else
#error "You need to specify a pin for the mic"
#endif

ros::NodeHandle  nh;

std_msgs::Empty clap_msg;
ros::Publisher p("clap", &clap_msg);

enum clapper_state { clap1, clap_one_waiting,  pause, clap2};
clapper_state clap;

int volume_thresh = 200;  //a clap sound needs to be:
//abs(clap_volume) > average noise + volume_thresh
AnalogIn mic_pin(mic);
int adc_ave=0;

Timer t;
int main() {
    t.start();
    nh.initNode();

    nh.advertise(p);

    //measure the average volume of the noise in the area
    for (int i =0; i<10; i++) adc_ave += mic_pin.read_u16();
    adc_ave /= 10;

    long event_timer = 0;

    while (1) {
        int mic_val = 0;
        for (int i=0; i<4; i++) mic_val += mic_pin.read_u16();

        mic_val = mic_val/4-adc_ave;

        switch (clap) {
            case clap1:
                if (abs(mic_val) > volume_thresh) {
                    clap = clap_one_waiting;
                    event_timer = t.read_ms();
                }
                break;
            case clap_one_waiting:
                if ( (abs(mic_val) < 30) && ( (t.read_ms()- event_timer) > 20 ) ) {
                    clap= pause;
                    event_timer = t.read_ms();

                }
                break;
            case pause: // make sure there is a pause between
                // the loud sounds
                if ( mic_val > volume_thresh) {
                    clap = clap1;

                } else if ( (t.read_ms()-event_timer)> 60)  {
                    clap = clap2;
                    event_timer = t.read_ms();

                }
                break;
            case clap2:
                if (abs(mic_val) > volume_thresh) { //we have got a double clap!
                    clap = clap1;
                    p.publish(&clap_msg);
                } else if ( (t.read_ms()-event_timer)> 200) {
                    clap= clap1; // no clap detected, reset state machine
                }

                break;
        }
        nh.spinOnce();
    }
}